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
@@ -1,194 +0,0 @@
1
- from typing import Literal
2
-
3
- from pydantic import BaseModel
4
-
5
- from klaude_code.protocol import llm_param, message, model
6
-
7
- """
8
- Event is how Agent Executor and UI Display communicate.
9
- """
10
-
11
-
12
- class EndEvent(BaseModel):
13
- pass
14
-
15
-
16
- class ErrorEvent(BaseModel):
17
- error_message: str
18
- can_retry: bool = False
19
- session_id: str | None = None
20
-
21
-
22
- class TaskStartEvent(BaseModel):
23
- session_id: str
24
- sub_agent_state: model.SubAgentState | None = None
25
-
26
-
27
- class TaskFinishEvent(BaseModel):
28
- session_id: str
29
- task_result: str
30
- has_structured_output: bool = False
31
-
32
-
33
- class TurnStartEvent(BaseModel):
34
- """For now, this event is used for UI to flush developer message buffer and print an empty line"""
35
-
36
- session_id: str
37
-
38
-
39
- class TurnEndEvent(BaseModel):
40
- session_id: str
41
-
42
-
43
- class TurnToolCallStartEvent(BaseModel):
44
- """For UI changing status text"""
45
-
46
- session_id: str
47
- response_id: str | None = None
48
- tool_call_id: str
49
- tool_name: str
50
- arguments: str
51
-
52
-
53
- class ThinkingDeltaEvent(BaseModel):
54
- session_id: str
55
- response_id: str | None = None
56
- content: str
57
-
58
-
59
- class AssistantTextDeltaEvent(BaseModel):
60
- session_id: str
61
- response_id: str | None = None
62
- content: str
63
-
64
-
65
- class AssistantImageDeltaEvent(BaseModel):
66
- session_id: str
67
- response_id: str | None = None
68
- file_path: str
69
-
70
-
71
- class AssistantMessageEvent(BaseModel):
72
- response_id: str | None = None
73
- session_id: str
74
- content: str
75
- thinking_text: str | None = None
76
-
77
-
78
- class DeveloperMessageEvent(BaseModel):
79
- """DeveloperMessages are reminders in user messages or tool results, see: core/reminders.py"""
80
-
81
- session_id: str
82
- item: message.DeveloperMessage
83
-
84
-
85
- class ToolCallEvent(BaseModel):
86
- session_id: str
87
- response_id: str | None = None
88
- tool_call_id: str
89
- tool_name: str
90
- arguments: str
91
-
92
-
93
- class ToolResultEvent(BaseModel):
94
- session_id: str
95
- response_id: str | None = None
96
- tool_call_id: str
97
- tool_name: str
98
- result: str
99
- ui_extra: model.ToolResultUIExtra | None = None
100
- status: Literal["success", "error"]
101
- task_metadata: model.TaskMetadata | None = None # Sub-agent task metadata
102
- # Whether this tool result is the last one emitted in the current turn.
103
- # Used by UI renderers to close tree-style prefixes.
104
- is_last_in_turn: bool = True
105
-
106
-
107
- class ResponseMetadataEvent(BaseModel):
108
- """Internal event for turn-level metadata. Not exposed to UI directly."""
109
-
110
- session_id: str
111
- metadata: model.Usage
112
-
113
-
114
- class TaskMetadataEvent(BaseModel):
115
- """Task-level aggregated metadata for UI display."""
116
-
117
- session_id: str
118
- metadata: model.TaskMetadataItem
119
-
120
-
121
- class UserMessageEvent(BaseModel):
122
- session_id: str
123
- content: str
124
- images: list[message.ImageURLPart] | None = None
125
-
126
-
127
- class WelcomeEvent(BaseModel):
128
- work_dir: str
129
- llm_config: llm_param.LLMConfigParameter
130
-
131
-
132
- class InterruptEvent(BaseModel):
133
- session_id: str
134
-
135
-
136
- class TodoChangeEvent(BaseModel):
137
- session_id: str
138
- todos: list[model.TodoItem]
139
-
140
-
141
- class ContextUsageEvent(BaseModel):
142
- """Real-time context usage update during task execution."""
143
-
144
- session_id: str
145
- context_percent: float # Context usage percentage (0-100)
146
-
147
-
148
- HistoryItemEvent = (
149
- TaskStartEvent
150
- | TaskFinishEvent
151
- | TurnStartEvent # This event is used for UI to print new empty line
152
- | AssistantImageDeltaEvent
153
- | AssistantMessageEvent
154
- | ToolCallEvent
155
- | ToolResultEvent
156
- | UserMessageEvent
157
- | TaskMetadataEvent
158
- | InterruptEvent
159
- | DeveloperMessageEvent
160
- | ErrorEvent
161
- )
162
-
163
-
164
- class ReplayHistoryEvent(BaseModel):
165
- session_id: str
166
- events: list[HistoryItemEvent]
167
- updated_at: float
168
- is_load: bool = True
169
-
170
-
171
- Event = (
172
- TaskStartEvent
173
- | TaskFinishEvent
174
- | ThinkingDeltaEvent
175
- | AssistantTextDeltaEvent
176
- | AssistantImageDeltaEvent
177
- | AssistantMessageEvent
178
- | ToolCallEvent
179
- | ToolResultEvent
180
- | ResponseMetadataEvent
181
- | TaskMetadataEvent
182
- | ReplayHistoryEvent
183
- | ErrorEvent
184
- | EndEvent
185
- | WelcomeEvent
186
- | UserMessageEvent
187
- | InterruptEvent
188
- | DeveloperMessageEvent
189
- | TodoChangeEvent
190
- | TurnStartEvent
191
- | TurnEndEvent
192
- | TurnToolCallStartEvent
193
- | ContextUsageEvent
194
- )
@@ -1,108 +0,0 @@
1
- ---
2
- name: dev-docs
3
- description: Manage development documentation for complex tasks. Use this skill when users want to create a strategic plan with structured task breakdown, or update development documentation before context compaction/reset. Triggers include "create a plan", "dev docs", "update docs before context reset", "context limit approaching".
4
- metadata:
5
- short-description: Create and update development documentation
6
- ---
7
-
8
- # Dev Docs
9
-
10
- Manage development documentation for complex, multi-phase tasks. This skill supports two workflows:
11
- 1. **Create**: Generate a comprehensive strategic plan with structured task breakdown
12
- 2. **Update**: Update documentation before context compaction or reset
13
-
14
- ## Create Development Plan
15
-
16
- When creating a new plan:
17
-
18
- 1. **Analyze the request** and determine the scope of planning needed
19
- 2. **Examine relevant files** in the codebase to understand current state
20
- 3. **Create a structured plan** with:
21
- - Executive Summary
22
- - Current State Analysis
23
- - Proposed Future State
24
- - Implementation Phases (broken into sections)
25
- - Detailed Tasks (actionable items with clear acceptance criteria)
26
- - Risk Assessment and Mitigation Strategies
27
- - Success Metrics
28
- - Required Resources and Dependencies
29
-
30
- 4. **Task Breakdown Structure**:
31
- - Each major section represents a phase or component
32
- - Number and prioritize tasks within sections
33
- - Include clear acceptance criteria for each task
34
- - Specify dependencies between tasks
35
- - Estimate effort levels (S/M/L/XL)
36
-
37
- 5. **Create task management structure**:
38
- - Create directory: `dev/active/[task-name]/` (relative to project root)
39
- - Generate three files:
40
- - `[task-name]-plan.md` - The comprehensive plan
41
- - `[task-name]-context.md` - Key files, decisions, dependencies
42
- - `[task-name]-tasks.md` - Checklist format for tracking progress
43
- - Include "Last Updated: YYYY-MM-DD" in each file
44
-
45
- 6. **Stop and Consult**: Pause and negotiate the plan with the user.
46
-
47
- ### Quality Standards
48
-
49
- - Plans must be self-contained with all necessary context
50
- - Use clear, actionable language
51
- - Include specific technical details where relevant
52
- - Consider both technical and business perspectives
53
- - Account for potential risks and edge cases
54
-
55
- ## Update Development Documentation
56
-
57
- When approaching context limits or before context reset:
58
-
59
- ### 1. Update Active Task Documentation
60
-
61
- For each task in `/dev/active/`:
62
-
63
- Update `[task-name]-context.md` with:
64
- - Current implementation state
65
- - Key decisions made this session
66
- - Files modified and why
67
- - Any blockers or issues discovered
68
- - Next immediate steps
69
- - Last Updated timestamp
70
-
71
- Update `[task-name]-tasks.md` with:
72
- - Mark completed tasks with checkmark
73
- - Add any new tasks discovered
74
- - Update in-progress tasks with current status
75
- - Reorder priorities if needed
76
-
77
- ### 2. Capture Session Context
78
-
79
- Include any relevant information about:
80
- - Complex problems solved
81
- - Architectural decisions made
82
- - Tricky bugs found and fixed
83
- - Integration points discovered
84
- - Testing approaches used
85
- - Performance optimizations made
86
-
87
- ### 3. Update Memory (if applicable)
88
-
89
- - Store any new patterns or solutions in project memory/documentation
90
- - Update entity relationships discovered
91
- - Add observations about system behavior
92
-
93
- ### 4. Document Unfinished Work
94
-
95
- - What was being worked on when context limit approached
96
- - Exact state of any partially completed features
97
- - Commands that need to be run on restart
98
- - Any temporary workarounds that need permanent fixes
99
-
100
- ### 5. Create Handoff Notes
101
-
102
- If switching to a new conversation:
103
- - Exact file and line being edited
104
- - The goal of current changes
105
- - Any uncommitted changes that need attention
106
- - Test commands to verify work
107
-
108
- **Priority**: Focus on capturing information that would be hard to rediscover or reconstruct from code alone.
@@ -1,21 +0,0 @@
1
- from .log import (
2
- DebugType,
3
- get_current_log_file,
4
- is_debug_enabled,
5
- log,
6
- log_debug,
7
- logger,
8
- prepare_debug_log_file,
9
- set_debug_logging,
10
- )
11
-
12
- __all__ = [
13
- "DebugType",
14
- "get_current_log_file",
15
- "is_debug_enabled",
16
- "log",
17
- "log_debug",
18
- "logger",
19
- "prepare_debug_log_file",
20
- "set_debug_logging",
21
- ]
@@ -1,48 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from collections.abc import Awaitable, Callable
4
- from enum import Enum
5
-
6
-
7
- class Stage(Enum):
8
- WAITING = "waiting"
9
- THINKING = "thinking"
10
- ASSISTANT = "assistant"
11
- TOOL_CALL = "tool_call"
12
- TOOL_RESULT = "tool_result"
13
-
14
-
15
- class StageManager:
16
- """Manage display stage transitions and invoke lifecycle callbacks."""
17
-
18
- def __init__(
19
- self,
20
- *,
21
- finish_assistant: Callable[[], Awaitable[None]],
22
- finish_thinking: Callable[[], Awaitable[None]],
23
- ):
24
- self._stage = Stage.WAITING
25
- self._finish_assistant = finish_assistant
26
- self._finish_thinking = finish_thinking
27
-
28
- @property
29
- def current_stage(self) -> Stage:
30
- return self._stage
31
-
32
- async def transition_to(self, new_stage: Stage) -> None:
33
- if self._stage == new_stage:
34
- return
35
- await self._leave_current_stage()
36
- self._stage = new_stage
37
-
38
- async def enter_thinking_stage(self) -> None:
39
- if self._stage == Stage.THINKING:
40
- return
41
- await self.transition_to(Stage.THINKING)
42
-
43
- async def _leave_current_stage(self) -> None:
44
- if self._stage == Stage.THINKING:
45
- await self._finish_thinking()
46
- elif self._stage == Stage.ASSISTANT:
47
- await self._finish_assistant()
48
- self._stage = Stage.WAITING
@@ -1 +0,0 @@
1
- # UI mode implementations
@@ -1 +0,0 @@
1
- # Debug mode
@@ -1 +0,0 @@
1
- # Exec mode
@@ -1,61 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import contextlib
4
- from typing import override
5
-
6
- from klaude_code.protocol import events
7
- from klaude_code.ui.core.display import DisplayABC
8
- from klaude_code.ui.modes.repl.event_handler import DisplayEventHandler
9
- from klaude_code.ui.modes.repl.renderer import REPLRenderer
10
- from klaude_code.ui.terminal.notifier import TerminalNotifier
11
-
12
-
13
- class REPLDisplay(DisplayABC):
14
- """
15
- Interactive terminal display using Rich for rendering.
16
-
17
- REPLDisplay provides a full-featured terminal UI with:
18
- - Rich markdown rendering for assistant messages
19
- - Syntax-highlighted code blocks and diffs
20
- - Animated spinners for in-progress operations
21
- - Tool call and result visualization
22
- - OSC94 progress bar integration (for supported terminals)
23
- - Desktop notifications on task completion
24
-
25
- This is the primary display mode for interactive klaude-code sessions.
26
- For non-interactive use, see ExecDisplay. For debugging, wrap with
27
- DebugEventDisplay.
28
-
29
- Lifecycle:
30
- 1. start(): No-op (initialization happens in __init__)
31
- 2. consume_event(): Delegates to DisplayEventHandler for event processing
32
- 3. stop(): Stops the event handler and ensures spinner is cleaned up
33
-
34
- Attributes:
35
- renderer: The REPLRenderer instance for terminal output
36
- notifier: TerminalNotifier for desktop notifications
37
- event_handler: DisplayEventHandler that processes events
38
- """
39
-
40
- def __init__(self, theme: str | None = None, notifier: TerminalNotifier | None = None):
41
- self.renderer = REPLRenderer(theme)
42
- self.notifier = notifier or TerminalNotifier()
43
- self.event_handler = DisplayEventHandler(self.renderer, notifier=self.notifier)
44
-
45
- @override
46
- async def consume_event(self, event: events.Event) -> None:
47
- await self.event_handler.consume_event(event)
48
-
49
- @override
50
- async def start(self) -> None:
51
- pass
52
-
53
- @override
54
- async def stop(self) -> None:
55
- await self.event_handler.stop()
56
- # Ensure any active spinner is stopped so Rich restores the cursor.
57
- # Spinner may already be stopped or not started; ignore.
58
- with contextlib.suppress(Exception):
59
- self.renderer.spinner_stop()
60
- with contextlib.suppress(Exception):
61
- self.renderer.stop_bottom_live()