klaude-code 1.9.0__tar.gz → 2.0.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 (236) hide show
  1. {klaude_code-1.9.0 → klaude_code-2.0.0}/PKG-INFO +4 -2
  2. {klaude_code-1.9.0 → klaude_code-2.0.0}/README.md +1 -0
  3. {klaude_code-1.9.0 → klaude_code-2.0.0}/pyproject.toml +3 -2
  4. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/base.py +2 -6
  5. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/auth_cmd.py +4 -4
  6. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/list_model.py +1 -1
  7. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/main.py +1 -1
  8. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/runtime.py +7 -5
  9. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/self_update.py +1 -1
  10. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/session_cmd.py +1 -1
  11. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/clear_cmd.py +6 -2
  12. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/command_abc.py +2 -2
  13. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/debug_cmd.py +4 -4
  14. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/export_cmd.py +2 -2
  15. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/export_online_cmd.py +12 -12
  16. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/fork_session_cmd.py +29 -23
  17. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/help_cmd.py +4 -4
  18. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/model_cmd.py +4 -4
  19. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/model_select.py +1 -1
  20. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/prompt-commit.md +11 -2
  21. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/prompt_command.py +3 -3
  22. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/refresh_cmd.py +2 -2
  23. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/registry.py +7 -5
  24. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/release_notes_cmd.py +4 -4
  25. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/resume_cmd.py +15 -11
  26. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/status_cmd.py +4 -4
  27. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/terminal_setup_cmd.py +8 -8
  28. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/thinking_cmd.py +4 -4
  29. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/config/assets/builtin_config.yaml +16 -0
  30. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/config/builtin_config.py +16 -5
  31. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/config/config.py +7 -2
  32. klaude_code-2.0.0/src/klaude_code/const.py +219 -0
  33. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/agent.py +3 -12
  34. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/executor.py +21 -13
  35. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/manager/sub_agent_manager.py +71 -7
  36. klaude_code-2.0.0/src/klaude_code/core/prompts/prompt-sub-agent-image-gen.md +1 -0
  37. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +27 -1
  38. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/reminders.py +88 -69
  39. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/task.py +44 -45
  40. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/apply_patch_tool.py +9 -9
  41. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/diff_builder.py +3 -5
  42. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/edit_tool.py +23 -23
  43. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/move_tool.py +43 -43
  44. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/read_tool.py +44 -39
  45. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/write_tool.py +14 -14
  46. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/report_back_tool.py +4 -4
  47. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/shell/bash_tool.py +23 -23
  48. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/skill/skill_tool.py +7 -7
  49. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/sub_agent_tool.py +38 -9
  50. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/todo/todo_write_tool.py +8 -8
  51. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/todo/update_plan_tool.py +6 -6
  52. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/tool_abc.py +2 -2
  53. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/tool_context.py +27 -0
  54. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/tool_runner.py +88 -42
  55. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/truncation.py +38 -20
  56. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/web/mermaid_tool.py +6 -7
  57. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/web/web_fetch_tool.py +68 -30
  58. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/web/web_search_tool.py +15 -17
  59. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/turn.py +120 -73
  60. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/anthropic/client.py +79 -44
  61. klaude_code-2.0.0/src/klaude_code/llm/anthropic/input.py +232 -0
  62. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/bedrock/client.py +8 -5
  63. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/claude/client.py +18 -8
  64. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/client.py +4 -3
  65. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/codex/client.py +15 -9
  66. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/google/client.py +122 -60
  67. klaude_code-2.0.0/src/klaude_code/llm/google/input.py +201 -0
  68. klaude_code-2.0.0/src/klaude_code/llm/image.py +123 -0
  69. klaude_code-2.0.0/src/klaude_code/llm/input_common.py +180 -0
  70. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/openai_compatible/client.py +17 -7
  71. klaude_code-2.0.0/src/klaude_code/llm/openai_compatible/input.py +81 -0
  72. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/openai_compatible/stream.py +119 -67
  73. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +23 -11
  74. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/openrouter/client.py +34 -9
  75. klaude_code-2.0.0/src/klaude_code/llm/openrouter/input.py +147 -0
  76. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/openrouter/reasoning.py +22 -24
  77. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/registry.py +20 -17
  78. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/responses/client.py +107 -45
  79. klaude_code-2.0.0/src/klaude_code/llm/responses/input.py +203 -0
  80. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/usage.py +52 -25
  81. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/__init__.py +1 -0
  82. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/events.py +16 -12
  83. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/llm_param.py +20 -2
  84. klaude_code-2.0.0/src/klaude_code/protocol/message.py +250 -0
  85. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/model.py +94 -281
  86. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/op.py +2 -2
  87. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/sub_agent/__init__.py +1 -0
  88. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/sub_agent/explore.py +10 -0
  89. klaude_code-2.0.0/src/klaude_code/protocol/sub_agent/image_gen.py +119 -0
  90. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/sub_agent/task.py +10 -0
  91. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/sub_agent/web.py +10 -0
  92. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/codec.py +6 -6
  93. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/export.py +261 -62
  94. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/selector.py +7 -24
  95. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/session.py +126 -54
  96. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/store.py +5 -32
  97. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/templates/export_session.html +1 -1
  98. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/templates/mermaid_viewer.html +1 -1
  99. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/trace/log.py +11 -6
  100. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/core/input.py +1 -1
  101. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/core/stage_manager.py +1 -8
  102. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/debug/display.py +2 -2
  103. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/clipboard.py +2 -2
  104. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/completers.py +18 -10
  105. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/event_handler.py +136 -127
  106. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/input_prompt_toolkit.py +1 -1
  107. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/key_bindings.py +1 -1
  108. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/renderer.py +107 -15
  109. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/assistant.py +2 -2
  110. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/common.py +65 -7
  111. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/developer.py +7 -6
  112. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/diffs.py +11 -11
  113. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/mermaid_viewer.py +49 -2
  114. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/metadata.py +33 -5
  115. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/sub_agent.py +57 -16
  116. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/thinking.py +37 -2
  117. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/tools.py +180 -165
  118. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/live.py +3 -1
  119. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/markdown.py +39 -7
  120. klaude_code-2.0.0/src/klaude_code/ui/rich/quote.py +109 -0
  121. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/status.py +14 -8
  122. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/theme.py +8 -2
  123. klaude_code-2.0.0/src/klaude_code/ui/terminal/image.py +34 -0
  124. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/terminal/notifier.py +2 -1
  125. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/terminal/progress_bar.py +4 -4
  126. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/terminal/selector.py +22 -4
  127. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/utils/common.py +11 -2
  128. klaude_code-1.9.0/src/klaude_code/const.py +0 -164
  129. klaude_code-1.9.0/src/klaude_code/llm/anthropic/input.py +0 -224
  130. klaude_code-1.9.0/src/klaude_code/llm/google/input.py +0 -215
  131. klaude_code-1.9.0/src/klaude_code/llm/input_common.py +0 -233
  132. klaude_code-1.9.0/src/klaude_code/llm/openai_compatible/input.py +0 -111
  133. klaude_code-1.9.0/src/klaude_code/llm/openrouter/input.py +0 -148
  134. klaude_code-1.9.0/src/klaude_code/llm/responses/input.py +0 -186
  135. klaude_code-1.9.0/src/klaude_code/ui/rich/quote.py +0 -34
  136. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/__init__.py +0 -0
  137. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/__init__.py +0 -0
  138. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/claude/__init__.py +0 -0
  139. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/claude/exceptions.py +0 -0
  140. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/claude/oauth.py +0 -0
  141. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/claude/token_manager.py +0 -0
  142. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/codex/__init__.py +0 -0
  143. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/codex/exceptions.py +0 -0
  144. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
  145. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/codex/oauth.py +0 -0
  146. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/auth/codex/token_manager.py +0 -0
  147. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/__init__.py +0 -0
  148. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/config_cmd.py +0 -0
  149. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/cost_cmd.py +0 -0
  150. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/cli/debug.py +0 -0
  151. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/__init__.py +0 -0
  152. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/command/prompt-init.md +0 -0
  153. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/config/__init__.py +0 -0
  154. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/config/assets/__init__.py +0 -0
  155. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/config/select_model.py +0 -0
  156. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/config/thinking.py +0 -0
  157. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/__init__.py +0 -0
  158. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/manager/__init__.py +0 -0
  159. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/manager/llm_clients.py +0 -0
  160. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
  161. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompt.py +0 -0
  162. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
  163. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
  164. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +0 -0
  165. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-codex.md +0 -0
  166. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
  167. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
  168. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
  169. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
  170. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/__init__.py +0 -0
  171. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/__init__.py +0 -0
  172. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/_utils.py +0 -0
  173. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
  174. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
  175. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
  176. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/move_tool.md +0 -0
  177. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/read_tool.md +0 -0
  178. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/file/write_tool.md +0 -0
  179. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/shell/__init__.py +0 -0
  180. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
  181. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
  182. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/skill/__init__.py +0 -0
  183. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/skill/skill_tool.md +0 -0
  184. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/todo/__init__.py +0 -0
  185. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
  186. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
  187. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
  188. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/tool_registry.py +0 -0
  189. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/web/__init__.py +0 -0
  190. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/web/mermaid_tool.md +0 -0
  191. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
  192. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
  193. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/__init__.py +0 -0
  194. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/anthropic/__init__.py +0 -0
  195. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/bedrock/__init__.py +0 -0
  196. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/claude/__init__.py +0 -0
  197. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/codex/__init__.py +0 -0
  198. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/google/__init__.py +0 -0
  199. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
  200. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/openrouter/__init__.py +0 -0
  201. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/llm/responses/__init__.py +0 -0
  202. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/commands.py +0 -0
  203. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/op_handler.py +0 -0
  204. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/protocol/tools.py +0 -0
  205. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/session/__init__.py +0 -0
  206. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/__init__.py +0 -0
  207. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/assets/deslop/SKILL.md +0 -0
  208. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/assets/dev-docs/SKILL.md +0 -0
  209. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/assets/handoff/SKILL.md +0 -0
  210. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/assets/jj-workspace/SKILL.md +0 -0
  211. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/assets/skill-creator/SKILL.md +0 -0
  212. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/loader.py +0 -0
  213. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/manager.py +0 -0
  214. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/skill/system_skills.py +0 -0
  215. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/trace/__init__.py +0 -0
  216. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/__init__.py +0 -0
  217. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/core/__init__.py +0 -0
  218. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/core/display.py +0 -0
  219. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/__init__.py +0 -0
  220. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/debug/__init__.py +0 -0
  221. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/exec/__init__.py +0 -0
  222. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/exec/display.py +0 -0
  223. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/__init__.py +0 -0
  224. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/modes/repl/display.py +0 -0
  225. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/__init__.py +0 -0
  226. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/bash_syntax.py +0 -0
  227. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/errors.py +0 -0
  228. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/renderers/user_input.py +0 -0
  229. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/__init__.py +0 -0
  230. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/cjk_wrap.py +0 -0
  231. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/code_panel.py +0 -0
  232. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/rich/searchable_text.py +0 -0
  233. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/terminal/__init__.py +0 -0
  234. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/terminal/color.py +0 -0
  235. {klaude_code-1.9.0 → klaude_code-2.0.0}/src/klaude_code/ui/terminal/control.py +0 -0
  236. {klaude_code-1.9.0 → klaude_code-2.0.0}/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.0
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.0"
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
 
@@ -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
 
@@ -3,7 +3,7 @@ from typing import TYPE_CHECKING
3
3
 
4
4
  from klaude_code.command.command_abc import Agent, CommandResult
5
5
  from klaude_code.command.prompt_command import PromptCommand
6
- from klaude_code.protocol import commands, events, model, op
6
+ from klaude_code.protocol import commands, events, message, model, op
7
7
  from klaude_code.trace import log_debug
8
8
 
9
9
  if TYPE_CHECKING:
@@ -133,7 +133,7 @@ def is_slash_command_name(name: str) -> bool:
133
133
  return _resolve_command_key(name) is not None
134
134
 
135
135
 
136
- async def dispatch_command(user_input: model.UserInputPayload, agent: Agent, *, submission_id: str) -> CommandResult:
136
+ async def dispatch_command(user_input: message.UserInputPayload, agent: Agent, *, submission_id: str) -> CommandResult:
137
137
  _ensure_commands_loaded()
138
138
  # Detect command name
139
139
  raw = user_input.text
@@ -168,7 +168,7 @@ async def dispatch_command(user_input: model.UserInputPayload, agent: Agent, *,
168
168
  command_identifier: commands.CommandName | str = command.name
169
169
 
170
170
  try:
171
- user_input_for_command = model.UserInputPayload(text=rest, images=user_input.images)
171
+ user_input_for_command = message.UserInputPayload(text=rest, images=user_input.images)
172
172
  result = await command.run(agent, user_input_for_command)
173
173
  ops = list(result.operations or [])
174
174
  for operation in ops:
@@ -187,8 +187,10 @@ async def dispatch_command(user_input: model.UserInputPayload, agent: Agent, *,
187
187
  events=[
188
188
  events.DeveloperMessageEvent(
189
189
  session_id=agent.session.id,
190
- item=model.DeveloperMessageItem(
191
- content=f"Command {command_identifier} error: [{e.__class__.__name__}] {e!s}",
190
+ item=message.DeveloperMessage(
191
+ parts=message.text_parts_from_str(
192
+ f"Command {command_identifier} error: [{e.__class__.__name__}] {e!s}"
193
+ ),
192
194
  command_output=command_output,
193
195
  ),
194
196
  )