klaude-code 2.0.1__py3-none-any.whl → 2.1.0__py3-none-any.whl

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 (160) hide show
  1. klaude_code/app/__init__.py +12 -0
  2. klaude_code/app/runtime.py +215 -0
  3. klaude_code/cli/auth_cmd.py +2 -2
  4. klaude_code/cli/config_cmd.py +2 -2
  5. klaude_code/cli/cost_cmd.py +1 -1
  6. klaude_code/cli/debug.py +12 -36
  7. klaude_code/cli/list_model.py +3 -3
  8. klaude_code/cli/main.py +17 -60
  9. klaude_code/cli/self_update.py +2 -187
  10. klaude_code/cli/session_cmd.py +2 -2
  11. klaude_code/config/config.py +1 -1
  12. klaude_code/config/select_model.py +1 -1
  13. klaude_code/const.py +10 -1
  14. klaude_code/core/agent.py +9 -62
  15. klaude_code/core/agent_profile.py +284 -0
  16. klaude_code/core/executor.py +343 -230
  17. klaude_code/core/manager/llm_clients_builder.py +1 -1
  18. klaude_code/core/manager/sub_agent_manager.py +16 -29
  19. klaude_code/core/reminders.py +107 -155
  20. klaude_code/core/task.py +12 -20
  21. klaude_code/core/tool/__init__.py +5 -19
  22. klaude_code/core/tool/context.py +84 -0
  23. klaude_code/core/tool/file/apply_patch_tool.py +18 -21
  24. klaude_code/core/tool/file/edit_tool.py +42 -44
  25. klaude_code/core/tool/file/read_tool.py +14 -9
  26. klaude_code/core/tool/file/write_tool.py +12 -13
  27. klaude_code/core/tool/report_back_tool.py +4 -1
  28. klaude_code/core/tool/shell/bash_tool.py +6 -11
  29. klaude_code/core/tool/skill/skill_tool.py +3 -1
  30. klaude_code/core/tool/sub_agent_tool.py +8 -7
  31. klaude_code/core/tool/todo/todo_write_tool.py +3 -9
  32. klaude_code/core/tool/todo/update_plan_tool.py +3 -5
  33. klaude_code/core/tool/tool_abc.py +2 -1
  34. klaude_code/core/tool/tool_registry.py +2 -33
  35. klaude_code/core/tool/tool_runner.py +13 -10
  36. klaude_code/core/tool/web/mermaid_tool.py +3 -1
  37. klaude_code/core/tool/web/web_fetch_tool.py +5 -3
  38. klaude_code/core/tool/web/web_search_tool.py +5 -3
  39. klaude_code/core/turn.py +86 -26
  40. klaude_code/llm/anthropic/client.py +1 -1
  41. klaude_code/llm/bedrock/client.py +1 -1
  42. klaude_code/llm/claude/client.py +1 -1
  43. klaude_code/llm/codex/client.py +1 -1
  44. klaude_code/llm/google/client.py +1 -1
  45. klaude_code/llm/openai_compatible/client.py +1 -1
  46. klaude_code/llm/openai_compatible/tool_call_accumulator.py +1 -1
  47. klaude_code/llm/openrouter/client.py +1 -1
  48. klaude_code/llm/openrouter/reasoning.py +1 -1
  49. klaude_code/llm/responses/client.py +1 -1
  50. klaude_code/protocol/events/__init__.py +57 -0
  51. klaude_code/protocol/events/base.py +18 -0
  52. klaude_code/protocol/events/chat.py +20 -0
  53. klaude_code/protocol/events/lifecycle.py +22 -0
  54. klaude_code/protocol/events/metadata.py +15 -0
  55. klaude_code/protocol/events/streaming.py +43 -0
  56. klaude_code/protocol/events/system.py +53 -0
  57. klaude_code/protocol/events/tools.py +23 -0
  58. klaude_code/protocol/message.py +3 -11
  59. klaude_code/protocol/model.py +78 -9
  60. klaude_code/protocol/op.py +5 -0
  61. klaude_code/protocol/sub_agent/explore.py +0 -15
  62. klaude_code/protocol/sub_agent/task.py +1 -1
  63. klaude_code/protocol/sub_agent/web.py +1 -17
  64. klaude_code/protocol/tools.py +0 -1
  65. klaude_code/session/session.py +6 -5
  66. klaude_code/skill/assets/create-plan/SKILL.md +76 -0
  67. klaude_code/skill/loader.py +1 -1
  68. klaude_code/skill/system_skills.py +1 -1
  69. klaude_code/tui/__init__.py +8 -0
  70. klaude_code/{command → tui/command}/clear_cmd.py +2 -1
  71. klaude_code/{command → tui/command}/debug_cmd.py +4 -3
  72. klaude_code/{command → tui/command}/export_cmd.py +2 -1
  73. klaude_code/{command → tui/command}/export_online_cmd.py +6 -5
  74. klaude_code/{command → tui/command}/fork_session_cmd.py +10 -9
  75. klaude_code/{command → tui/command}/help_cmd.py +3 -2
  76. klaude_code/{command → tui/command}/model_cmd.py +5 -4
  77. klaude_code/{command → tui/command}/model_select.py +2 -2
  78. klaude_code/{command → tui/command}/prompt_command.py +4 -3
  79. klaude_code/{command → tui/command}/refresh_cmd.py +3 -1
  80. klaude_code/{command → tui/command}/registry.py +16 -6
  81. klaude_code/{command → tui/command}/release_notes_cmd.py +3 -2
  82. klaude_code/{command → tui/command}/resume_cmd.py +6 -5
  83. klaude_code/{command → tui/command}/status_cmd.py +4 -3
  84. klaude_code/{command → tui/command}/terminal_setup_cmd.py +4 -3
  85. klaude_code/{command → tui/command}/thinking_cmd.py +4 -3
  86. klaude_code/tui/commands.py +164 -0
  87. klaude_code/{ui/renderers → tui/components}/assistant.py +3 -3
  88. klaude_code/{ui/renderers → tui/components}/bash_syntax.py +2 -2
  89. klaude_code/{ui/renderers → tui/components}/common.py +1 -1
  90. klaude_code/tui/components/developer.py +231 -0
  91. klaude_code/{ui/renderers → tui/components}/diffs.py +2 -2
  92. klaude_code/{ui/renderers → tui/components}/errors.py +2 -2
  93. klaude_code/{ui/renderers → tui/components}/metadata.py +34 -21
  94. klaude_code/{ui → tui/components}/rich/markdown.py +78 -34
  95. klaude_code/{ui → tui/components}/rich/status.py +2 -2
  96. klaude_code/{ui → tui/components}/rich/theme.py +12 -5
  97. klaude_code/{ui/renderers → tui/components}/sub_agent.py +23 -43
  98. klaude_code/{ui/renderers → tui/components}/thinking.py +3 -3
  99. klaude_code/{ui/renderers → tui/components}/tools.py +11 -48
  100. klaude_code/{ui/renderers → tui/components}/user_input.py +3 -20
  101. klaude_code/tui/display.py +85 -0
  102. klaude_code/{ui/modes/repl → tui/input}/__init__.py +1 -1
  103. klaude_code/{ui/modes/repl → tui/input}/completers.py +1 -1
  104. klaude_code/{ui/modes/repl/input_prompt_toolkit.py → tui/input/prompt_toolkit.py} +11 -7
  105. klaude_code/tui/machine.py +606 -0
  106. klaude_code/tui/renderer.py +707 -0
  107. klaude_code/tui/runner.py +321 -0
  108. klaude_code/tui/terminal/__init__.py +56 -0
  109. klaude_code/{ui → tui}/terminal/color.py +1 -1
  110. klaude_code/{ui → tui}/terminal/control.py +1 -1
  111. klaude_code/{ui → tui}/terminal/notifier.py +1 -1
  112. klaude_code/{ui → tui}/terminal/selector.py +36 -17
  113. klaude_code/ui/__init__.py +6 -50
  114. klaude_code/ui/core/display.py +3 -3
  115. klaude_code/ui/core/input.py +2 -1
  116. klaude_code/ui/{modes/debug/display.py → debug_mode.py} +1 -1
  117. klaude_code/ui/{modes/exec/display.py → exec_mode.py} +1 -4
  118. klaude_code/ui/terminal/__init__.py +6 -54
  119. klaude_code/ui/terminal/title.py +31 -0
  120. klaude_code/update.py +163 -0
  121. {klaude_code-2.0.1.dist-info → klaude_code-2.1.0.dist-info}/METADATA +1 -1
  122. klaude_code-2.1.0.dist-info/RECORD +235 -0
  123. klaude_code/cli/runtime.py +0 -525
  124. klaude_code/core/prompt.py +0 -108
  125. klaude_code/core/tool/file/move_tool.md +0 -41
  126. klaude_code/core/tool/file/move_tool.py +0 -435
  127. klaude_code/core/tool/tool_context.py +0 -148
  128. klaude_code/protocol/events.py +0 -194
  129. klaude_code/skill/assets/dev-docs/SKILL.md +0 -108
  130. klaude_code/trace/__init__.py +0 -21
  131. klaude_code/ui/core/stage_manager.py +0 -48
  132. klaude_code/ui/modes/__init__.py +0 -1
  133. klaude_code/ui/modes/debug/__init__.py +0 -1
  134. klaude_code/ui/modes/exec/__init__.py +0 -1
  135. klaude_code/ui/modes/repl/display.py +0 -61
  136. klaude_code/ui/modes/repl/event_handler.py +0 -634
  137. klaude_code/ui/modes/repl/renderer.py +0 -463
  138. klaude_code/ui/renderers/developer.py +0 -215
  139. klaude_code/ui/utils/__init__.py +0 -1
  140. klaude_code-2.0.1.dist-info/RECORD +0 -229
  141. /klaude_code/{trace/log.py → log.py} +0 -0
  142. /klaude_code/{command → tui/command}/__init__.py +0 -0
  143. /klaude_code/{command → tui/command}/command_abc.py +0 -0
  144. /klaude_code/{command → tui/command}/prompt-commit.md +0 -0
  145. /klaude_code/{command → tui/command}/prompt-init.md +0 -0
  146. /klaude_code/{ui/renderers → tui/components}/__init__.py +0 -0
  147. /klaude_code/{ui/renderers → tui/components}/mermaid_viewer.py +0 -0
  148. /klaude_code/{ui → tui/components}/rich/__init__.py +0 -0
  149. /klaude_code/{ui → tui/components}/rich/cjk_wrap.py +0 -0
  150. /klaude_code/{ui → tui/components}/rich/code_panel.py +0 -0
  151. /klaude_code/{ui → tui/components}/rich/live.py +0 -0
  152. /klaude_code/{ui → tui/components}/rich/quote.py +0 -0
  153. /klaude_code/{ui → tui/components}/rich/searchable_text.py +0 -0
  154. /klaude_code/{ui/modes/repl → tui/input}/clipboard.py +0 -0
  155. /klaude_code/{ui/modes/repl → tui/input}/key_bindings.py +0 -0
  156. /klaude_code/{ui → tui}/terminal/image.py +0 -0
  157. /klaude_code/{ui → tui}/terminal/progress_bar.py +0 -0
  158. /klaude_code/ui/{utils/common.py → common.py} +0 -0
  159. {klaude_code-2.0.1.dist-info → klaude_code-2.1.0.dist-info}/WHEEL +0 -0
  160. {klaude_code-2.0.1.dist-info → klaude_code-2.1.0.dist-info}/entry_points.txt +0 -0
@@ -5,10 +5,11 @@ from typing import Literal
5
5
 
6
6
  from prompt_toolkit.styles import Style
7
7
 
8
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
9
8
  from klaude_code.protocol import commands, events, message, model
10
- from klaude_code.ui.modes.repl.clipboard import copy_to_clipboard
11
- from klaude_code.ui.terminal.selector import SelectItem, select_one
9
+ from klaude_code.tui.input.clipboard import copy_to_clipboard
10
+ from klaude_code.tui.terminal.selector import SelectItem, select_one
11
+
12
+ from .command_abc import Agent, CommandABC, CommandResult
12
13
 
13
14
  FORK_SELECT_STYLE = Style(
14
15
  [
@@ -207,7 +208,7 @@ class ForkSessionCommand(CommandABC):
207
208
  session_id=agent.session.id,
208
209
  item=message.DeveloperMessage(
209
210
  parts=message.text_parts_from_str("(no messages to fork)"),
210
- command_output=model.CommandOutput(command_name=self.name),
211
+ ui_extra=model.build_command_output_extra(self.name),
211
212
  ),
212
213
  )
213
214
  return CommandResult(events=[event], persist_user_input=False, persist_events=False)
@@ -227,8 +228,8 @@ class ForkSessionCommand(CommandABC):
227
228
  session_id=agent.session.id,
228
229
  item=message.DeveloperMessage(
229
230
  parts=message.text_parts_from_str(f"Session forked successfully. New session id: {new_session.id}"),
230
- command_output=model.CommandOutput(
231
- command_name=self.name,
231
+ ui_extra=model.build_command_output_extra(
232
+ self.name,
232
233
  ui_extra=model.SessionIdUIExtra(session_id=new_session.id),
233
234
  ),
234
235
  ),
@@ -243,7 +244,7 @@ class ForkSessionCommand(CommandABC):
243
244
  session_id=agent.session.id,
244
245
  item=message.DeveloperMessage(
245
246
  parts=message.text_parts_from_str("(fork cancelled)"),
246
- command_output=model.CommandOutput(command_name=self.name),
247
+ ui_extra=model.build_command_output_extra(self.name),
247
248
  ),
248
249
  )
249
250
  return CommandResult(events=[event], persist_user_input=False, persist_events=False)
@@ -264,8 +265,8 @@ class ForkSessionCommand(CommandABC):
264
265
  parts=message.text_parts_from_str(
265
266
  f"Session forked ({fork_description}). New session id: {new_session.id}"
266
267
  ),
267
- command_output=model.CommandOutput(
268
- command_name=self.name,
268
+ ui_extra=model.build_command_output_extra(
269
+ self.name,
269
270
  ui_extra=model.SessionIdUIExtra(session_id=new_session.id),
270
271
  ),
271
272
  ),
@@ -1,6 +1,7 @@
1
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
1
  from klaude_code.protocol import commands, events, message, model
3
2
 
3
+ from .command_abc import Agent, CommandABC, CommandResult
4
+
4
5
 
5
6
  class HelpCommand(CommandABC):
6
7
  """Display help information for all available slash commands."""
@@ -43,7 +44,7 @@ Available slash commands:"""
43
44
  session_id=agent.session.id,
44
45
  item=message.DeveloperMessage(
45
46
  parts=message.text_parts_from_str("\n".join(lines)),
46
- command_output=model.CommandOutput(command_name=self.name),
47
+ ui_extra=model.build_command_output_extra(self.name),
47
48
  ),
48
49
  )
49
50
 
@@ -2,10 +2,11 @@ import asyncio
2
2
 
3
3
  from prompt_toolkit.styles import Style
4
4
 
5
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
- from klaude_code.command.model_select import select_model_interactive
7
5
  from klaude_code.protocol import commands, events, message, model, op
8
- from klaude_code.ui.terminal.selector import SelectItem, select_one
6
+ from klaude_code.tui.terminal.selector import SelectItem, select_one
7
+
8
+ from .command_abc import Agent, CommandABC, CommandResult
9
+ from .model_select import select_model_interactive
9
10
 
10
11
  SELECT_STYLE = Style(
11
12
  [
@@ -76,7 +77,7 @@ class ModelCommand(CommandABC):
76
77
  session_id=agent.session.id,
77
78
  item=message.DeveloperMessage(
78
79
  parts=message.text_parts_from_str("(no change)"),
79
- command_output=model.CommandOutput(command_name=self.name),
80
+ ui_extra=model.build_command_output_extra(self.name),
80
81
  ),
81
82
  )
82
83
  ]
@@ -4,7 +4,7 @@ import sys
4
4
 
5
5
  from klaude_code.config.config import load_config
6
6
  from klaude_code.config.select_model import match_model_from_config
7
- from klaude_code.trace import log
7
+ from klaude_code.log import log
8
8
 
9
9
 
10
10
  def select_model_interactive(preferred: str | None = None) -> str | None:
@@ -38,7 +38,7 @@ def select_model_interactive(preferred: str | None = None) -> str | None:
38
38
  # Interactive selection
39
39
  from prompt_toolkit.styles import Style
40
40
 
41
- from klaude_code.ui.terminal.selector import build_model_select_items, select_one
41
+ from klaude_code.tui.terminal.selector import build_model_select_items, select_one
42
42
 
43
43
  config = load_config()
44
44
  names = [m.model_name for m in result.filtered_models]
@@ -2,9 +2,10 @@ from importlib.resources import files
2
2
 
3
3
  import yaml
4
4
 
5
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
5
+ from klaude_code.log import log_debug
6
6
  from klaude_code.protocol import commands, message, op
7
- from klaude_code.trace import log_debug
7
+
8
+ from .command_abc import Agent, CommandABC, CommandResult
8
9
 
9
10
 
10
11
  class PromptCommand(CommandABC):
@@ -30,7 +31,7 @@ class PromptCommand(CommandABC):
30
31
  return
31
32
 
32
33
  try:
33
- raw_text = files("klaude_code.command").joinpath(self.template_name).read_text(encoding="utf-8")
34
+ raw_text = files("klaude_code.tui.command").joinpath(self.template_name).read_text(encoding="utf-8")
34
35
 
35
36
  if raw_text.startswith("---"):
36
37
  parts = raw_text.split("---", 2)
@@ -1,6 +1,7 @@
1
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
1
  from klaude_code.protocol import commands, events, message
3
2
 
3
+ from .command_abc import Agent, CommandABC, CommandResult
4
+
4
5
 
5
6
  class RefreshTerminalCommand(CommandABC):
6
7
  """Refresh terminal display"""
@@ -26,6 +27,7 @@ class RefreshTerminalCommand(CommandABC):
26
27
  return CommandResult(
27
28
  events=[
28
29
  events.WelcomeEvent(
30
+ session_id=agent.session.id,
29
31
  work_dir=str(agent.session.work_dir),
30
32
  llm_config=agent.get_llm_client().get_llm_config(),
31
33
  ),
@@ -1,10 +1,11 @@
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
5
- from klaude_code.command.prompt_command import PromptCommand
4
+ from klaude_code.log import log_debug
6
5
  from klaude_code.protocol import commands, events, message, model, op
7
- from klaude_code.trace import log_debug
6
+
7
+ from .command_abc import Agent, CommandResult
8
+ from .prompt_command import PromptCommand
8
9
 
9
10
  if TYPE_CHECKING:
10
11
  from .command_abc import CommandABC
@@ -82,7 +83,7 @@ def register(cmd: "CommandABC") -> None:
82
83
  def load_prompt_commands():
83
84
  """Dynamically load prompt-based commands from the command directory."""
84
85
  try:
85
- command_files = files("klaude_code.command").iterdir()
86
+ command_files = files("klaude_code.tui.command").iterdir()
86
87
  for file_path in command_files:
87
88
  name = file_path.name
88
89
  if (name.startswith("prompt_") or name.startswith("prompt-")) and name.endswith(".md"):
@@ -94,7 +95,7 @@ def load_prompt_commands():
94
95
 
95
96
  def _ensure_commands_loaded() -> None:
96
97
  """Ensure all commands are loaded (lazy initialization)."""
97
- from klaude_code.command import ensure_commands_loaded
98
+ from klaude_code.tui.command import ensure_commands_loaded
98
99
 
99
100
  ensure_commands_loaded()
100
101
 
@@ -183,6 +184,15 @@ async def dispatch_command(user_input: message.UserInputPayload, agent: Agent, *
183
184
  if isinstance(command_identifier, commands.CommandName)
184
185
  else None
185
186
  )
187
+ ui_extra = (
188
+ model.build_command_output_extra(
189
+ command_output.command_name,
190
+ ui_extra=command_output.ui_extra,
191
+ is_error=command_output.is_error,
192
+ )
193
+ if command_output is not None
194
+ else None
195
+ )
186
196
  return CommandResult(
187
197
  events=[
188
198
  events.DeveloperMessageEvent(
@@ -191,7 +201,7 @@ async def dispatch_command(user_input: message.UserInputPayload, agent: Agent, *
191
201
  parts=message.text_parts_from_str(
192
202
  f"Command {command_identifier} error: [{e.__class__.__name__}] {e!s}"
193
203
  ),
194
- command_output=command_output,
204
+ ui_extra=ui_extra,
195
205
  ),
196
206
  )
197
207
  ]
@@ -1,8 +1,9 @@
1
1
  from pathlib import Path
2
2
 
3
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
4
3
  from klaude_code.protocol import commands, events, message, model
5
4
 
5
+ from .command_abc import Agent, CommandABC, CommandResult
6
+
6
7
 
7
8
  def _read_changelog() -> str:
8
9
  """Read CHANGELOG.md from project root."""
@@ -77,7 +78,7 @@ class ReleaseNotesCommand(CommandABC):
77
78
  session_id=agent.session.id,
78
79
  item=message.DeveloperMessage(
79
80
  parts=message.text_parts_from_str(content),
80
- command_output=model.CommandOutput(command_name=self.name),
81
+ ui_extra=model.build_command_output_extra(self.name),
81
82
  ),
82
83
  )
83
84
 
@@ -2,11 +2,12 @@ import asyncio
2
2
 
3
3
  from prompt_toolkit.styles import Style
4
4
 
5
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
5
+ from klaude_code.log import log
6
6
  from klaude_code.protocol import commands, events, message, model, op
7
7
  from klaude_code.session.selector import build_session_select_options, format_user_messages_display
8
- from klaude_code.trace import log
9
- from klaude_code.ui.terminal.selector import SelectItem, select_one
8
+ from klaude_code.tui.terminal.selector import SelectItem, select_one
9
+
10
+ from .command_abc import Agent, CommandABC, CommandResult
10
11
 
11
12
  SESSION_SELECT_STYLE = Style(
12
13
  [
@@ -92,7 +93,7 @@ class ResumeCommand(CommandABC):
92
93
  parts=message.text_parts_from_str(
93
94
  "Cannot resume: current session already has messages. Use `klaude -r` to start a new instance with session selection."
94
95
  ),
95
- command_output=model.CommandOutput(command_name=self.name, is_error=True),
96
+ ui_extra=model.build_command_output_extra(self.name, is_error=True),
96
97
  ),
97
98
  )
98
99
  return CommandResult(events=[event], persist_user_input=False, persist_events=False)
@@ -103,7 +104,7 @@ class ResumeCommand(CommandABC):
103
104
  session_id=agent.session.id,
104
105
  item=message.DeveloperMessage(
105
106
  parts=message.text_parts_from_str("(no session selected)"),
106
- command_output=model.CommandOutput(command_name=self.name),
107
+ ui_extra=model.build_command_output_extra(self.name),
107
108
  ),
108
109
  )
109
110
  return CommandResult(events=[event], persist_user_input=False, persist_events=False)
@@ -1,7 +1,8 @@
1
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
2
1
  from klaude_code.protocol import commands, events, message, model
3
2
  from klaude_code.session.session import Session
4
3
 
4
+ from .command_abc import Agent, CommandABC, CommandResult
5
+
5
6
 
6
7
  class AggregatedUsage(model.BaseModel):
7
8
  """Aggregated usage statistics including per-model breakdown."""
@@ -141,8 +142,8 @@ class StatusCommand(CommandABC):
141
142
  session_id=session.id,
142
143
  item=message.DeveloperMessage(
143
144
  parts=message.text_parts_from_str(format_status_content(aggregated)),
144
- command_output=model.CommandOutput(
145
- command_name=self.name,
145
+ ui_extra=model.build_command_output_extra(
146
+ self.name,
146
147
  ui_extra=model.SessionStatusUIExtra(
147
148
  usage=aggregated.total,
148
149
  task_count=aggregated.task_count,
@@ -2,9 +2,10 @@ import os
2
2
  import subprocess
3
3
  from pathlib import Path
4
4
 
5
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
5
  from klaude_code.protocol import commands, events, message, model
7
6
 
7
+ from .command_abc import Agent, CommandABC, CommandResult
8
+
8
9
 
9
10
  class TerminalSetupCommand(CommandABC):
10
11
  """Setup shift+enter newline functionality in terminal"""
@@ -229,7 +230,7 @@ class TerminalSetupCommand(CommandABC):
229
230
  session_id=agent.session.id,
230
231
  item=message.DeveloperMessage(
231
232
  parts=message.text_parts_from_str(msg),
232
- command_output=model.CommandOutput(command_name=self.name, is_error=False),
233
+ ui_extra=model.build_command_output_extra(self.name),
233
234
  ),
234
235
  )
235
236
  ]
@@ -243,7 +244,7 @@ class TerminalSetupCommand(CommandABC):
243
244
  session_id=agent.session.id,
244
245
  item=message.DeveloperMessage(
245
246
  parts=message.text_parts_from_str(msg),
246
- command_output=model.CommandOutput(command_name=self.name, is_error=True),
247
+ ui_extra=model.build_command_output_extra(self.name, is_error=True),
247
248
  ),
248
249
  )
249
250
  ]
@@ -2,10 +2,11 @@ import asyncio
2
2
 
3
3
  from prompt_toolkit.styles import Style
4
4
 
5
- from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
6
5
  from klaude_code.config.thinking import get_thinking_picker_data, parse_thinking_value
7
6
  from klaude_code.protocol import commands, events, llm_param, message, model, op
8
- from klaude_code.ui.terminal.selector import SelectItem, select_one
7
+ from klaude_code.tui.terminal.selector import SelectItem, select_one
8
+
9
+ from .command_abc import Agent, CommandABC, CommandResult
9
10
 
10
11
  SELECT_STYLE = Style(
11
12
  [
@@ -82,7 +83,7 @@ class ThinkingCommand(CommandABC):
82
83
  session_id=agent.session.id,
83
84
  item=message.DeveloperMessage(
84
85
  parts=message.text_parts_from_str("(no change)"),
85
- command_output=model.CommandOutput(command_name=self.name),
86
+ ui_extra=model.build_command_output_extra(self.name),
86
87
  ),
87
88
  )
88
89
  ]
@@ -0,0 +1,164 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ from rich.console import RenderableType
6
+ from rich.text import Text
7
+
8
+ from klaude_code.protocol import events
9
+
10
+
11
+ @dataclass(frozen=True, slots=True)
12
+ class RenderCommand:
13
+ pass
14
+
15
+
16
+ @dataclass(frozen=True, slots=True)
17
+ class RenderReplayHistory(RenderCommand):
18
+ event: events.ReplayHistoryEvent
19
+
20
+
21
+ @dataclass(frozen=True, slots=True)
22
+ class RenderWelcome(RenderCommand):
23
+ event: events.WelcomeEvent
24
+
25
+
26
+ @dataclass(frozen=True, slots=True)
27
+ class RenderUserMessage(RenderCommand):
28
+ event: events.UserMessageEvent
29
+
30
+
31
+ @dataclass(frozen=True, slots=True)
32
+ class RenderTaskStart(RenderCommand):
33
+ event: events.TaskStartEvent
34
+
35
+
36
+ @dataclass(frozen=True, slots=True)
37
+ class RenderDeveloperMessage(RenderCommand):
38
+ event: events.DeveloperMessageEvent
39
+
40
+
41
+ @dataclass(frozen=True, slots=True)
42
+ class RenderTurnStart(RenderCommand):
43
+ event: events.TurnStartEvent
44
+
45
+
46
+ @dataclass(frozen=True, slots=True)
47
+ class RenderAssistantImage(RenderCommand):
48
+ session_id: str
49
+ file_path: str
50
+
51
+
52
+ @dataclass(frozen=True, slots=True)
53
+ class RenderToolCall(RenderCommand):
54
+ event: events.ToolCallEvent
55
+
56
+
57
+ @dataclass(frozen=True, slots=True)
58
+ class RenderToolResult(RenderCommand):
59
+ event: events.ToolResultEvent
60
+ is_sub_agent_session: bool
61
+
62
+
63
+ @dataclass(frozen=True, slots=True)
64
+ class RenderTaskMetadata(RenderCommand):
65
+ event: events.TaskMetadataEvent
66
+
67
+
68
+ @dataclass(frozen=True, slots=True)
69
+ class RenderTaskFinish(RenderCommand):
70
+ event: events.TaskFinishEvent
71
+
72
+
73
+ @dataclass(frozen=True, slots=True)
74
+ class RenderInterrupt(RenderCommand):
75
+ session_id: str
76
+
77
+
78
+ @dataclass(frozen=True, slots=True)
79
+ class RenderError(RenderCommand):
80
+ event: events.ErrorEvent
81
+
82
+
83
+ @dataclass(frozen=True, slots=True)
84
+ class StartThinkingStream(RenderCommand):
85
+ session_id: str
86
+
87
+
88
+ @dataclass(frozen=True, slots=True)
89
+ class AppendThinking(RenderCommand):
90
+ session_id: str
91
+ content: str
92
+
93
+
94
+ @dataclass(frozen=True, slots=True)
95
+ class EndThinkingStream(RenderCommand):
96
+ session_id: str
97
+
98
+
99
+ @dataclass(frozen=True, slots=True)
100
+ class StartAssistantStream(RenderCommand):
101
+ session_id: str
102
+
103
+
104
+ @dataclass(frozen=True, slots=True)
105
+ class AppendAssistant(RenderCommand):
106
+ session_id: str
107
+ content: str
108
+
109
+
110
+ @dataclass(frozen=True, slots=True)
111
+ class EndAssistantStream(RenderCommand):
112
+ session_id: str
113
+
114
+
115
+ @dataclass(frozen=True, slots=True)
116
+ class RenderThinkingHeader(RenderCommand):
117
+ session_id: str
118
+ header: str
119
+
120
+
121
+ @dataclass(frozen=True, slots=True)
122
+ class SpinnerStart(RenderCommand):
123
+ pass
124
+
125
+
126
+ @dataclass(frozen=True, slots=True)
127
+ class SpinnerStop(RenderCommand):
128
+ pass
129
+
130
+
131
+ @dataclass(frozen=True, slots=True)
132
+ class SpinnerUpdate(RenderCommand):
133
+ status_text: str | Text
134
+ right_text: RenderableType | None
135
+
136
+
137
+ @dataclass(frozen=True, slots=True)
138
+ class PrintBlankLine(RenderCommand):
139
+ pass
140
+
141
+
142
+ @dataclass(frozen=True, slots=True)
143
+ class PrintRuleLine(RenderCommand):
144
+ pass
145
+
146
+
147
+ @dataclass(frozen=True, slots=True)
148
+ class EmitOsc94Error(RenderCommand):
149
+ pass
150
+
151
+
152
+ @dataclass(frozen=True, slots=True)
153
+ class EmitTmuxSignal(RenderCommand):
154
+ pass
155
+
156
+
157
+ @dataclass(frozen=True, slots=True)
158
+ class TaskClockStart(RenderCommand):
159
+ pass
160
+
161
+
162
+ @dataclass(frozen=True, slots=True)
163
+ class TaskClockClear(RenderCommand):
164
+ pass
@@ -3,9 +3,9 @@ from rich.padding import Padding
3
3
  from rich.text import Text
4
4
 
5
5
  from klaude_code.const import MARKDOWN_RIGHT_MARGIN
6
- from klaude_code.ui.renderers.common import create_grid
7
- from klaude_code.ui.rich.markdown import NoInsetMarkdown
8
- from klaude_code.ui.rich.theme import ThemeKey
6
+ from klaude_code.tui.components.common import create_grid
7
+ from klaude_code.tui.components.rich.markdown import NoInsetMarkdown
8
+ from klaude_code.tui.components.rich.theme import ThemeKey
9
9
 
10
10
  # UI markers
11
11
  ASSISTANT_MESSAGE_MARK = "•"
@@ -8,8 +8,8 @@ from pygments.token import Token
8
8
  from rich.text import Text
9
9
 
10
10
  from klaude_code.const import BASH_MULTILINE_STRING_TRUNCATE_MAX_LINES
11
- from klaude_code.ui.renderers.common import truncate_head
12
- from klaude_code.ui.rich.theme import ThemeKey
11
+ from klaude_code.tui.components.common import truncate_head
12
+ from klaude_code.tui.components.rich.theme import ThemeKey
13
13
 
14
14
  # Token types for bash syntax highlighting
15
15
  _STRING_TOKENS = frozenset(
@@ -11,7 +11,7 @@ from klaude_code.const import (
11
11
  TRUNCATE_DISPLAY_MAX_LINES,
12
12
  TRUNCATE_HEAD_MAX_LINES,
13
13
  )
14
- from klaude_code.ui.rich.theme import ThemeKey
14
+ from klaude_code.tui.components.rich.theme import ThemeKey
15
15
 
16
16
 
17
17
  def create_grid(*, overflow: Literal["fold", "crop", "ellipsis", "ignore"] = "fold") -> Table: