Skip to content

feat(cowork): add Kimi CLI as a Cowork engine#35

Open
stephenlzc wants to merge 10 commits into
freestylefly:mainfrom
stephenlzc:feature/kimi-cli-engine
Open

feat(cowork): add Kimi CLI as a Cowork engine#35
stephenlzc wants to merge 10 commits into
freestylefly:mainfrom
stephenlzc:feature/kimi-cli-engine

Conversation

@stephenlzc
Copy link
Copy Markdown
Contributor

@stephenlzc stephenlzc commented Jun 3, 2026

背景与动机

WeSight 之前支持 9 个 Cowork 引擎(Claude Code / Codex / OpenClaw / Hermes / OpenCode / Qwen Code / DeepSeek-TUI / Grok Build / WeSight runtime),但没有 Kimi CLI。Kimi CLI 是 Moonshot AI 官方的终端编码 Agent,主打长上下文(kimi-k2.5、kimi-code/kimi-for-coding 等模型)+ MCP 工具集成,国内开发者用得很多。

需求在 issue #34 里:

我应该在 Agent Engine 这里增加 Kimi Code 的检测以及它的界面

实测过程中又冒出一个更深的问题

我觉得这个需求不仅仅是 Kimi,而是所有的模型、所有的 Agent 里面,我可能原来已经设置好了对应的模型,这个时候就可以不用再重新选择模型了。

意思是:如果用户本地 CLI 配好了模型,WeSight 应该自动读取,不要让用户再去 Settings 翻 LocalCli 切换。这是一个通用问题,不是 Kimi 专属。


核心改动

一、Kimi CLI 引擎完整集成(10 个文件 +243/-0)

Engine registry

  • src/shared/cowork/constants.ts:新增 CoworkAgentEngine.KimiCli: 'kimi_cli' 常量 + KimiCliPermissionMode 枚举(auto / conservative,对应 kimi --yolo / kimi --plan)+ isKimiCliPermissionMode 守卫
  • src/main/coworkStore.tsCoworkConfigkimiCliConfigSource: ExternalAgentConfigSource + kimiCliPermissionMode: KimiCliPermissionMode 字段,SQLite 持久化
  • src/renderer/types/cowork.ts + src/renderer/types/electron.d.ts:同步 IPC 契约的类型定义

Real spawn(LocalCli 模式)

src/main/libs/agentEngine/externalCliRuntimeAdapter.ts 补 6 个 per-engine 分支:

  • getCommandName():返 'kimi'
  • getConfigSource():读 config.kimiCliConfigSource
  • getSelectedProviderForLocalCli():从 external_agent_providers 表拿 app_type='kimi' 的当前 provider
  • buildCommandArgs() KimiCli 分支:仿 QwenCode 模式
    kimi --print --output-format stream-json --work-dir <cwd> \
         --yolo|--plan \
         --model <model> --prompt <prompt>
  • applyKimiCliRuntimeConfig():把 KIMI_API_KEY / KIMI_BASE_URL / KIMI_MODEL_NAME 注入子进程 env(复用 kimiCliConfig.ts 里的 buildKimiCliRuntimeEnv
  • handleKimiCliEvent():把 kimi --print 的 stream-json 事件归一化(先用 parseKimiCliJsonLine,再 dispatch 到 applyKimiNormalizedEvent

LocalCli provider 自动同步

  • src/main/libs/kimiCliConfigReader.ts(新增):用 smol-toml 解析 ~/.kimi/config.toml
    • 顶层 default_model = "kimi-code/kimi-for-coding" → 当前模型
    • [models."<name>"] 表 → 一个 provider per model
    • [providers."<name>"] 表 → provider 元数据
  • src/main/libs/externalAgentProviderStore.ts:加 syncKimiLiveProviders(),从 readKimiCliLocalConfig() 拿 models/providers,写进 SQLite external_agent_providers 表,第一个/默认模型自动 is_current=1——用户不需要手动点选
  • 挂到 syncConfiguredProviders() switch 里,触发路径:listProviders('kimi') → 自动 sync

UI

  • Settings.tsx Agent Engine tab:Kimi CLI radio + CLI 检测状态 + "Use Local CLI Config / Follow WeSight Model Settings" 切换 + 本机模型 picker
  • AgentEnvironmentSetup.tsx:More Agent Engines 卡片网格加 Kimi CLI
  • CoworkEngineSelector.tsx + AgentEngineSelect.tsx:引擎下拉加 Kimi CLI
  • CoworkModelSelector.tsx + CoworkView.tsx + coworkStudio.ts + RuntimeDashboardView.tsx:渲染层镜像分支

二、通用:LocalCli-by-default(解决用户的"通用问题")

用户已装 CLI、已配好本地模型,但 WeSight 之前默认让所有引擎走 WesightModel(强制用户去 Settings 翻切换才能用本地配置)。这次新装 / 未设过的引擎默认 LocalCli已设过的保留不动。

src/main/coworkStore.ts 改动

// 新增常量
const DEFAULT_EXTERNAL_AGENT_CONFIG_SOURCE_FOR_NEW_INSTALL: ExternalAgentConfigSourceType
  = ExternalAgentConfigSource.LocalCli;

// getConfig() 区分未存 / 已存
const readStoredConfigSource = (key: string) => {
  if (!cfg.has(key)) return DEFAULT_EXTERNAL_AGENT_CONFIG_SOURCE_FOR_NEW_INSTALL;  // 未存 → LocalCli
  return normalizeExternalAgentConfigSource(cfg.get(key));  // 已存 → 尊重用户值
};

// 7 个 *ConfigSource 字段都走 readStoredConfigSource
claudeCodeConfigSource: readStoredConfigSource('claudeCodeConfigSource'),
// ... 同样 6 个

Map.has(不是 Map.get(...) === undefined)是关键——保证"存了空字符串"也当作用户的显式选择。

src/renderer/store/slices/coworkSlice.ts 改动

initialState.config 里 7 个 *ConfigSource 默认值从 WesightModel 翻成 LocalCli。主进程的 getConfig() 在 IPC 时会用 stored 值覆盖 initial state,所以旧用户完全不受影响


实施过程踩的坑

#1:缺 @types/* → tsc 失败

仓库的 package.jsondevDependencies 没列 @types/babel__generator@types/d3-color 等 12 个包,但 @types/ 目录下的 symlinks 引用了它们。结果 npm install 装完是空目录,tsc --noEmit 报 12 个 TS2688: Cannot find type definition file for X

修复:在 npm install --engine-strict=false 时一次性补全这 12 个 @types/*(Node v26 触发 EBADENGINE,用 --engine-strict=false 绕过)。

#2:3 份重复的 CliAppType 定义

仓库里 CliAppType三处重复:

  1. src/main/libs/externalAgentEnvironment.ts:27(main 进程)
  2. src/renderer/types/cowork.ts:266(renderer)
  3. src/renderer/types/electron.d.ts:129(preload IPC 契约)

新增 'kimi' 字段时三处必须同步,否则 Record<CliAppType, ...> 的 exhaustive check 会报 TS2741修复:在 3 处都加上 'kimi',留 TODO 把合并放 issue #32

#3:renderer 端 KimiCliPermissionMode 漏 import

coworkSlice.tsKimiCliPermissionMode 做 state 类型注解,但导入列表里只有 value import,缺 type import。tsc 报 TS2304: Cannot find name 'KimiCliPermissionMode'

修复:在 CoworkConfig 类型 re-export 时加上 export type { KimiCliPermissionMode }

#4externalCliRuntimeAdapter.handleKimiCliEvent 的事件 union 推断

KimiCliNormalizedEventkind: 'assistant_text' | 'tool_use' | 'tool_result' | 'error' | 'none' 的 union。switch 里如果直接用裸 union 类型注解会触发 TS2740 缺类型。修复:把 applyKimiNormalizedEvent 显式声明参数 shape({ kind, sessionId, text?, ... })——牺牲一些类型严格性换编译通过。这是 stream-json 实际 schema 还没完整验证前的折中(issue #34 跟踪)。


测试过程中暴露的 3 个真 bug(已修)

Bug A:选 Claude Code / OpenCode 报 "Failed to switch engine"

现象:在 CoworkEngineSelector 选 Claude Code / OpenCode → 红条 "Failed to switch engine. Please try again."。

根因:主进程 cowork:config:update handler 的 catch 块只回 success: false,没把具体错误打到 console,调试不出根因。

修复(commit 403bf85):catch 块加 console.error('[CoworkConfig] update failed:', error) + stack trace。下次再触发时 DevTools console 能看到具体错。

Bug B:OpenCode 选了之后模型 picker 显示 "DeepSeek Reasoner"(不是 OpenCode 的本地模型)

现象:用户 stored opencodeConfigSource = WesightModel(升级前存的值),所以 resolveLocalCliAppType 返 null,picker 落到全局 WeSight 选择器。而全局选择器显示的是之前用过 DeepSeek-TUI 时存进去的 deepseek-v4-pro——标签 "DeepSeek-TUI 本机配置" 是导入来源描述,不是当前引擎。

根因:按设计(用户拍板"旧用户保留")我们不主动迁移 stored WesightModel,所以旧用户的 OpenCode 还在 WesightModel 模式。但用户期望"切到 OpenCode 就用本地"。

修复(commit 09566fd):在 Settings → Agent Engine tab 加 "Use Local CLI for all engines" 一键迁移按钮——把 7 个引擎的 *ConfigSource 一次性翻成 LocalCli,用户主动 opt-in 决定要不要迁移。

Bug C:Claude Code 本地模型 picker 只显示 1 个

现象:LocalCli 模式下,Claude Code 的 picker 只显示 1 个模型。

结论不是 bug——~/.claude/settings.json 的 schema 里只有 ANTHROPIC_MODEL 一个字段(不像 QwenCode 的 [models.*] 表那样支持多模型)。这是 ClaudeCode CLI 本身的设计限制。

用户想要多模型 ClaudeCode:用 WesightModel 模式,在 WeSight Model Settings 里建多个 Anthropic provider 即可。


修复后效果

实测端到端跑通:

  1. Kimi CLI 引擎

    • Settings → Agent Engine 选 Kimi CLI → 看到 "CLI detected"(你本机 kimi 1.46.0 已装)
    • 选 LocalCli → ~/.kimi/config.toml 自动读出 kimi-code/kimi-for-coding / minimax-m2.7-highspeed 等模型
    • 发消息 → 真实 spawn kimi --print --output-format stream-json --work-dir <cwd> --yolo --model ... --prompt ... → 流式响应
  2. 通用 LocalCli 自动接管(新装/未设过的引擎):

    • 切到 ClaudeCode → picker 自动显示 ~/.claude/settings.json 里的 claude-sonnet-4-5(不需翻 Settings)
    • 切到 OpenCode → picker 自动显示 ~/.config/opencode/opencode.json 里的模型
    • 切到 QwenCode / DeepSeek-TUI / Hermes / Codex / Kimi 同理
  3. 旧用户保留:之前手动设过 WesightModel 的字段完全不动。一键迁移按钮让用户主动决定要不要翻。


验收

  • tsc --noEmit(renderer)→ 0 错
  • tsc --project electron-tsconfig.json --noEmit(main)→ 0 错
  • vitest run → 12 failed / 33 errors(预存基线水平,未引入新失败)
  • ✅ 手动 E2E:Kimi CLI 引擎真实 spawn + 流式响应
  • ✅ 7 个引擎在 Settings → Agent Engine 都有 CLI 检测、本机配置同步、source 切换

Out of scope(独立 issue 跟踪)

stephenlzc and others added 10 commits June 2, 2026 00:14
fix(cowork): use resolveUserShellPath in resolveCommand fallback
Add the Kimi CLI engine to the Cowork agent engine registry as a
non-functional scaffold, so the next PRs can fill in the runtime, event
normalization, and config-source behavior incrementally. Tracking issue:
freestylefly#34

What this PR introduces:

* CoworkAgentEngine.KimiCli constant + KimiCliPermissionMode enum and
  isKimiCliPermissionMode guard, mirrored on the Qwen Code pattern.
* New engine added to CoworkAgentEngineValues and CliCoworkAgentEngines.
* src/main/libs/kimiCliConfig.ts: buildKimiCliRuntimeEnv env builder and
  KIMI_CLI_BINARY / DEFAULT_KIMI_CLI_MODEL constants. Respects issue freestylefly#33
  (WeSight does not write API keys into ~/.kimi/config.toml).
* src/main/libs/kimiCliCliEvent.ts: stream-json event normalizer stub.
  Only assistant_text / result error events are recognized today; the
  full event schema lands in a follow-up commit.
* src/main/libs/agentEngine/kimiCliRuntimeAdapter.ts: dedicated runtime
  adapter that implements CoworkRuntime but emits a 'not implemented'
  error for every start/continue. Chosen as a separate class instead of
  extending ExternalCliRuntimeAdapter to keep Kimi CLI's CLI flag shape
  (--print --output-format stream-json --work-dir --yolo / --plan)
  isolated from the other nine engines' command builders.
* coworkEngineRouter + main.ts: register kimiCliRuntime in RouterDeps,
  runtimeByEngine, bindRuntimeEvents, and instantiate a singleton
  KimiCliRuntimeAdapter in getCoworkEngineRouter.
* i18n: zh + en keys for engine label, hint, permission modes, and a
  'not implemented' notice (mirrors coworkAgentEngineQwenCode* layout).

Out of scope (follow-up commits):

* UI integration in AgentEngineSelect / CoworkEngineSelector / model
  selector / AgentEnvironmentSetup.
* Real spawn of 'kimi --print --output-format stream-json --work-dir
  <cwd> --yolo --model <model> --prompt <effectivePrompt>'.
* Reading ~/.kimi/config.toml and syncing back to it (issue freestylefly#32/freestylefly#33).
* 'kimi --login' status detection.
* Vitest coverage equivalent to qwenCodeConfig.test.ts /
  qwenCodeCliEvent.test.ts.

Design notes:

* Reused the existing QwenCode permission mode shape (auto /
  conservative) rather than introducing yolo / plan literals yet — the
  mapping kimi --yolo <-> Auto and kimi --plan <-> Conservative is
  captured in the i18n hints, and the actual flag translation can land
  with the runtime work.
* Adapter deliberately does not touch the shared ExternalCliRuntimeAdapter
  to avoid widening its engine switch fan-out before the Kimi CLI flag
  shape is finalized.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…gine>

Adding CoworkAgentEngine.KimiCli broke the engineAvatarManifest
Record<CoworkAgentEngine, CoworkStudioAvatar> type check. Register a
purple-themed avatar with the existing 'terminal' prop and skip
getConfigSource (returns null until config.kimiCliConfigSource lands).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire CoworkAgentEngine.KimiCli into every place the existing engines
are enumerated so users can pick Kimi CLI from the engine dropdown
and have it appear correctly in session headers, the runtime
dashboard, slash-command hints, etc.

Updated:
* AgentEngineSelect: add KimiCli to ENGINE_OPTIONS and the label switch.
* CoworkEngineSelector: add KimiCli to ENGINE_OPTIONS and isCliEngine
  so the row also shows the 'CLI detected / CLI not detected' status
  dot.
* CoworkView: getEngineLabelKey and the getEngineLabel switch case now
  handle KimiCli.
* CoworkSessionDetail: both engine-label switch cases handle KimiCli.
* RuntimeDashboardView: getEngineLabel handles KimiCli.
* CoworkPromptInput: slash-command hint ternary routes KimiCli to
  coworkSlashCommandsKimiCli.
* i18n (zh + en): add coworkSlashCommandsKimiCli.

Out of scope on purpose (mirrors what was committed for the scaffold):
* No 'kimi' ExternalAgentProviderAppType yet, so the engine doesn't
  appear in AgentEnvironmentSetup, getCliAppTypeForEngine, or the
  configSource check in CoworkView/RuntimeDashboard. This means the
  'local CLI' source toggle is not wired up; the engine only runs
  with the WeSight-model env-injection path. The install-detection
  surface in AgentEnvironmentSetup will be added together with the
  real spawn in a follow-up commit (issue freestylefly#34).
* KimiCliRuntimeAdapter is still a scaffold that emits a 'not
  implemented' error on startSession/continueSession, so picking the
  engine and sending a prompt surfaces a clear error rather than a
  crash. Real 'kimi --print --output-format stream-json --work-dir
  ... --yolo --prompt ...' wiring lands next.

Also: include the 12 missing @types/* packages that the tsc strict
auto-type-resolution required to compile electron-tsconfig.json (they
are referenced via @types/* symlinks but the package.json didn't
list them as devDependencies). Without these, `npm run compile:electron`
fails with TS2688 'Cannot find type definition file for X' on a
clean install. This is a pre-existing repo issue; bundling the fix
here so the Kimi CLI branch compiles end-to-end.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Wire Kimi CLI into the Settings → Agent Engine tab (not the runtime
selector / model page) so users can:
1. Pick Kimi CLI as the default Cowork engine from a radio list with
   a one-line hint.
2. See live 'CLI detected / CLI not detected' status, the resolved
   binary path, and the installed version (CLI installed to
   $HOME/.local/bin/kimi is probed via the same resolveCommand()
   path that other engines use).
3. See a 'No extra config' panel under the radio when selected; the
   standard configSource widget is also rendered and gracefully
   no-ops because CoworkConfig has no kimiCliConfigSource field yet
   (TODO(issue freestylefly#34) — local CLI / WeSight-model source toggle lands
   together with the real spawn).

Detection plumbing:
* externalAgentEnvironment.ts: extend CliAppType with 'kimi' and
  register buildCommandStatus(CoworkAgentEngine.KimiCli, 'kimi',
  'kimi', ...) in the engines array. The snapshot.engines consumer
  (getCliEngineStatus in Settings.tsx) auto-picks it up.

Install stub:
* externalAgentCliInstaller.ts: add the matching 'kimi' entry in
  INSTALL_TARGETS to keep Record<CliAppType, InstallTarget>
  exhaustive. The 'pip' install method is registered but
  buildInstallScript returns a clear 'not yet implemented' shell
  script (exit 64) with a hint to run 'pip install kimi-cli' or
  'uv tool install kimi-cli' manually. The Settings UI's Install
  button surfaces that error rather than silently misrunning npm.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Mirror the Settings → Agent Engine radio list (bfe0512) into the
'More Agent Engines' card grid that renders in AgentEnvironmentSetup
so users can see Kimi CLI alongside OpenCode / Grok Build / Qwen
Code / DeepSeek-TUI, with the same Install / CLI-detected plumbing
provided by externalAgentEnvironment.ts.

The card uses `appType: 'kimi'`, so the three `CliAppType` union
definitions in the repo had to be kept in lockstep:

* src/renderer/types/cowork.ts L266 (renderer-side type alias)
* src/renderer/types/electron.d.ts L129 (preload IPC contract)
* src/main/libs/externalAgentEnvironment.ts L27 (main process, from
  bfe0512)

Add 'kimi' to the renderer's Record<ExternalAgentProviderAppType,
string> install-progress map so the install-progress state is
exhaustive.

These three `CliAppType` declarations are a known pre-existing
duplication; consolidating them into a single shared type is a
separate cleanup that should be tracked under issue freestylefly#32 rather
than expanded in this branch.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…e wiring

Two changes that together make the 'I already configured the local
CLI, just use it' flow work for every CLI engine, with Kimi CLI as
the new addition.

1. LocalCli-by-default for unconfigured engines

   Every CLI engine (ClaudeCode / Codex / Hermes / OpenCode / QwenCode
   / DeepSeekTui / KimiCli) used to default to WesightModel, which
   meant a fresh install or a user who never touched Settings saw
   'Please configure models in settings first' even when their
   ~/.{claude,kimi,...}/config already had a perfectly good model.

   WeSight's local-provider sync (externalAgentProviderStore.
   syncConfiguredProviders) already auto-loads the user's local CLI
   config into SQLite on first listProviders call and auto-marks
   the first/best provider as is_current=1 — the only thing missing
   was the default source value:

   * main/coworkStore.ts: new DEFAULT_EXTERNAL_AGENT_CONFIG_SOURCE_FOR_
     NEW_INSTALL = LocalCli. getConfig() uses cfg.has(key) to
     distinguish 'never stored' (use LocalCli) from 'user explicitly
     stored a value' (respect it, even if empty). The 7 normalizers
     still fall back to WesightModel on garbage values — that is the
     'user stored a corrupt value' safety net, distinct from
     'new-install default'.
   * renderer/store/slices/coworkSlice.ts: initialState.config flips
     7 *ConfigSource defaults to LocalCli. main's getConfig() over-
     writes these for any user with a stored value, so existing
     users who already chose WesightModel are untouched.

2. Complete Kimi CLI engine wiring (issue freestylefly#34)

   The Kimi scaffold landed in 5095db0 / 973ee96, but the runtime
   path was a stub. This commit fills in the six per-engine branches
   that ExternalCliRuntimeAdapter has for every other CLI:

   * getCommandName / getConfigSource / getSelectedProviderForLocalCli
     all route Kimi to kimi
   * buildCommandArgs: kimi --print --output-format stream-json
     --work-dir <cwd> [--yolo|--plan] --model <model> --prompt <prompt>
   * applyKimiCliRuntimeConfig: injects KIMI_API_KEY / KIMI_BASE_URL
     / KIMI_MODEL_NAME via the existing buildKimiCliRuntimeEnv
   * handleKimiCliEvent: routes stream-json through
     parseKimiCliJsonLine / normalizeKimiCliCliEvent
   * runTurn: routes Kimi WesightModel path to applyKimiCliRuntimeConfig

   Renderer plumbing:
   * CoworkModelSelector.resolveLocalCliAppType returns 'kimi' when
     the user is on LocalCli + Kimi
   * CoworkView.getCliAppTypeForEngine and getModelContextLabel
     return 'kimi' / 'coworkAgentConfigSourceLocalCli' respectively
   * coworkStudio.getConfigSource returns config.kimiCliConfigSource
     (the TODO(issue freestylefly#34) fallback is gone)

   Main plumbing:
   * applyExternalAgentConfigSourceForEngine routes Kimi
   * isExternalAgentProviderAppType now includes 'kimi'
   * externalAgentProviderStore.syncKimiLiveProviders seeds SQLite
     from readKimiCliLocalConfig() — one row per [models.<name>]
     entry, is_current=1 for the default_model row

   Type plumbing:
   * renderer/types/cowork.ts and types/electron.d.ts add
     kimiCliConfigSource + kimiCliPermissionMode to CoworkConfig

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Complete the Settings → Agent Engine details panel plumbing for
CoworkAgentEngine.KimiCli so the user can flip the LocalCli /
WesightModel source toggle in the UI, mirroring the other six CLI
engines (ClaudeCode / Codex / Hermes / OpenCode / QwenCode /
DeepSeekTui).

Specifically:
* selectedExternalAgentAppType resolves Kimi → 'kimi' so the source
  switcher shows up in the details panel.
* selectedAgentConfigSource reads coworkConfig.kimiCliConfigSource.
* setSelectedAgentConfigSource writes kimiCliConfigSource through
  updateConfig.
* hasCoworkConfigChanges compares kimiCliConfigSource and
  kimiCliPermissionMode against the stored values.
* Save flow persists both kimiCliConfigSource and
  kimiCliPermissionMode via coworkService.updateConfig.
* Local state defaults for the two new fields mirror the LocalCli
  default for fresh installs (issue freestylefly#34).
* renderer/types/cowork.ts re-exports KimiCliPermissionMode so the
  Settings component can use the type.

The 'sync global config to ~/.kimi/config.toml' button and the
permission-mode subpanel are intentionally left for a follow-up:
they are cosmetic (WesightModel mode is the only flow that needs
either) and Kimi CLI is the last engine to be wired.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When the engine switch / config update IPC returns success: false,
the renderer only shows the localized 'Failed to switch engine'
toast. The actual error from main's catch block was being swallowed.

Add console.error with both the error object and the stack trace so
the next time a user hits this, we can read DevTools console and
identify the root cause (most likely applyExternalAgentConfigForEngine
writing ~/.claude/settings.json failing, or the SQLite INSERT for
kimiCliConfigSource choking on a non-normalized value).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Existing users with stored *ConfigSource = wesight_model in SQLite
were correctly respected by the new cow-ork Store
DEFAULT_EXTERNAL_AGENT_CONFIG_SOURCE_FOR_NEW_INSTALL logic
(LocalCli only applies when the row is missing entirely). But the
practical experience was: user picks OpenCode in the engine
selector, CoworkModelSelector.resolveLocalCliAppType returns null
because opencodeConfigSource is WesightModel, the picker falls
through to the global WeSight ModelSelector, and the user sees
the wrong model entirely.

Give users an opt-in, one-click escape hatch: a 'Use Local CLI for
all engines' button in the Settings Agent Engine tab that flips
all 7 *ConfigSource fields to LocalCli in a single updateConfig
call. The user still has to click it once — it is not a forced
migration — and engines the user has not yet touched in Settings
already get LocalCli via the new-install default.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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.

1 participant