klaude-code 2.2.0__tar.gz → 2.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (240) hide show
  1. {klaude_code-2.2.0 → klaude_code-2.4.0}/PKG-INFO +21 -74
  2. {klaude_code-2.2.0 → klaude_code-2.4.0}/README.md +20 -73
  3. {klaude_code-2.2.0 → klaude_code-2.4.0}/pyproject.toml +11 -1
  4. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/app/runtime.py +2 -15
  5. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/list_model.py +30 -13
  6. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/main.py +26 -10
  7. klaude_code-2.4.0/src/klaude_code/config/assets/builtin_config.yaml +236 -0
  8. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/config/config.py +158 -21
  9. klaude_code-2.2.0/src/klaude_code/config/select_model.py → klaude_code-2.4.0/src/klaude_code/config/model_matcher.py +41 -16
  10. klaude_code-2.4.0/src/klaude_code/config/sub_agent_model_helper.py +217 -0
  11. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/config/thinking.py +2 -2
  12. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/const.py +1 -1
  13. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/agent_profile.py +43 -5
  14. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/executor.py +129 -47
  15. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/manager/llm_clients_builder.py +17 -11
  16. klaude_code-2.4.0/src/klaude_code/core/prompts/prompt-nano-banana.md +1 -0
  17. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/diff_builder.py +25 -18
  18. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/sub_agent_tool.py +2 -1
  19. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/anthropic/client.py +12 -9
  20. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/anthropic/input.py +54 -29
  21. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/client.py +1 -1
  22. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/codex/client.py +2 -2
  23. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/google/client.py +7 -7
  24. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/google/input.py +23 -2
  25. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/input_common.py +2 -2
  26. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openai_compatible/client.py +3 -3
  27. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openai_compatible/input.py +22 -13
  28. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openai_compatible/stream.py +1 -1
  29. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openrouter/client.py +4 -4
  30. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openrouter/input.py +35 -25
  31. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/responses/client.py +5 -5
  32. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/responses/input.py +96 -57
  33. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/commands.py +1 -2
  34. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/__init__.py +7 -1
  35. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/chat.py +10 -0
  36. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/system.py +4 -0
  37. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/llm_param.py +1 -1
  38. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/model.py +0 -26
  39. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/op.py +17 -5
  40. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/op_handler.py +5 -0
  41. klaude_code-2.4.0/src/klaude_code/protocol/sub_agent/AGENTS.md +28 -0
  42. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/sub_agent/__init__.py +10 -14
  43. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/sub_agent/image_gen.py +2 -1
  44. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/codec.py +2 -6
  45. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/session.py +13 -3
  46. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/assets/create-plan/SKILL.md +3 -5
  47. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/__init__.py +3 -6
  48. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/clear_cmd.py +0 -1
  49. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/command_abc.py +6 -4
  50. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/copy_cmd.py +10 -10
  51. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/debug_cmd.py +11 -10
  52. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/export_online_cmd.py +18 -23
  53. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/fork_session_cmd.py +39 -43
  54. klaude_code-2.4.0/src/klaude_code/tui/command/model_cmd.py +55 -0
  55. klaude_code-2.4.0/src/klaude_code/tui/command/model_picker.py +142 -0
  56. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/refresh_cmd.py +0 -1
  57. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/registry.py +15 -21
  58. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/resume_cmd.py +10 -16
  59. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/status_cmd.py +8 -12
  60. klaude_code-2.4.0/src/klaude_code/tui/command/sub_agent_model_cmd.py +185 -0
  61. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/terminal_setup_cmd.py +8 -11
  62. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/thinking_cmd.py +4 -6
  63. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/commands.py +5 -0
  64. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/bash_syntax.py +1 -1
  65. klaude_code-2.4.0/src/klaude_code/tui/components/command_output.py +96 -0
  66. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/common.py +1 -1
  67. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/developer.py +3 -115
  68. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/metadata.py +1 -63
  69. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/cjk_wrap.py +3 -2
  70. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/status.py +49 -3
  71. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/theme.py +2 -0
  72. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/sub_agent.py +25 -46
  73. klaude_code-2.4.0/src/klaude_code/tui/components/welcome.py +99 -0
  74. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/input/prompt_toolkit.py +19 -8
  75. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/machine.py +5 -0
  76. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/renderer.py +7 -8
  77. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/runner.py +0 -6
  78. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/terminal/selector.py +8 -6
  79. klaude_code-2.2.0/src/klaude_code/config/assets/builtin_config.yaml +0 -369
  80. klaude_code-2.2.0/src/klaude_code/core/prompts/prompt-nano-banana.md +0 -1
  81. klaude_code-2.2.0/src/klaude_code/tui/command/help_cmd.py +0 -51
  82. klaude_code-2.2.0/src/klaude_code/tui/command/model_cmd.py +0 -94
  83. klaude_code-2.2.0/src/klaude_code/tui/command/model_select.py +0 -84
  84. klaude_code-2.2.0/src/klaude_code/tui/command/release_notes_cmd.py +0 -85
  85. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/__init__.py +0 -0
  86. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/app/__init__.py +0 -0
  87. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/__init__.py +0 -0
  88. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/base.py +0 -0
  89. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/claude/__init__.py +0 -0
  90. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/claude/exceptions.py +0 -0
  91. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/claude/oauth.py +0 -0
  92. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/claude/token_manager.py +0 -0
  93. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/codex/__init__.py +0 -0
  94. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/codex/exceptions.py +0 -0
  95. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
  96. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/codex/oauth.py +0 -0
  97. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/auth/codex/token_manager.py +0 -0
  98. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/__init__.py +0 -0
  99. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/auth_cmd.py +0 -0
  100. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/config_cmd.py +0 -0
  101. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/cost_cmd.py +0 -0
  102. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/debug.py +0 -0
  103. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/self_update.py +0 -0
  104. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/cli/session_cmd.py +0 -0
  105. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/config/__init__.py +0 -0
  106. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/config/assets/__init__.py +0 -0
  107. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/config/builtin_config.py +0 -0
  108. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/__init__.py +0 -0
  109. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/agent.py +0 -0
  110. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/manager/__init__.py +0 -0
  111. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/manager/llm_clients.py +0 -0
  112. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/manager/sub_agent_manager.py +0 -0
  113. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
  114. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
  115. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
  116. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
  117. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
  118. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
  119. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
  120. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +0 -0
  121. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +0 -0
  122. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
  123. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/reminders.py +0 -0
  124. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/task.py +0 -0
  125. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/__init__.py +0 -0
  126. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/context.py +0 -0
  127. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/__init__.py +0 -0
  128. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/_utils.py +0 -0
  129. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
  130. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
  131. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/apply_patch_tool.py +0 -0
  132. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
  133. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/edit_tool.py +0 -0
  134. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/read_tool.md +0 -0
  135. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/read_tool.py +0 -0
  136. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/write_tool.md +0 -0
  137. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/file/write_tool.py +0 -0
  138. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/report_back_tool.py +0 -0
  139. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/shell/__init__.py +0 -0
  140. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
  141. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/shell/bash_tool.py +0 -0
  142. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
  143. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/todo/__init__.py +0 -0
  144. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
  145. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
  146. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
  147. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
  148. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
  149. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/tool_abc.py +0 -0
  150. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/tool_registry.py +0 -0
  151. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/tool_runner.py +0 -0
  152. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/truncation.py +0 -0
  153. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/web/__init__.py +0 -0
  154. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
  155. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
  156. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
  157. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/web/web_fetch_tool.py +0 -0
  158. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
  159. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/tool/web/web_search_tool.py +0 -0
  160. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/core/turn.py +0 -0
  161. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/__init__.py +0 -0
  162. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/anthropic/__init__.py +0 -0
  163. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/bedrock/__init__.py +0 -0
  164. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/bedrock/client.py +0 -0
  165. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/claude/__init__.py +0 -0
  166. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/claude/client.py +0 -0
  167. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/codex/__init__.py +0 -0
  168. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/google/__init__.py +0 -0
  169. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/image.py +0 -0
  170. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
  171. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +0 -0
  172. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openrouter/__init__.py +0 -0
  173. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/openrouter/reasoning.py +0 -0
  174. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/registry.py +0 -0
  175. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/responses/__init__.py +0 -0
  176. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/llm/usage.py +0 -0
  177. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/log.py +0 -0
  178. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/__init__.py +0 -0
  179. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/base.py +0 -0
  180. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/lifecycle.py +0 -0
  181. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/metadata.py +0 -0
  182. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/streaming.py +0 -0
  183. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/events/tools.py +0 -0
  184. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/message.py +0 -0
  185. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
  186. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/sub_agent/task.py +0 -0
  187. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/sub_agent/web.py +0 -0
  188. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/protocol/tools.py +0 -0
  189. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/__init__.py +0 -0
  190. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/export.py +0 -0
  191. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/selector.py +0 -0
  192. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/store.py +0 -0
  193. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/templates/export_session.html +0 -0
  194. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/session/templates/mermaid_viewer.html +0 -0
  195. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/__init__.py +0 -0
  196. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
  197. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/assets/handoff/SKILL.md +0 -0
  198. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/assets/jj-workspace/SKILL.md +0 -0
  199. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/assets/skill-creator/SKILL.md +0 -0
  200. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/loader.py +0 -0
  201. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/manager.py +0 -0
  202. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/skill/system_skills.py +0 -0
  203. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/__init__.py +0 -0
  204. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/export_cmd.py +0 -0
  205. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/prompt-init.md +0 -0
  206. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/command/prompt_command.py +0 -0
  207. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/__init__.py +0 -0
  208. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/assistant.py +0 -0
  209. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/diffs.py +0 -0
  210. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/errors.py +0 -0
  211. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/mermaid_viewer.py +0 -0
  212. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/__init__.py +0 -0
  213. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/code_panel.py +0 -0
  214. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/live.py +0 -0
  215. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/markdown.py +0 -0
  216. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/quote.py +0 -0
  217. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/rich/searchable_text.py +0 -0
  218. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/thinking.py +0 -0
  219. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/tools.py +0 -0
  220. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/components/user_input.py +0 -0
  221. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/display.py +0 -0
  222. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/input/__init__.py +0 -0
  223. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/input/clipboard.py +0 -0
  224. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/input/completers.py +0 -0
  225. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/input/key_bindings.py +0 -0
  226. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/terminal/__init__.py +0 -0
  227. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/terminal/color.py +0 -0
  228. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/terminal/control.py +0 -0
  229. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/terminal/image.py +0 -0
  230. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/terminal/notifier.py +0 -0
  231. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/tui/terminal/progress_bar.py +0 -0
  232. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/__init__.py +0 -0
  233. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/common.py +0 -0
  234. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/core/__init__.py +0 -0
  235. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/core/display.py +0 -0
  236. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/core/input.py +0 -0
  237. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/debug_mode.py +0 -0
  238. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/terminal/__init__.py +0 -0
  239. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/ui/terminal/title.py +0 -0
  240. {klaude_code-2.2.0 → klaude_code-2.4.0}/src/klaude_code/update.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: klaude-code
3
- Version: 2.2.0
3
+ Version: 2.4.0
4
4
  Summary: Minimal code agent CLI
5
5
  Requires-Dist: anthropic>=0.66.0
6
6
  Requires-Dist: chardet>=5.2.0
@@ -155,95 +155,42 @@ Open in editor:
155
155
  klaude config
156
156
  ```
157
157
 
158
- ##### Adding Models to Built-in Providers
158
+ ##### Model Configuration
159
159
 
160
- You can add custom models to existing built-in providers without redefining the entire provider. Just reference the `provider_name` and add your `model_list`:
160
+ You can add custom models to built-in providers or define new ones. Configuration is inherited from built-in providers by matching `provider_name`.
161
161
 
162
162
  ```yaml
163
163
  # ~/.klaude/klaude-config.yaml
164
164
  provider_list:
165
- - provider_name: openrouter # Reference existing built-in provider
166
- model_list:
167
- - model_name: seed
168
- model_params:
169
- model: bytedance-seed/seed-1.6 # Model ID from OpenRouter
170
- context_limit: 262000
171
- cost:
172
- input: 0.25
173
- output: 2
174
- ```
175
-
176
- **How merging works:**
177
- - Your models are merged with the built-in models for that provider
178
- - You only need `provider_name` and `model_list` - protocol, api_key, etc. are inherited from the built-in config
179
- - To override a built-in model, use the same `model_name` (e.g., `sonnet` to customize the built-in sonnet)
180
-
181
- **More examples:**
182
-
183
- ```yaml
184
- provider_list:
185
- # Add multiple models to OpenRouter
165
+ # Add/Override models for built-in OpenRouter provider
186
166
  - provider_name: openrouter
187
167
  model_list:
188
168
  - model_name: qwen-coder
189
- model_params:
190
- model: qwen/qwen-2.5-coder-32b-instruct
191
- context_limit: 131072
192
- cost:
193
- input: 0.3
194
- output: 0.9
195
- - model_name: llama-405b
196
- model_params:
197
- model: meta-llama/llama-3.1-405b-instruct
198
- context_limit: 131072
199
- cost:
200
- input: 0.8
201
- output: 0.8
202
-
203
- # Add models to Anthropic provider
204
- - provider_name: anthropic
205
- model_list:
206
- - model_name: haiku@ant
207
- model_params:
208
- model: claude-3-5-haiku-20241022
209
- context_limit: 200000
210
- cost:
211
- input: 1.0
212
- output: 5.0
213
- ```
214
-
215
- After adding models, run `klaude list` to verify they appear in the model list.
216
-
217
- ##### Overriding Provider Settings
218
-
219
- Override provider-level settings (like api_key) while keeping built-in models:
220
-
221
- ```yaml
222
- provider_list:
223
- - provider_name: anthropic
224
- api_key: sk-my-custom-key # Override the default ${ANTHROPIC_API_KEY}
225
- # Built-in models (sonnet, opus) are still available
226
- ```
227
-
228
- ##### Adding New Providers
229
-
230
- For providers not in the built-in list, you must specify `protocol`:
231
-
232
- ```yaml
233
- provider_list:
234
- - provider_name: my-azure-openai
169
+ model_id: qwen/qwen-2.5-coder-32b-instruct
170
+ context_limit: 131072
171
+ cost: { input: 0.3, output: 0.9 }
172
+ - model_name: sonnet # Override built-in sonnet params
173
+ model_id: anthropic/claude-3.5-sonnet
174
+ context_limit: 200000
175
+
176
+ # Add a completely new provider
177
+ - provider_name: my-azure
235
178
  protocol: openai
236
179
  api_key: ${AZURE_OPENAI_KEY}
237
180
  base_url: https://my-instance.openai.azure.com/
238
181
  is_azure: true
239
182
  azure_api_version: "2024-02-15-preview"
240
183
  model_list:
241
- - model_name: gpt-4-azure
242
- model_params:
243
- model: gpt-4
244
- context_limit: 128000
184
+ - model_name: gpt-4
185
+ model_id: gpt-4-deploy-name
186
+ context_limit: 128000
245
187
  ```
246
188
 
189
+ **Key Tips:**
190
+ - **Merging**: If `provider_name` matches a built-in provider, settings like `protocol` and `api_key` are inherited.
191
+ - **Overriding**: Use the same `model_name` as a built-in model to override its parameters.
192
+ - **Environment Variables**: Use `${VAR_NAME}` syntax for secrets.
193
+
247
194
  ##### Supported Protocols
248
195
 
249
196
  - `anthropic` - Anthropic Messages API
@@ -133,95 +133,42 @@ Open in editor:
133
133
  klaude config
134
134
  ```
135
135
 
136
- ##### Adding Models to Built-in Providers
136
+ ##### Model Configuration
137
137
 
138
- You can add custom models to existing built-in providers without redefining the entire provider. Just reference the `provider_name` and add your `model_list`:
138
+ You can add custom models to built-in providers or define new ones. Configuration is inherited from built-in providers by matching `provider_name`.
139
139
 
140
140
  ```yaml
141
141
  # ~/.klaude/klaude-config.yaml
142
142
  provider_list:
143
- - provider_name: openrouter # Reference existing built-in provider
144
- model_list:
145
- - model_name: seed
146
- model_params:
147
- model: bytedance-seed/seed-1.6 # Model ID from OpenRouter
148
- context_limit: 262000
149
- cost:
150
- input: 0.25
151
- output: 2
152
- ```
153
-
154
- **How merging works:**
155
- - Your models are merged with the built-in models for that provider
156
- - You only need `provider_name` and `model_list` - protocol, api_key, etc. are inherited from the built-in config
157
- - To override a built-in model, use the same `model_name` (e.g., `sonnet` to customize the built-in sonnet)
158
-
159
- **More examples:**
160
-
161
- ```yaml
162
- provider_list:
163
- # Add multiple models to OpenRouter
143
+ # Add/Override models for built-in OpenRouter provider
164
144
  - provider_name: openrouter
165
145
  model_list:
166
146
  - model_name: qwen-coder
167
- model_params:
168
- model: qwen/qwen-2.5-coder-32b-instruct
169
- context_limit: 131072
170
- cost:
171
- input: 0.3
172
- output: 0.9
173
- - model_name: llama-405b
174
- model_params:
175
- model: meta-llama/llama-3.1-405b-instruct
176
- context_limit: 131072
177
- cost:
178
- input: 0.8
179
- output: 0.8
180
-
181
- # Add models to Anthropic provider
182
- - provider_name: anthropic
183
- model_list:
184
- - model_name: haiku@ant
185
- model_params:
186
- model: claude-3-5-haiku-20241022
187
- context_limit: 200000
188
- cost:
189
- input: 1.0
190
- output: 5.0
191
- ```
192
-
193
- After adding models, run `klaude list` to verify they appear in the model list.
194
-
195
- ##### Overriding Provider Settings
196
-
197
- Override provider-level settings (like api_key) while keeping built-in models:
198
-
199
- ```yaml
200
- provider_list:
201
- - provider_name: anthropic
202
- api_key: sk-my-custom-key # Override the default ${ANTHROPIC_API_KEY}
203
- # Built-in models (sonnet, opus) are still available
204
- ```
205
-
206
- ##### Adding New Providers
207
-
208
- For providers not in the built-in list, you must specify `protocol`:
209
-
210
- ```yaml
211
- provider_list:
212
- - provider_name: my-azure-openai
147
+ model_id: qwen/qwen-2.5-coder-32b-instruct
148
+ context_limit: 131072
149
+ cost: { input: 0.3, output: 0.9 }
150
+ - model_name: sonnet # Override built-in sonnet params
151
+ model_id: anthropic/claude-3.5-sonnet
152
+ context_limit: 200000
153
+
154
+ # Add a completely new provider
155
+ - provider_name: my-azure
213
156
  protocol: openai
214
157
  api_key: ${AZURE_OPENAI_KEY}
215
158
  base_url: https://my-instance.openai.azure.com/
216
159
  is_azure: true
217
160
  azure_api_version: "2024-02-15-preview"
218
161
  model_list:
219
- - model_name: gpt-4-azure
220
- model_params:
221
- model: gpt-4
222
- context_limit: 128000
162
+ - model_name: gpt-4
163
+ model_id: gpt-4-deploy-name
164
+ context_limit: 128000
223
165
  ```
224
166
 
167
+ **Key Tips:**
168
+ - **Merging**: If `provider_name` matches a built-in provider, settings like `protocol` and `api_key` are inherited.
169
+ - **Overriding**: Use the same `model_name` as a built-in model to override its parameters.
170
+ - **Environment Variables**: Use `${VAR_NAME}` syntax for secrets.
171
+
225
172
  ##### Supported Protocols
226
173
 
227
174
  - `anthropic` - Anthropic Messages API
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "klaude-code"
7
- version = "2.2.0"
7
+ version = "2.4.0"
8
8
  description = "Minimal code agent CLI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -40,6 +40,7 @@ dev = [
40
40
  "pyright>=1.1.407",
41
41
  "pytest>=8.4.1",
42
42
  "pytest-cov>=7.0.0",
43
+ "ty>=0.0.8",
43
44
  ]
44
45
 
45
46
 
@@ -74,6 +75,15 @@ exclude = [".venv/"]
74
75
  root = "."
75
76
  extraPaths = ["src"]
76
77
 
78
+ [tool.ty.environment]
79
+ python-version = "3.13"
80
+
81
+ [tool.ty.src]
82
+ include = [
83
+ "src",
84
+ "tests",
85
+ ]
86
+
77
87
  [tool.importlinter]
78
88
  root_packages = ["klaude_code"]
79
89
  include_external_packages = false
@@ -55,24 +55,11 @@ async def initialize_app_components(
55
55
 
56
56
  config = load_config()
57
57
 
58
- if init_config.banana:
59
- # Banana mode is strict: it requires the built-in Nano Banana image model to be available.
60
- required_model = "nano-banana-pro@or"
61
- available = {m.model_name for m in config.iter_model_entries(only_available=True)}
62
- if required_model not in available:
63
- log(
64
- (
65
- f"Error: --banana requires model '{required_model}', but it is not available in the current environment",
66
- "red",
67
- )
68
- )
69
- log(("Hint: set OPENROUTER_API_KEY (Nano Banana Pro is configured via OpenRouter by default)", "yellow"))
70
- raise typer.Exit(2)
71
-
72
58
  try:
73
59
  llm_clients = build_llm_clients(
74
60
  config,
75
61
  model_override=init_config.model,
62
+ skip_sub_agents=init_config.vanilla or init_config.banana,
76
63
  )
77
64
  except ValueError as exc:
78
65
  if init_config.model:
@@ -92,7 +79,7 @@ async def initialize_app_components(
92
79
  elif init_config.vanilla:
93
80
  model_profile_provider = VanillaModelProfileProvider()
94
81
  else:
95
- model_profile_provider = DefaultModelProfileProvider()
82
+ model_profile_provider = DefaultModelProfileProvider(config=config)
96
83
 
97
84
  event_queue: asyncio.Queue[events.Event] = asyncio.Queue()
98
85
 
@@ -181,7 +181,7 @@ def format_env_var_display(value: str | None) -> Text:
181
181
 
182
182
  def _get_model_params_display(model: ModelConfig) -> list[Text]:
183
183
  """Get display elements for model parameters."""
184
- param_strings = format_model_params(model.model_params)
184
+ param_strings = format_model_params(model)
185
185
  if param_strings:
186
186
  return [Text(s) for s in param_strings]
187
187
  return [Text("")]
@@ -243,18 +243,34 @@ def _build_provider_info_panel(provider: ProviderConfig, available: bool) -> Quo
243
243
 
244
244
 
245
245
  def _build_models_table(
246
- provider: ProviderConfig, main_model: str | None, sub_agent_models: dict[str, str] | None = None
246
+ provider: ProviderConfig,
247
+ config: Config,
247
248
  ) -> Table:
248
249
  """Build a table for models under a provider."""
249
250
  provider_available = not provider.is_api_key_missing()
250
251
 
252
+ def _resolve_selector(value: str | None) -> str | None:
253
+ if not value:
254
+ return None
255
+ try:
256
+ resolved = config.resolve_model_location_prefer_available(value) or config.resolve_model_location(value)
257
+ except ValueError:
258
+ return None
259
+ if resolved is None:
260
+ return None
261
+ return f"{resolved[0]}@{resolved[1]}"
262
+
263
+ default_selector = _resolve_selector(config.main_model)
264
+
251
265
  # Build reverse mapping: model_name -> list of agent roles using it
252
266
  model_to_agents: dict[str, list[str]] = {}
253
- if sub_agent_models:
254
- for agent_role, model_name in sub_agent_models.items():
255
- if model_name not in model_to_agents:
256
- model_to_agents[model_name] = []
257
- model_to_agents[model_name].append(agent_role)
267
+ for agent_role, model_name in (config.sub_agent_models or {}).items():
268
+ selector = _resolve_selector(model_name)
269
+ if selector is None:
270
+ continue
271
+ if selector not in model_to_agents:
272
+ model_to_agents[selector] = []
273
+ model_to_agents[selector].append(agent_role)
258
274
 
259
275
  models_table = Table.grid(
260
276
  padding=(0, 2),
@@ -270,15 +286,16 @@ def _build_models_table(
270
286
 
271
287
  if not provider_available:
272
288
  name = Text.assemble((prefix, ThemeKey.LINES), (model.model_name, "dim"))
273
- model_id = Text(model.model_params.model or "", style="dim")
289
+ model_id = Text(model.model_id or "", style="dim")
274
290
  params = Text("(unavailable)", style="dim")
275
291
  else:
276
292
  # Build role tags for this model
277
293
  roles: list[str] = []
278
- if model.model_name == main_model:
294
+ selector = f"{model.model_name}@{provider.provider_name}"
295
+ if selector == default_selector:
279
296
  roles.append("default")
280
- if model.model_name in model_to_agents:
281
- roles.extend(role.lower() for role in model_to_agents[model.model_name])
297
+ if selector in model_to_agents:
298
+ roles.extend(role.lower() for role in model_to_agents[selector])
282
299
 
283
300
  if roles:
284
301
  name = Text.assemble(
@@ -288,7 +305,7 @@ def _build_models_table(
288
305
  )
289
306
  else:
290
307
  name = Text.assemble((prefix, ThemeKey.LINES), (model.model_name, ThemeKey.CONFIG_ITEM_NAME))
291
- model_id = Text(model.model_params.model or "")
308
+ model_id = Text(model.model_id or "")
292
309
  params = Text(" · ").join(_get_model_params_display(model))
293
310
 
294
311
  models_table.add_row(name, model_id, params)
@@ -350,6 +367,6 @@ def display_models_and_providers(config: Config, *, show_all: bool = False):
350
367
  console.print()
351
368
 
352
369
  # Models table for this provider
353
- models_table = _build_models_table(provider, config.main_model, config.sub_agent_models)
370
+ models_table = _build_models_table(provider, config)
354
371
  console.print(models_table)
355
372
  console.print("\n")
@@ -124,18 +124,28 @@ def main_callback(
124
124
  raise typer.Exit(2)
125
125
 
126
126
  from klaude_code.app.runtime import AppInitConfig
127
- from klaude_code.tui.command.model_select import select_model_interactive
127
+ from klaude_code.tui.command.model_picker import ModelSelectStatus, select_model_interactive
128
128
  from klaude_code.tui.runner import run_interactive
129
129
 
130
130
  update_terminal_title()
131
131
 
132
132
  chosen_model = model
133
133
  if banana:
134
- # Banana mode always uses the built-in Nano Banana Pro image model.
135
- chosen_model = "nano-banana-pro@or"
134
+ keywords = ["gemini-3-pro-image", "gemini-2.5-flash-image"]
135
+ model_result = select_model_interactive(keywords=keywords)
136
+ if model_result.status == ModelSelectStatus.SELECTED and model_result.model is not None:
137
+ chosen_model = model_result.model
138
+ elif model_result.status == ModelSelectStatus.CANCELLED:
139
+ return
140
+ else:
141
+ log(("Error: no available nano-banana model", "red"))
142
+ log(("Hint: set OPENROUTER_API_KEY or GOOGLE_API_KEY to enable nano-banana models", "yellow"))
143
+ raise typer.Exit(2)
136
144
  elif model or select_model:
137
- chosen_model = select_model_interactive(preferred=model)
138
- if chosen_model is None:
145
+ model_result = select_model_interactive(preferred=model)
146
+ if model_result.status == ModelSelectStatus.SELECTED and model_result.model is not None:
147
+ chosen_model = model_result.model
148
+ else:
139
149
  return
140
150
 
141
151
  # Resolve session id before entering asyncio loop
@@ -162,7 +172,12 @@ def main_callback(
162
172
  cfg = load_config()
163
173
 
164
174
  if session_meta.model_config_name:
165
- if any(m.model_name == session_meta.model_config_name for m in cfg.iter_model_entries()):
175
+ try:
176
+ model_is_known = cfg.has_model_config_name(session_meta.model_config_name)
177
+ except ValueError:
178
+ model_is_known = False
179
+
180
+ if model_is_known:
166
181
  chosen_model = session_meta.model_config_name
167
182
  else:
168
183
  log(
@@ -176,9 +191,9 @@ def main_callback(
176
191
  raw_model = session_meta.model_name.strip()
177
192
  if raw_model:
178
193
  matches = [
179
- m.model_name
194
+ m.selector
180
195
  for m in cfg.iter_model_entries()
181
- if (m.model_params.model or "").strip().lower() == raw_model.lower()
196
+ if (m.model_id or "").strip().lower() == raw_model.lower()
182
197
  ]
183
198
  if len(matches) == 1:
184
199
  chosen_model = matches[0]
@@ -189,9 +204,10 @@ def main_callback(
189
204
 
190
205
  cfg = load_config()
191
206
  if cfg.main_model is None:
192
- chosen_model = select_model_interactive()
193
- if chosen_model is None:
207
+ model_result = select_model_interactive()
208
+ if model_result.status != ModelSelectStatus.SELECTED or model_result.model is None:
194
209
  raise typer.Exit(1)
210
+ chosen_model = model_result.model
195
211
  # Save the selection as default
196
212
  cfg.main_model = chosen_model
197
213
  from klaude_code.config.config import config_path