klaude-code 2.0.2__py3-none-any.whl → 2.1.1__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/app/__init__.py +12 -0
- klaude_code/app/runtime.py +215 -0
- klaude_code/cli/auth_cmd.py +2 -2
- klaude_code/cli/config_cmd.py +2 -2
- klaude_code/cli/cost_cmd.py +1 -1
- klaude_code/cli/debug.py +12 -36
- klaude_code/cli/list_model.py +3 -3
- klaude_code/cli/main.py +17 -60
- klaude_code/cli/self_update.py +2 -187
- klaude_code/cli/session_cmd.py +2 -2
- klaude_code/config/config.py +1 -1
- klaude_code/config/select_model.py +1 -1
- klaude_code/const.py +9 -1
- klaude_code/core/agent.py +9 -62
- klaude_code/core/agent_profile.py +291 -0
- klaude_code/core/executor.py +335 -230
- klaude_code/core/manager/llm_clients_builder.py +1 -1
- klaude_code/core/manager/sub_agent_manager.py +16 -29
- klaude_code/core/reminders.py +84 -103
- klaude_code/core/task.py +12 -20
- klaude_code/core/tool/__init__.py +5 -19
- klaude_code/core/tool/context.py +84 -0
- klaude_code/core/tool/file/apply_patch_tool.py +18 -21
- klaude_code/core/tool/file/edit_tool.py +39 -42
- klaude_code/core/tool/file/read_tool.py +14 -9
- klaude_code/core/tool/file/write_tool.py +12 -13
- klaude_code/core/tool/report_back_tool.py +4 -1
- klaude_code/core/tool/shell/bash_tool.py +6 -11
- klaude_code/core/tool/sub_agent_tool.py +8 -7
- klaude_code/core/tool/todo/todo_write_tool.py +3 -9
- klaude_code/core/tool/todo/update_plan_tool.py +3 -5
- klaude_code/core/tool/tool_abc.py +2 -1
- klaude_code/core/tool/tool_registry.py +2 -33
- klaude_code/core/tool/tool_runner.py +13 -10
- klaude_code/core/tool/web/mermaid_tool.py +3 -1
- klaude_code/core/tool/web/web_fetch_tool.py +5 -3
- klaude_code/core/tool/web/web_search_tool.py +5 -3
- klaude_code/core/turn.py +87 -30
- klaude_code/llm/anthropic/client.py +1 -1
- klaude_code/llm/bedrock/client.py +1 -1
- klaude_code/llm/claude/client.py +1 -1
- klaude_code/llm/codex/client.py +1 -1
- klaude_code/llm/google/client.py +1 -1
- klaude_code/llm/openai_compatible/client.py +1 -1
- klaude_code/llm/openai_compatible/tool_call_accumulator.py +1 -1
- klaude_code/llm/openrouter/client.py +1 -1
- klaude_code/llm/openrouter/reasoning.py +1 -1
- klaude_code/llm/responses/client.py +1 -1
- klaude_code/protocol/commands.py +1 -0
- klaude_code/protocol/events/__init__.py +57 -0
- klaude_code/protocol/events/base.py +18 -0
- klaude_code/protocol/events/chat.py +20 -0
- klaude_code/protocol/events/lifecycle.py +22 -0
- klaude_code/protocol/events/metadata.py +15 -0
- klaude_code/protocol/events/streaming.py +43 -0
- klaude_code/protocol/events/system.py +53 -0
- klaude_code/protocol/events/tools.py +27 -0
- klaude_code/protocol/op.py +5 -0
- klaude_code/protocol/tools.py +0 -1
- klaude_code/session/session.py +6 -7
- klaude_code/skill/assets/create-plan/SKILL.md +76 -0
- klaude_code/skill/loader.py +32 -88
- klaude_code/skill/manager.py +38 -0
- klaude_code/skill/system_skills.py +1 -1
- klaude_code/tui/__init__.py +8 -0
- klaude_code/{command → tui/command}/__init__.py +3 -0
- klaude_code/{command → tui/command}/clear_cmd.py +2 -1
- klaude_code/tui/command/copy_cmd.py +53 -0
- klaude_code/{command → tui/command}/debug_cmd.py +3 -2
- klaude_code/{command → tui/command}/export_cmd.py +2 -1
- klaude_code/{command → tui/command}/export_online_cmd.py +2 -1
- klaude_code/{command → tui/command}/fork_session_cmd.py +4 -3
- klaude_code/{command → tui/command}/help_cmd.py +2 -1
- klaude_code/{command → tui/command}/model_cmd.py +4 -3
- klaude_code/{command → tui/command}/model_select.py +2 -2
- klaude_code/{command → tui/command}/prompt_command.py +4 -3
- klaude_code/{command → tui/command}/refresh_cmd.py +3 -1
- klaude_code/{command → tui/command}/registry.py +6 -5
- klaude_code/{command → tui/command}/release_notes_cmd.py +2 -1
- klaude_code/{command → tui/command}/resume_cmd.py +4 -3
- klaude_code/{command → tui/command}/status_cmd.py +2 -1
- klaude_code/{command → tui/command}/terminal_setup_cmd.py +2 -1
- klaude_code/{command → tui/command}/thinking_cmd.py +3 -2
- klaude_code/tui/commands.py +164 -0
- klaude_code/{ui/renderers → tui/components}/assistant.py +3 -3
- klaude_code/{ui/renderers → tui/components}/bash_syntax.py +2 -2
- klaude_code/{ui/renderers → tui/components}/common.py +1 -1
- klaude_code/{ui/renderers → tui/components}/developer.py +4 -4
- klaude_code/{ui/renderers → tui/components}/diffs.py +2 -2
- klaude_code/{ui/renderers → tui/components}/errors.py +2 -2
- klaude_code/{ui/renderers → tui/components}/metadata.py +7 -7
- klaude_code/{ui → tui/components}/rich/markdown.py +9 -23
- klaude_code/{ui → tui/components}/rich/status.py +2 -2
- klaude_code/{ui → tui/components}/rich/theme.py +3 -1
- klaude_code/{ui/renderers → tui/components}/sub_agent.py +23 -43
- klaude_code/{ui/renderers → tui/components}/thinking.py +3 -3
- klaude_code/{ui/renderers → tui/components}/tools.py +13 -17
- klaude_code/{ui/renderers → tui/components}/user_input.py +3 -20
- klaude_code/tui/display.py +85 -0
- klaude_code/{ui/modes/repl → tui/input}/__init__.py +1 -1
- klaude_code/{ui/modes/repl → tui/input}/completers.py +1 -1
- klaude_code/{ui/modes/repl/input_prompt_toolkit.py → tui/input/prompt_toolkit.py} +6 -6
- klaude_code/tui/machine.py +608 -0
- klaude_code/tui/renderer.py +707 -0
- klaude_code/tui/runner.py +321 -0
- klaude_code/tui/terminal/__init__.py +56 -0
- klaude_code/{ui → tui}/terminal/color.py +1 -1
- klaude_code/{ui → tui}/terminal/control.py +1 -1
- klaude_code/{ui → tui}/terminal/notifier.py +1 -1
- klaude_code/ui/__init__.py +6 -50
- klaude_code/ui/core/display.py +3 -3
- klaude_code/ui/core/input.py +2 -1
- klaude_code/ui/{modes/debug/display.py → debug_mode.py} +1 -1
- klaude_code/ui/{modes/exec/display.py → exec_mode.py} +0 -2
- klaude_code/ui/terminal/__init__.py +6 -54
- klaude_code/ui/terminal/title.py +31 -0
- klaude_code/update.py +163 -0
- {klaude_code-2.0.2.dist-info → klaude_code-2.1.1.dist-info}/METADATA +1 -1
- klaude_code-2.1.1.dist-info/RECORD +233 -0
- klaude_code/cli/runtime.py +0 -518
- klaude_code/core/prompt.py +0 -108
- klaude_code/core/tool/skill/skill_tool.md +0 -24
- klaude_code/core/tool/skill/skill_tool.py +0 -87
- klaude_code/core/tool/tool_context.py +0 -148
- klaude_code/protocol/events.py +0 -195
- klaude_code/skill/assets/dev-docs/SKILL.md +0 -108
- klaude_code/trace/__init__.py +0 -21
- klaude_code/ui/core/stage_manager.py +0 -48
- klaude_code/ui/modes/__init__.py +0 -1
- klaude_code/ui/modes/debug/__init__.py +0 -1
- klaude_code/ui/modes/exec/__init__.py +0 -1
- klaude_code/ui/modes/repl/display.py +0 -61
- klaude_code/ui/modes/repl/event_handler.py +0 -629
- klaude_code/ui/modes/repl/renderer.py +0 -464
- klaude_code/ui/renderers/__init__.py +0 -0
- klaude_code/ui/utils/__init__.py +0 -1
- klaude_code-2.0.2.dist-info/RECORD +0 -227
- /klaude_code/{trace/log.py → log.py} +0 -0
- /klaude_code/{command → tui/command}/command_abc.py +0 -0
- /klaude_code/{command → tui/command}/prompt-commit.md +0 -0
- /klaude_code/{command → tui/command}/prompt-init.md +0 -0
- /klaude_code/{core/tool/skill → tui/components}/__init__.py +0 -0
- /klaude_code/{ui/renderers → tui/components}/mermaid_viewer.py +0 -0
- /klaude_code/{ui → tui/components}/rich/__init__.py +0 -0
- /klaude_code/{ui → tui/components}/rich/cjk_wrap.py +0 -0
- /klaude_code/{ui → tui/components}/rich/code_panel.py +0 -0
- /klaude_code/{ui → tui/components}/rich/live.py +0 -0
- /klaude_code/{ui → tui/components}/rich/quote.py +0 -0
- /klaude_code/{ui → tui/components}/rich/searchable_text.py +0 -0
- /klaude_code/{ui/modes/repl → tui/input}/clipboard.py +0 -0
- /klaude_code/{ui/modes/repl → tui/input}/key_bindings.py +0 -0
- /klaude_code/{ui → tui}/terminal/image.py +0 -0
- /klaude_code/{ui → tui}/terminal/progress_bar.py +0 -0
- /klaude_code/{ui → tui}/terminal/selector.py +0 -0
- /klaude_code/ui/{utils/common.py → common.py} +0 -0
- {klaude_code-2.0.2.dist-info → klaude_code-2.1.1.dist-info}/WHEEL +0 -0
- {klaude_code-2.0.2.dist-info → klaude_code-2.1.1.dist-info}/entry_points.txt +0 -0
|
@@ -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."""
|
|
@@ -2,11 +2,12 @@ import asyncio
|
|
|
2
2
|
|
|
3
3
|
from prompt_toolkit.styles import Style
|
|
4
4
|
|
|
5
|
-
from klaude_code.
|
|
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.
|
|
9
|
-
|
|
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
|
[
|
|
@@ -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."""
|
|
@@ -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"""
|
|
@@ -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.
|
|
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
|
[
|
|
@@ -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.
|
|
7
|
-
from klaude_code.
|
|
8
|
-
from klaude_code.
|
|
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.
|
|
12
|
-
from klaude_code.
|
|
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.
|
|
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:
|
|
@@ -4,10 +4,10 @@ from rich.table import Table
|
|
|
4
4
|
from rich.text import Text
|
|
5
5
|
|
|
6
6
|
from klaude_code.protocol import commands, events, message, model
|
|
7
|
-
from klaude_code.
|
|
8
|
-
from klaude_code.
|
|
9
|
-
from klaude_code.
|
|
10
|
-
from klaude_code.
|
|
7
|
+
from klaude_code.tui.components.common import create_grid, truncate_middle
|
|
8
|
+
from klaude_code.tui.components.rich.markdown import NoInsetMarkdown
|
|
9
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
10
|
+
from klaude_code.tui.components.tools import render_path
|
|
11
11
|
|
|
12
12
|
REMINDER_BULLET = " ⧉"
|
|
13
13
|
|
|
@@ -6,8 +6,8 @@ from rich.text import Text
|
|
|
6
6
|
|
|
7
7
|
from klaude_code.const import DIFF_PREFIX_WIDTH, MAX_DIFF_LINES
|
|
8
8
|
from klaude_code.protocol import model
|
|
9
|
-
from klaude_code.
|
|
10
|
-
from klaude_code.
|
|
9
|
+
from klaude_code.tui.components.common import create_grid
|
|
10
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
def _make_diff_prefix(line: str, new_ln: int | None, width: int) -> tuple[str, int | None]:
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
from rich.console import RenderableType
|
|
2
2
|
from rich.text import Text
|
|
3
3
|
|
|
4
|
-
from klaude_code.
|
|
5
|
-
from klaude_code.
|
|
4
|
+
from klaude_code.tui.components.common import create_grid
|
|
5
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def render_error(error_msg: Text) -> RenderableType:
|
|
@@ -5,12 +5,12 @@ from rich.padding import Padding
|
|
|
5
5
|
from rich.text import Text
|
|
6
6
|
|
|
7
7
|
from klaude_code.const import DEFAULT_MAX_TOKENS
|
|
8
|
+
from klaude_code.log import is_debug_enabled
|
|
8
9
|
from klaude_code.protocol import events, model
|
|
9
|
-
from klaude_code.
|
|
10
|
-
from klaude_code.
|
|
11
|
-
from klaude_code.
|
|
12
|
-
from klaude_code.ui.
|
|
13
|
-
from klaude_code.ui.utils.common import format_model_params, format_number
|
|
10
|
+
from klaude_code.tui.components.common import create_grid
|
|
11
|
+
from klaude_code.tui.components.rich.quote import Quote
|
|
12
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
13
|
+
from klaude_code.ui.common import format_model_params, format_number
|
|
14
14
|
|
|
15
15
|
|
|
16
16
|
def _get_version() -> str:
|
|
@@ -99,7 +99,7 @@ def _render_task_metadata_block(
|
|
|
99
99
|
)
|
|
100
100
|
)
|
|
101
101
|
if metadata.usage is not None:
|
|
102
|
-
# Context
|
|
102
|
+
# Context usage
|
|
103
103
|
if show_context_and_time and metadata.usage.context_usage_percent is not None:
|
|
104
104
|
context_size = format_number(metadata.usage.context_size or 0)
|
|
105
105
|
# Calculate effective limit (same as Usage.context_usage_percent)
|
|
@@ -169,7 +169,7 @@ def render_task_metadata(e: events.TaskMetadataEvent) -> RenderableType:
|
|
|
169
169
|
|
|
170
170
|
# Render each sub-agent metadata block
|
|
171
171
|
for meta in e.metadata.sub_agent_task_metadata:
|
|
172
|
-
renderables.append(_render_task_metadata_block(meta, is_sub_agent=True, show_context_and_time=
|
|
172
|
+
renderables.append(_render_task_metadata_block(meta, is_sub_agent=True, show_context_and_time=True))
|
|
173
173
|
|
|
174
174
|
# Add total cost line when there are sub-agents
|
|
175
175
|
if e.metadata.sub_agent_task_metadata:
|
|
@@ -24,7 +24,7 @@ from klaude_code.const import (
|
|
|
24
24
|
MARKDOWN_STREAM_SYNCHRONIZED_OUTPUT_ENABLED,
|
|
25
25
|
UI_REFRESH_RATE_FPS,
|
|
26
26
|
)
|
|
27
|
-
from klaude_code.
|
|
27
|
+
from klaude_code.tui.components.rich.code_panel import CodePanel
|
|
28
28
|
|
|
29
29
|
|
|
30
30
|
class NoInsetCodeBlock(CodeBlock):
|
|
@@ -61,7 +61,13 @@ class Divider(MarkdownElement):
|
|
|
61
61
|
|
|
62
62
|
class MarkdownTable(TableElement):
|
|
63
63
|
def __rich_console__(self, console: Console, options: ConsoleOptions) -> RenderResult:
|
|
64
|
-
|
|
64
|
+
# rich.box.MARKDOWN intentionally includes a blank top/bottom edge row. Rather than
|
|
65
|
+
# post-processing rendered segments, disable outer edges to avoid emitting those rows.
|
|
66
|
+
table = Table(
|
|
67
|
+
box=box.MARKDOWN,
|
|
68
|
+
show_edge=False,
|
|
69
|
+
border_style=console.get_style("markdown.table.border"),
|
|
70
|
+
)
|
|
65
71
|
|
|
66
72
|
if self.header is not None and self.header.row is not None:
|
|
67
73
|
for column in self.header.row.cells:
|
|
@@ -72,27 +78,7 @@ class MarkdownTable(TableElement):
|
|
|
72
78
|
row_content = [element.content for element in row.cells]
|
|
73
79
|
table.add_row(*row_content)
|
|
74
80
|
|
|
75
|
-
|
|
76
|
-
segments = list(console.render(table, options))
|
|
77
|
-
|
|
78
|
-
# Skip leading blank line (before first newline)
|
|
79
|
-
first_newline_idx = next((i for i, s in enumerate(segments) if s.text == "\n"), None)
|
|
80
|
-
if first_newline_idx is not None:
|
|
81
|
-
first_line = "".join(s.text for s in segments[:first_newline_idx])
|
|
82
|
-
if not first_line.strip():
|
|
83
|
-
segments = segments[first_newline_idx + 1 :]
|
|
84
|
-
|
|
85
|
-
# Skip trailing blank line (after last newline)
|
|
86
|
-
while len(segments) >= 2 and segments[-1].text == "\n":
|
|
87
|
-
prev_newline = next((i for i in range(len(segments) - 2, -1, -1) if segments[i].text == "\n"), None)
|
|
88
|
-
if prev_newline is not None:
|
|
89
|
-
between = "".join(s.text for s in segments[prev_newline + 1 : -1])
|
|
90
|
-
if not between.strip():
|
|
91
|
-
segments = segments[: prev_newline + 1]
|
|
92
|
-
continue
|
|
93
|
-
break
|
|
94
|
-
|
|
95
|
-
yield from segments
|
|
81
|
+
yield table
|
|
96
82
|
|
|
97
83
|
|
|
98
84
|
class LeftHeading(Heading):
|
|
@@ -23,8 +23,8 @@ from klaude_code.const import (
|
|
|
23
23
|
STATUS_SHIMMER_BAND_HALF_WIDTH,
|
|
24
24
|
STATUS_SHIMMER_PADDING,
|
|
25
25
|
)
|
|
26
|
-
from klaude_code.
|
|
27
|
-
from klaude_code.
|
|
26
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
27
|
+
from klaude_code.tui.terminal.color import get_last_terminal_background_rgb
|
|
28
28
|
|
|
29
29
|
# Use an existing Rich spinner name; BreathingSpinner overrides its rendering
|
|
30
30
|
BREATHING_SPINNER_NAME = "dots"
|
|
@@ -138,6 +138,7 @@ class ThemeKey(str, Enum):
|
|
|
138
138
|
STATUS_TEXT = "spinner.status.text"
|
|
139
139
|
STATUS_TEXT_BOLD = "spinner.status.text.bold"
|
|
140
140
|
STATUS_TEXT_BOLD_ITALIC = "spinner.status.text.bold_italic"
|
|
141
|
+
STATUS_TOAST = "spinner.status.toast"
|
|
141
142
|
# STATUS
|
|
142
143
|
STATUS_HINT = "status.hint"
|
|
143
144
|
# USER_INPUT
|
|
@@ -262,6 +263,7 @@ def get_theme(theme: str | None = None) -> Themes:
|
|
|
262
263
|
ThemeKey.STATUS_TEXT.value: palette.blue,
|
|
263
264
|
ThemeKey.STATUS_TEXT_BOLD.value: "bold " + palette.blue,
|
|
264
265
|
ThemeKey.STATUS_TEXT_BOLD_ITALIC.value: "bold italic " + palette.blue,
|
|
266
|
+
ThemeKey.STATUS_TOAST.value: "bold " + palette.yellow,
|
|
265
267
|
ThemeKey.STATUS_HINT.value: palette.grey2,
|
|
266
268
|
# REMINDER
|
|
267
269
|
ThemeKey.REMINDER.value: palette.grey1,
|
|
@@ -275,7 +277,7 @@ def get_theme(theme: str | None = None) -> Themes:
|
|
|
275
277
|
ThemeKey.TOOL_RESULT.value: palette.grey_green,
|
|
276
278
|
ThemeKey.TOOL_RESULT_TREE_PREFIX.value: palette.grey3 + " dim",
|
|
277
279
|
ThemeKey.TOOL_RESULT_BOLD.value: "bold " + palette.grey_green,
|
|
278
|
-
ThemeKey.TOOL_RESULT_TRUNCATED.value: palette.grey1,
|
|
280
|
+
ThemeKey.TOOL_RESULT_TRUNCATED.value: palette.grey1 + " dim",
|
|
279
281
|
ThemeKey.TOOL_MARK.value: "bold",
|
|
280
282
|
ThemeKey.TOOL_APPROVED.value: palette.green + " bold reverse",
|
|
281
283
|
ThemeKey.TOOL_REJECTED.value: palette.red + " bold reverse",
|
|
@@ -1,19 +1,16 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from typing import Any, cast
|
|
3
3
|
|
|
4
|
-
from rich import box
|
|
5
4
|
from rich.console import Group, RenderableType
|
|
6
5
|
from rich.json import JSON
|
|
7
|
-
from rich.
|
|
8
|
-
from rich.style import Style
|
|
6
|
+
from rich.style import Style, StyleType
|
|
9
7
|
from rich.text import Text
|
|
10
8
|
|
|
11
9
|
from klaude_code.const import SUB_AGENT_RESULT_MAX_LINES
|
|
12
10
|
from klaude_code.protocol import events, model
|
|
13
11
|
from klaude_code.protocol.sub_agent import get_sub_agent_profile_by_tool
|
|
14
|
-
from klaude_code.
|
|
15
|
-
from klaude_code.
|
|
16
|
-
from klaude_code.ui.rich.theme import ThemeKey
|
|
12
|
+
from klaude_code.tui.components.common import truncate_head
|
|
13
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
17
14
|
|
|
18
15
|
|
|
19
16
|
def _compact_schema_value(value: dict[str, Any]) -> str | list[Any] | dict[str, Any]:
|
|
@@ -83,13 +80,11 @@ def render_sub_agent_result(
|
|
|
83
80
|
result: str,
|
|
84
81
|
*,
|
|
85
82
|
code_theme: str,
|
|
86
|
-
style:
|
|
83
|
+
style: StyleType | None = None,
|
|
87
84
|
has_structured_output: bool = False,
|
|
88
85
|
description: str | None = None,
|
|
89
|
-
panel_style: Style | None = None,
|
|
90
86
|
) -> RenderableType:
|
|
91
87
|
stripped_result = result.strip()
|
|
92
|
-
result_panel_style = panel_style or ThemeKey.SUB_AGENT_RESULT_PANEL
|
|
93
88
|
|
|
94
89
|
# Extract agentId footer for separate styling
|
|
95
90
|
main_content, agent_id_footer = _extract_agent_id_footer(stripped_result)
|
|
@@ -106,15 +101,10 @@ def render_sub_agent_result(
|
|
|
106
101
|
JSON(stripped_result),
|
|
107
102
|
]
|
|
108
103
|
if description:
|
|
109
|
-
group_elements.insert(0,
|
|
104
|
+
group_elements.insert(0, Text(f"\n{description}", style=style or ""))
|
|
110
105
|
if agent_id_footer:
|
|
111
106
|
group_elements.append(Text(agent_id_footer, style=ThemeKey.SUB_AGENT_FOOTER))
|
|
112
|
-
return
|
|
113
|
-
Group(*group_elements),
|
|
114
|
-
box=box.SIMPLE,
|
|
115
|
-
border_style=ThemeKey.LINES,
|
|
116
|
-
style=result_panel_style,
|
|
117
|
-
)
|
|
107
|
+
return Group(*group_elements)
|
|
118
108
|
except json.JSONDecodeError:
|
|
119
109
|
# Fall back to markdown if not valid JSON
|
|
120
110
|
pass
|
|
@@ -122,42 +112,32 @@ def render_sub_agent_result(
|
|
|
122
112
|
if not stripped_result:
|
|
123
113
|
return Text()
|
|
124
114
|
|
|
125
|
-
# Add markdown heading if description is provided for non-structured output
|
|
126
|
-
if description:
|
|
127
|
-
stripped_result = f"# {description}\n\n{stripped_result}"
|
|
128
|
-
|
|
129
115
|
lines = stripped_result.splitlines()
|
|
130
116
|
if len(lines) > SUB_AGENT_RESULT_MAX_LINES:
|
|
131
117
|
hidden_count = len(lines) - SUB_AGENT_RESULT_MAX_LINES
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
118
|
+
tail_text = "\n".join(lines[-SUB_AGENT_RESULT_MAX_LINES:])
|
|
119
|
+
truncated_elements: list[RenderableType] = []
|
|
120
|
+
# Add description heading separately so it won't be truncated
|
|
121
|
+
if description:
|
|
122
|
+
truncated_elements.append(Text(f"---\n{description}", style=style or ""))
|
|
123
|
+
truncated_elements.append(
|
|
138
124
|
Text(
|
|
139
|
-
f"( … more {hidden_count} lines
|
|
125
|
+
f"( … more {hidden_count} lines)",
|
|
140
126
|
style=ThemeKey.TOOL_RESULT_TRUNCATED,
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
truncated_elements.append(Text(tail_text, style=style or ""))
|
|
144
130
|
if agent_id_footer:
|
|
145
131
|
truncated_elements.append(Text(agent_id_footer, style=ThemeKey.SUB_AGENT_FOOTER))
|
|
146
|
-
return
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
normal_elements: list[RenderableType] = [NoInsetMarkdown(stripped_result, code_theme=code_theme)]
|
|
132
|
+
return Group(*truncated_elements)
|
|
133
|
+
|
|
134
|
+
# No truncation needed - add description heading if provided
|
|
135
|
+
if description:
|
|
136
|
+
stripped_result = f"\n# {description}\n\n{stripped_result}"
|
|
137
|
+
normal_elements: list[RenderableType] = [Text(stripped_result)]
|
|
153
138
|
if agent_id_footer:
|
|
154
139
|
normal_elements.append(Text(agent_id_footer, style=ThemeKey.SUB_AGENT_FOOTER))
|
|
155
|
-
return
|
|
156
|
-
Group(*normal_elements),
|
|
157
|
-
box=box.SIMPLE,
|
|
158
|
-
border_style=ThemeKey.LINES,
|
|
159
|
-
style=result_panel_style,
|
|
160
|
-
)
|
|
140
|
+
return Group(*normal_elements)
|
|
161
141
|
|
|
162
142
|
|
|
163
143
|
def build_sub_agent_state_from_tool_call(e: events.ToolCallEvent) -> model.SubAgentState | None:
|
|
@@ -5,9 +5,9 @@ from rich.padding import Padding
|
|
|
5
5
|
from rich.text import Text
|
|
6
6
|
|
|
7
7
|
from klaude_code.const import MARKDOWN_RIGHT_MARGIN
|
|
8
|
-
from klaude_code.
|
|
9
|
-
from klaude_code.
|
|
10
|
-
from klaude_code.
|
|
8
|
+
from klaude_code.tui.components.common import create_grid
|
|
9
|
+
from klaude_code.tui.components.rich.markdown import ThinkingMarkdown
|
|
10
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
11
11
|
|
|
12
12
|
# UI markers
|
|
13
13
|
THINKING_MESSAGE_MARK = "∴"
|
|
@@ -17,14 +17,14 @@ from klaude_code.const import (
|
|
|
17
17
|
)
|
|
18
18
|
from klaude_code.protocol import events, model, tools
|
|
19
19
|
from klaude_code.protocol.sub_agent import is_sub_agent_tool as _is_sub_agent_tool
|
|
20
|
-
from klaude_code.
|
|
21
|
-
from klaude_code.
|
|
22
|
-
from klaude_code.
|
|
23
|
-
from klaude_code.
|
|
24
|
-
from klaude_code.
|
|
25
|
-
from klaude_code.
|
|
26
|
-
from klaude_code.
|
|
27
|
-
from klaude_code.
|
|
20
|
+
from klaude_code.tui.components import diffs as r_diffs
|
|
21
|
+
from klaude_code.tui.components import mermaid_viewer as r_mermaid_viewer
|
|
22
|
+
from klaude_code.tui.components.bash_syntax import highlight_bash_command
|
|
23
|
+
from klaude_code.tui.components.common import create_grid, truncate_middle
|
|
24
|
+
from klaude_code.tui.components.rich.code_panel import CodePanel
|
|
25
|
+
from klaude_code.tui.components.rich.markdown import NoInsetMarkdown
|
|
26
|
+
from klaude_code.tui.components.rich.quote import TreeQuote
|
|
27
|
+
from klaude_code.tui.components.rich.theme import ThemeKey
|
|
28
28
|
|
|
29
29
|
# Tool markers (Unicode symbols for UI display)
|
|
30
30
|
MARK_GENERIC = "⚒"
|
|
@@ -37,7 +37,6 @@ MARK_MERMAID = "⧉"
|
|
|
37
37
|
MARK_WEB_FETCH = "→"
|
|
38
38
|
MARK_WEB_SEARCH = "✱"
|
|
39
39
|
MARK_DONE = "✔"
|
|
40
|
-
MARK_SKILL = "✪"
|
|
41
40
|
|
|
42
41
|
# Todo status markers
|
|
43
42
|
MARK_TODO_PENDING = "▢"
|
|
@@ -487,11 +486,11 @@ def render_mermaid_tool_result(
|
|
|
487
486
|
*,
|
|
488
487
|
session_id: str | None = None,
|
|
489
488
|
) -> RenderableType:
|
|
490
|
-
from klaude_code.
|
|
489
|
+
from klaude_code.tui.terminal import supports_osc8_hyperlinks
|
|
491
490
|
|
|
492
491
|
link_info = _extract_mermaid_link(tr.ui_extra)
|
|
493
492
|
if link_info is None:
|
|
494
|
-
return render_generic_tool_result(tr.result, is_error=tr.
|
|
493
|
+
return render_generic_tool_result(tr.result, is_error=tr.is_error)
|
|
495
494
|
|
|
496
495
|
use_osc8 = supports_osc8_hyperlinks()
|
|
497
496
|
viewer = _render_mermaid_viewer_link(tr, link_info, use_osc8=use_osc8)
|
|
@@ -537,7 +536,6 @@ _TOOL_ACTIVE_FORM: dict[str, str] = {
|
|
|
537
536
|
tools.WRITE: "Writing",
|
|
538
537
|
tools.TODO_WRITE: "Planning",
|
|
539
538
|
tools.UPDATE_PLAN: "Planning",
|
|
540
|
-
tools.SKILL: "Skilling",
|
|
541
539
|
tools.MERMAID: "Diagramming",
|
|
542
540
|
tools.WEB_FETCH: "Fetching Web",
|
|
543
541
|
tools.WEB_SEARCH: "Searching Web",
|
|
@@ -589,8 +587,6 @@ def render_tool_call(e: events.ToolCallEvent) -> RenderableType | None:
|
|
|
589
587
|
return render_update_plan_tool_call(e.arguments)
|
|
590
588
|
case tools.MERMAID:
|
|
591
589
|
return render_mermaid_tool_call(e.arguments)
|
|
592
|
-
case tools.SKILL:
|
|
593
|
-
return render_generic_tool_call(e.tool_name, e.arguments, MARK_SKILL)
|
|
594
590
|
case tools.REPORT_BACK:
|
|
595
591
|
return render_report_back_tool_call()
|
|
596
592
|
case tools.WEB_FETCH:
|
|
@@ -649,7 +645,7 @@ def render_tool_result(
|
|
|
649
645
|
return TreeQuote.for_tool_result(content, is_last=e.is_last_in_turn)
|
|
650
646
|
|
|
651
647
|
# Handle error case
|
|
652
|
-
if e.
|
|
648
|
+
if e.is_error and e.ui_extra is None:
|
|
653
649
|
return wrap(render_generic_tool_result(e.result, is_error=True))
|
|
654
650
|
|
|
655
651
|
# Render multiple ui blocks if present
|
|
@@ -666,7 +662,7 @@ def render_tool_result(
|
|
|
666
662
|
# Show truncation info if output was truncated and saved to file
|
|
667
663
|
truncation_info = get_truncation_info(e)
|
|
668
664
|
if truncation_info:
|
|
669
|
-
result = render_generic_tool_result(e.result, is_error=e.
|
|
665
|
+
result = render_generic_tool_result(e.result, is_error=e.is_error)
|
|
670
666
|
return wrap(Group(render_truncation_info(truncation_info), result))
|
|
671
667
|
|
|
672
668
|
diff_ui = _extract_diff(e.ui_extra)
|
|
@@ -675,7 +671,7 @@ def render_tool_result(
|
|
|
675
671
|
def _render_fallback() -> TreeQuote:
|
|
676
672
|
if len(e.result.strip()) == 0:
|
|
677
673
|
return wrap(render_generic_tool_result("(no content)"))
|
|
678
|
-
return wrap(render_generic_tool_result(e.result, is_error=e.
|
|
674
|
+
return wrap(render_generic_tool_result(e.result, is_error=e.is_error))
|
|
679
675
|
|
|
680
676
|
match e.tool_name:
|
|
681
677
|
case tools.READ:
|