klaude-code 1.2.11__py3-none-any.whl → 1.2.13__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/codex/oauth.py +3 -3
- klaude_code/cli/main.py +5 -5
- klaude_code/cli/runtime.py +19 -27
- klaude_code/cli/session_cmd.py +6 -8
- klaude_code/command/__init__.py +31 -28
- klaude_code/command/clear_cmd.py +0 -2
- klaude_code/command/diff_cmd.py +0 -2
- klaude_code/command/export_cmd.py +3 -5
- klaude_code/command/help_cmd.py +0 -2
- klaude_code/command/model_cmd.py +0 -2
- klaude_code/command/refresh_cmd.py +0 -2
- klaude_code/command/registry.py +5 -9
- klaude_code/command/release_notes_cmd.py +0 -2
- klaude_code/command/status_cmd.py +2 -4
- klaude_code/command/terminal_setup_cmd.py +2 -4
- klaude_code/command/thinking_cmd.py +229 -0
- klaude_code/config/__init__.py +1 -1
- klaude_code/config/list_model.py +1 -1
- klaude_code/config/select_model.py +5 -15
- klaude_code/const/__init__.py +1 -1
- klaude_code/core/agent.py +14 -69
- klaude_code/core/executor.py +11 -10
- klaude_code/core/manager/agent_manager.py +4 -4
- klaude_code/core/manager/llm_clients.py +10 -49
- klaude_code/core/manager/llm_clients_builder.py +8 -21
- klaude_code/core/manager/sub_agent_manager.py +3 -3
- klaude_code/core/prompt.py +3 -3
- klaude_code/core/reminders.py +1 -1
- klaude_code/core/task.py +4 -5
- klaude_code/core/tool/__init__.py +16 -25
- klaude_code/core/tool/file/_utils.py +1 -1
- klaude_code/core/tool/file/apply_patch.py +17 -25
- klaude_code/core/tool/file/apply_patch_tool.py +4 -7
- klaude_code/core/tool/file/edit_tool.py +4 -11
- klaude_code/core/tool/file/multi_edit_tool.py +2 -3
- klaude_code/core/tool/file/read_tool.py +3 -4
- klaude_code/core/tool/file/write_tool.py +2 -3
- klaude_code/core/tool/memory/memory_tool.py +2 -8
- klaude_code/core/tool/memory/skill_loader.py +3 -2
- klaude_code/core/tool/shell/command_safety.py +0 -1
- klaude_code/core/tool/tool_context.py +1 -3
- klaude_code/core/tool/tool_registry.py +2 -1
- klaude_code/core/tool/tool_runner.py +1 -1
- klaude_code/core/tool/truncation.py +2 -5
- klaude_code/core/turn.py +9 -4
- klaude_code/llm/anthropic/client.py +62 -49
- klaude_code/llm/client.py +2 -20
- klaude_code/llm/codex/client.py +51 -32
- klaude_code/llm/input_common.py +2 -2
- klaude_code/llm/openai_compatible/client.py +60 -39
- klaude_code/llm/openai_compatible/stream_processor.py +2 -1
- klaude_code/llm/openrouter/client.py +79 -45
- klaude_code/llm/openrouter/reasoning_handler.py +19 -132
- klaude_code/llm/registry.py +6 -5
- klaude_code/llm/responses/client.py +65 -43
- klaude_code/llm/usage.py +1 -49
- klaude_code/protocol/commands.py +1 -0
- klaude_code/protocol/events.py +7 -0
- klaude_code/protocol/llm_param.py +1 -9
- klaude_code/protocol/model.py +10 -6
- klaude_code/protocol/sub_agent.py +2 -1
- klaude_code/session/export.py +1 -8
- klaude_code/session/selector.py +12 -7
- klaude_code/session/session.py +2 -4
- klaude_code/trace/__init__.py +1 -1
- klaude_code/trace/log.py +1 -1
- klaude_code/ui/__init__.py +4 -9
- klaude_code/ui/core/stage_manager.py +7 -4
- klaude_code/ui/modes/repl/__init__.py +1 -1
- klaude_code/ui/modes/repl/completers.py +6 -7
- klaude_code/ui/modes/repl/display.py +3 -4
- klaude_code/ui/modes/repl/event_handler.py +63 -5
- klaude_code/ui/modes/repl/key_bindings.py +2 -3
- klaude_code/ui/modes/repl/renderer.py +2 -1
- klaude_code/ui/renderers/diffs.py +1 -4
- klaude_code/ui/renderers/metadata.py +1 -12
- klaude_code/ui/rich/markdown.py +3 -3
- klaude_code/ui/rich/searchable_text.py +6 -6
- klaude_code/ui/rich/status.py +3 -4
- klaude_code/ui/rich/theme.py +1 -4
- klaude_code/ui/terminal/control.py +7 -16
- klaude_code/ui/terminal/notifier.py +2 -4
- klaude_code/ui/utils/common.py +1 -1
- klaude_code/ui/utils/debouncer.py +2 -2
- {klaude_code-1.2.11.dist-info → klaude_code-1.2.13.dist-info}/METADATA +1 -1
- {klaude_code-1.2.11.dist-info → klaude_code-1.2.13.dist-info}/RECORD +88 -87
- {klaude_code-1.2.11.dist-info → klaude_code-1.2.13.dist-info}/WHEEL +0 -0
- {klaude_code-1.2.11.dist-info → klaude_code-1.2.13.dist-info}/entry_points.txt +0 -0
klaude_code/auth/codex/oauth.py
CHANGED
|
@@ -78,13 +78,13 @@ class OAuthCallbackHandler(BaseHTTPRequestHandler):
|
|
|
78
78
|
self.end_headers()
|
|
79
79
|
|
|
80
80
|
if OAuthCallbackHandler.error:
|
|
81
|
-
html = """
|
|
81
|
+
html = f"""
|
|
82
82
|
<html><body style="font-family: sans-serif; text-align: center; padding: 50px;">
|
|
83
83
|
<h1>Authentication Failed</h1>
|
|
84
|
-
<p>Error: {}</p>
|
|
84
|
+
<p>Error: {OAuthCallbackHandler.error}</p>
|
|
85
85
|
<p>Please close this window and try again.</p>
|
|
86
86
|
</body></html>
|
|
87
|
-
"""
|
|
87
|
+
"""
|
|
88
88
|
else:
|
|
89
89
|
html = """
|
|
90
90
|
<html><body style="font-family: sans-serif; text-align: center; padding: 50px;">
|
klaude_code/cli/main.py
CHANGED
|
@@ -67,7 +67,7 @@ def login_command(
|
|
|
67
67
|
if state and not state.is_expired():
|
|
68
68
|
log(("You are already logged in to Codex.", "green"))
|
|
69
69
|
log(f" Account ID: {state.account_id[:8]}...")
|
|
70
|
-
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.
|
|
70
|
+
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
|
|
71
71
|
log(f" Expires: {expires_dt.strftime('%Y-%m-%d %H:%M:%S UTC')}")
|
|
72
72
|
if not typer.confirm("Do you want to re-login?"):
|
|
73
73
|
return
|
|
@@ -80,11 +80,11 @@ def login_command(
|
|
|
80
80
|
state = oauth.login()
|
|
81
81
|
log(("Login successful!", "green"))
|
|
82
82
|
log(f" Account ID: {state.account_id[:8]}...")
|
|
83
|
-
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.
|
|
83
|
+
expires_dt = datetime.datetime.fromtimestamp(state.expires_at, tz=datetime.UTC)
|
|
84
84
|
log(f" Expires: {expires_dt.strftime('%Y-%m-%d %H:%M:%S UTC')}")
|
|
85
85
|
except Exception as e:
|
|
86
86
|
log((f"Login failed: {e}", "red"))
|
|
87
|
-
raise typer.Exit(1)
|
|
87
|
+
raise typer.Exit(1) from None
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
@app.command("logout")
|
|
@@ -173,11 +173,11 @@ def edit_config() -> None:
|
|
|
173
173
|
subprocess.run([editor, str(config_path)], check=True)
|
|
174
174
|
except subprocess.CalledProcessError as e:
|
|
175
175
|
log((f"Error: Failed to open editor: {e}", "red"))
|
|
176
|
-
raise typer.Exit(1)
|
|
176
|
+
raise typer.Exit(1) from None
|
|
177
177
|
except FileNotFoundError:
|
|
178
178
|
log((f"Error: Editor '{editor}' not found", "red"))
|
|
179
179
|
log("Please install a text editor or set your $EDITOR environment variable")
|
|
180
|
-
raise typer.Exit(1)
|
|
180
|
+
raise typer.Exit(1) from None
|
|
181
181
|
|
|
182
182
|
|
|
183
183
|
@app.command("exec")
|
klaude_code/cli/runtime.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import contextlib
|
|
2
3
|
import sys
|
|
3
4
|
from dataclasses import dataclass
|
|
4
5
|
from typing import Any, Protocol
|
|
@@ -169,32 +170,26 @@ async def cleanup_app_components(components: AppComponents) -> None:
|
|
|
169
170
|
await components.display_task
|
|
170
171
|
finally:
|
|
171
172
|
# Always attempt to clear Ghostty progress bar and restore cursor visibility
|
|
172
|
-
|
|
173
|
+
# Best-effort only; never fail cleanup due to OSC errors
|
|
174
|
+
with contextlib.suppress(Exception):
|
|
173
175
|
emit_osc94(OSC94States.HIDDEN)
|
|
174
|
-
except Exception:
|
|
175
|
-
# Best-effort only; never fail cleanup due to OSC errors
|
|
176
|
-
pass
|
|
177
176
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
177
|
+
# Ensure the terminal cursor is visible even if Rich's Status spinner
|
|
178
|
+
# did not get a chance to stop cleanly (e.g. on KeyboardInterrupt).
|
|
179
|
+
# If this fails the shell can still recover via `reset`/`stty sane`.
|
|
180
|
+
with contextlib.suppress(Exception):
|
|
181
181
|
stream = getattr(sys, "__stdout__", None) or sys.stdout
|
|
182
182
|
stream.write("\033[?25h")
|
|
183
183
|
stream.flush()
|
|
184
|
-
except Exception:
|
|
185
|
-
# If this fails the shell can still recover via `reset`/`stty sane`.
|
|
186
|
-
pass
|
|
187
184
|
|
|
188
185
|
|
|
189
186
|
async def _handle_keyboard_interrupt(executor: Executor) -> None:
|
|
190
187
|
"""Handle Ctrl+C by logging and sending a global interrupt."""
|
|
191
188
|
|
|
192
189
|
log("Bye!")
|
|
193
|
-
|
|
190
|
+
# Executor might already be stopping
|
|
191
|
+
with contextlib.suppress(Exception):
|
|
194
192
|
await executor.submit(op.InterruptOperation(target_session_id=None))
|
|
195
|
-
except Exception:
|
|
196
|
-
# Executor might already be stopping
|
|
197
|
-
pass
|
|
198
193
|
|
|
199
194
|
|
|
200
195
|
async def run_exec(init_config: AppInitConfig, input_content: str) -> None:
|
|
@@ -259,9 +254,12 @@ async def run_interactive(init_config: AppInitConfig, session_id: str | None = N
|
|
|
259
254
|
if isinstance(components.display, ui.REPLDisplay):
|
|
260
255
|
printer = components.display.renderer
|
|
261
256
|
# Check if it's a DebugEventDisplay wrapping a REPLDisplay
|
|
262
|
-
elif
|
|
263
|
-
|
|
264
|
-
|
|
257
|
+
elif (
|
|
258
|
+
isinstance(components.display, ui.DebugEventDisplay)
|
|
259
|
+
and components.display.wrapped_display
|
|
260
|
+
and isinstance(components.display.wrapped_display, ui.REPLDisplay)
|
|
261
|
+
):
|
|
262
|
+
printer = components.display.wrapped_display.renderer
|
|
265
263
|
|
|
266
264
|
if printer is not None:
|
|
267
265
|
printer.print(Text(f" {MSG} ", style="bold yellow reverse"))
|
|
@@ -272,10 +270,8 @@ async def run_interactive(init_config: AppInitConfig, session_id: str | None = N
|
|
|
272
270
|
print(MSG, file=sys.stderr)
|
|
273
271
|
|
|
274
272
|
def _hide_progress() -> None:
|
|
275
|
-
|
|
273
|
+
with contextlib.suppress(Exception):
|
|
276
274
|
emit_osc94(OSC94States.HIDDEN)
|
|
277
|
-
except Exception:
|
|
278
|
-
pass
|
|
279
275
|
|
|
280
276
|
restore_sigint = install_sigint_double_press_exit(_show_toast_once, _hide_progress)
|
|
281
277
|
|
|
@@ -315,17 +311,13 @@ async def run_interactive(init_config: AppInitConfig, session_id: str | None = N
|
|
|
315
311
|
finally:
|
|
316
312
|
# Stop ESC monitor and wait for it to finish cleaning up TTY
|
|
317
313
|
stop_event.set()
|
|
318
|
-
|
|
314
|
+
with contextlib.suppress(Exception):
|
|
319
315
|
await esc_task
|
|
320
|
-
except Exception:
|
|
321
|
-
pass
|
|
322
316
|
|
|
323
317
|
except KeyboardInterrupt:
|
|
324
318
|
await _handle_keyboard_interrupt(components.executor)
|
|
325
319
|
finally:
|
|
326
|
-
|
|
327
|
-
|
|
320
|
+
# Restore original SIGINT handler
|
|
321
|
+
with contextlib.suppress(Exception):
|
|
328
322
|
restore_sigint()
|
|
329
|
-
except Exception:
|
|
330
|
-
pass
|
|
331
323
|
await cleanup_app_components(components)
|
klaude_code/cli/session_cmd.py
CHANGED
|
@@ -46,10 +46,9 @@ def session_clean(
|
|
|
46
46
|
log(f"No sessions with fewer than {min_messages} messages found.")
|
|
47
47
|
return
|
|
48
48
|
|
|
49
|
-
if not yes:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
return
|
|
49
|
+
if not yes and not _session_confirm(to_delete, "Delete these sessions?"):
|
|
50
|
+
log("Aborted.")
|
|
51
|
+
return
|
|
53
52
|
|
|
54
53
|
deleted = Session.clean_small_sessions(min_messages)
|
|
55
54
|
log(f"Deleted {deleted} session(s).")
|
|
@@ -65,10 +64,9 @@ def session_clean_all(
|
|
|
65
64
|
log("No sessions found.")
|
|
66
65
|
return
|
|
67
66
|
|
|
68
|
-
if not yes:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return
|
|
67
|
+
if not yes and not _session_confirm(sessions, "Delete ALL sessions? This cannot be undone."):
|
|
68
|
+
log("Aborted.")
|
|
69
|
+
return
|
|
72
70
|
|
|
73
71
|
deleted = Session.clean_all_sessions()
|
|
74
72
|
log(f"Deleted {deleted} session(s).")
|
klaude_code/command/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ from .registry import (
|
|
|
5
5
|
has_interactive_command,
|
|
6
6
|
is_slash_command_name,
|
|
7
7
|
load_prompt_commands,
|
|
8
|
-
|
|
8
|
+
register,
|
|
9
9
|
)
|
|
10
10
|
|
|
11
11
|
# Lazy load commands to avoid heavy imports at module load time
|
|
@@ -17,38 +17,41 @@ def ensure_commands_loaded() -> None:
|
|
|
17
17
|
|
|
18
18
|
This function is called internally by registry functions like get_commands(),
|
|
19
19
|
dispatch_command(), etc. It can also be called explicitly if early loading is desired.
|
|
20
|
+
|
|
21
|
+
Commands are registered in display order - the order here determines
|
|
22
|
+
the order shown in slash command completion.
|
|
20
23
|
"""
|
|
21
24
|
global _commands_loaded
|
|
22
25
|
if _commands_loaded:
|
|
23
26
|
return
|
|
24
27
|
_commands_loaded = True
|
|
25
28
|
|
|
26
|
-
# Import
|
|
27
|
-
from . import
|
|
28
|
-
from . import
|
|
29
|
-
from . import
|
|
30
|
-
from . import
|
|
31
|
-
from . import
|
|
32
|
-
from . import
|
|
33
|
-
from . import
|
|
34
|
-
from . import
|
|
35
|
-
from . import
|
|
36
|
-
|
|
37
|
-
# Suppress unused variable warnings
|
|
38
|
-
_ = (
|
|
39
|
-
_clear_cmd,
|
|
40
|
-
_diff_cmd,
|
|
41
|
-
_export_cmd,
|
|
42
|
-
_help_cmd,
|
|
43
|
-
_model_cmd,
|
|
44
|
-
_refresh_cmd,
|
|
45
|
-
_release_notes_cmd,
|
|
46
|
-
_status_cmd,
|
|
47
|
-
_terminal_setup_cmd,
|
|
48
|
-
)
|
|
29
|
+
# Import and register commands in display order
|
|
30
|
+
from .clear_cmd import ClearCommand
|
|
31
|
+
from .diff_cmd import DiffCommand
|
|
32
|
+
from .export_cmd import ExportCommand
|
|
33
|
+
from .help_cmd import HelpCommand
|
|
34
|
+
from .model_cmd import ModelCommand
|
|
35
|
+
from .refresh_cmd import RefreshTerminalCommand
|
|
36
|
+
from .release_notes_cmd import ReleaseNotesCommand
|
|
37
|
+
from .status_cmd import StatusCommand
|
|
38
|
+
from .terminal_setup_cmd import TerminalSetupCommand
|
|
39
|
+
from .thinking_cmd import ThinkingCommand
|
|
49
40
|
|
|
50
|
-
#
|
|
41
|
+
# Register in desired display order
|
|
42
|
+
register(ExportCommand())
|
|
43
|
+
register(RefreshTerminalCommand())
|
|
44
|
+
register(ThinkingCommand())
|
|
45
|
+
register(ModelCommand())
|
|
51
46
|
load_prompt_commands()
|
|
47
|
+
register(ClearCommand())
|
|
48
|
+
register(StatusCommand())
|
|
49
|
+
register(DiffCommand())
|
|
50
|
+
register(HelpCommand())
|
|
51
|
+
register(ReleaseNotesCommand())
|
|
52
|
+
register(TerminalSetupCommand())
|
|
53
|
+
|
|
54
|
+
# Load prompt-based commands (appended after built-in commands)
|
|
52
55
|
|
|
53
56
|
|
|
54
57
|
# Lazy accessors for command classes
|
|
@@ -63,6 +66,7 @@ def __getattr__(name: str) -> object:
|
|
|
63
66
|
"ReleaseNotesCommand": "release_notes_cmd",
|
|
64
67
|
"StatusCommand": "status_cmd",
|
|
65
68
|
"TerminalSetupCommand": "terminal_setup_cmd",
|
|
69
|
+
"ThinkingCommand": "thinking_cmd",
|
|
66
70
|
}
|
|
67
71
|
if name in _commands_map:
|
|
68
72
|
import importlib
|
|
@@ -77,14 +81,13 @@ __all__ = [
|
|
|
77
81
|
# "ClearCommand", "DiffCommand", "HelpCommand", "ModelCommand",
|
|
78
82
|
# "ExportCommand", "RefreshTerminalCommand", "ReleaseNotesCommand",
|
|
79
83
|
# "StatusCommand", "TerminalSetupCommand",
|
|
80
|
-
"register_command",
|
|
81
84
|
"CommandABC",
|
|
82
85
|
"CommandResult",
|
|
83
86
|
"InputAction",
|
|
84
87
|
"InputActionType",
|
|
85
88
|
"dispatch_command",
|
|
89
|
+
"ensure_commands_loaded",
|
|
86
90
|
"get_commands",
|
|
87
|
-
"is_slash_command_name",
|
|
88
91
|
"has_interactive_command",
|
|
89
|
-
"
|
|
92
|
+
"is_slash_command_name",
|
|
90
93
|
]
|
klaude_code/command/clear_cmd.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
from klaude_code.command.command_abc import CommandABC, CommandResult, InputAction
|
|
4
|
-
from klaude_code.command.registry import register_command
|
|
5
4
|
from klaude_code.protocol import commands
|
|
6
5
|
|
|
7
6
|
if TYPE_CHECKING:
|
|
8
7
|
from klaude_code.core.agent import Agent
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
@register_command
|
|
12
10
|
class ClearCommand(CommandABC):
|
|
13
11
|
"""Clear current session and start a new conversation"""
|
|
14
12
|
|
klaude_code/command/diff_cmd.py
CHANGED
|
@@ -3,14 +3,12 @@ from pathlib import Path
|
|
|
3
3
|
from typing import TYPE_CHECKING
|
|
4
4
|
|
|
5
5
|
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
6
|
-
from klaude_code.command.registry import register_command
|
|
7
6
|
from klaude_code.protocol import commands, events, model
|
|
8
7
|
|
|
9
8
|
if TYPE_CHECKING:
|
|
10
9
|
from klaude_code.core.agent import Agent
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
@register_command
|
|
14
12
|
class DiffCommand(CommandABC):
|
|
15
13
|
"""Show git diff for the current repository."""
|
|
16
14
|
|
|
@@ -5,7 +5,6 @@ from pathlib import Path
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
7
|
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
8
|
-
from klaude_code.command.registry import register_command
|
|
9
8
|
from klaude_code.protocol import commands, events, model
|
|
10
9
|
from klaude_code.session.export import build_export_html, get_default_export_path
|
|
11
10
|
|
|
@@ -13,7 +12,6 @@ if TYPE_CHECKING:
|
|
|
13
12
|
from klaude_code.core.agent import Agent
|
|
14
13
|
|
|
15
14
|
|
|
16
|
-
@register_command
|
|
17
15
|
class ExportCommand(CommandABC):
|
|
18
16
|
"""Export the current session into a standalone HTML transcript."""
|
|
19
17
|
|
|
@@ -33,7 +31,7 @@ class ExportCommand(CommandABC):
|
|
|
33
31
|
def is_interactive(self) -> bool:
|
|
34
32
|
return False
|
|
35
33
|
|
|
36
|
-
async def run(self, raw: str, agent:
|
|
34
|
+
async def run(self, raw: str, agent: Agent) -> CommandResult:
|
|
37
35
|
try:
|
|
38
36
|
output_path = self._resolve_output_path(raw, agent)
|
|
39
37
|
html_doc = self._build_html(agent)
|
|
@@ -60,7 +58,7 @@ class ExportCommand(CommandABC):
|
|
|
60
58
|
)
|
|
61
59
|
return CommandResult(events=[event])
|
|
62
60
|
|
|
63
|
-
def _resolve_output_path(self, raw: str, agent:
|
|
61
|
+
def _resolve_output_path(self, raw: str, agent: Agent) -> Path:
|
|
64
62
|
trimmed = raw.strip()
|
|
65
63
|
if trimmed:
|
|
66
64
|
candidate = Path(trimmed).expanduser()
|
|
@@ -81,7 +79,7 @@ class ExportCommand(CommandABC):
|
|
|
81
79
|
msg = f"Failed to open HTML with `open`: {exc}"
|
|
82
80
|
raise RuntimeError(msg) from exc
|
|
83
81
|
|
|
84
|
-
def _build_html(self, agent:
|
|
82
|
+
def _build_html(self, agent: Agent) -> str:
|
|
85
83
|
profile = agent.profile
|
|
86
84
|
system_prompt = (profile.system_prompt if profile else "") or ""
|
|
87
85
|
tools = profile.tools if profile else []
|
klaude_code/command/help_cmd.py
CHANGED
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
4
|
-
from klaude_code.command.registry import register_command
|
|
5
4
|
from klaude_code.protocol import commands, events, model
|
|
6
5
|
|
|
7
6
|
if TYPE_CHECKING:
|
|
8
7
|
from klaude_code.core.agent import Agent
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
@register_command
|
|
12
10
|
class HelpCommand(CommandABC):
|
|
13
11
|
"""Display help information for all available slash commands."""
|
|
14
12
|
|
klaude_code/command/model_cmd.py
CHANGED
|
@@ -2,7 +2,6 @@ import asyncio
|
|
|
2
2
|
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from klaude_code.command.command_abc import CommandABC, CommandResult, InputAction
|
|
5
|
-
from klaude_code.command.registry import register_command
|
|
6
5
|
from klaude_code.config import select_model_from_config
|
|
7
6
|
from klaude_code.protocol import commands, events, model
|
|
8
7
|
|
|
@@ -10,7 +9,6 @@ if TYPE_CHECKING:
|
|
|
10
9
|
from klaude_code.core.agent import Agent
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
@register_command
|
|
14
12
|
class ModelCommand(CommandABC):
|
|
15
13
|
"""Display or change the model configuration."""
|
|
16
14
|
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
4
|
-
from klaude_code.command.registry import register_command
|
|
5
4
|
from klaude_code.protocol import commands, events
|
|
6
5
|
|
|
7
6
|
if TYPE_CHECKING:
|
|
8
7
|
from klaude_code.core.agent import Agent
|
|
9
8
|
|
|
10
9
|
|
|
11
|
-
@register_command
|
|
12
10
|
class RefreshTerminalCommand(CommandABC):
|
|
13
11
|
"""Refresh terminal display"""
|
|
14
12
|
|
klaude_code/command/registry.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from importlib.resources import files
|
|
2
|
-
from typing import TYPE_CHECKING
|
|
2
|
+
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from klaude_code.command.command_abc import CommandResult, InputAction
|
|
5
5
|
from klaude_code.command.prompt_command import PromptCommand
|
|
@@ -13,14 +13,10 @@ if TYPE_CHECKING:
|
|
|
13
13
|
|
|
14
14
|
_COMMANDS: dict[commands.CommandName | str, "CommandABC"] = {}
|
|
15
15
|
|
|
16
|
-
T = TypeVar("T", bound="CommandABC")
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
instance = cls()
|
|
22
|
-
_COMMANDS[instance.name] = instance
|
|
23
|
-
return cls
|
|
17
|
+
def register(cmd: "CommandABC") -> None:
|
|
18
|
+
"""Register a command instance. Order of registration determines display order."""
|
|
19
|
+
_COMMANDS[cmd.name] = cmd
|
|
24
20
|
|
|
25
21
|
|
|
26
22
|
def load_prompt_commands():
|
|
@@ -98,7 +94,7 @@ async def dispatch_command(raw: str, agent: "Agent") -> CommandResult:
|
|
|
98
94
|
events.DeveloperMessageEvent(
|
|
99
95
|
session_id=agent.session.id,
|
|
100
96
|
item=model.DeveloperMessageItem(
|
|
101
|
-
content=f"Command {command_identifier} error: [{e.__class__.__name__}] {
|
|
97
|
+
content=f"Command {command_identifier} error: [{e.__class__.__name__}] {e!s}",
|
|
102
98
|
command_output=command_output,
|
|
103
99
|
),
|
|
104
100
|
)
|
|
@@ -2,7 +2,6 @@ from pathlib import Path
|
|
|
2
2
|
from typing import TYPE_CHECKING
|
|
3
3
|
|
|
4
4
|
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
5
|
-
from klaude_code.command.registry import register_command
|
|
6
5
|
from klaude_code.protocol import commands, events, model
|
|
7
6
|
|
|
8
7
|
if TYPE_CHECKING:
|
|
@@ -62,7 +61,6 @@ def _extract_releases(changelog: str, count: int = 1) -> str:
|
|
|
62
61
|
return "\n".join("\n".join(release) for release in releases).strip()
|
|
63
62
|
|
|
64
63
|
|
|
65
|
-
@register_command
|
|
66
64
|
class ReleaseNotesCommand(CommandABC):
|
|
67
65
|
"""Display the latest release notes from CHANGELOG.md."""
|
|
68
66
|
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from typing import TYPE_CHECKING
|
|
2
2
|
|
|
3
3
|
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
4
|
-
from klaude_code.command.registry import register_command
|
|
5
4
|
from klaude_code.protocol import commands, events, model
|
|
6
5
|
from klaude_code.session.session import Session
|
|
7
6
|
|
|
@@ -60,8 +59,8 @@ def accumulate_session_usage(session: Session) -> AggregatedUsage:
|
|
|
60
59
|
total.cache_read_cost = (total.cache_read_cost or 0.0) + usage.cache_read_cost
|
|
61
60
|
|
|
62
61
|
# Track peak context window size (max across all tasks)
|
|
63
|
-
if usage.
|
|
64
|
-
total.
|
|
62
|
+
if usage.context_size is not None:
|
|
63
|
+
total.context_size = usage.context_size
|
|
65
64
|
|
|
66
65
|
# Keep the latest context_limit for computed context_usage_percent
|
|
67
66
|
if usage.context_limit is not None:
|
|
@@ -127,7 +126,6 @@ def format_status_content(aggregated: AggregatedUsage) -> str:
|
|
|
127
126
|
return "\n".join(lines)
|
|
128
127
|
|
|
129
128
|
|
|
130
|
-
@register_command
|
|
131
129
|
class StatusCommand(CommandABC):
|
|
132
130
|
"""Display session usage statistics."""
|
|
133
131
|
|
|
@@ -4,14 +4,12 @@ from pathlib import Path
|
|
|
4
4
|
from typing import TYPE_CHECKING
|
|
5
5
|
|
|
6
6
|
from klaude_code.command.command_abc import CommandABC, CommandResult
|
|
7
|
-
from klaude_code.command.registry import register_command
|
|
8
7
|
from klaude_code.protocol import commands, events, model
|
|
9
8
|
|
|
10
9
|
if TYPE_CHECKING:
|
|
11
10
|
from klaude_code.core.agent import Agent
|
|
12
11
|
|
|
13
12
|
|
|
14
|
-
@register_command
|
|
15
13
|
class TerminalSetupCommand(CommandABC):
|
|
16
14
|
"""Setup shift+enter newline functionality in terminal"""
|
|
17
15
|
|
|
@@ -45,7 +43,7 @@ class TerminalSetupCommand(CommandABC):
|
|
|
45
43
|
return self._create_success_result(agent, message)
|
|
46
44
|
|
|
47
45
|
except Exception as e:
|
|
48
|
-
return self._create_error_result(agent, f"Error configuring terminal: {
|
|
46
|
+
return self._create_error_result(agent, f"Error configuring terminal: {e!s}")
|
|
49
47
|
|
|
50
48
|
def _setup_ghostty(self) -> str:
|
|
51
49
|
"""Configure shift+enter newline for Ghostty terminal"""
|
|
@@ -115,7 +113,7 @@ class TerminalSetupCommand(CommandABC):
|
|
|
115
113
|
)
|
|
116
114
|
|
|
117
115
|
except Exception as e:
|
|
118
|
-
raise Exception(f"Error configuring iTerm: {
|
|
116
|
+
raise Exception(f"Error configuring iTerm: {e!s}") from e
|
|
119
117
|
|
|
120
118
|
def _setup_vscode_family(self) -> str:
|
|
121
119
|
"""Configure shift+enter newline for VS Code family terminals (VS Code, Windsurf, Cursor).
|