klaude-code 1.2.1__py3-none-any.whl → 1.2.3__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 (140) hide show
  1. klaude_code/cli/main.py +9 -4
  2. klaude_code/cli/runtime.py +42 -43
  3. klaude_code/command/__init__.py +7 -5
  4. klaude_code/command/clear_cmd.py +6 -29
  5. klaude_code/command/command_abc.py +44 -8
  6. klaude_code/command/diff_cmd.py +33 -27
  7. klaude_code/command/export_cmd.py +18 -26
  8. klaude_code/command/help_cmd.py +10 -8
  9. klaude_code/command/model_cmd.py +11 -40
  10. klaude_code/command/{prompt-update-dev-doc.md → prompt-dev-docs-update.md} +3 -2
  11. klaude_code/command/{prompt-dev-doc.md → prompt-dev-docs.md} +3 -2
  12. klaude_code/command/prompt-init.md +2 -5
  13. klaude_code/command/prompt_command.py +6 -6
  14. klaude_code/command/refresh_cmd.py +4 -5
  15. klaude_code/command/registry.py +16 -19
  16. klaude_code/command/terminal_setup_cmd.py +12 -11
  17. klaude_code/config/__init__.py +4 -0
  18. klaude_code/config/config.py +25 -26
  19. klaude_code/config/list_model.py +8 -3
  20. klaude_code/config/select_model.py +1 -1
  21. klaude_code/const/__init__.py +1 -1
  22. klaude_code/core/__init__.py +0 -3
  23. klaude_code/core/agent.py +25 -50
  24. klaude_code/core/executor.py +268 -101
  25. klaude_code/core/prompt.py +12 -12
  26. klaude_code/core/{prompt → prompts}/prompt-gemini.md +1 -1
  27. klaude_code/core/reminders.py +76 -95
  28. klaude_code/core/task.py +21 -14
  29. klaude_code/core/tool/__init__.py +45 -11
  30. klaude_code/core/tool/file/apply_patch.py +5 -1
  31. klaude_code/core/tool/file/apply_patch_tool.py +11 -13
  32. klaude_code/core/tool/file/edit_tool.py +27 -23
  33. klaude_code/core/tool/file/multi_edit_tool.py +15 -17
  34. klaude_code/core/tool/file/read_tool.py +41 -36
  35. klaude_code/core/tool/file/write_tool.py +13 -15
  36. klaude_code/core/tool/memory/memory_tool.py +85 -68
  37. klaude_code/core/tool/memory/skill_tool.py +10 -12
  38. klaude_code/core/tool/shell/bash_tool.py +24 -22
  39. klaude_code/core/tool/shell/command_safety.py +12 -1
  40. klaude_code/core/tool/sub_agent_tool.py +11 -12
  41. klaude_code/core/tool/todo/todo_write_tool.py +21 -28
  42. klaude_code/core/tool/todo/update_plan_tool.py +14 -24
  43. klaude_code/core/tool/tool_abc.py +3 -4
  44. klaude_code/core/tool/tool_context.py +7 -7
  45. klaude_code/core/tool/tool_registry.py +30 -47
  46. klaude_code/core/tool/tool_runner.py +35 -43
  47. klaude_code/core/tool/truncation.py +14 -20
  48. klaude_code/core/tool/web/mermaid_tool.py +12 -14
  49. klaude_code/core/tool/web/web_fetch_tool.py +15 -17
  50. klaude_code/core/turn.py +19 -7
  51. klaude_code/llm/__init__.py +3 -4
  52. klaude_code/llm/anthropic/client.py +30 -46
  53. klaude_code/llm/anthropic/input.py +4 -11
  54. klaude_code/llm/client.py +29 -8
  55. klaude_code/llm/input_common.py +66 -36
  56. klaude_code/llm/openai_compatible/client.py +42 -84
  57. klaude_code/llm/openai_compatible/input.py +11 -16
  58. klaude_code/llm/openai_compatible/tool_call_accumulator.py +2 -2
  59. klaude_code/llm/openrouter/client.py +40 -289
  60. klaude_code/llm/openrouter/input.py +13 -35
  61. klaude_code/llm/openrouter/reasoning_handler.py +209 -0
  62. klaude_code/llm/registry.py +5 -75
  63. klaude_code/llm/responses/client.py +34 -55
  64. klaude_code/llm/responses/input.py +24 -26
  65. klaude_code/llm/usage.py +109 -0
  66. klaude_code/protocol/__init__.py +4 -0
  67. klaude_code/protocol/events.py +3 -2
  68. klaude_code/protocol/{llm_parameter.py → llm_param.py} +12 -32
  69. klaude_code/protocol/model.py +49 -4
  70. klaude_code/protocol/op.py +18 -16
  71. klaude_code/protocol/op_handler.py +28 -0
  72. klaude_code/{core → protocol}/sub_agent.py +7 -0
  73. klaude_code/session/export.py +150 -70
  74. klaude_code/session/session.py +28 -14
  75. klaude_code/session/templates/export_session.html +180 -42
  76. klaude_code/trace/__init__.py +2 -2
  77. klaude_code/trace/log.py +11 -5
  78. klaude_code/ui/__init__.py +91 -8
  79. klaude_code/ui/core/__init__.py +1 -0
  80. klaude_code/ui/core/display.py +103 -0
  81. klaude_code/ui/core/input.py +71 -0
  82. klaude_code/ui/modes/__init__.py +1 -0
  83. klaude_code/ui/modes/debug/__init__.py +1 -0
  84. klaude_code/ui/{base/debug_event_display.py → modes/debug/display.py} +9 -5
  85. klaude_code/ui/modes/exec/__init__.py +1 -0
  86. klaude_code/ui/{base/exec_display.py → modes/exec/display.py} +28 -2
  87. klaude_code/ui/{repl → modes/repl}/__init__.py +5 -6
  88. klaude_code/ui/modes/repl/clipboard.py +152 -0
  89. klaude_code/ui/modes/repl/completers.py +429 -0
  90. klaude_code/ui/modes/repl/display.py +60 -0
  91. klaude_code/ui/modes/repl/event_handler.py +375 -0
  92. klaude_code/ui/modes/repl/input_prompt_toolkit.py +198 -0
  93. klaude_code/ui/modes/repl/key_bindings.py +170 -0
  94. klaude_code/ui/{repl → modes/repl}/renderer.py +109 -132
  95. klaude_code/ui/renderers/assistant.py +21 -0
  96. klaude_code/ui/renderers/common.py +0 -16
  97. klaude_code/ui/renderers/developer.py +18 -18
  98. klaude_code/ui/renderers/diffs.py +36 -14
  99. klaude_code/ui/renderers/errors.py +1 -1
  100. klaude_code/ui/renderers/metadata.py +50 -27
  101. klaude_code/ui/renderers/sub_agent.py +43 -9
  102. klaude_code/ui/renderers/thinking.py +33 -1
  103. klaude_code/ui/renderers/tools.py +212 -20
  104. klaude_code/ui/renderers/user_input.py +19 -23
  105. klaude_code/ui/rich/__init__.py +1 -0
  106. klaude_code/ui/{rich_ext → rich}/searchable_text.py +3 -1
  107. klaude_code/ui/{renderers → rich}/status.py +29 -18
  108. klaude_code/ui/{base → rich}/theme.py +8 -2
  109. klaude_code/ui/terminal/__init__.py +1 -0
  110. klaude_code/ui/{base/terminal_color.py → terminal/color.py} +4 -1
  111. klaude_code/ui/{base/terminal_control.py → terminal/control.py} +1 -0
  112. klaude_code/ui/{base/terminal_notifier.py → terminal/notifier.py} +5 -2
  113. klaude_code/ui/utils/__init__.py +1 -0
  114. klaude_code/ui/{base/utils.py → utils/common.py} +35 -3
  115. {klaude_code-1.2.1.dist-info → klaude_code-1.2.3.dist-info}/METADATA +1 -1
  116. klaude_code-1.2.3.dist-info/RECORD +161 -0
  117. klaude_code/core/clipboard_manifest.py +0 -124
  118. klaude_code/llm/openrouter/tool_call_accumulator.py +0 -80
  119. klaude_code/ui/base/__init__.py +0 -1
  120. klaude_code/ui/base/display_abc.py +0 -36
  121. klaude_code/ui/base/input_abc.py +0 -20
  122. klaude_code/ui/repl/display.py +0 -36
  123. klaude_code/ui/repl/event_handler.py +0 -247
  124. klaude_code/ui/repl/input.py +0 -773
  125. klaude_code/ui/rich_ext/__init__.py +0 -1
  126. klaude_code-1.2.1.dist-info/RECORD +0 -151
  127. /klaude_code/core/{prompt → prompts}/prompt-claude-code.md +0 -0
  128. /klaude_code/core/{prompt → prompts}/prompt-codex.md +0 -0
  129. /klaude_code/core/{prompt → prompts}/prompt-subagent-explore.md +0 -0
  130. /klaude_code/core/{prompt → prompts}/prompt-subagent-oracle.md +0 -0
  131. /klaude_code/core/{prompt → prompts}/prompt-subagent-webfetch.md +0 -0
  132. /klaude_code/core/{prompt → prompts}/prompt-subagent.md +0 -0
  133. /klaude_code/ui/{base → core}/stage_manager.py +0 -0
  134. /klaude_code/ui/{rich_ext → rich}/live.py +0 -0
  135. /klaude_code/ui/{rich_ext → rich}/markdown.py +0 -0
  136. /klaude_code/ui/{rich_ext → rich}/quote.py +0 -0
  137. /klaude_code/ui/{base → terminal}/progress_bar.py +0 -0
  138. /klaude_code/ui/{base → utils}/debouncer.py +0 -0
  139. {klaude_code-1.2.1.dist-info → klaude_code-1.2.3.dist-info}/WHEEL +0 -0
  140. {klaude_code-1.2.1.dist-info → klaude_code-1.2.3.dist-info}/entry_points.txt +0 -0
@@ -1,15 +1,10 @@
1
1
  import asyncio
2
2
 
3
- from klaude_code.command.command_abc import CommandABC, CommandResult
3
+ from klaude_code.command.command_abc import CommandABC, CommandResult, InputAction
4
4
  from klaude_code.command.registry import register_command
5
- from klaude_code.config import load_config
6
- from klaude_code.config.select_model import select_model_from_config
7
- from klaude_code.core import Agent
8
- from klaude_code.llm.registry import create_llm_client
9
- from klaude_code.protocol.commands import CommandName
10
- from klaude_code.protocol.events import DeveloperMessageEvent, WelcomeEvent
11
- from klaude_code.protocol.model import CommandOutput, DeveloperMessageItem
12
- from klaude_code.trace import DebugType, log_debug
5
+ from klaude_code.config import select_model_from_config
6
+ from klaude_code.core.agent import Agent
7
+ from klaude_code.protocol import commands, events, model
13
8
 
14
9
 
15
10
  @register_command
@@ -17,8 +12,8 @@ class ModelCommand(CommandABC):
17
12
  """Display or change the model configuration."""
18
13
 
19
14
  @property
20
- def name(self) -> CommandName:
21
- return CommandName.MODEL
15
+ def name(self) -> commands.CommandName:
16
+ return commands.CommandName.MODEL
22
17
 
23
18
  @property
24
19
  def summary(self) -> str:
@@ -35,38 +30,14 @@ class ModelCommand(CommandABC):
35
30
  if selected_model is None or selected_model == current_model:
36
31
  return CommandResult(
37
32
  events=[
38
- DeveloperMessageEvent(
33
+ events.DeveloperMessageEvent(
39
34
  session_id=agent.session.id,
40
- item=DeveloperMessageItem(
41
- content="(no change)", command_output=CommandOutput(command_name=self.name)
35
+ item=model.DeveloperMessageItem(
36
+ content="(no change)",
37
+ command_output=model.CommandOutput(command_name=self.name),
42
38
  ),
43
39
  )
44
40
  ]
45
41
  )
46
42
 
47
- config = load_config()
48
- assert config is not None
49
- llm_config = config.get_model_config(selected_model)
50
-
51
- log_debug(
52
- "Updated LLM config",
53
- llm_config.model_dump_json(exclude_none=True),
54
- style="yellow",
55
- debug_type=DebugType.LLM_CONFIG,
56
- )
57
-
58
- llm_client = create_llm_client(llm_config)
59
- agent.set_model_profile(agent.build_model_profile(llm_client))
60
-
61
- return CommandResult(
62
- events=[
63
- DeveloperMessageEvent(
64
- session_id=agent.session.id,
65
- item=DeveloperMessageItem(
66
- content=f"switched to model: {selected_model}",
67
- command_output=CommandOutput(command_name=self.name),
68
- ),
69
- ),
70
- WelcomeEvent(llm_config=llm_config, work_dir=str(agent.session.work_dir)),
71
- ]
72
- )
43
+ return CommandResult(actions=[InputAction.change_model(selected_model)])
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Update dev documentation before context compaction
3
- argument-hint: Optional - specific context or tasks to focus on (leave empty for comprehensive update)
3
+ from: https://github.com/diet103/claude-code-infrastructure-showcase/blob/main/.claude/commands/dev-docs-update.md
4
4
  ---
5
5
 
6
6
  We're approaching context limits. Please update the development documentation to ensure seamless continuation after context reset.
@@ -50,6 +50,7 @@ If switching to a new conversation:
50
50
  - Any uncommitted changes that need attention
51
51
  - Test commands to verify work
52
52
 
53
- ## Additional Context: $ARGUMENTS
53
+ ## Additional Context:
54
+ $ARGUMENTS
54
55
 
55
56
  **Priority**: Focus on capturing information that would be hard to rediscover or reconstruct from code alone.
@@ -1,9 +1,10 @@
1
1
  ---
2
2
  description: Create a comprehensive strategic plan with structured task breakdown
3
- argument-hint: Describe what you need planned (e.g., "refactor authentication system", "implement microservices")
3
+ from: https://github.com/diet103/claude-code-infrastructure-showcase/blob/main/.claude/commands/dev-docs.md
4
4
  ---
5
5
 
6
- You are an elite strategic planning specialist. Create a comprehensive, actionable plan for: $ARGUMENTS
6
+ Create a comprehensive, actionable plan for:
7
+ $ARGUMENTS
7
8
 
8
9
  ## Instructions
9
10
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: Create an AGENTS.md file with instructions for agent
3
- argument-hint: Additional user instructions
3
+ from: https://github.com/openai/codex/blob/main/codex-rs/tui/prompt_for_init_command.md
4
4
  ---
5
5
 
6
6
  Generate/Update a file named AGENTS.md that serves as a contributor guide for this repository.
@@ -42,7 +42,4 @@ Commit & Pull Request Guidelines
42
42
  - Summarize commit message conventions found in the project’s Git history.
43
43
  - Outline pull request requirements (descriptions, linked issues, screenshots, etc.).
44
44
 
45
- (Optional) Add other sections if relevant, such as Security & Configuration Tips, Architecture Overview, or Agent-Specific Instructions.
46
-
47
- Additional Instructions:
48
- $ARGUMENTS
45
+ (Optional) Add other sections if relevant, such as Security & Configuration Tips, Architecture Overview, or Agent-Specific Instructions.
@@ -2,9 +2,9 @@ from importlib.resources import files
2
2
 
3
3
  import yaml
4
4
 
5
- from klaude_code.command.command_abc import CommandABC, CommandResult
6
- from klaude_code.core import Agent
7
- from klaude_code.protocol.commands import CommandName
5
+ from klaude_code.command.command_abc import CommandABC, CommandResult, InputAction
6
+ from klaude_code.core.agent import Agent
7
+ from klaude_code.protocol import commands
8
8
 
9
9
 
10
10
  class PromptCommand(CommandABC):
@@ -17,7 +17,7 @@ class PromptCommand(CommandABC):
17
17
  self._metadata: dict[str, str] = {}
18
18
 
19
19
  @property
20
- def name(self) -> str | CommandName:
20
+ def name(self) -> str | commands.CommandName:
21
21
  return self._command_name
22
22
 
23
23
  @property
@@ -57,7 +57,7 @@ class PromptCommand(CommandABC):
57
57
  async def run(self, raw: str, agent: Agent) -> CommandResult:
58
58
  self._ensure_loaded()
59
59
  template_content = self._content or ""
60
- user_input = raw.strip()
60
+ user_input = raw.strip() or "<none>"
61
61
 
62
62
  if "$ARGUMENTS" in template_content:
63
63
  final_prompt = template_content.replace("$ARGUMENTS", user_input)
@@ -66,4 +66,4 @@ class PromptCommand(CommandABC):
66
66
  if user_input:
67
67
  final_prompt += f"\n\nAdditional Instructions:\n{user_input}"
68
68
 
69
- return CommandResult(agent_input=final_prompt)
69
+ return CommandResult(actions=[InputAction.run_agent(final_prompt)])
@@ -1,8 +1,7 @@
1
1
  from klaude_code.command.command_abc import CommandABC, CommandResult
2
2
  from klaude_code.command.registry import register_command
3
- from klaude_code.core import Agent
4
- from klaude_code.protocol import events
5
- from klaude_code.protocol.commands import CommandName
3
+ from klaude_code.core.agent import Agent
4
+ from klaude_code.protocol import commands, events
6
5
 
7
6
 
8
7
  @register_command
@@ -10,8 +9,8 @@ class RefreshTerminalCommand(CommandABC):
10
9
  """Refresh terminal display"""
11
10
 
12
11
  @property
13
- def name(self) -> CommandName:
14
- return CommandName.REFRESH_TERMINAL
12
+ def name(self) -> commands.CommandName:
13
+ return commands.CommandName.REFRESH_TERMINAL
15
14
 
16
15
  @property
17
16
  def summary(self) -> str:
@@ -1,17 +1,15 @@
1
1
  from importlib.resources import files
2
2
  from typing import TYPE_CHECKING, TypeVar
3
3
 
4
- from klaude_code.command.command_abc import CommandResult
4
+ from klaude_code.command.command_abc import CommandResult, InputAction
5
5
  from klaude_code.command.prompt_command import PromptCommand
6
6
  from klaude_code.core.agent import Agent
7
- from klaude_code.protocol.commands import CommandName
8
- from klaude_code.protocol.events import DeveloperMessageEvent
9
- from klaude_code.protocol.model import CommandOutput, DeveloperMessageItem
7
+ from klaude_code.protocol import commands, events, model
10
8
 
11
9
  if TYPE_CHECKING:
12
10
  from .command_abc import CommandABC
13
11
 
14
- _COMMANDS: dict[CommandName | str, "CommandABC"] = {}
12
+ _COMMANDS: dict[commands.CommandName | str, "CommandABC"] = {}
15
13
 
16
14
  T = TypeVar("T", bound="CommandABC")
17
15
 
@@ -37,20 +35,19 @@ def load_prompt_commands():
37
35
  pass
38
36
 
39
37
 
40
- def get_commands() -> dict[CommandName | str, "CommandABC"]:
38
+ def get_commands() -> dict[commands.CommandName | str, "CommandABC"]:
41
39
  """Get all registered commands."""
42
40
  return _COMMANDS.copy()
43
41
 
44
42
 
45
- def get_command_names() -> list[str]:
46
- """Get all registered command names for completion."""
47
- return [str(k) for k in _COMMANDS.keys()]
43
+ def is_slash_command_name(name: str) -> bool:
44
+ return name in _COMMANDS
48
45
 
49
46
 
50
47
  async def dispatch_command(raw: str, agent: Agent) -> CommandResult:
51
48
  # Detect command name
52
49
  if not raw.startswith("/"):
53
- return CommandResult(agent_input=raw)
50
+ return CommandResult(actions=[InputAction.run_agent(raw)])
54
51
 
55
52
  splits = raw.split(" ", maxsplit=1)
56
53
  command_name_raw = splits[0][1:]
@@ -65,31 +62,31 @@ async def dispatch_command(raw: str, agent: Agent) -> CommandResult:
65
62
  else:
66
63
  # Then try Enum conversion for standard commands
67
64
  try:
68
- enum_key = CommandName(command_name_raw)
65
+ enum_key = commands.CommandName(command_name_raw)
69
66
  if enum_key in _COMMANDS:
70
67
  command_key = enum_key
71
68
  except ValueError:
72
69
  pass
73
70
 
74
71
  if command_key is None:
75
- return CommandResult(agent_input=raw)
72
+ return CommandResult(actions=[InputAction.run_agent(raw)])
76
73
 
77
74
  command = _COMMANDS[command_key]
78
- command_identifier: CommandName | str = command.name
75
+ command_identifier: commands.CommandName | str = command.name
79
76
 
80
77
  try:
81
78
  return await command.run(rest, agent)
82
79
  except Exception as e:
83
80
  command_output = (
84
- CommandOutput(command_name=command_identifier, is_error=True)
85
- if isinstance(command_identifier, CommandName)
81
+ model.CommandOutput(command_name=command_identifier, is_error=True)
82
+ if isinstance(command_identifier, commands.CommandName)
86
83
  else None
87
84
  )
88
85
  return CommandResult(
89
86
  events=[
90
- DeveloperMessageEvent(
87
+ events.DeveloperMessageEvent(
91
88
  session_id=agent.session.id,
92
- item=DeveloperMessageItem(
89
+ item=model.DeveloperMessageItem(
93
90
  content=f"Command {command_identifier} error: [{e.__class__.__name__}] {str(e)}",
94
91
  command_output=command_output,
95
92
  ),
@@ -98,13 +95,13 @@ async def dispatch_command(raw: str, agent: Agent) -> CommandResult:
98
95
  )
99
96
 
100
97
 
101
- def is_interactive_command(raw: str) -> bool:
98
+ def has_interactive_command(raw: str) -> bool:
102
99
  if not raw.startswith("/"):
103
100
  return False
104
101
  splits = raw.split(" ", maxsplit=1)
105
102
  command_name_raw = splits[0][1:]
106
103
  try:
107
- command_name = CommandName(command_name_raw)
104
+ command_name = commands.CommandName(command_name_raw)
108
105
  except ValueError:
109
106
  return False
110
107
  if command_name not in _COMMANDS:
@@ -4,10 +4,8 @@ from pathlib import Path
4
4
 
5
5
  from klaude_code.command.command_abc import CommandABC, CommandResult
6
6
  from klaude_code.command.registry import register_command
7
- from klaude_code.core import Agent
8
- from klaude_code.protocol import events
9
- from klaude_code.protocol.commands import CommandName
10
- from klaude_code.protocol.model import CommandOutput, DeveloperMessageItem
7
+ from klaude_code.core.agent import Agent
8
+ from klaude_code.protocol import commands, events, model
11
9
 
12
10
 
13
11
  @register_command
@@ -15,8 +13,8 @@ class TerminalSetupCommand(CommandABC):
15
13
  """Setup shift+enter newline functionality in terminal"""
16
14
 
17
15
  @property
18
- def name(self) -> CommandName:
19
- return CommandName.TERMINAL_SETUP
16
+ def name(self) -> commands.CommandName:
17
+ return commands.CommandName.TERMINAL_SETUP
20
18
 
21
19
  @property
22
20
  def summary(self) -> str:
@@ -197,7 +195,10 @@ class TerminalSetupCommand(CommandABC):
197
195
  return True, "appended mapping"
198
196
 
199
197
  # Not an array – avoid modifying to prevent corrupting user config
200
- return False, "unsupported keybindings.json format (not an array); please add mapping manually"
198
+ return (
199
+ False,
200
+ "unsupported keybindings.json format (not an array); please add mapping manually",
201
+ )
201
202
 
202
203
  def _setup_generic(self, term_program: str) -> str:
203
204
  """Provide generic manual configuration guide for unknown or unsupported terminals"""
@@ -228,9 +229,9 @@ class TerminalSetupCommand(CommandABC):
228
229
  events=[
229
230
  events.DeveloperMessageEvent(
230
231
  session_id=agent.session.id,
231
- item=DeveloperMessageItem(
232
+ item=model.DeveloperMessageItem(
232
233
  content=message,
233
- command_output=CommandOutput(command_name=self.name, is_error=False),
234
+ command_output=model.CommandOutput(command_name=self.name, is_error=False),
234
235
  ),
235
236
  )
236
237
  ]
@@ -242,9 +243,9 @@ class TerminalSetupCommand(CommandABC):
242
243
  events=[
243
244
  events.DeveloperMessageEvent(
244
245
  session_id=agent.session.id,
245
- item=DeveloperMessageItem(
246
+ item=model.DeveloperMessageItem(
246
247
  content=message,
247
- command_output=CommandOutput(command_name=self.name, is_error=True),
248
+ command_output=model.CommandOutput(command_name=self.name, is_error=True),
248
249
  ),
249
250
  )
250
251
  ]
@@ -1,7 +1,11 @@
1
1
  from .config import Config, config_path, load_config
2
+ from .list_model import display_models_and_providers
3
+ from .select_model import select_model_from_config
2
4
 
3
5
  __all__ = [
4
6
  "Config",
5
7
  "load_config",
6
8
  "config_path",
9
+ "display_models_and_providers",
10
+ "select_model_from_config",
7
11
  ]
@@ -6,15 +6,8 @@ from typing import Any, cast
6
6
  import yaml
7
7
  from pydantic import BaseModel, Field, ValidationError, model_validator
8
8
 
9
- from klaude_code.core.sub_agent import iter_sub_agent_profiles
10
- from klaude_code.protocol.llm_parameter import (
11
- LLMClientProtocol,
12
- LLMConfigModelParameter,
13
- LLMConfigParameter,
14
- LLMConfigProviderParameter,
15
- OpenRouterProviderRouting,
16
- Thinking,
17
- )
9
+ from klaude_code.protocol import llm_param
10
+ from klaude_code.protocol.sub_agent import iter_sub_agent_profiles
18
11
  from klaude_code.trace import log
19
12
 
20
13
  config_path = Path.home() / ".klaude" / "klaude-config.yaml"
@@ -23,11 +16,11 @@ config_path = Path.home() / ".klaude" / "klaude-config.yaml"
23
16
  class ModelConfig(BaseModel):
24
17
  model_name: str
25
18
  provider: str
26
- model_params: LLMConfigModelParameter
19
+ model_params: llm_param.LLMConfigModelParameter
27
20
 
28
21
 
29
22
  class Config(BaseModel):
30
- provider_list: list[LLMConfigProviderParameter]
23
+ provider_list: list[llm_param.LLMConfigProviderParameter]
31
24
  model_list: list[ModelConfig]
32
25
  main_model: str
33
26
  subagent_models: dict[str, str] = Field(default_factory=dict)
@@ -46,10 +39,10 @@ class Config(BaseModel):
46
39
  data["subagent_models"] = normalized
47
40
  return data
48
41
 
49
- def get_main_model_config(self) -> LLMConfigParameter:
42
+ def get_main_model_config(self) -> llm_param.LLMConfigParameter:
50
43
  return self.get_model_config(self.main_model)
51
44
 
52
- def get_model_config(self, model_name: str) -> LLMConfigParameter:
45
+ def get_model_config(self, model_name: str) -> llm_param.LLMConfigParameter:
53
46
  model = next(
54
47
  (model for model in self.model_list if model.model_name == model_name),
55
48
  None,
@@ -64,7 +57,7 @@ class Config(BaseModel):
64
57
  if provider is None:
65
58
  raise ValueError(f"Unknown provider: {model.provider}")
66
59
 
67
- return LLMConfigParameter(
60
+ return llm_param.LLMConfigParameter(
68
61
  **provider.model_dump(),
69
62
  **model.model_params.model_dump(),
70
63
  )
@@ -88,15 +81,15 @@ def get_example_config() -> Config:
88
81
  main_model="gpt-5.1",
89
82
  subagent_models={"explore": "haiku", "oracle": "gpt-5.1-high"},
90
83
  provider_list=[
91
- LLMConfigProviderParameter(
84
+ llm_param.LLMConfigProviderParameter(
92
85
  provider_name="openai",
93
- protocol=LLMClientProtocol.RESPONSES,
86
+ protocol=llm_param.LLMClientProtocol.RESPONSES,
94
87
  api_key="your-openai-api-key",
95
88
  base_url="https://api.openai.com/v1",
96
89
  ),
97
- LLMConfigProviderParameter(
90
+ llm_param.LLMConfigProviderParameter(
98
91
  provider_name="openrouter",
99
- protocol=LLMClientProtocol.OPENROUTER,
92
+ protocol=llm_param.LLMClientProtocol.OPENROUTER,
100
93
  api_key="your-openrouter-api-key",
101
94
  ),
102
95
  ],
@@ -104,12 +97,15 @@ def get_example_config() -> Config:
104
97
  ModelConfig(
105
98
  model_name="gpt-5.1",
106
99
  provider="openai",
107
- model_params=LLMConfigModelParameter(
100
+ model_params=llm_param.LLMConfigModelParameter(
108
101
  model="gpt-5.1-2025-11-13",
109
102
  max_tokens=32000,
110
103
  verbosity="medium",
111
- thinking=Thinking(
112
- reasoning_effort="medium", reasoning_summary="auto", type="enabled", budget_tokens=None
104
+ thinking=llm_param.Thinking(
105
+ reasoning_effort="medium",
106
+ reasoning_summary="auto",
107
+ type="enabled",
108
+ budget_tokens=None,
113
109
  ),
114
110
  context_limit=368000,
115
111
  ),
@@ -117,12 +113,15 @@ def get_example_config() -> Config:
117
113
  ModelConfig(
118
114
  model_name="gpt-5.1-high",
119
115
  provider="openai",
120
- model_params=LLMConfigModelParameter(
116
+ model_params=llm_param.LLMConfigModelParameter(
121
117
  model="gpt-5.1-2025-11-13",
122
118
  max_tokens=32000,
123
119
  verbosity="medium",
124
- thinking=Thinking(
125
- reasoning_effort="high", reasoning_summary="auto", type="enabled", budget_tokens=None
120
+ thinking=llm_param.Thinking(
121
+ reasoning_effort="high",
122
+ reasoning_summary="auto",
123
+ type="enabled",
124
+ budget_tokens=None,
126
125
  ),
127
126
  context_limit=368000,
128
127
  ),
@@ -130,10 +129,10 @@ def get_example_config() -> Config:
130
129
  ModelConfig(
131
130
  model_name="haiku",
132
131
  provider="openrouter",
133
- model_params=LLMConfigModelParameter(
132
+ model_params=llm_param.LLMConfigModelParameter(
134
133
  model="anthropic/claude-haiku-4.5",
135
134
  max_tokens=32000,
136
- provider_routing=OpenRouterProviderRouting(
135
+ provider_routing=llm_param.OpenRouterProviderRouting(
137
136
  sort="throughput",
138
137
  ),
139
138
  context_limit=168000,
@@ -4,8 +4,8 @@ from rich.table import Table
4
4
  from rich.text import Text
5
5
 
6
6
  from klaude_code.config import Config
7
- from klaude_code.core.sub_agent import iter_sub_agent_profiles
8
- from klaude_code.ui.base.theme import ThemeKey, get_theme
7
+ from klaude_code.protocol.sub_agent import iter_sub_agent_profiles
8
+ from klaude_code.ui.rich.theme import ThemeKey, get_theme
9
9
 
10
10
 
11
11
  def mask_api_key(api_key: str | None) -> str:
@@ -143,7 +143,12 @@ def display_models_and_providers(config: Config):
143
143
 
144
144
  # Display main model info
145
145
  console.print()
146
- console.print(Text.assemble(("Default Model: ", "bold"), (config.main_model, ThemeKey.CONFIG_STATUS_PRIMARY)))
146
+ console.print(
147
+ Text.assemble(
148
+ ("Default Model: ", "bold"),
149
+ (config.main_model, ThemeKey.CONFIG_STATUS_PRIMARY),
150
+ )
151
+ )
147
152
 
148
153
  for profile in iter_sub_agent_profiles():
149
154
  sub_model_name = config.subagent_models.get(profile.name)
@@ -1,6 +1,6 @@
1
1
  from klaude_code.config.config import load_config
2
2
  from klaude_code.trace import log
3
- from klaude_code.ui.rich_ext.searchable_text import SearchableFormattedList
3
+ from klaude_code.ui.rich.searchable_text import SearchableFormattedList
4
4
 
5
5
 
6
6
  def select_model_from_config(preferred: str | None = None) -> str | None:
@@ -109,7 +109,7 @@ STATUS_SHIMMER_PADDING = 10
109
109
  # Duration in seconds for one full shimmer sweep across the text
110
110
  STATUS_SHIMMER_SWEEP_SECONDS = 2
111
111
  # Half-width of the shimmer band in characters
112
- STATUS_SHIMMER_BAND_HALF_WIDTH = 3.0
112
+ STATUS_SHIMMER_BAND_HALF_WIDTH = 5.0
113
113
  # Scale factor applied to shimmer intensity when blending colors
114
114
  STATUS_SHIMMER_ALPHA_SCALE = 0.7
115
115
 
@@ -1,3 +0,0 @@
1
- from .agent import Agent
2
-
3
- __all__ = ["Agent"]