klaude-code 1.2.19__tar.gz → 1.2.21__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 (204) hide show
  1. {klaude_code-1.2.19 → klaude_code-1.2.21}/PKG-INFO +2 -1
  2. {klaude_code-1.2.19 → klaude_code-1.2.21}/pyproject.toml +2 -1
  3. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/main.py +23 -0
  4. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/runtime.py +17 -0
  5. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/__init__.py +1 -3
  6. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/clear_cmd.py +5 -4
  7. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/command_abc.py +5 -40
  8. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/debug_cmd.py +2 -2
  9. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/diff_cmd.py +2 -1
  10. klaude_code-1.2.21/src/klaude_code/command/export_cmd.py +52 -0
  11. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/export_online_cmd.py +2 -1
  12. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/help_cmd.py +2 -1
  13. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/model_cmd.py +7 -5
  14. klaude_code-1.2.21/src/klaude_code/command/prompt-jj-workspace.md +18 -0
  15. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/prompt_command.py +16 -9
  16. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/refresh_cmd.py +3 -2
  17. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/registry.py +31 -6
  18. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/release_notes_cmd.py +2 -1
  19. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/status_cmd.py +2 -1
  20. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/terminal_setup_cmd.py +2 -1
  21. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/thinking_cmd.py +12 -1
  22. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/executor.py +177 -190
  23. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/manager/sub_agent_manager.py +3 -0
  24. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompt.py +4 -1
  25. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-sub-agent-web.md +3 -3
  26. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/reminders.py +70 -26
  27. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/task.py +4 -5
  28. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/__init__.py +2 -0
  29. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/apply_patch_tool.py +3 -1
  30. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/edit_tool.py +7 -5
  31. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/multi_edit_tool.py +7 -5
  32. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/read_tool.py +5 -2
  33. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/write_tool.py +8 -6
  34. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/shell/bash_tool.py +90 -17
  35. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/sub_agent_tool.py +5 -1
  36. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/tool_abc.py +18 -0
  37. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/tool_context.py +6 -6
  38. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/tool_runner.py +7 -7
  39. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/web/mermaid_tool.md +26 -0
  40. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/web/web_fetch_tool.py +77 -22
  41. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/web/web_search_tool.py +5 -1
  42. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/model.py +8 -1
  43. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/op.py +47 -0
  44. klaude_code-1.2.21/src/klaude_code/protocol/op_handler.py +52 -0
  45. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/sub_agent/web.py +1 -1
  46. klaude_code-1.2.21/src/klaude_code/session/codec.py +71 -0
  47. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/session/export.py +21 -11
  48. klaude_code-1.2.21/src/klaude_code/session/session.py +408 -0
  49. klaude_code-1.2.21/src/klaude_code/session/store.py +215 -0
  50. klaude_code-1.2.21/src/klaude_code/session/templates/export_session.html +1726 -0
  51. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/completers.py +1 -2
  52. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/event_handler.py +7 -23
  53. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/input_prompt_toolkit.py +4 -6
  54. klaude_code-1.2.21/src/klaude_code/ui/rich/__init__.py +10 -0
  55. klaude_code-1.2.21/src/klaude_code/ui/rich/cjk_wrap.py +228 -0
  56. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/rich/status.py +0 -1
  57. klaude_code-1.2.19/src/klaude_code/command/export_cmd.py +0 -87
  58. klaude_code-1.2.19/src/klaude_code/protocol/op_handler.py +0 -28
  59. klaude_code-1.2.19/src/klaude_code/session/session.py +0 -557
  60. klaude_code-1.2.19/src/klaude_code/session/templates/export_session.html +0 -1727
  61. klaude_code-1.2.19/src/klaude_code/ui/rich/__init__.py +0 -1
  62. klaude_code-1.2.19/src/klaude_code/ui/utils/debouncer.py +0 -42
  63. {klaude_code-1.2.19 → klaude_code-1.2.21}/README.md +0 -0
  64. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/__init__.py +0 -0
  65. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/auth/__init__.py +0 -0
  66. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/auth/codex/__init__.py +0 -0
  67. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/auth/codex/exceptions.py +0 -0
  68. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/auth/codex/jwt_utils.py +0 -0
  69. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/auth/codex/oauth.py +0 -0
  70. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/auth/codex/token_manager.py +0 -0
  71. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/__init__.py +0 -0
  72. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/auth_cmd.py +0 -0
  73. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/config_cmd.py +0 -0
  74. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/debug.py +0 -0
  75. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/list_model.py +0 -0
  76. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/self_update.py +0 -0
  77. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/cli/session_cmd.py +0 -0
  78. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/prompt-deslop.md +0 -0
  79. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/prompt-dev-docs-update.md +0 -0
  80. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/prompt-dev-docs.md +0 -0
  81. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/prompt-handoff.md +0 -0
  82. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/command/prompt-init.md +0 -0
  83. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/config/__init__.py +0 -0
  84. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/config/config.py +0 -0
  85. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/config/select_model.py +0 -0
  86. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/const/__init__.py +0 -0
  87. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/__init__.py +0 -0
  88. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/agent.py +0 -0
  89. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/manager/__init__.py +0 -0
  90. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/manager/llm_clients.py +0 -0
  91. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/manager/llm_clients_builder.py +0 -0
  92. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-claude-code.md +0 -0
  93. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +0 -0
  94. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-codex-gpt-5-1.md +0 -0
  95. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-gemini.md +0 -0
  96. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-minimal.md +0 -0
  97. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-sub-agent-explore.md +0 -0
  98. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-sub-agent-oracle.md +0 -0
  99. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/prompts/prompt-sub-agent.md +0 -0
  100. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/__init__.py +0 -0
  101. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/_utils.py +0 -0
  102. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/apply_patch.py +0 -0
  103. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/apply_patch_tool.md +0 -0
  104. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/edit_tool.md +0 -0
  105. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/multi_edit_tool.md +0 -0
  106. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/read_tool.md +0 -0
  107. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/file/write_tool.md +0 -0
  108. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/memory/__init__.py +0 -0
  109. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/memory/memory_tool.md +0 -0
  110. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/memory/memory_tool.py +0 -0
  111. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/memory/skill_loader.py +0 -0
  112. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/memory/skill_tool.md +0 -0
  113. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/memory/skill_tool.py +0 -0
  114. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/report_back_tool.py +0 -0
  115. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/shell/__init__.py +0 -0
  116. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/shell/bash_tool.md +0 -0
  117. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/shell/command_safety.py +0 -0
  118. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/todo/__init__.py +0 -0
  119. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/todo/todo_write_tool.md +0 -0
  120. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/todo/todo_write_tool.py +0 -0
  121. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/todo/todo_write_tool_raw.md +0 -0
  122. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/todo/update_plan_tool.md +0 -0
  123. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/todo/update_plan_tool.py +0 -0
  124. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/tool_registry.py +0 -0
  125. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/truncation.py +0 -0
  126. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/web/__init__.py +0 -0
  127. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/web/mermaid_tool.py +0 -0
  128. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/web/web_fetch_tool.md +0 -0
  129. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/tool/web/web_search_tool.md +0 -0
  130. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/core/turn.py +0 -0
  131. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/__init__.py +0 -0
  132. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/anthropic/__init__.py +0 -0
  133. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/anthropic/client.py +0 -0
  134. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/anthropic/input.py +0 -0
  135. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/client.py +0 -0
  136. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/codex/__init__.py +0 -0
  137. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/codex/client.py +0 -0
  138. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/input_common.py +0 -0
  139. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openai_compatible/__init__.py +0 -0
  140. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openai_compatible/client.py +0 -0
  141. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openai_compatible/input.py +0 -0
  142. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openai_compatible/stream_processor.py +0 -0
  143. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openai_compatible/tool_call_accumulator.py +0 -0
  144. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openrouter/__init__.py +0 -0
  145. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openrouter/client.py +0 -0
  146. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openrouter/input.py +0 -0
  147. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/openrouter/reasoning_handler.py +0 -0
  148. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/registry.py +0 -0
  149. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/responses/__init__.py +0 -0
  150. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/responses/client.py +0 -0
  151. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/responses/input.py +0 -0
  152. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/llm/usage.py +0 -0
  153. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/__init__.py +0 -0
  154. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/commands.py +0 -0
  155. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/events.py +0 -0
  156. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/llm_param.py +0 -0
  157. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/sub_agent/__init__.py +0 -0
  158. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/sub_agent/explore.py +0 -0
  159. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/sub_agent/oracle.py +0 -0
  160. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/sub_agent/task.py +0 -0
  161. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/protocol/tools.py +0 -0
  162. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/session/__init__.py +0 -0
  163. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/session/selector.py +0 -0
  164. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/trace/__init__.py +0 -0
  165. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/trace/log.py +0 -0
  166. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/__init__.py +0 -0
  167. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/core/__init__.py +0 -0
  168. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/core/display.py +0 -0
  169. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/core/input.py +0 -0
  170. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/core/stage_manager.py +0 -0
  171. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/__init__.py +0 -0
  172. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/debug/__init__.py +0 -0
  173. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/debug/display.py +0 -0
  174. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/exec/__init__.py +0 -0
  175. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/exec/display.py +0 -0
  176. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/__init__.py +0 -0
  177. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/clipboard.py +0 -0
  178. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/display.py +0 -0
  179. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/key_bindings.py +0 -0
  180. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/modes/repl/renderer.py +0 -0
  181. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/__init__.py +0 -0
  182. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/assistant.py +0 -0
  183. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/common.py +0 -0
  184. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/developer.py +0 -0
  185. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/diffs.py +0 -0
  186. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/errors.py +0 -0
  187. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/metadata.py +0 -0
  188. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/sub_agent.py +0 -0
  189. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/thinking.py +0 -0
  190. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/tools.py +0 -0
  191. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/renderers/user_input.py +0 -0
  192. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/rich/code_panel.py +0 -0
  193. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/rich/live.py +0 -0
  194. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/rich/markdown.py +0 -0
  195. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/rich/quote.py +0 -0
  196. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/rich/searchable_text.py +0 -0
  197. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/rich/theme.py +0 -0
  198. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/terminal/__init__.py +0 -0
  199. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/terminal/color.py +0 -0
  200. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/terminal/control.py +0 -0
  201. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/terminal/notifier.py +0 -0
  202. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/terminal/progress_bar.py +0 -0
  203. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/utils/__init__.py +0 -0
  204. {klaude_code-1.2.19 → klaude_code-1.2.21}/src/klaude_code/ui/utils/common.py +0 -0
@@ -1,8 +1,9 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: klaude-code
3
- Version: 1.2.19
3
+ Version: 1.2.21
4
4
  Summary: Add your description here
5
5
  Requires-Dist: anthropic>=0.66.0
6
+ Requires-Dist: chardet>=5.2.0
6
7
  Requires-Dist: ddgs>=9.9.3
7
8
  Requires-Dist: openai>=1.102.0
8
9
  Requires-Dist: pillow>=12.0.0
@@ -4,12 +4,13 @@ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "klaude-code"
7
- version = "1.2.19"
7
+ version = "1.2.21"
8
8
  description = "Add your description here"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.13"
11
11
  dependencies = [
12
12
  "anthropic>=0.66.0",
13
+ "chardet>=5.2.0",
13
14
  "ddgs>=9.9.3",
14
15
  "openai>=1.102.0",
15
16
  "pillow>=12.0.0",
@@ -194,6 +194,11 @@ def main_callback(
194
194
  ),
195
195
  continue_: bool = typer.Option(False, "--continue", "-c", help="Continue from latest session"),
196
196
  resume: bool = typer.Option(False, "--resume", "-r", help="Select a session to resume for this project"),
197
+ resume_by_id: str | None = typer.Option(
198
+ None,
199
+ "--resume-by-id",
200
+ help="Resume a session by its ID (must exist)",
201
+ ),
197
202
  select_model: bool = typer.Option(
198
203
  False,
199
204
  "--select-model",
@@ -224,6 +229,7 @@ def main_callback(
224
229
  if ctx.invoked_subcommand is None:
225
230
  from klaude_code.cli.runtime import AppInitConfig, run_interactive
226
231
  from klaude_code.config.select_model import select_model_from_config
232
+ from klaude_code.trace import log
227
233
 
228
234
  update_terminal_title()
229
235
 
@@ -236,6 +242,16 @@ def main_callback(
236
242
  # Resolve session id before entering asyncio loop
237
243
  # session_id=None means create a new session
238
244
  session_id: str | None = None
245
+
246
+ resume_by_id_value = resume_by_id.strip() if resume_by_id is not None else None
247
+ if resume_by_id_value == "":
248
+ log(("Error: --resume-by-id cannot be empty", "red"))
249
+ raise typer.Exit(2)
250
+
251
+ if resume_by_id_value is not None and (resume or continue_):
252
+ log(("Error: --resume-by-id cannot be combined with --resume/--continue", "red"))
253
+ raise typer.Exit(2)
254
+
239
255
  if resume:
240
256
  session_id = resume_select_session()
241
257
  if session_id is None:
@@ -243,6 +259,13 @@ def main_callback(
243
259
  # If user didn't pick, allow fallback to --continue
244
260
  if session_id is None and continue_:
245
261
  session_id = Session.most_recent_session_id()
262
+
263
+ if resume_by_id_value is not None:
264
+ if not Session.exists(resume_by_id_value):
265
+ log((f"Error: session id '{resume_by_id_value}' not found for this project", "red"))
266
+ log(("Hint: run `klaude --resume` to select an existing session", "yellow"))
267
+ raise typer.Exit(2)
268
+ session_id = resume_by_id_value
246
269
  # If still no session_id, leave as None to create a new session
247
270
 
248
271
  if session_id is not None and chosen_model is None:
@@ -17,6 +17,7 @@ from klaude_code.core.executor import Executor
17
17
  from klaude_code.core.manager import build_llm_clients
18
18
  from klaude_code.protocol import events, op
19
19
  from klaude_code.protocol.model import UserInputPayload
20
+ from klaude_code.session.session import Session, close_default_store
20
21
  from klaude_code.trace import DebugType, log, set_debug_logging
21
22
  from klaude_code.ui.modes.repl import build_repl_status_snapshot
22
23
  from klaude_code.ui.modes.repl.input_prompt_toolkit import REPLStatusSnapshot
@@ -184,6 +185,10 @@ async def cleanup_app_components(components: AppComponents) -> None:
184
185
  # Clean shutdown
185
186
  await components.executor.stop()
186
187
  components.executor_task.cancel()
188
+ with contextlib.suppress(asyncio.CancelledError):
189
+ await components.executor_task
190
+ with contextlib.suppress(Exception):
191
+ await close_default_store()
187
192
 
188
193
  # Signal UI to stop
189
194
  await components.event_queue.put(events.EndEvent())
@@ -207,6 +212,9 @@ async def _handle_keyboard_interrupt(executor: Executor) -> None:
207
212
  """Handle Ctrl+C by logging and sending a global interrupt."""
208
213
 
209
214
  log("Bye!")
215
+ session_id = executor.context.current_session_id()
216
+ if session_id and Session.exists(session_id):
217
+ log(("Resume with:", "dim"), (f"klaude --resume-by-id {session_id}", "green"))
210
218
  # Executor might already be stopping
211
219
  with contextlib.suppress(Exception):
212
220
  await executor.submit(op.InterruptOperation(target_session_id=None))
@@ -291,6 +299,8 @@ async def run_interactive(init_config: AppInitConfig, session_id: str | None = N
291
299
 
292
300
  restore_sigint = install_sigint_double_press_exit(_show_toast_once, _hide_progress)
293
301
 
302
+ exit_hint_printed = False
303
+
294
304
  try:
295
305
  await initialize_session(components.executor, components.event_queue, session_id=session_id)
296
306
  _backfill_session_model_config(
@@ -342,8 +352,15 @@ async def run_interactive(init_config: AppInitConfig, session_id: str | None = N
342
352
 
343
353
  except KeyboardInterrupt:
344
354
  await _handle_keyboard_interrupt(components.executor)
355
+ exit_hint_printed = True
345
356
  finally:
346
357
  # Restore original SIGINT handler
347
358
  with contextlib.suppress(Exception):
348
359
  restore_sigint()
349
360
  await cleanup_app_components(components)
361
+
362
+ if not exit_hint_printed:
363
+ active_session_id = components.executor.context.current_session_id()
364
+ if active_session_id and Session.exists(active_session_id):
365
+ log(f"Session ID: {active_session_id}")
366
+ log(f"Resume with: klaude --resume-by-id {active_session_id}")
@@ -1,4 +1,4 @@
1
- from .command_abc import CommandABC, CommandResult, InputAction, InputActionType
1
+ from .command_abc import CommandABC, CommandResult
2
2
  from .registry import (
3
3
  dispatch_command,
4
4
  get_commands,
@@ -89,8 +89,6 @@ __all__ = [
89
89
  # "StatusCommand", "TerminalSetupCommand",
90
90
  "CommandABC",
91
91
  "CommandResult",
92
- "InputAction",
93
- "InputActionType",
94
92
  "dispatch_command",
95
93
  "ensure_commands_loaded",
96
94
  "get_commands",
@@ -1,5 +1,5 @@
1
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult, InputAction
2
- from klaude_code.protocol import commands
1
+ from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
+ from klaude_code.protocol import commands, model, op
3
3
 
4
4
 
5
5
  class ClearCommand(CommandABC):
@@ -13,5 +13,6 @@ 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, raw: str, agent: Agent) -> CommandResult:
17
- return CommandResult(actions=[InputAction.clear()])
16
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
17
+ del user_input # unused
18
+ return CommandResult(operations=[op.ClearSessionOperation(session_id=agent.session.id)])
@@ -1,11 +1,10 @@
1
1
  from abc import ABC, abstractmethod
2
- from enum import Enum
3
2
  from typing import Protocol
4
3
 
5
4
  from pydantic import BaseModel
6
5
 
7
6
  from klaude_code.llm import LLMClientABC
8
- from klaude_code.protocol import commands, llm_param
7
+ from klaude_code.protocol import commands, llm_param, model, op
9
8
  from klaude_code.protocol import events as protocol_events
10
9
  from klaude_code.session.session import Session
11
10
 
@@ -34,40 +33,6 @@ class Agent(Protocol):
34
33
  def get_llm_client(self) -> LLMClientABC: ...
35
34
 
36
35
 
37
- class InputActionType(str, Enum):
38
- """Supported input action kinds."""
39
-
40
- RUN_AGENT = "run_agent"
41
- CHANGE_MODEL = "change_model"
42
- CLEAR = "clear"
43
-
44
-
45
- class InputAction(BaseModel):
46
- """Structured executor action derived from a user input."""
47
-
48
- type: InputActionType
49
- text: str = ""
50
- model_name: str | None = None
51
-
52
- @classmethod
53
- def run_agent(cls, text: str) -> "InputAction":
54
- """Create a RunAgent action preserving the provided text."""
55
-
56
- return cls(type=InputActionType.RUN_AGENT, text=text)
57
-
58
- @classmethod
59
- def change_model(cls, model_name: str) -> "InputAction":
60
- """Create a ChangeModel action for the provided model name."""
61
-
62
- return cls(type=InputActionType.CHANGE_MODEL, model_name=model_name)
63
-
64
- @classmethod
65
- def clear(cls) -> "InputAction":
66
- """Create a Clear action to reset the session."""
67
-
68
- return cls(type=InputActionType.CLEAR)
69
-
70
-
71
36
  class CommandResult(BaseModel):
72
37
  """Result of a command execution."""
73
38
 
@@ -75,7 +40,7 @@ class CommandResult(BaseModel):
75
40
  list[protocol_events.DeveloperMessageEvent | protocol_events.WelcomeEvent | protocol_events.ReplayHistoryEvent]
76
41
  | None
77
42
  ) = None # List of UI events to display immediately
78
- actions: list[InputAction] | None = None
43
+ operations: list[op.Operation] | None = None
79
44
 
80
45
 
81
46
  class CommandABC(ABC):
@@ -109,13 +74,13 @@ class CommandABC(ABC):
109
74
  return "additional instructions"
110
75
 
111
76
  @abstractmethod
112
- async def run(self, raw: str, agent: Agent) -> CommandResult:
77
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
113
78
  """
114
79
  Execute the command.
115
80
 
116
81
  Args:
117
- raw: The full command string as typed by user (e.g., "/help" or "/model gpt-4")
118
- session_id: Current session ID, may be None if no session initialized yet
82
+ agent: The agent instance
83
+ user_input: User input with text containing command arguments (without command name)
119
84
 
120
85
  Returns:
121
86
  CommandResult: Result of the command execution
@@ -45,8 +45,8 @@ class DebugCommand(CommandABC):
45
45
  def placeholder(self) -> str:
46
46
  return "filter types"
47
47
 
48
- async def run(self, raw: str, agent: Agent) -> CommandResult:
49
- raw = raw.strip()
48
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
49
+ raw = user_input.text.strip()
50
50
 
51
51
  # /debug (no args) - enable debug
52
52
  if not raw:
@@ -16,7 +16,8 @@ class DiffCommand(CommandABC):
16
16
  def summary(self) -> str:
17
17
  return "Show git diff"
18
18
 
19
- async def run(self, raw: str, agent: Agent) -> CommandResult:
19
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
20
+ del user_input # unused
20
21
  try:
21
22
  # Check if current directory is in a git repository
22
23
  git_check = subprocess.run(
@@ -0,0 +1,52 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+ from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
+ from klaude_code.protocol import commands, model, op
7
+
8
+
9
+ class ExportCommand(CommandABC):
10
+ """Export the current session into a standalone HTML transcript."""
11
+
12
+ @property
13
+ def name(self) -> commands.CommandName:
14
+ return commands.CommandName.EXPORT
15
+
16
+ @property
17
+ def summary(self) -> str:
18
+ return "Export current session to HTML"
19
+
20
+ @property
21
+ def support_addition_params(self) -> bool:
22
+ return True
23
+
24
+ @property
25
+ def placeholder(self) -> str:
26
+ return "output path"
27
+
28
+ @property
29
+ def is_interactive(self) -> bool:
30
+ return False
31
+
32
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
33
+ output_path = self._normalize_output_path(user_input.text, agent)
34
+ return CommandResult(
35
+ operations=[
36
+ op.ExportSessionOperation(
37
+ session_id=agent.session.id,
38
+ output_path=str(output_path) if output_path is not None else None,
39
+ )
40
+ ]
41
+ )
42
+
43
+ def _normalize_output_path(self, raw: str, agent: Agent) -> Path | None:
44
+ trimmed = raw.strip()
45
+ if trimmed:
46
+ candidate = Path(trimmed).expanduser()
47
+ if not candidate.is_absolute():
48
+ candidate = Path(agent.session.work_dir) / candidate
49
+ if candidate.suffix.lower() != ".html":
50
+ candidate = candidate.with_suffix(".html")
51
+ return candidate
52
+ return None
@@ -33,7 +33,8 @@ class ExportOnlineCommand(CommandABC):
33
33
  def is_interactive(self) -> bool:
34
34
  return False
35
35
 
36
- async def run(self, raw: str, agent: Agent) -> CommandResult:
36
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
37
+ del user_input # unused
37
38
  # Check if npx or surge is available
38
39
  surge_cmd = self._get_surge_command()
39
40
  if not surge_cmd:
@@ -13,7 +13,8 @@ class HelpCommand(CommandABC):
13
13
  def summary(self) -> str:
14
14
  return "Show help and available commands"
15
15
 
16
- async def run(self, raw: str, agent: Agent) -> CommandResult:
16
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
17
+ del user_input # unused
17
18
  lines: list[str] = [
18
19
  """
19
20
  Usage:
@@ -1,8 +1,8 @@
1
1
  import asyncio
2
2
 
3
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult, InputAction
3
+ from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
4
4
  from klaude_code.config.select_model import select_model_from_config
5
- from klaude_code.protocol import commands, events, model
5
+ from klaude_code.protocol import commands, events, model, op
6
6
 
7
7
 
8
8
  class ModelCommand(CommandABC):
@@ -28,8 +28,8 @@ class ModelCommand(CommandABC):
28
28
  def placeholder(self) -> str:
29
29
  return "model name"
30
30
 
31
- async def run(self, raw: str, agent: Agent) -> CommandResult:
32
- selected_model = await asyncio.to_thread(select_model_from_config, preferred=raw)
31
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
32
+ selected_model = await asyncio.to_thread(select_model_from_config, preferred=user_input.text)
33
33
 
34
34
  current_model = agent.profile.llm_client.model_name if agent.profile else None
35
35
  if selected_model is None or selected_model == current_model:
@@ -45,4 +45,6 @@ class ModelCommand(CommandABC):
45
45
  ]
46
46
  )
47
47
 
48
- return CommandResult(actions=[InputAction.change_model(selected_model)])
48
+ return CommandResult(
49
+ operations=[op.ChangeModelOperation(session_id=agent.session.id, model_name=selected_model)]
50
+ )
@@ -0,0 +1,18 @@
1
+ ---
2
+ description: Create a jj workspace before starting work to enable parallel Clauding
3
+ ---
4
+ <task>
5
+ $ARGUMENTS
6
+ </task>
7
+ <system>
8
+ You are now in jj-workspace mode. Before working on any task, you MUST first create a dedicated jj workspace. This allows multiple Claude sessions to work in parallel without conflicts.
9
+
10
+ If the <task> above is empty, inform the user that you are ready to work in jj-workspace mode and waiting for a task description. Once provided, follow the steps below.
11
+
12
+ When a task is provided, follow these steps:
13
+ 1. Generate a short, descriptive workspace name based on the task (e.g., `workspace-add-login` or `workspace-fix-typo`)
14
+ 2. Run `jj workspace add <workspace-name>` to create the workspace
15
+ 3. Change into the workspace directory: `cd <workspace-name>`
16
+ 4. Describe the change: `jj describe -m '<brief task description>'`
17
+ 5. Continue all subsequent work within this workspace directory
18
+ </system>
@@ -2,8 +2,8 @@ from importlib.resources import files
2
2
 
3
3
  import yaml
4
4
 
5
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult, InputAction
6
- from klaude_code.protocol import commands
5
+ from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
+ from klaude_code.protocol import commands, model, op
7
7
  from klaude_code.trace import log_debug
8
8
 
9
9
 
@@ -55,16 +55,23 @@ class PromptCommand(CommandABC):
55
55
  def support_addition_params(self) -> bool:
56
56
  return True
57
57
 
58
- async def run(self, raw: str, agent: Agent) -> CommandResult:
58
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
59
59
  self._ensure_loaded()
60
60
  template_content = self._content or ""
61
- user_input = raw.strip() or "<none>"
61
+ user_input_text = user_input.text.strip() or "<none>"
62
62
 
63
63
  if "$ARGUMENTS" in template_content:
64
- final_prompt = template_content.replace("$ARGUMENTS", user_input)
64
+ final_prompt = template_content.replace("$ARGUMENTS", user_input_text)
65
65
  else:
66
66
  final_prompt = template_content
67
- if user_input:
68
- final_prompt += f"\n\nAdditional Instructions:\n{user_input}"
69
-
70
- return CommandResult(actions=[InputAction.run_agent(final_prompt)])
67
+ if user_input_text:
68
+ final_prompt += f"\n\nAdditional Instructions:\n{user_input_text}"
69
+
70
+ return CommandResult(
71
+ operations=[
72
+ op.RunAgentOperation(
73
+ session_id=agent.session.id,
74
+ input=model.UserInputPayload(text=final_prompt, images=user_input.images),
75
+ )
76
+ ]
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
2
+ from klaude_code.protocol import commands, events, model
3
3
 
4
4
 
5
5
  class RefreshTerminalCommand(CommandABC):
@@ -17,7 +17,8 @@ class RefreshTerminalCommand(CommandABC):
17
17
  def is_interactive(self) -> bool:
18
18
  return True
19
19
 
20
- async def run(self, raw: str, agent: Agent) -> CommandResult:
20
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
21
+ del user_input # unused
21
22
  import os
22
23
 
23
24
  os.system("cls" if os.name == "nt" else "clear")
@@ -1,9 +1,9 @@
1
1
  from importlib.resources import files
2
2
  from typing import TYPE_CHECKING
3
3
 
4
- from klaude_code.command.command_abc import Agent, CommandResult, InputAction
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
6
+ from klaude_code.protocol import commands, events, model, op
7
7
  from klaude_code.trace import log_debug
8
8
 
9
9
  if TYPE_CHECKING:
@@ -110,11 +110,20 @@ def is_slash_command_name(name: str) -> bool:
110
110
  return _resolve_command_key(name) is not None
111
111
 
112
112
 
113
- async def dispatch_command(raw: str, agent: Agent) -> CommandResult:
113
+ async def dispatch_command(user_input: model.UserInputPayload, agent: Agent, *, submission_id: str) -> CommandResult:
114
114
  _ensure_commands_loaded()
115
115
  # Detect command name
116
+ raw = user_input.text
116
117
  if not raw.startswith("/"):
117
- return CommandResult(actions=[InputAction.run_agent(raw)])
118
+ return CommandResult(
119
+ operations=[
120
+ op.RunAgentOperation(
121
+ id=submission_id,
122
+ session_id=agent.session.id,
123
+ input=user_input,
124
+ )
125
+ ]
126
+ )
118
127
 
119
128
  splits = raw.split(" ", maxsplit=1)
120
129
  command_name_raw = splits[0][1:]
@@ -122,13 +131,29 @@ async def dispatch_command(raw: str, agent: Agent) -> CommandResult:
122
131
 
123
132
  command_key = _resolve_command_key(command_name_raw)
124
133
  if command_key is None:
125
- return CommandResult(actions=[InputAction.run_agent(raw)])
134
+ return CommandResult(
135
+ operations=[
136
+ op.RunAgentOperation(
137
+ id=submission_id,
138
+ session_id=agent.session.id,
139
+ input=user_input,
140
+ )
141
+ ]
142
+ )
126
143
 
127
144
  command = _COMMANDS[command_key]
128
145
  command_identifier: commands.CommandName | str = command.name
129
146
 
130
147
  try:
131
- return await command.run(rest, agent)
148
+ user_input_for_command = model.UserInputPayload(text=rest, images=user_input.images)
149
+ result = await command.run(agent, user_input_for_command)
150
+ ops = list(result.operations or [])
151
+ for operation in ops:
152
+ if isinstance(operation, op.RunAgentOperation):
153
+ operation.id = submission_id
154
+ if ops:
155
+ result.operations = ops
156
+ return result
132
157
  except Exception as e:
133
158
  command_output = (
134
159
  model.CommandOutput(command_name=command_identifier, is_error=True)
@@ -68,7 +68,8 @@ class ReleaseNotesCommand(CommandABC):
68
68
  def summary(self) -> str:
69
69
  return "Show the latest release notes"
70
70
 
71
- async def run(self, raw: str, agent: Agent) -> CommandResult:
71
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
72
+ del user_input # unused
72
73
  changelog = _read_changelog()
73
74
  content = _extract_releases(changelog, count=10)
74
75
 
@@ -132,7 +132,8 @@ class StatusCommand(CommandABC):
132
132
  def summary(self) -> str:
133
133
  return "Show session usage statistics"
134
134
 
135
- async def run(self, raw: str, agent: Agent) -> CommandResult:
135
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
136
+ del user_input # unused
136
137
  session = agent.session
137
138
  aggregated = accumulate_session_usage(session)
138
139
 
@@ -21,7 +21,8 @@ class TerminalSetupCommand(CommandABC):
21
21
  def is_interactive(self) -> bool:
22
22
  return False
23
23
 
24
- async def run(self, raw: str, agent: Agent) -> CommandResult:
24
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
25
+ del user_input # unused
25
26
  term_program = os.environ.get("TERM_PROGRAM", "").lower()
26
27
 
27
28
  try:
@@ -10,6 +10,7 @@ RESPONSES_LEVELS = ["low", "medium", "high"]
10
10
  RESPONSES_GPT51_LEVELS = ["none", "low", "medium", "high"]
11
11
  RESPONSES_GPT52_LEVELS = ["none", "low", "medium", "high", "xhigh"]
12
12
  RESPONSES_CODEX_MAX_LEVELS = ["medium", "high", "xhigh"]
13
+ RESPONSES_GEMINI_FLASH_LEVELS = ["minimal", "low", "medium", "high"]
13
14
 
14
15
  ANTHROPIC_LEVELS: list[tuple[str, int | None]] = [
15
16
  ("off", 0),
@@ -48,6 +49,13 @@ def _is_codex_max_model(model_name: str | None) -> bool:
48
49
  return "codex-max" in model_name.lower()
49
50
 
50
51
 
52
+ def _is_gemini_flash_model(model_name: str | None) -> bool:
53
+ """Check if the model is Gemini 3 Flash."""
54
+ if not model_name:
55
+ return False
56
+ return "gemini-3-flash" in model_name.lower()
57
+
58
+
51
59
  def _get_levels_for_responses(model_name: str | None) -> list[str]:
52
60
  """Get thinking levels for responses protocol."""
53
61
  if _is_codex_max_model(model_name):
@@ -56,6 +64,8 @@ def _get_levels_for_responses(model_name: str | None) -> list[str]:
56
64
  return RESPONSES_GPT52_LEVELS
57
65
  if _is_gpt51_model(model_name):
58
66
  return RESPONSES_GPT51_LEVELS
67
+ if _is_gemini_flash_model(model_name):
68
+ return RESPONSES_GEMINI_FLASH_LEVELS
59
69
  return RESPONSES_LEVELS
60
70
 
61
71
 
@@ -169,7 +179,8 @@ class ThinkingCommand(CommandABC):
169
179
  def is_interactive(self) -> bool:
170
180
  return True
171
181
 
172
- async def run(self, raw: str, agent: Agent) -> CommandResult:
182
+ async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
183
+ del user_input # unused
173
184
  if not agent.profile:
174
185
  return self._no_change_result(agent, "No profile configured")
175
186