klaude-code 1.9.0__tar.gz → 2.0.1__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 (237) hide show
  1. {klaude_code-1.9.0 → klaude_code-2.0.1}/PKG-INFO +4 -2
  2. {klaude_code-1.9.0 → klaude_code-2.0.1}/README.md +1 -0
  3. {klaude_code-1.9.0 → klaude_code-2.0.1}/pyproject.toml +3 -2
  4. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/base.py +2 -6
  5. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/auth_cmd.py +4 -4
  6. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/cost_cmd.py +1 -1
  7. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/list_model.py +1 -1
  8. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/main.py +1 -1
  9. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/runtime.py +7 -5
  10. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/self_update.py +1 -1
  11. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/session_cmd.py +1 -1
  12. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/clear_cmd.py +6 -2
  13. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/command_abc.py +2 -2
  14. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/debug_cmd.py +4 -4
  15. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/export_cmd.py +2 -2
  16. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/export_online_cmd.py +12 -12
  17. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/fork_session_cmd.py +29 -23
  18. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/help_cmd.py +4 -4
  19. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/model_cmd.py +4 -4
  20. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/model_select.py +1 -1
  21. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/prompt-commit.md +11 -2
  22. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/prompt_command.py +3 -3
  23. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/refresh_cmd.py +2 -2
  24. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/registry.py +7 -5
  25. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/release_notes_cmd.py +4 -4
  26. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/resume_cmd.py +15 -11
  27. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/status_cmd.py +4 -4
  28. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/terminal_setup_cmd.py +8 -8
  29. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/thinking_cmd.py +4 -4
  30. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/config/assets/builtin_config.yaml +20 -0
  31. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/config/builtin_config.py +16 -5
  32. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/config/config.py +7 -2
  33. klaude_code-2.0.1/src/klaude_code/const.py +220 -0
  34. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/agent.py +3 -12
  35. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/executor.py +18 -39
  36. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/manager/sub_agent_manager.py +71 -7
  37. klaude_code-2.0.1/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +1 -0
  38. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +27 -1
  39. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/reminders.py +88 -69
  40. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/task.py +44 -45
  41. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/apply_patch_tool.py +9 -9
  42. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/diff_builder.py +3 -5
  43. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/edit_tool.py +23 -23
  44. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/move_tool.py +43 -43
  45. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/read_tool.py +44 -39
  46. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/write_tool.py +14 -14
  47. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/report_back_tool.py +4 -4
  48. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/shell/bash_tool.py +23 -23
  49. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/skill/skill_tool.py +7 -7
  50. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/sub_agent_tool.py +38 -9
  51. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/todo/todo_write_tool.py +9 -10
  52. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/todo/update_plan_tool.py +6 -6
  53. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/tool_abc.py +2 -2
  54. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/tool_context.py +27 -0
  55. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/tool_runner.py +88 -42
  56. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/truncation.py +38 -20
  57. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/web/mermaid_tool.py +6 -7
  58. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/web/web_fetch_tool.py +68 -30
  59. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/web/web_search_tool.py +15 -17
  60. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/turn.py +120 -73
  61. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/anthropic/client.py +79 -44
  62. klaude_code-2.0.1/src/klaude_code/llm/anthropic/input.py +232 -0
  63. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/bedrock/client.py +8 -5
  64. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/claude/client.py +18 -8
  65. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/client.py +4 -3
  66. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/codex/client.py +15 -9
  67. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/google/client.py +122 -60
  68. klaude_code-2.0.1/src/klaude_code/llm/google/input.py +201 -0
  69. klaude_code-2.0.1/src/klaude_code/llm/image.py +123 -0
  70. klaude_code-2.0.1/src/klaude_code/llm/input_common.py +180 -0
  71. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/openai_compatible/client.py +17 -7
  72. klaude_code-2.0.1/src/klaude_code/llm/openai_compatible/input.py +81 -0
  73. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/openai_compatible/stream.py +119 -67
  74. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +23 -11
  75. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/openrouter/client.py +34 -9
  76. klaude_code-2.0.1/src/klaude_code/llm/openrouter/input.py +147 -0
  77. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/openrouter/reasoning.py +22 -24
  78. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/registry.py +20 -17
  79. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/responses/client.py +107 -45
  80. klaude_code-2.0.1/src/klaude_code/llm/responses/input.py +203 -0
  81. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/usage.py +52 -25
  82. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/__init__.py +1 -0
  83. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/events.py +16 -12
  84. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/llm_param.py +20 -2
  85. klaude_code-2.0.1/src/klaude_code/protocol/message.py +250 -0
  86. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/model.py +95 -285
  87. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/op.py +2 -15
  88. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/op_handler.py +0 -5
  89. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/sub_agent/__init__.py +1 -0
  90. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/sub_agent/explore.py +10 -0
  91. klaude_code-2.0.1/src/klaude_code/protocol/sub_agent/image_gen.py +119 -0
  92. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/sub_agent/task.py +10 -0
  93. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/sub_agent/web.py +10 -0
  94. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/codec.py +6 -6
  95. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/export.py +261 -62
  96. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/selector.py +7 -24
  97. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/session.py +126 -54
  98. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/store.py +5 -32
  99. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/templates/export_session.html +1 -1
  100. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/templates/mermaid_viewer.html +1 -1
  101. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/trace/log.py +11 -6
  102. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/core/input.py +1 -1
  103. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/core/stage_manager.py +1 -8
  104. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/debug/display.py +2 -2
  105. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/clipboard.py +2 -2
  106. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/completers.py +18 -10
  107. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/event_handler.py +138 -132
  108. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/input_prompt_toolkit.py +1 -1
  109. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/key_bindings.py +136 -2
  110. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/renderer.py +107 -15
  111. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/assistant.py +2 -2
  112. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/bash_syntax.py +36 -4
  113. klaude_code-2.0.1/src/klaude_code/ui/renderers/common.py +146 -0
  114. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/developer.py +7 -6
  115. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/diffs.py +11 -11
  116. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/mermaid_viewer.py +49 -2
  117. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/metadata.py +33 -5
  118. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/sub_agent.py +57 -16
  119. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/thinking.py +37 -2
  120. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/tools.py +188 -178
  121. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/live.py +3 -1
  122. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/markdown.py +39 -7
  123. klaude_code-2.0.1/src/klaude_code/ui/rich/quote.py +109 -0
  124. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/status.py +14 -8
  125. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/theme.py +20 -14
  126. klaude_code-2.0.1/src/klaude_code/ui/terminal/image.py +34 -0
  127. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/terminal/notifier.py +2 -1
  128. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/terminal/progress_bar.py +4 -4
  129. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/terminal/selector.py +22 -4
  130. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/utils/common.py +11 -2
  131. klaude_code-1.9.0/src/klaude_code/const.py +0 -164
  132. klaude_code-1.9.0/src/klaude_code/llm/anthropic/input.py +0 -224
  133. klaude_code-1.9.0/src/klaude_code/llm/google/input.py +0 -215
  134. klaude_code-1.9.0/src/klaude_code/llm/input_common.py +0 -233
  135. klaude_code-1.9.0/src/klaude_code/llm/openai_compatible/input.py +0 -111
  136. klaude_code-1.9.0/src/klaude_code/llm/openrouter/input.py +0 -148
  137. klaude_code-1.9.0/src/klaude_code/llm/responses/input.py +0 -186
  138. klaude_code-1.9.0/src/klaude_code/ui/renderers/common.py +0 -86
  139. klaude_code-1.9.0/src/klaude_code/ui/rich/quote.py +0 -34
  140. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/__init__.py +0 -0
  141. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/__init__.py +0 -0
  142. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/claude/__init__.py +0 -0
  143. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/claude/exceptions.py +0 -0
  144. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/claude/oauth.py +0 -0
  145. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/claude/token_manager.py +0 -0
  146. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/codex/__init__.py +0 -0
  147. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/codex/exceptions.py +0 -0
  148. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
  149. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/codex/oauth.py +0 -0
  150. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/auth/codex/token_manager.py +0 -0
  151. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/__init__.py +0 -0
  152. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/config_cmd.py +0 -0
  153. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/cli/debug.py +0 -0
  154. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/__init__.py +0 -0
  155. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/command/prompt-init.md +0 -0
  156. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/config/__init__.py +0 -0
  157. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/config/assets/__init__.py +0 -0
  158. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/config/select_model.py +0 -0
  159. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/config/thinking.py +0 -0
  160. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/__init__.py +0 -0
  161. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/manager/__init__.py +0 -0
  162. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/manager/llm_clients.py +0 -0
  163. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
  164. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompt.py +0 -0
  165. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
  166. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
  167. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
  168. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
  169. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
  170. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
  171. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
  172. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
  173. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/__init__.py +0 -0
  174. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/__init__.py +0 -0
  175. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/_utils.py +0 -0
  176. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
  177. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
  178. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
  179. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/move_tool.md +0 -0
  180. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/read_tool.md +0 -0
  181. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/file/write_tool.md +0 -0
  182. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/shell/__init__.py +0 -0
  183. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
  184. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
  185. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/skill/__init__.py +0 -0
  186. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/skill/skill_tool.md +0 -0
  187. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/todo/__init__.py +0 -0
  188. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
  189. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
  190. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
  191. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/tool_registry.py +0 -0
  192. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/web/__init__.py +0 -0
  193. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
  194. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
  195. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
  196. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/__init__.py +0 -0
  197. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/anthropic/__init__.py +0 -0
  198. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/bedrock/__init__.py +0 -0
  199. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/claude/__init__.py +0 -0
  200. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/codex/__init__.py +0 -0
  201. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/google/__init__.py +0 -0
  202. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
  203. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/openrouter/__init__.py +0 -0
  204. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/llm/responses/__init__.py +0 -0
  205. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/commands.py +0 -0
  206. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/protocol/tools.py +0 -0
  207. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/session/__init__.py +0 -0
  208. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/__init__.py +0 -0
  209. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
  210. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/assets/dev-docs/SKILL.md +0 -0
  211. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/assets/handoff/SKILL.md +0 -0
  212. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/assets/jj-workspace/SKILL.md +0 -0
  213. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/assets/skill-creator/SKILL.md +0 -0
  214. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/loader.py +0 -0
  215. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/manager.py +0 -0
  216. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/skill/system_skills.py +0 -0
  217. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/trace/__init__.py +0 -0
  218. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/__init__.py +0 -0
  219. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/core/__init__.py +0 -0
  220. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/core/display.py +0 -0
  221. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/__init__.py +0 -0
  222. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/debug/__init__.py +0 -0
  223. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/exec/__init__.py +0 -0
  224. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/exec/display.py +0 -0
  225. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/__init__.py +0 -0
  226. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/modes/repl/display.py +0 -0
  227. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/__init__.py +0 -0
  228. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/errors.py +0 -0
  229. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/renderers/user_input.py +0 -0
  230. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/__init__.py +0 -0
  231. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/cjk_wrap.py +0 -0
  232. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/code_panel.py +0 -0
  233. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/rich/searchable_text.py +0 -0
  234. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/terminal/__init__.py +0 -0
  235. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/terminal/color.py +0 -0
  236. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/terminal/control.py +0 -0
  237. {klaude_code-1.9.0 → klaude_code-2.0.1}/src/klaude_code/ui/utils/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: klaude-code
3
- Version: 1.9.0
3
+ Version: 2.0.1
4
4
  Summary: Minimal code agent CLI
5
5
  Requires-Dist: anthropic>=0.66.0
6
6
  Requires-Dist: chardet>=5.2.0
@@ -9,11 +9,12 @@ Requires-Dist: diff-match-patch>=20241021
9
9
  Requires-Dist: google-genai>=1.56.0
10
10
  Requires-Dist: markdown-it-py>=4.0.0
11
11
  Requires-Dist: openai>=1.102.0
12
- Requires-Dist: pillow>=12.0.0
12
+ Requires-Dist: pillow>=9.1,<11.0
13
13
  Requires-Dist: prompt-toolkit>=3.0.52
14
14
  Requires-Dist: pydantic>=2.11.7
15
15
  Requires-Dist: pyyaml>=6.0.2
16
16
  Requires-Dist: rich>=14.1.0
17
+ Requires-Dist: term-image>=0.7.2
17
18
  Requires-Dist: trafilatura>=2.0.0
18
19
  Requires-Dist: typer>=0.17.3
19
20
  Requires-Python: >=3.13
@@ -395,3 +396,4 @@ The main agent can spawn specialized sub-agents for specific tasks:
395
396
  | **Explore** | Fast codebase exploration - find files, search code, answer questions about the codebase |
396
397
  | **Task** | Handle complex multi-step tasks autonomously |
397
398
  | **WebAgent** | Search the web, fetch pages, and analyze content |
399
+ | **ImageGen** | Generate images from text prompts via OpenRouter Nano Banana Pro |
@@ -374,3 +374,4 @@ The main agent can spawn specialized sub-agents for specific tasks:
374
374
  | **Explore** | Fast codebase exploration - find files, search code, answer questions about the codebase |
375
375
  | **Task** | Handle complex multi-step tasks autonomously |
376
376
  | **WebAgent** | Search the web, fetch pages, and analyze content |
377
+ | **ImageGen** | Generate images from text prompts via OpenRouter Nano Banana Pro |
@@ -4,7 +4,7 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "klaude-code"
7
- version = "1.9.0"
7
+ version = "2.0.1"
8
8
  description = "Minimal code agent CLI"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
@@ -16,11 +16,12 @@ dependencies = [
16
16
  "google-genai>=1.56.0",
17
17
  "markdown-it-py>=4.0.0",
18
18
  "openai>=1.102.0",
19
- "pillow>=12.0.0",
19
+ "pillow>=9.1,<11.0",
20
20
  "prompt-toolkit>=3.0.52",
21
21
  "pydantic>=2.11.7",
22
22
  "pyyaml>=6.0.2",
23
23
  "rich>=14.1.0",
24
+ "term-image>=0.7.2",
24
25
  "trafilatura>=2.0.0",
25
26
  "typer>=0.17.3",
26
27
  ]
@@ -4,11 +4,10 @@ import json
4
4
  import time
5
5
  from abc import ABC, abstractmethod
6
6
  from pathlib import Path
7
- from typing import Any, Generic, TypeVar, cast
7
+ from typing import Any, cast
8
8
 
9
9
  from pydantic import BaseModel
10
10
 
11
-
12
11
  KLAUDE_AUTH_FILE = Path.home() / ".klaude" / "klaude-auth.json"
13
12
 
14
13
 
@@ -24,10 +23,7 @@ class BaseAuthState(BaseModel):
24
23
  return time.time() + buffer_seconds >= self.expires_at
25
24
 
26
25
 
27
- T = TypeVar("T", bound=BaseAuthState)
28
-
29
-
30
- class BaseTokenManager(ABC, Generic[T]):
26
+ class BaseTokenManager[T: BaseAuthState](ABC):
31
27
  """Base class for OAuth token management."""
32
28
 
33
29
  def __init__(self, auth_file: Path | None = None):
@@ -56,20 +56,20 @@ def login_command(
56
56
  state = token_manager.get_state()
57
57
  if state and not state.is_expired():
58
58
  log(("You are already logged in to Codex.", "green"))
59
- log(f" Account ID: {state.account_id[:8]}...")
59
+ log(f" Account ID: {state.account_id[:8]}")
60
60
  expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
61
61
  log(f" Expires: {expires_dt.strftime('%Y-%m-%d %H:%M:%S UTC')}")
62
62
  if not typer.confirm("Do you want to re-login?"):
63
63
  return
64
64
 
65
- log("Starting Codex OAuth login flow...")
65
+ log("Starting Codex OAuth login flow")
66
66
  log("A browser window will open for authentication.")
67
67
 
68
68
  try:
69
69
  oauth = CodexOAuth(token_manager)
70
70
  state = oauth.login()
71
71
  log(("Login successful!", "green"))
72
- log(f" Account ID: {state.account_id[:8]}...")
72
+ log(f" Account ID: {state.account_id[:8]}")
73
73
  expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
74
74
  log(f" Expires: {expires_dt.strftime('%Y-%m-%d %H:%M:%S UTC')}")
75
75
  except Exception as e:
@@ -90,7 +90,7 @@ def login_command(
90
90
  if not typer.confirm("Do you want to re-login?"):
91
91
  return
92
92
 
93
- log("Starting Claude OAuth login flow...")
93
+ log("Starting Claude OAuth login flow")
94
94
  log("A browser window will open for authentication.")
95
95
  log("After login, paste the authorization code in the terminal.")
96
96
 
@@ -179,7 +179,7 @@ def render_cost_table(daily_stats: dict[str, DailyStats]) -> Table:
179
179
  show_header=True,
180
180
  header_style="bold",
181
181
  border_style="bright_black dim",
182
- padding=(0, 1, 0, 2),
182
+ padding=(0, 1, 0, 1),
183
183
  box=ASCII_HORIZONAL,
184
184
  )
185
185
 
@@ -50,7 +50,7 @@ def _get_codex_status_rows() -> list[tuple[Text, Text]]:
50
50
  Text.assemble(
51
51
  ("Logged in", ThemeKey.CONFIG_STATUS_OK),
52
52
  (
53
- f" (account: {state.account_id[:8]}..., expires: {expires_dt.strftime('%Y-%m-%d %H:%M UTC')})",
53
+ f" (account: {state.account_id[:8]}…, expires: {expires_dt.strftime('%Y-%m-%d %H:%M UTC')})",
54
54
  "dim",
55
55
  ),
56
56
  ),
@@ -286,7 +286,7 @@ def main_callback(
286
286
  raise typer.Exit(2)
287
287
 
288
288
  # In non-interactive environments, default to exec-mode behavior.
289
- # This allows: echo "..." | klaude
289
+ # This allows: echo "" | klaude
290
290
  if not sys.stdin.isatty() or not sys.stdout.isatty():
291
291
  if continue_ or resume or resume_by_id is not None:
292
292
  log(("Error: --continue/--resume options require a TTY", "red"))
@@ -17,8 +17,8 @@ from klaude_code.core.agent import Agent, DefaultModelProfileProvider, VanillaMo
17
17
  from klaude_code.core.executor import Executor
18
18
  from klaude_code.core.manager import build_llm_clients
19
19
  from klaude_code.protocol import events, llm_param, op
20
- from klaude_code.protocol import model as protocol_model
21
- from klaude_code.protocol.model import UserInputPayload
20
+ from klaude_code.protocol import message as protocol_message
21
+ from klaude_code.protocol.message import UserInputPayload
22
22
  from klaude_code.session.session import Session, close_default_store
23
23
  from klaude_code.trace import DebugType, log, set_debug_logging
24
24
  from klaude_code.ui.modes.repl import build_repl_status_snapshot
@@ -105,9 +105,11 @@ async def submit_user_input_payload(
105
105
  if result.persist_user_input:
106
106
  agent.session.append_history(
107
107
  [
108
- protocol_model.UserMessageItem(
109
- content=persisted_user_input.text,
110
- images=persisted_user_input.images,
108
+ protocol_message.UserMessage(
109
+ parts=protocol_message.parts_from_text_and_images(
110
+ persisted_user_input.text,
111
+ persisted_user_input.images,
112
+ )
111
113
  )
112
114
  ]
113
115
  )
@@ -228,7 +228,7 @@ def update_command(
228
228
  log(f"To update, install uv and run `uv tool upgrade {PACKAGE_NAME}`.")
229
229
  raise typer.Exit(1)
230
230
 
231
- log(f"Running `uv tool upgrade {PACKAGE_NAME}`...")
231
+ log(f"Running `uv tool upgrade {PACKAGE_NAME}`…")
232
232
  result = subprocess.run(["uv", "tool", "upgrade", PACKAGE_NAME], check=False)
233
233
  if result.returncode != 0:
234
234
  log((f"Error: update failed (exit code {result.returncode}).", "red"))
@@ -25,7 +25,7 @@ def _session_confirm(sessions: list[Session.SessionMetaBrief], message: str) ->
25
25
  first_msg_text = s.user_messages[0] if s.user_messages else ""
26
26
  first_msg = first_msg_text.strip().replace("\n", " ")[:50]
27
27
  if len(first_msg_text) > 50:
28
- first_msg += "..."
28
+ first_msg += ""
29
29
  log(f" {_fmt(s.updated_at)} {msg_count_display:>3} msgs {first_msg}")
30
30
 
31
31
  items: list[SelectItem[bool]] = [
@@ -1,5 +1,5 @@
1
1
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
- from klaude_code.protocol import commands, model, op
2
+ from klaude_code.protocol import commands, message, op
3
3
 
4
4
 
5
5
  class ClearCommand(CommandABC):
@@ -13,8 +13,12 @@ class ClearCommand(CommandABC):
13
13
  def summary(self) -> str:
14
14
  return "Clear conversation history and free up context"
15
15
 
16
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
16
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
17
17
  del user_input # unused
18
+ import os
19
+
20
+ os.system("cls" if os.name == "nt" else "clear")
21
+
18
22
  return CommandResult(
19
23
  operations=[op.ClearSessionOperation(session_id=agent.session.id)],
20
24
  persist_user_input=False,
@@ -4,7 +4,7 @@ from typing import Protocol
4
4
  from pydantic import BaseModel
5
5
 
6
6
  from klaude_code.llm import LLMClientABC
7
- from klaude_code.protocol import commands, llm_param, model, op
7
+ from klaude_code.protocol import commands, llm_param, message, op
8
8
  from klaude_code.protocol import events as protocol_events
9
9
  from klaude_code.session.session import Session
10
10
 
@@ -78,7 +78,7 @@ class CommandABC(ABC):
78
78
  return "additional instructions"
79
79
 
80
80
  @abstractmethod
81
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
81
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
82
82
  """
83
83
  Execute the command.
84
84
 
@@ -1,5 +1,5 @@
1
1
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
- from klaude_code.protocol import commands, events, model
2
+ from klaude_code.protocol import commands, events, message, model
3
3
  from klaude_code.trace import DebugType, get_current_log_file, is_debug_enabled, set_debug_logging
4
4
 
5
5
 
@@ -45,7 +45,7 @@ class DebugCommand(CommandABC):
45
45
  def placeholder(self) -> str:
46
46
  return "filter types"
47
47
 
48
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
48
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
49
49
  raw = user_input.text.strip()
50
50
 
51
51
  # /debug (no args) - enable debug
@@ -70,8 +70,8 @@ class DebugCommand(CommandABC):
70
70
  events=[
71
71
  events.DeveloperMessageEvent(
72
72
  session_id=agent.session.id,
73
- item=model.DeveloperMessageItem(
74
- content=content,
73
+ item=message.DeveloperMessage(
74
+ parts=message.text_parts_from_str(content),
75
75
  command_output=model.CommandOutput(command_name=self.name),
76
76
  ),
77
77
  )
@@ -3,7 +3,7 @@ from __future__ import annotations
3
3
  from pathlib import Path
4
4
 
5
5
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
- from klaude_code.protocol import commands, model, op
6
+ from klaude_code.protocol import commands, message, op
7
7
 
8
8
 
9
9
  class ExportCommand(CommandABC):
@@ -29,7 +29,7 @@ class ExportCommand(CommandABC):
29
29
  def is_interactive(self) -> bool:
30
30
  return False
31
31
 
32
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
32
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
33
33
  output_path = self._normalize_output_path(user_input.text, agent)
34
34
  return CommandResult(
35
35
  operations=[
@@ -10,7 +10,7 @@ from rich.console import Console
10
10
  from rich.text import Text
11
11
 
12
12
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
13
- from klaude_code.protocol import commands, events, model
13
+ from klaude_code.protocol import commands, events, message, model
14
14
  from klaude_code.session.export import build_export_html
15
15
 
16
16
 
@@ -33,15 +33,15 @@ class ExportOnlineCommand(CommandABC):
33
33
  def is_interactive(self) -> bool:
34
34
  return False
35
35
 
36
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
36
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
37
37
  del user_input # unused
38
38
  # Check if npx or surge is available
39
39
  surge_cmd = self._get_surge_command()
40
40
  if not surge_cmd:
41
41
  event = events.DeveloperMessageEvent(
42
42
  session_id=agent.session.id,
43
- item=model.DeveloperMessageItem(
44
- content="surge.sh CLI not found. Install with: npm install -g surge",
43
+ item=message.DeveloperMessage(
44
+ parts=message.text_parts_from_str("surge.sh CLI not found. Install with: npm install -g surge"),
45
45
  command_output=model.CommandOutput(command_name=self.name, is_error=True),
46
46
  ),
47
47
  )
@@ -50,29 +50,29 @@ class ExportOnlineCommand(CommandABC):
50
50
  try:
51
51
  console = Console()
52
52
  # Check login status inside status context since npx surge whoami can be slow
53
- with console.status(Text("Checking surge.sh login status...", style="dim"), spinner_style="dim"):
53
+ with console.status(Text("Checking surge.sh login status", style="dim"), spinner_style="dim"):
54
54
  logged_in = self._is_surge_logged_in(surge_cmd)
55
55
 
56
56
  if not logged_in:
57
57
  login_cmd = " ".join([*surge_cmd, "login"])
58
58
  event = events.DeveloperMessageEvent(
59
59
  session_id=agent.session.id,
60
- item=model.DeveloperMessageItem(
61
- content=f"Not logged in to surge.sh. Please run: {login_cmd}",
60
+ item=message.DeveloperMessage(
61
+ parts=message.text_parts_from_str(f"Not logged in to surge.sh. Please run: {login_cmd}"),
62
62
  command_output=model.CommandOutput(command_name=self.name, is_error=True),
63
63
  ),
64
64
  )
65
65
  return CommandResult(events=[event])
66
66
 
67
- with console.status(Text("Deploying to surge.sh...", style="dim"), spinner_style="dim"):
67
+ with console.status(Text("Deploying to surge.sh", style="dim"), spinner_style="dim"):
68
68
  html_doc = self._build_html(agent)
69
69
  domain = self._generate_domain()
70
70
  url = self._deploy_to_surge(surge_cmd, html_doc, domain)
71
71
 
72
72
  event = events.DeveloperMessageEvent(
73
73
  session_id=agent.session.id,
74
- item=model.DeveloperMessageItem(
75
- content=f"Session deployed to: {url}",
74
+ item=message.DeveloperMessage(
75
+ parts=message.text_parts_from_str(f"Session deployed to: {url}"),
76
76
  command_output=model.CommandOutput(command_name=self.name),
77
77
  ),
78
78
  )
@@ -82,8 +82,8 @@ class ExportOnlineCommand(CommandABC):
82
82
 
83
83
  event = events.DeveloperMessageEvent(
84
84
  session_id=agent.session.id,
85
- item=model.DeveloperMessageItem(
86
- content=f"Failed to deploy session: {exc}\n{traceback.format_exc()}",
85
+ item=message.DeveloperMessage(
86
+ parts=message.text_parts_from_str(f"Failed to deploy session: {exc}\n{traceback.format_exc()}"),
87
87
  command_output=model.CommandOutput(command_name=self.name, is_error=True),
88
88
  ),
89
89
  )
@@ -6,7 +6,7 @@ from typing import Literal
6
6
  from prompt_toolkit.styles import Style
7
7
 
8
8
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
9
- from klaude_code.protocol import commands, events, model
9
+ from klaude_code.protocol import commands, events, message, model
10
10
  from klaude_code.ui.modes.repl.clipboard import copy_to_clipboard
11
11
  from klaude_code.ui.terminal.selector import SelectItem, select_one
12
12
 
@@ -41,29 +41,29 @@ def _truncate(text: str, max_len: int = 60) -> str:
41
41
  text = text.replace("\n", " ").strip()
42
42
  if len(text) <= max_len:
43
43
  return text
44
- return text[: max_len - 3] + "..."
44
+ return text[: max_len - 1] + ""
45
45
 
46
46
 
47
- def _build_fork_points(conversation_history: list[model.ConversationItem]) -> list[ForkPoint]:
47
+ def _build_fork_points(conversation_history: list[message.HistoryEvent]) -> list[ForkPoint]:
48
48
  """Build list of fork points from conversation history.
49
49
 
50
50
  Fork points are:
51
- - Each UserMessageItem position (for UI display, including first which would be empty session)
51
+ - Each UserMessage position (for UI display, including first which would be empty session)
52
52
  - The end of the conversation (fork entire conversation)
53
53
  """
54
54
  fork_points: list[ForkPoint] = []
55
55
  user_indices: list[int] = []
56
56
 
57
57
  for i, item in enumerate(conversation_history):
58
- if isinstance(item, model.UserMessageItem):
58
+ if isinstance(item, message.UserMessage):
59
59
  user_indices.append(i)
60
60
 
61
- # For each UserMessageItem, create a fork point at that position
61
+ # For each UserMessage, create a fork point at that position
62
62
  for i, user_idx in enumerate(user_indices):
63
63
  user_item = conversation_history[user_idx]
64
- assert isinstance(user_item, model.UserMessageItem)
64
+ assert isinstance(user_item, message.UserMessage)
65
65
 
66
- # Find the end of this "task" (next UserMessageItem or end of history)
66
+ # Find the end of this "task" (next UserMessage or end of history)
67
67
  next_user_idx = user_indices[i + 1] if i + 1 < len(user_indices) else len(conversation_history)
68
68
 
69
69
  # Count tool calls by name and find last assistant message in this segment
@@ -71,15 +71,19 @@ def _build_fork_points(conversation_history: list[model.ConversationItem]) -> li
71
71
  last_assistant_content = ""
72
72
  for j in range(user_idx, next_user_idx):
73
73
  item = conversation_history[j]
74
- if isinstance(item, model.ToolCallItem):
75
- tool_stats[item.name] = tool_stats.get(item.name, 0) + 1
76
- elif isinstance(item, model.AssistantMessageItem) and item.content:
77
- last_assistant_content = item.content
78
-
74
+ if isinstance(item, message.AssistantMessage):
75
+ for part in item.parts:
76
+ if isinstance(part, message.ToolCallPart):
77
+ tool_stats[part.tool_name] = tool_stats.get(part.tool_name, 0) + 1
78
+ text = message.join_text_parts(item.parts)
79
+ if text:
80
+ last_assistant_content = text
81
+
82
+ user_text = message.join_text_parts(user_item.parts)
79
83
  fork_points.append(
80
84
  ForkPoint(
81
85
  history_index=user_idx,
82
- user_message=user_item.content or "(empty)",
86
+ user_message=user_text or "(empty)",
83
87
  tool_call_stats=tool_stats,
84
88
  last_assistant_summary=_truncate(last_assistant_content) if last_assistant_content else "",
85
89
  )
@@ -195,14 +199,14 @@ class ForkSessionCommand(CommandABC):
195
199
  def is_interactive(self) -> bool:
196
200
  return True
197
201
 
198
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
202
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
199
203
  del user_input # unused
200
204
 
201
205
  if agent.session.messages_count == 0:
202
206
  event = events.DeveloperMessageEvent(
203
207
  session_id=agent.session.id,
204
- item=model.DeveloperMessageItem(
205
- content="(no messages to fork)",
208
+ item=message.DeveloperMessage(
209
+ parts=message.text_parts_from_str("(no messages to fork)"),
206
210
  command_output=model.CommandOutput(command_name=self.name),
207
211
  ),
208
212
  )
@@ -221,8 +225,8 @@ class ForkSessionCommand(CommandABC):
221
225
 
222
226
  event = events.DeveloperMessageEvent(
223
227
  session_id=agent.session.id,
224
- item=model.DeveloperMessageItem(
225
- content=f"Session forked successfully. New session id: {new_session.id}",
228
+ item=message.DeveloperMessage(
229
+ parts=message.text_parts_from_str(f"Session forked successfully. New session id: {new_session.id}"),
226
230
  command_output=model.CommandOutput(
227
231
  command_name=self.name,
228
232
  ui_extra=model.SessionIdUIExtra(session_id=new_session.id),
@@ -237,8 +241,8 @@ class ForkSessionCommand(CommandABC):
237
241
  if selected == "cancelled":
238
242
  event = events.DeveloperMessageEvent(
239
243
  session_id=agent.session.id,
240
- item=model.DeveloperMessageItem(
241
- content="(fork cancelled)",
244
+ item=message.DeveloperMessage(
245
+ parts=message.text_parts_from_str("(fork cancelled)"),
242
246
  command_output=model.CommandOutput(command_name=self.name),
243
247
  ),
244
248
  )
@@ -256,8 +260,10 @@ class ForkSessionCommand(CommandABC):
256
260
 
257
261
  event = events.DeveloperMessageEvent(
258
262
  session_id=agent.session.id,
259
- item=model.DeveloperMessageItem(
260
- content=f"Session forked ({fork_description}). New session id: {new_session.id}",
263
+ item=message.DeveloperMessage(
264
+ parts=message.text_parts_from_str(
265
+ f"Session forked ({fork_description}). New session id: {new_session.id}"
266
+ ),
261
267
  command_output=model.CommandOutput(
262
268
  command_name=self.name,
263
269
  ui_extra=model.SessionIdUIExtra(session_id=new_session.id),
@@ -1,5 +1,5 @@
1
1
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
- from klaude_code.protocol import commands, events, model
2
+ from klaude_code.protocol import commands, events, message, model
3
3
 
4
4
 
5
5
  class HelpCommand(CommandABC):
@@ -13,7 +13,7 @@ class HelpCommand(CommandABC):
13
13
  def summary(self) -> str:
14
14
  return "Show help and available commands"
15
15
 
16
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
16
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
17
17
  del user_input # unused
18
18
  lines: list[str] = [
19
19
  """
@@ -41,8 +41,8 @@ Available slash commands:"""
41
41
 
42
42
  event = events.DeveloperMessageEvent(
43
43
  session_id=agent.session.id,
44
- item=model.DeveloperMessageItem(
45
- content="\n".join(lines),
44
+ item=message.DeveloperMessage(
45
+ parts=message.text_parts_from_str("\n".join(lines)),
46
46
  command_output=model.CommandOutput(command_name=self.name),
47
47
  ),
48
48
  )
@@ -4,7 +4,7 @@ from prompt_toolkit.styles import Style
4
4
 
5
5
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
6
  from klaude_code.command.model_select import select_model_interactive
7
- from klaude_code.protocol import commands, events, model, op
7
+ from klaude_code.protocol import commands, events, message, model, op
8
8
  from klaude_code.ui.terminal.selector import SelectItem, select_one
9
9
 
10
10
  SELECT_STYLE = Style(
@@ -65,7 +65,7 @@ class ModelCommand(CommandABC):
65
65
  def placeholder(self) -> str:
66
66
  return "model name"
67
67
 
68
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
68
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
69
69
  selected_model = await asyncio.to_thread(select_model_interactive, preferred=user_input.text)
70
70
 
71
71
  current_model = agent.profile.llm_client.model_name if agent.profile else None
@@ -74,8 +74,8 @@ class ModelCommand(CommandABC):
74
74
  events=[
75
75
  events.DeveloperMessageEvent(
76
76
  session_id=agent.session.id,
77
- item=model.DeveloperMessageItem(
78
- content="(no change)",
77
+ item=message.DeveloperMessage(
78
+ parts=message.text_parts_from_str("(no change)"),
79
79
  command_output=model.CommandOutput(command_name=self.name),
80
80
  ),
81
81
  )
@@ -50,7 +50,7 @@ def select_model_interactive(preferred: str | None = None) -> str | None:
50
50
  selected = select_one(
51
51
  message=message,
52
52
  items=items,
53
- pointer="->",
53
+ pointer="",
54
54
  use_search_filter=True,
55
55
  initial_value=config.main_model,
56
56
  style=Style(
@@ -6,9 +6,18 @@ description: Commit current git changes
6
6
 
7
7
  ### Step 1: Detect version control system
8
8
 
9
- Check if `jj` is available in the current environment.
9
+ Check if `jj` is available in the current environment. (check in your <env> tag)
10
10
 
11
- ### Step 2A: If jj is available
11
+ ### Step 2: Run pre-commit checks
12
+
13
+ Before creating a commit, run the following checks:
14
+
15
+ 1. Run the project's linter to check and fix code style issues
16
+ 2. Run the project's test suite to ensure all tests pass
17
+ 3. If either check fails, stop the commit process and report the errors to the user
18
+ 4. If both checks pass, proceed to the next step
19
+
20
+ ### Step 3A: If jj is available
12
21
 
13
22
  1. Run `jj status` and `jj log -r 'ancestors(@, 10)'` to see working copy changes and the last 10 changes
14
23
  2. For each change that has no description (shows as "(no description set)"):
@@ -3,7 +3,7 @@ from importlib.resources import files
3
3
  import yaml
4
4
 
5
5
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
- from klaude_code.protocol import commands, model, op
6
+ from klaude_code.protocol import commands, message, op
7
7
  from klaude_code.trace import log_debug
8
8
 
9
9
 
@@ -55,7 +55,7 @@ class PromptCommand(CommandABC):
55
55
  def support_addition_params(self) -> bool:
56
56
  return True
57
57
 
58
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
58
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
59
59
  self._ensure_loaded()
60
60
  template_content = self._content or ""
61
61
  user_input_text = user_input.text.strip() or "<none>"
@@ -71,7 +71,7 @@ class PromptCommand(CommandABC):
71
71
  operations=[
72
72
  op.RunAgentOperation(
73
73
  session_id=agent.session.id,
74
- input=model.UserInputPayload(text=final_prompt, images=user_input.images),
74
+ input=message.UserInputPayload(text=final_prompt, images=user_input.images),
75
75
  )
76
76
  ]
77
77
  )
@@ -1,5 +1,5 @@
1
1
  from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
- from klaude_code.protocol import commands, events, model
2
+ from klaude_code.protocol import commands, events, message
3
3
 
4
4
 
5
5
  class RefreshTerminalCommand(CommandABC):
@@ -17,7 +17,7 @@ class RefreshTerminalCommand(CommandABC):
17
17
  def is_interactive(self) -> bool:
18
18
  return True
19
19
 
20
- async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
20
+ async def run(self, agent: Agent, user_input: message.UserInputPayload) -> CommandResult:
21
21
  del user_input # unused
22
22
  import os
23
23