klaude-code 1.2.6__py3-none-any.whl → 1.8.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.
- klaude_code/auth/__init__.py +24 -0
- klaude_code/auth/codex/__init__.py +20 -0
- klaude_code/auth/codex/exceptions.py +17 -0
- klaude_code/auth/codex/jwt_utils.py +45 -0
- klaude_code/auth/codex/oauth.py +229 -0
- klaude_code/auth/codex/token_manager.py +84 -0
- klaude_code/cli/auth_cmd.py +73 -0
- klaude_code/cli/config_cmd.py +91 -0
- klaude_code/cli/cost_cmd.py +338 -0
- klaude_code/cli/debug.py +78 -0
- klaude_code/cli/list_model.py +307 -0
- klaude_code/cli/main.py +233 -134
- klaude_code/cli/runtime.py +309 -117
- klaude_code/{version.py → cli/self_update.py} +114 -5
- klaude_code/cli/session_cmd.py +37 -21
- klaude_code/command/__init__.py +88 -27
- klaude_code/command/clear_cmd.py +8 -7
- klaude_code/command/command_abc.py +31 -31
- klaude_code/command/debug_cmd.py +79 -0
- klaude_code/command/export_cmd.py +19 -53
- klaude_code/command/export_online_cmd.py +154 -0
- klaude_code/command/fork_session_cmd.py +267 -0
- klaude_code/command/help_cmd.py +7 -8
- klaude_code/command/model_cmd.py +60 -10
- klaude_code/command/model_select.py +84 -0
- klaude_code/command/prompt-jj-describe.md +32 -0
- klaude_code/command/prompt_command.py +19 -11
- klaude_code/command/refresh_cmd.py +8 -10
- klaude_code/command/registry.py +139 -40
- klaude_code/command/release_notes_cmd.py +84 -0
- klaude_code/command/resume_cmd.py +111 -0
- klaude_code/command/status_cmd.py +104 -60
- klaude_code/command/terminal_setup_cmd.py +7 -9
- klaude_code/command/thinking_cmd.py +98 -0
- klaude_code/config/__init__.py +14 -6
- klaude_code/config/assets/__init__.py +1 -0
- klaude_code/config/assets/builtin_config.yaml +303 -0
- klaude_code/config/builtin_config.py +38 -0
- klaude_code/config/config.py +378 -109
- klaude_code/config/select_model.py +117 -53
- klaude_code/config/thinking.py +269 -0
- klaude_code/{const/__init__.py → const.py} +50 -19
- klaude_code/core/agent.py +20 -28
- klaude_code/core/executor.py +327 -112
- klaude_code/core/manager/__init__.py +2 -4
- klaude_code/core/manager/llm_clients.py +1 -15
- klaude_code/core/manager/llm_clients_builder.py +10 -11
- klaude_code/core/manager/sub_agent_manager.py +37 -6
- klaude_code/core/prompt.py +63 -44
- klaude_code/core/prompts/prompt-claude-code.md +2 -13
- klaude_code/core/prompts/prompt-codex-gpt-5-1-codex-max.md +117 -0
- klaude_code/core/prompts/prompt-codex-gpt-5-2-codex.md +117 -0
- klaude_code/core/prompts/prompt-codex.md +9 -42
- klaude_code/core/prompts/prompt-minimal.md +12 -0
- klaude_code/core/prompts/{prompt-subagent-explore.md → prompt-sub-agent-explore.md} +16 -3
- klaude_code/core/prompts/{prompt-subagent-oracle.md → prompt-sub-agent-oracle.md} +1 -2
- klaude_code/core/prompts/prompt-sub-agent-web.md +51 -0
- klaude_code/core/reminders.py +283 -95
- klaude_code/core/task.py +113 -75
- klaude_code/core/tool/__init__.py +24 -31
- klaude_code/core/tool/file/_utils.py +36 -0
- klaude_code/core/tool/file/apply_patch.py +17 -25
- klaude_code/core/tool/file/apply_patch_tool.py +57 -77
- klaude_code/core/tool/file/diff_builder.py +151 -0
- klaude_code/core/tool/file/edit_tool.py +50 -63
- klaude_code/core/tool/file/move_tool.md +41 -0
- klaude_code/core/tool/file/move_tool.py +435 -0
- klaude_code/core/tool/file/read_tool.md +1 -1
- klaude_code/core/tool/file/read_tool.py +86 -86
- klaude_code/core/tool/file/write_tool.py +59 -69
- klaude_code/core/tool/report_back_tool.py +84 -0
- klaude_code/core/tool/shell/bash_tool.py +265 -22
- klaude_code/core/tool/shell/command_safety.py +3 -6
- klaude_code/core/tool/{memory → skill}/skill_tool.py +16 -26
- klaude_code/core/tool/sub_agent_tool.py +13 -2
- klaude_code/core/tool/todo/todo_write_tool.md +0 -157
- klaude_code/core/tool/todo/todo_write_tool.py +1 -1
- klaude_code/core/tool/todo/todo_write_tool_raw.md +182 -0
- klaude_code/core/tool/todo/update_plan_tool.py +1 -1
- klaude_code/core/tool/tool_abc.py +18 -0
- klaude_code/core/tool/tool_context.py +27 -12
- klaude_code/core/tool/tool_registry.py +7 -7
- klaude_code/core/tool/tool_runner.py +44 -36
- klaude_code/core/tool/truncation.py +29 -14
- klaude_code/core/tool/web/mermaid_tool.md +43 -0
- klaude_code/core/tool/web/mermaid_tool.py +2 -5
- klaude_code/core/tool/web/web_fetch_tool.md +1 -1
- klaude_code/core/tool/web/web_fetch_tool.py +112 -22
- klaude_code/core/tool/web/web_search_tool.md +23 -0
- klaude_code/core/tool/web/web_search_tool.py +130 -0
- klaude_code/core/turn.py +168 -66
- klaude_code/llm/__init__.py +2 -10
- klaude_code/llm/anthropic/client.py +190 -178
- klaude_code/llm/anthropic/input.py +39 -15
- klaude_code/llm/bedrock/__init__.py +3 -0
- klaude_code/llm/bedrock/client.py +60 -0
- klaude_code/llm/client.py +7 -21
- klaude_code/llm/codex/__init__.py +5 -0
- klaude_code/llm/codex/client.py +149 -0
- klaude_code/llm/google/__init__.py +3 -0
- klaude_code/llm/google/client.py +309 -0
- klaude_code/llm/google/input.py +215 -0
- klaude_code/llm/input_common.py +3 -9
- klaude_code/llm/openai_compatible/client.py +72 -164
- klaude_code/llm/openai_compatible/input.py +6 -4
- klaude_code/llm/openai_compatible/stream.py +273 -0
- klaude_code/llm/openai_compatible/tool_call_accumulator.py +17 -1
- klaude_code/llm/openrouter/client.py +89 -160
- klaude_code/llm/openrouter/input.py +18 -30
- klaude_code/llm/openrouter/reasoning.py +118 -0
- klaude_code/llm/registry.py +39 -7
- klaude_code/llm/responses/client.py +184 -171
- klaude_code/llm/responses/input.py +20 -1
- klaude_code/llm/usage.py +17 -12
- klaude_code/protocol/commands.py +17 -1
- klaude_code/protocol/events.py +31 -4
- klaude_code/protocol/llm_param.py +13 -10
- klaude_code/protocol/model.py +232 -29
- klaude_code/protocol/op.py +90 -1
- klaude_code/protocol/op_handler.py +35 -1
- klaude_code/protocol/sub_agent/__init__.py +117 -0
- klaude_code/protocol/sub_agent/explore.py +63 -0
- klaude_code/protocol/sub_agent/oracle.py +91 -0
- klaude_code/protocol/sub_agent/task.py +61 -0
- klaude_code/protocol/sub_agent/web.py +79 -0
- klaude_code/protocol/tools.py +4 -2
- klaude_code/session/__init__.py +2 -2
- klaude_code/session/codec.py +71 -0
- klaude_code/session/export.py +293 -86
- klaude_code/session/selector.py +89 -67
- klaude_code/session/session.py +320 -309
- klaude_code/session/store.py +220 -0
- klaude_code/session/templates/export_session.html +595 -83
- klaude_code/session/templates/mermaid_viewer.html +926 -0
- klaude_code/skill/__init__.py +27 -0
- klaude_code/skill/assets/deslop/SKILL.md +17 -0
- klaude_code/skill/assets/dev-docs/SKILL.md +108 -0
- klaude_code/skill/assets/handoff/SKILL.md +39 -0
- klaude_code/skill/assets/jj-workspace/SKILL.md +20 -0
- klaude_code/skill/assets/skill-creator/SKILL.md +139 -0
- klaude_code/{core/tool/memory/skill_loader.py → skill/loader.py} +55 -15
- klaude_code/skill/manager.py +70 -0
- klaude_code/skill/system_skills.py +192 -0
- klaude_code/trace/__init__.py +20 -2
- klaude_code/trace/log.py +150 -5
- klaude_code/ui/__init__.py +4 -9
- klaude_code/ui/core/input.py +1 -1
- klaude_code/ui/core/stage_manager.py +7 -7
- klaude_code/ui/modes/debug/display.py +2 -1
- klaude_code/ui/modes/repl/__init__.py +3 -48
- klaude_code/ui/modes/repl/clipboard.py +5 -5
- klaude_code/ui/modes/repl/completers.py +487 -123
- klaude_code/ui/modes/repl/display.py +5 -4
- klaude_code/ui/modes/repl/event_handler.py +370 -117
- klaude_code/ui/modes/repl/input_prompt_toolkit.py +552 -105
- klaude_code/ui/modes/repl/key_bindings.py +146 -23
- klaude_code/ui/modes/repl/renderer.py +189 -99
- klaude_code/ui/renderers/assistant.py +9 -2
- klaude_code/ui/renderers/bash_syntax.py +178 -0
- klaude_code/ui/renderers/common.py +78 -0
- klaude_code/ui/renderers/developer.py +104 -48
- klaude_code/ui/renderers/diffs.py +87 -6
- klaude_code/ui/renderers/errors.py +11 -6
- klaude_code/ui/renderers/mermaid_viewer.py +57 -0
- klaude_code/ui/renderers/metadata.py +112 -76
- klaude_code/ui/renderers/sub_agent.py +92 -7
- klaude_code/ui/renderers/thinking.py +40 -18
- klaude_code/ui/renderers/tools.py +405 -227
- klaude_code/ui/renderers/user_input.py +73 -13
- klaude_code/ui/rich/__init__.py +10 -1
- klaude_code/ui/rich/cjk_wrap.py +228 -0
- klaude_code/ui/rich/code_panel.py +131 -0
- klaude_code/ui/rich/live.py +17 -0
- klaude_code/ui/rich/markdown.py +305 -170
- klaude_code/ui/rich/searchable_text.py +10 -13
- klaude_code/ui/rich/status.py +190 -49
- klaude_code/ui/rich/theme.py +135 -39
- klaude_code/ui/terminal/__init__.py +55 -0
- klaude_code/ui/terminal/color.py +1 -1
- klaude_code/ui/terminal/control.py +13 -22
- klaude_code/ui/terminal/notifier.py +44 -4
- klaude_code/ui/terminal/selector.py +658 -0
- klaude_code/ui/utils/common.py +0 -18
- klaude_code-1.8.0.dist-info/METADATA +377 -0
- klaude_code-1.8.0.dist-info/RECORD +219 -0
- {klaude_code-1.2.6.dist-info → klaude_code-1.8.0.dist-info}/entry_points.txt +1 -0
- klaude_code/command/diff_cmd.py +0 -138
- klaude_code/command/prompt-dev-docs-update.md +0 -56
- klaude_code/command/prompt-dev-docs.md +0 -46
- klaude_code/config/list_model.py +0 -162
- klaude_code/core/manager/agent_manager.py +0 -127
- klaude_code/core/prompts/prompt-subagent-webfetch.md +0 -46
- klaude_code/core/tool/file/multi_edit_tool.md +0 -42
- klaude_code/core/tool/file/multi_edit_tool.py +0 -199
- klaude_code/core/tool/memory/memory_tool.md +0 -16
- klaude_code/core/tool/memory/memory_tool.py +0 -462
- klaude_code/llm/openrouter/reasoning_handler.py +0 -209
- klaude_code/protocol/sub_agent.py +0 -348
- klaude_code/ui/utils/debouncer.py +0 -42
- klaude_code-1.2.6.dist-info/METADATA +0 -178
- klaude_code-1.2.6.dist-info/RECORD +0 -167
- /klaude_code/core/prompts/{prompt-subagent.md → prompt-sub-agent.md} +0 -0
- /klaude_code/core/tool/{memory → skill}/__init__.py +0 -0
- /klaude_code/core/tool/{memory → skill}/skill_tool.md +0 -0
- {klaude_code-1.2.6.dist-info → klaude_code-1.8.0.dist-info}/WHEEL +0 -0
|
@@ -1,47 +1,70 @@
|
|
|
1
|
-
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
2
|
-
from klaude_code.command.registry import register_command
|
|
3
|
-
from klaude_code.core.agent import Agent
|
|
1
|
+
from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
|
|
4
2
|
from klaude_code.protocol import commands, events, model
|
|
5
3
|
from klaude_code.session.session import Session
|
|
6
4
|
|
|
7
5
|
|
|
8
|
-
|
|
9
|
-
"""
|
|
6
|
+
class AggregatedUsage(model.BaseModel):
|
|
7
|
+
"""Aggregated usage statistics including per-model breakdown."""
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
total: model.Usage
|
|
10
|
+
by_model: list[model.TaskMetadata]
|
|
11
|
+
task_count: int
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def accumulate_session_usage(session: Session) -> AggregatedUsage:
|
|
15
|
+
"""Accumulate usage statistics from all TaskMetadataItems in session history.
|
|
16
|
+
|
|
17
|
+
Includes both main agent and sub-agent task metadata, grouped by model+provider.
|
|
13
18
|
"""
|
|
14
|
-
|
|
19
|
+
all_metadata: list[model.TaskMetadata] = []
|
|
15
20
|
task_count = 0
|
|
16
21
|
|
|
17
22
|
for item in session.conversation_history:
|
|
18
|
-
if isinstance(item, model.
|
|
23
|
+
if isinstance(item, model.TaskMetadataItem):
|
|
19
24
|
task_count += 1
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
25
|
+
all_metadata.append(item.main_agent)
|
|
26
|
+
all_metadata.extend(item.sub_agent_task_metadata)
|
|
27
|
+
|
|
28
|
+
# Aggregate by model+provider
|
|
29
|
+
by_model = model.TaskMetadata.aggregate_by_model(all_metadata)
|
|
30
|
+
|
|
31
|
+
# Calculate total from aggregated results
|
|
32
|
+
total = model.Usage()
|
|
33
|
+
for meta in by_model:
|
|
34
|
+
if not meta.usage:
|
|
35
|
+
continue
|
|
36
|
+
usage = meta.usage
|
|
37
|
+
|
|
38
|
+
# Set currency from first
|
|
39
|
+
if total.currency == "USD" and usage.currency:
|
|
40
|
+
total.currency = usage.currency
|
|
41
|
+
|
|
42
|
+
# Accumulate primary token fields (total_tokens is computed)
|
|
43
|
+
total.input_tokens += usage.input_tokens
|
|
44
|
+
total.cached_tokens += usage.cached_tokens
|
|
45
|
+
total.reasoning_tokens += usage.reasoning_tokens
|
|
46
|
+
total.output_tokens += usage.output_tokens
|
|
47
|
+
|
|
48
|
+
# Accumulate cost components (total_cost is computed)
|
|
49
|
+
if usage.input_cost is not None:
|
|
50
|
+
total.input_cost = (total.input_cost or 0.0) + usage.input_cost
|
|
51
|
+
if usage.output_cost is not None:
|
|
52
|
+
total.output_cost = (total.output_cost or 0.0) + usage.output_cost
|
|
53
|
+
if usage.cache_read_cost is not None:
|
|
54
|
+
total.cache_read_cost = (total.cache_read_cost or 0.0) + usage.cache_read_cost
|
|
55
|
+
|
|
56
|
+
# Track peak context window size (max across all tasks)
|
|
57
|
+
if usage.context_size is not None:
|
|
58
|
+
total.context_size = usage.context_size
|
|
59
|
+
|
|
60
|
+
# Keep the latest context_limit for computed context_usage_percent
|
|
61
|
+
if usage.context_limit is not None:
|
|
62
|
+
total.context_limit = usage.context_limit
|
|
63
|
+
|
|
64
|
+
return AggregatedUsage(total=total, by_model=by_model, task_count=task_count)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def format_tokens(tokens: int) -> str:
|
|
45
68
|
"""Format token count with K/M suffix for readability."""
|
|
46
69
|
if tokens >= 1_000_000:
|
|
47
70
|
return f"{tokens / 1_000_000:.2f}M"
|
|
@@ -50,32 +73,54 @@ def _format_tokens(tokens: int) -> str:
|
|
|
50
73
|
return str(tokens)
|
|
51
74
|
|
|
52
75
|
|
|
53
|
-
def
|
|
54
|
-
"""Format cost
|
|
76
|
+
def format_cost(cost: float | None, currency: str = "USD") -> str:
|
|
77
|
+
"""Format cost with currency symbol."""
|
|
55
78
|
if cost is None:
|
|
56
79
|
return "-"
|
|
80
|
+
symbol = "¥" if currency == "CNY" else "$"
|
|
57
81
|
if cost < 0.01:
|
|
58
|
-
return f"
|
|
59
|
-
return f"
|
|
82
|
+
return f"{symbol}{cost:.4f}"
|
|
83
|
+
return f"{symbol}{cost:.2f}"
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _format_model_usage_line(meta: model.TaskMetadata) -> str:
|
|
87
|
+
"""Format a single model's usage as a line."""
|
|
88
|
+
model_label = meta.model_name
|
|
89
|
+
if meta.provider:
|
|
90
|
+
model_label = f"{meta.model_name} ({meta.provider})"
|
|
91
|
+
|
|
92
|
+
usage = meta.usage
|
|
93
|
+
if not usage:
|
|
94
|
+
return f" {model_label}: no usage data"
|
|
95
|
+
|
|
96
|
+
cost_str = format_cost(usage.total_cost, usage.currency)
|
|
97
|
+
return (
|
|
98
|
+
f" {model_label}: "
|
|
99
|
+
f"{format_tokens(usage.input_tokens)} input, "
|
|
100
|
+
f"{format_tokens(usage.output_tokens)} output, "
|
|
101
|
+
f"{format_tokens(usage.cached_tokens)} cache read, "
|
|
102
|
+
f"{format_tokens(usage.reasoning_tokens)} thinking, "
|
|
103
|
+
f"({cost_str})"
|
|
104
|
+
)
|
|
60
105
|
|
|
61
106
|
|
|
62
|
-
def format_status_content(
|
|
63
|
-
"""Format session status
|
|
64
|
-
|
|
107
|
+
def format_status_content(aggregated: AggregatedUsage) -> str:
|
|
108
|
+
"""Format session status with per-model breakdown."""
|
|
109
|
+
lines: list[str] = []
|
|
65
110
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
parts.append(f"Output: {_format_tokens(usage.output_tokens)}")
|
|
70
|
-
parts.append(f"Total: {_format_tokens(usage.total_tokens)}")
|
|
111
|
+
# Total cost line
|
|
112
|
+
total_cost_str = format_cost(aggregated.total.total_cost, aggregated.total.currency)
|
|
113
|
+
lines.append(f"Total cost: {total_cost_str}")
|
|
71
114
|
|
|
72
|
-
|
|
73
|
-
|
|
115
|
+
# Per-model breakdown
|
|
116
|
+
if aggregated.by_model:
|
|
117
|
+
lines.append("Usage by model:")
|
|
118
|
+
for stats in aggregated.by_model:
|
|
119
|
+
lines.append(_format_model_usage_line(stats))
|
|
74
120
|
|
|
75
|
-
return "
|
|
121
|
+
return "\n".join(lines)
|
|
76
122
|
|
|
77
123
|
|
|
78
|
-
@register_command
|
|
79
124
|
class StatusCommand(CommandABC):
|
|
80
125
|
"""Display session usage statistics."""
|
|
81
126
|
|
|
@@ -87,25 +132,24 @@ class StatusCommand(CommandABC):
|
|
|
87
132
|
def summary(self) -> str:
|
|
88
133
|
return "Show session usage statistics"
|
|
89
134
|
|
|
90
|
-
async def run(self,
|
|
135
|
+
async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
|
|
136
|
+
del user_input # unused
|
|
91
137
|
session = agent.session
|
|
92
|
-
|
|
138
|
+
aggregated = accumulate_session_usage(session)
|
|
93
139
|
|
|
94
140
|
event = events.DeveloperMessageEvent(
|
|
95
141
|
session_id=session.id,
|
|
96
142
|
item=model.DeveloperMessageItem(
|
|
97
|
-
content=format_status_content(
|
|
143
|
+
content=format_status_content(aggregated),
|
|
98
144
|
command_output=model.CommandOutput(
|
|
99
145
|
command_name=self.name,
|
|
100
|
-
ui_extra=model.
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
task_count=task_count,
|
|
105
|
-
),
|
|
146
|
+
ui_extra=model.SessionStatusUIExtra(
|
|
147
|
+
usage=aggregated.total,
|
|
148
|
+
task_count=aggregated.task_count,
|
|
149
|
+
by_model=aggregated.by_model,
|
|
106
150
|
),
|
|
107
151
|
),
|
|
108
152
|
),
|
|
109
153
|
)
|
|
110
154
|
|
|
111
|
-
return CommandResult(events=[event])
|
|
155
|
+
return CommandResult(events=[event], persist_user_input=False, persist_events=False)
|
|
@@ -2,13 +2,10 @@ import os
|
|
|
2
2
|
import subprocess
|
|
3
3
|
from pathlib import Path
|
|
4
4
|
|
|
5
|
-
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
6
|
-
from klaude_code.command.registry import register_command
|
|
7
|
-
from klaude_code.core.agent import Agent
|
|
5
|
+
from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
|
|
8
6
|
from klaude_code.protocol import commands, events, model
|
|
9
7
|
|
|
10
8
|
|
|
11
|
-
@register_command
|
|
12
9
|
class TerminalSetupCommand(CommandABC):
|
|
13
10
|
"""Setup shift+enter newline functionality in terminal"""
|
|
14
11
|
|
|
@@ -24,7 +21,8 @@ class TerminalSetupCommand(CommandABC):
|
|
|
24
21
|
def is_interactive(self) -> bool:
|
|
25
22
|
return False
|
|
26
23
|
|
|
27
|
-
async def run(self,
|
|
24
|
+
async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
|
|
25
|
+
del user_input # unused
|
|
28
26
|
term_program = os.environ.get("TERM_PROGRAM", "").lower()
|
|
29
27
|
|
|
30
28
|
try:
|
|
@@ -42,7 +40,7 @@ class TerminalSetupCommand(CommandABC):
|
|
|
42
40
|
return self._create_success_result(agent, message)
|
|
43
41
|
|
|
44
42
|
except Exception as e:
|
|
45
|
-
return self._create_error_result(agent, f"Error configuring terminal: {
|
|
43
|
+
return self._create_error_result(agent, f"Error configuring terminal: {e!s}")
|
|
46
44
|
|
|
47
45
|
def _setup_ghostty(self) -> str:
|
|
48
46
|
"""Configure shift+enter newline for Ghostty terminal"""
|
|
@@ -112,7 +110,7 @@ class TerminalSetupCommand(CommandABC):
|
|
|
112
110
|
)
|
|
113
111
|
|
|
114
112
|
except Exception as e:
|
|
115
|
-
raise Exception(f"Error configuring iTerm: {
|
|
113
|
+
raise Exception(f"Error configuring iTerm: {e!s}") from e
|
|
116
114
|
|
|
117
115
|
def _setup_vscode_family(self) -> str:
|
|
118
116
|
"""Configure shift+enter newline for VS Code family terminals (VS Code, Windsurf, Cursor).
|
|
@@ -223,7 +221,7 @@ class TerminalSetupCommand(CommandABC):
|
|
|
223
221
|
|
|
224
222
|
return message
|
|
225
223
|
|
|
226
|
-
def _create_success_result(self, agent: Agent, message: str) -> CommandResult:
|
|
224
|
+
def _create_success_result(self, agent: "Agent", message: str) -> CommandResult:
|
|
227
225
|
"""Create success result"""
|
|
228
226
|
return CommandResult(
|
|
229
227
|
events=[
|
|
@@ -237,7 +235,7 @@ class TerminalSetupCommand(CommandABC):
|
|
|
237
235
|
]
|
|
238
236
|
)
|
|
239
237
|
|
|
240
|
-
def _create_error_result(self, agent: Agent, message: str) -> CommandResult:
|
|
238
|
+
def _create_error_result(self, agent: "Agent", message: str) -> CommandResult:
|
|
241
239
|
"""Create error result"""
|
|
242
240
|
return CommandResult(
|
|
243
241
|
events=[
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from prompt_toolkit.styles import Style
|
|
4
|
+
|
|
5
|
+
from klaude_code.command.command_abc import Agent, CommandABC, CommandResult
|
|
6
|
+
from klaude_code.config.thinking import get_thinking_picker_data, parse_thinking_value
|
|
7
|
+
from klaude_code.protocol import commands, events, llm_param, model, op
|
|
8
|
+
from klaude_code.ui.terminal.selector import SelectItem, select_one
|
|
9
|
+
|
|
10
|
+
SELECT_STYLE = Style(
|
|
11
|
+
[
|
|
12
|
+
("instruction", "ansibrightblack"),
|
|
13
|
+
("pointer", "ansigreen"),
|
|
14
|
+
("highlighted", "ansigreen"),
|
|
15
|
+
("text", "ansibrightblack"),
|
|
16
|
+
("question", "bold"),
|
|
17
|
+
]
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _select_thinking_sync(config: llm_param.LLMConfigParameter) -> llm_param.Thinking | None:
|
|
22
|
+
"""Select thinking level (sync version)."""
|
|
23
|
+
data = get_thinking_picker_data(config)
|
|
24
|
+
if data is None:
|
|
25
|
+
return None
|
|
26
|
+
|
|
27
|
+
items: list[SelectItem[str]] = [
|
|
28
|
+
SelectItem(title=[("class:text", opt.label + "\n")], value=opt.value, search_text=opt.label)
|
|
29
|
+
for opt in data.options
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
result = select_one(
|
|
34
|
+
message=data.message,
|
|
35
|
+
items=items,
|
|
36
|
+
pointer="→",
|
|
37
|
+
style=SELECT_STYLE,
|
|
38
|
+
use_search_filter=False,
|
|
39
|
+
)
|
|
40
|
+
if result is None:
|
|
41
|
+
return None
|
|
42
|
+
return parse_thinking_value(result)
|
|
43
|
+
except KeyboardInterrupt:
|
|
44
|
+
return None
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
async def select_thinking_for_protocol(config: llm_param.LLMConfigParameter) -> llm_param.Thinking | None:
|
|
48
|
+
"""Select thinking configuration based on the LLM protocol.
|
|
49
|
+
|
|
50
|
+
Returns the selected Thinking config, or None if user cancelled.
|
|
51
|
+
"""
|
|
52
|
+
return await asyncio.to_thread(_select_thinking_sync, config)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ThinkingCommand(CommandABC):
|
|
56
|
+
"""Configure model thinking/reasoning level."""
|
|
57
|
+
|
|
58
|
+
@property
|
|
59
|
+
def name(self) -> commands.CommandName:
|
|
60
|
+
return commands.CommandName.THINKING
|
|
61
|
+
|
|
62
|
+
@property
|
|
63
|
+
def summary(self) -> str:
|
|
64
|
+
return "Configure model thinking/reasoning level"
|
|
65
|
+
|
|
66
|
+
@property
|
|
67
|
+
def is_interactive(self) -> bool:
|
|
68
|
+
return True
|
|
69
|
+
|
|
70
|
+
async def run(self, agent: Agent, user_input: model.UserInputPayload) -> CommandResult:
|
|
71
|
+
del user_input # unused
|
|
72
|
+
if agent.profile is None:
|
|
73
|
+
return CommandResult(events=[])
|
|
74
|
+
|
|
75
|
+
config = agent.profile.llm_client.get_llm_config()
|
|
76
|
+
new_thinking = await select_thinking_for_protocol(config)
|
|
77
|
+
|
|
78
|
+
if new_thinking is None:
|
|
79
|
+
return CommandResult(
|
|
80
|
+
events=[
|
|
81
|
+
events.DeveloperMessageEvent(
|
|
82
|
+
session_id=agent.session.id,
|
|
83
|
+
item=model.DeveloperMessageItem(
|
|
84
|
+
content="(no change)",
|
|
85
|
+
command_output=model.CommandOutput(command_name=self.name),
|
|
86
|
+
),
|
|
87
|
+
)
|
|
88
|
+
]
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
return CommandResult(
|
|
92
|
+
operations=[
|
|
93
|
+
op.ChangeThinkingOperation(
|
|
94
|
+
session_id=agent.session.id,
|
|
95
|
+
thinking=new_thinking,
|
|
96
|
+
)
|
|
97
|
+
]
|
|
98
|
+
)
|
klaude_code/config/__init__.py
CHANGED
|
@@ -1,11 +1,19 @@
|
|
|
1
|
-
from .config import
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
from .config import (
|
|
2
|
+
Config,
|
|
3
|
+
UserConfig,
|
|
4
|
+
config_path,
|
|
5
|
+
create_example_config,
|
|
6
|
+
example_config_path,
|
|
7
|
+
load_config,
|
|
8
|
+
print_no_available_models_hint,
|
|
9
|
+
)
|
|
4
10
|
|
|
5
11
|
__all__ = [
|
|
6
12
|
"Config",
|
|
7
|
-
"
|
|
13
|
+
"UserConfig",
|
|
8
14
|
"config_path",
|
|
9
|
-
"
|
|
10
|
-
"
|
|
15
|
+
"create_example_config",
|
|
16
|
+
"example_config_path",
|
|
17
|
+
"load_config",
|
|
18
|
+
"print_no_available_models_hint",
|
|
11
19
|
]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Asset files for config module
|