Skip to content

fix(opencode): decode agents whose hidden flag is null - #388

Merged
yuga-hashimoto merged 3 commits into
yuga-hashimoto:mainfrom
doublepi123:fix/upstream-agent-hidden-null
Oct 18, 2026
Merged

yuga-hashimoto merged 3 commits into
yuga-hashimoto:mainfrom
doublepi123:fix/upstream-agent-hidden-null

Conversation

@doublepi123

Copy link
Copy Markdown
Contributor

Summary

With a plugin such as oh-my-opencode-slim installed, OpenCode's GET /agent reports the plugin agents (orchestrator, fixer, explorer, ...) with "hidden": null. OpenCodeAgent.hidden was a non-null Boolean, so kotlinx.serialization rejected the whole list: the catalogue fell back to no agents and the mode chip opened an empty menu, so tapping build appeared to do nothing.

  • hidden is now nullable on both the V1 (OpenCodeAgent) and V2 (V2Agent) DTOs, and only true hides an agent. false, null and a missing key all stay visible, as before.
  • Small extra: the voice assistant's title used a hard-coded "AndCode"; it now reads R.string.app_name.

Testing

  • ./gradlew spotlessCheck detekt :app:testGithubDebugUnitTest --tests '*core.api*' (JDK 17 + SDK 35): passed.
  • OpenCodeAgentSelectionTest decodes a real-shaped /agent response with "hidden": null through the production defaultJson; the V2 AGENT_LIST fixture now covers false, null and true.
  • Verified against a live OpenCode 1.19.3 server with oh-my-opencode-slim enabled: the mode picker lists the plugin's primary agents.

Pre-PR review

判定: APPROVE

ブロッカー

なし

提案(非ブロッキング)

  • app/src/main/java/com/yugahashimoto/andcode/ui/components/AndCodeComponents.kt:48 に、音声アシスタントのタイトルと同じハードコード text = "AndCode" がまだ残っています。今回の PR の範囲外ですが、別 PR で stringResource(R.string.app_name) に揃えると一貫します。

チェック済み項目

  • 範囲:.summary.txt で3コミット(a162a405 / 145b406 / 88b37c8、HEAD = 88b37c8)と5ファイル(+38/−10)を確認しました。.diff は全ハンクを読み、ワークツリーの内容と一致することも確かめています。
  • 修正の正しさ:OpenCodeApiModels.kt:173 の hidden は Boolean = false から Boolean? = null に変わりました。selectablePrimaryAgents()(:186)は !it.hidden から it.hidden != true に変わっています。その結果、true は非表示、false・null・キーなしは表示となり、変更前と同じ挙動です。V2 の V2Agent.hidden(OpenCodeV2ApiClient.kt:1570)と filterNot { it.hidden == true }(:194)も同じ判定です。
  • 原因の説明:OpenCodeApiClient.defaultJson(:771-776)には coerceInputValues がありません。このため、非 null の Boolean フィールドに null が来るとリスト全体のデコードが失敗する、というコミットメッセージの説明はコードと合っています。
  • 型変更の影響:hidden を読んでいる本番コードは、rg '\.hidden\b' で調べたところ上の2か所だけでした。OpenCodeAgent(...) を作っている箇所(ClaudeCodeTarget.kt:358、AntigravityTarget.kt:158、CodexModels.kt:39、OpenCodeV2ApiClient.kt:195)は、どれも hidden を渡していないか名前付き引数なので、コンパイルにも挙動にも影響しません。
  • テスト:
    • OpenCodeAgentSelectionTest の新しいテストは、本番と同じ defaultJson を使い、"hidden":null と未知キー variant を含む実際の応答の形で、デコード・primary の絞り込み・デフォルトエージェントを確認しています。
    • assertTrue から assertEquals(true, …) への書き換えは型変更に合わせたものです。assertTrue の import は他で使われていないので、消しても問題ありません。
    • V2 の AGENT_LIST は false・null・true の3つを含み、期待値が ["build","orchestrator"] に更新されています。
  • i18n:新しい文字列キーは追加されていません。app_name は values / ar / es / fr / ja / pt-rBR / ru / zh-rCN の全8ロケールにあります。AndCodeVoiceSession.kt:520 ではすでに同じブロックで stringResource を使っているので、import を足す必要はありません。行の長さは .editorconfig の max_line_length = 140 に収まっています。
  • DI / ViewModelFactory、Compose の状態、コルーチン、リソースリーク、セキュリティに関わる変更はありません。

With oh-my-opencode-slim installed, OpenCode's GET /agent reports the
plugin agents (orchestrator, fixer, explorer, ...) with "hidden": null.
OpenCodeAgent.hidden was a non-null Boolean, so kotlinx.serialization
rejected the whole list, the catalogue fell back to no agents, and the
mode chip opened an empty menu - tapping "build" appeared to do nothing.

Make hidden nullable (V1 and V2 DTOs) and treat only true as hidden.
Verified against a live OpenCode 1.19.3 server with the plugin enabled.
@yuga-hashimoto
yuga-hashimoto merged commit 2dbba4c into yuga-hashimoto:main Oct 18, 2026
4 checks passed
Demonic1594 pushed a commit to Demonic1594/and-code that referenced this pull request Oct 19, 2026
Termux dropped proot 5.1.107.96 from packages.termux.dev (404 on every
mirror it was on; grimler.se answers with a body that does not match the
pinned SHA-256). A CI run that misses the generated-runtime cache then
fails in :app:prepareOpenCodeRuntimeAssets before any test starts, as
the re-run of the yuga-hashimoto#388 merge commit did twice.

- Refresh runtime_tools/termux_assets.lock.json with
  `prepare_android_runtime_assets.py --lock-only`. Only proot changes
  (5.1.107.96 -> 5.1.107.97, new filename and SHA-256 for arm64-v8a and
  x86_64); libandroid-shmem and libtalloc are unchanged.
- Mirror the matching termux-packages recipe: only TERMUX_PKG_VERSION and
  TERMUX_PKG_SHA256 differ from the previous one.
- Point THIRD_PARTY_NOTICES.md and its offline copy at the 5.1.107.97
  source archive and SHA-256.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xw2ucui6t6dQdyGRrnCbHb
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