Skip to content

feat: add OpenCode CLI provider support#100

Open
ryanchao0518 wants to merge 5 commits intoPleasePrompto:mainfrom
ryanchao0518:add-opencode-provider
Open

feat: add OpenCode CLI provider support#100
ryanchao0518 wants to merge 5 commits intoPleasePrompto:mainfrom
ryanchao0518:add-opencode-provider

Conversation

@ryanchao0518
Copy link
Copy Markdown

@ryanchao0518 ryanchao0518 commented Apr 9, 2026

Summary

Add OpenCodeCLI provider support, remove Claude Code CLI from ductor's UI, fix Gemini CLI model discovery for Homebrew Cellar installations, and wire up opencode with MiniMax as the default model.

Changes

Commit 1: feat: add OpenCode CLI provider support

File Change
ductor_bot/cli/opencode_provider.py New — OpenCodeCLI class with send() / send_streaming()
ductor_bot/cli/opencode_events.py New — NDJSON stream parser for opencode JSON output
ductor_bot/cli/factory.py Add opencode branch to create_cli()
ductor_bot/cli/auth.py Add check_opencode_auth() + add to _CHECKERS dict
ductor_bot/cli/service.py Add opencode_cli_parameters field
ductor_bot/config.py Add opencode: list[str] to CLIParametersConfig
ductor_bot/orchestrator/core.py Add opencode_cli_parameters to both CLIServiceConfig instantiations
ductor_bot/cli/init_wizard.py Add opencode CLI detection in _check_clis()
ductor_bot/i18n/en/wizard.toml Add opencode label in CLI backends list

Commit 2: refactor: remove Claude from provider UI, add OpenCode to provider list

File Change
ductor_bot/orchestrator/selectors/model_selector.py Remove CLAUDE button; add OPENCODE button
ductor_bot/messenger/telegram/app.py Update session_help: remove claude refs, add opencode refs
ductor_bot/orchestrator/providers.py Remove "Claude Code" from active_provider_name, add "OpenCode"
ductor_bot/text/response_format.py Update new_session_text provider_label map
ductor_bot/i18n/en/chat.toml Update no_auth, session_help strings

Commit 3: fix: detect Gemini CLI models.js in Homebrew Cellar layout

File Change
ductor_bot/cli/gemini_utils.py Add _gemini_cellar_candidates() to walk up to Homebrew Cellar prefix

Commit 4: feat: wire up opencode as first-class provider with MiniMax default

File Change
ductor_bot/config.py Map minimax/, kimi-for-coding/, opencode/ prefixes to opencode provider
ductor_bot/orchestrator/providers.py default_model_for_provider("opencode")minimax/MiniMax-M2.7; add opencode to resolve_session_directive()
ductor_bot/orchestrator/selectors/model_selector.py _build_model_step: opencode branch immediately switches to default MiniMax model; _handle_model_selected: opencode models switch immediately
ductor_bot/orchestrator/selectors/model_selector.py _build_model_step now takes orch+key args (refactored for async switch)

Model Discovery Results

  • Gemini: 7 models found (was 0 before Homebrew Cellar fix)
    • gemini-2.5-pro, gemini-2.5-flash, gemini-2.5-flash-lite
    • gemini-3-pro-preview, gemini-3-flash-preview
    • gemini-3.1-pro-preview, gemini-3.1-pro-preview-customtools
  • Codex: 4 models confirmed (gpt-5.4, gpt-5.4-mini, gpt-5.3-codex, gpt-5.2)
  • OpenCode: defaults to minimax/MiniMax-M2.7 (MiniMax series available: M2, M2.1, M2.5, M2.5-highspeed, M2.7, M2.7-highspeed)

Testing

  • All ruff checks: PASSED
  • All mypy checks: PASSED
  • Gemini discovery tested: 7 models found ✅
  • UI tested on Telegram: /model shows CODEX / GEMINI / OPENCODE (no CLAUDE) ✅

ryanchao added 5 commits April 9, 2026 21:39
- Add opencode_provider.py: OpenCodeCLI class implementing BaseCLI
- Add opencode_events.py: NDJSON stream parser for OpenCode output
- Add opencode to factory.py: provider selection branch
- Add opencode_cli_parameters to CLIParametersConfig and CLIServiceConfig
- Add check_opencode_auth to auth.py and _CHECKERS dict
- Add opencode to init_wizard.py: CLI detection and i18n
- Add opencode to orchestrator/core.py: both CLIServiceConfig instances
- Add opencode entry to en/wizard.toml i18n

Allows /model command to switch between claude, codex, gemini, and opencode CLIs.
- Remove CLAUDE button from /model selector (claude CLI not used)
- Add OPENCODE button to /model selector
- Update session_help i18n: remove claude refs, add opencode refs
- Update active_provider_name: remove claude, add opencode
- Update provider_label maps: remove claude, add opencode
- Update no_auth message to remove claude auth reference
Gemini CLI installed via Homebrew (macOS) stores gemini-cli-core in
Cellar/<version>/libexec/lib/node_modules/ instead of the usual npm
layout.  Add _gemini_cellar_candidates() that walks up the directory
tree from the package root to find the Homebrew Cellar prefix and
discovers models.js there.

Discovery now finds all 7 models instead of 0:
- gemini-2.5-flash, gemini-2.5-flash-lite, gemini-2.5-pro
- gemini-3-flash-preview, gemini-3-pro-preview
- gemini-3.1-pro-preview, gemini-3.1-pro-preview-customtools
- config.py: add opencode model prefixes (minimax/, kimi-for-coding/, opencode/)
  to provider_for() so model IDs route to opencode provider
- providers.py: add opencode to default_model_for_provider() -> minimax/MiniMax-M2.7
- providers.py: add opencode to resolve_session_directive() for @OpenCode directive
- model_selector.py: add opencode branch in _build_model_step() that
  immediately switches to default MiniMax model without showing a picker
- model_selector.py: add opencode to _handle_model_selected() switch so
  opencode models switch immediately (no reasoning effort picker)
- _build_model_step() now takes orch+key args to support async switch
- Remove redundant double-check in _OpenCodeServer.ensure_running()
  (mypy incorrectly flagged second check as unreachable)
- Add explicit None guards for process.stdout/stderr pipes
- Change send_streaming to yield events directly via async for
  delegation instead of returning a coroutine
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