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 +1,56 @@
|
|
|
1
1
|
# Terminal utilities
|
|
2
|
+
import os
|
|
3
|
+
from functools import lru_cache
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@lru_cache(maxsize=1)
|
|
7
|
+
def supports_osc8_hyperlinks() -> bool:
|
|
8
|
+
"""Check if the current terminal supports OSC 8 hyperlinks.
|
|
9
|
+
|
|
10
|
+
Based on known terminal support. Returns False for unknown terminals.
|
|
11
|
+
"""
|
|
12
|
+
term_program = os.environ.get("TERM_PROGRAM", "").lower()
|
|
13
|
+
term = os.environ.get("TERM", "").lower()
|
|
14
|
+
|
|
15
|
+
# Known terminals that do NOT support OSC 8
|
|
16
|
+
unsupported = ("warp", "apple_terminal")
|
|
17
|
+
if any(t in term_program for t in unsupported):
|
|
18
|
+
return False
|
|
19
|
+
|
|
20
|
+
# Known terminals that support OSC 8
|
|
21
|
+
supported = (
|
|
22
|
+
"iterm.app",
|
|
23
|
+
"ghostty",
|
|
24
|
+
"wezterm",
|
|
25
|
+
"kitty",
|
|
26
|
+
"alacritty",
|
|
27
|
+
"hyper",
|
|
28
|
+
"contour",
|
|
29
|
+
"vscode",
|
|
30
|
+
)
|
|
31
|
+
if any(t in term_program for t in supported):
|
|
32
|
+
return True
|
|
33
|
+
|
|
34
|
+
# Kitty sets TERM to xterm-kitty
|
|
35
|
+
if "kitty" in term:
|
|
36
|
+
return True
|
|
37
|
+
|
|
38
|
+
# Ghostty sets TERM to xterm-ghostty
|
|
39
|
+
if "ghostty" in term:
|
|
40
|
+
return True
|
|
41
|
+
|
|
42
|
+
# Windows Terminal
|
|
43
|
+
if os.environ.get("WT_SESSION"):
|
|
44
|
+
return True
|
|
45
|
+
|
|
46
|
+
# VTE-based terminals (GNOME Terminal, etc.) version 0.50+
|
|
47
|
+
vte_version = os.environ.get("VTE_VERSION", "")
|
|
48
|
+
if vte_version:
|
|
49
|
+
try:
|
|
50
|
+
if int(vte_version) >= 5000:
|
|
51
|
+
return True
|
|
52
|
+
except ValueError:
|
|
53
|
+
pass
|
|
54
|
+
|
|
55
|
+
# Default to False for unknown terminals
|
|
56
|
+
return False
|
klaude_code/ui/terminal/color.py
CHANGED
|
@@ -182,7 +182,7 @@ def _parse_osc_color_response(data: bytes) -> tuple[int, int, int] | None:
|
|
|
182
182
|
|
|
183
183
|
try:
|
|
184
184
|
text = data.decode("ascii", errors="ignore")
|
|
185
|
-
except
|
|
185
|
+
except LookupError: # encoding lookup failure (should not happen with "ascii")
|
|
186
186
|
return None
|
|
187
187
|
|
|
188
188
|
match = _OSC_BG_REGEX.search(text)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import contextlib
|
|
2
3
|
import os
|
|
3
4
|
import select
|
|
4
5
|
import signal
|
|
@@ -38,7 +39,7 @@ def start_esc_interrupt_monitor(
|
|
|
38
39
|
# Fallback for non-interactive or non-POSIX environments.
|
|
39
40
|
if not sys.stdin.isatty() or os.name != "posix":
|
|
40
41
|
|
|
41
|
-
async def _noop() -> None:
|
|
42
|
+
async def _noop() -> None:
|
|
42
43
|
return None
|
|
43
44
|
|
|
44
45
|
return stop_event, asyncio.create_task(_noop())
|
|
@@ -47,7 +48,7 @@ def start_esc_interrupt_monitor(
|
|
|
47
48
|
try:
|
|
48
49
|
fd = sys.stdin.fileno()
|
|
49
50
|
old = termios.tcgetattr(fd)
|
|
50
|
-
except
|
|
51
|
+
except OSError as exc: # pragma: no cover - environment dependent
|
|
51
52
|
log((f"esc monitor init error: {exc}", "r red"))
|
|
52
53
|
return
|
|
53
54
|
|
|
@@ -59,7 +60,7 @@ def start_esc_interrupt_monitor(
|
|
|
59
60
|
continue
|
|
60
61
|
try:
|
|
61
62
|
ch = os.read(fd, 1).decode(errors="ignore")
|
|
62
|
-
except
|
|
63
|
+
except OSError:
|
|
63
64
|
continue
|
|
64
65
|
if ch != "\x1b":
|
|
65
66
|
continue
|
|
@@ -70,24 +71,20 @@ def start_esc_interrupt_monitor(
|
|
|
70
71
|
while r2:
|
|
71
72
|
try:
|
|
72
73
|
seq += os.read(fd, 1).decode(errors="ignore")
|
|
73
|
-
except
|
|
74
|
+
except OSError:
|
|
74
75
|
break
|
|
75
76
|
r2, _, _ = select.select([sys.stdin], [], [], 0.0)
|
|
76
77
|
|
|
77
78
|
if seq == "":
|
|
78
|
-
|
|
79
|
+
# Best-effort only; failures here should not crash the UI.
|
|
80
|
+
with contextlib.suppress(Exception):
|
|
79
81
|
asyncio.run_coroutine_threadsafe(on_interrupt(), loop)
|
|
80
|
-
except Exception:
|
|
81
|
-
# Best-effort only; failures here should not crash the UI.
|
|
82
|
-
pass
|
|
83
82
|
stop.set()
|
|
84
83
|
except Exception as exc: # pragma: no cover - environment dependent
|
|
85
84
|
log((f"esc monitor error: {exc}", "r red"))
|
|
86
85
|
finally:
|
|
87
|
-
|
|
88
|
-
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
|
89
|
-
except Exception:
|
|
90
|
-
pass
|
|
86
|
+
with contextlib.suppress(Exception):
|
|
87
|
+
termios.tcsetattr(fd, termios.TCSADRAIN, old)
|
|
91
88
|
|
|
92
89
|
esc_task: asyncio.Task[None] = asyncio.create_task(asyncio.to_thread(_esc_monitor, stop_event))
|
|
93
90
|
return stop_event, esc_task
|
|
@@ -119,29 +116,23 @@ def install_sigint_double_press_exit(
|
|
|
119
116
|
now = time.monotonic()
|
|
120
117
|
if now - last_sigint_time <= window_seconds:
|
|
121
118
|
# Second press within window: hide progress UI and exit.
|
|
122
|
-
|
|
119
|
+
with contextlib.suppress(Exception):
|
|
123
120
|
hide_progress()
|
|
124
|
-
except Exception:
|
|
125
|
-
pass
|
|
126
121
|
raise KeyboardInterrupt
|
|
127
122
|
|
|
128
123
|
# First press: remember timestamp and show toast.
|
|
129
124
|
last_sigint_time = now
|
|
130
|
-
|
|
125
|
+
with contextlib.suppress(Exception):
|
|
131
126
|
show_toast()
|
|
132
|
-
except Exception:
|
|
133
|
-
pass
|
|
134
127
|
|
|
135
128
|
try:
|
|
136
129
|
signal.signal(signal.SIGINT, _handler)
|
|
137
|
-
except
|
|
130
|
+
except (OSError, ValueError): # pragma: no cover - platform dependent
|
|
138
131
|
# If installing the handler fails, restore() will be a no-op.
|
|
139
132
|
return lambda: None
|
|
140
133
|
|
|
141
134
|
def restore() -> None:
|
|
142
|
-
|
|
135
|
+
with contextlib.suppress(Exception):
|
|
143
136
|
signal.signal(signal.SIGINT, original_handler)
|
|
144
|
-
except Exception:
|
|
145
|
-
pass
|
|
146
137
|
|
|
147
138
|
return restore
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
|
+
import subprocess
|
|
4
5
|
import sys
|
|
5
6
|
from dataclasses import dataclass
|
|
6
7
|
from enum import Enum
|
|
@@ -8,6 +9,9 @@ from typing import TextIO, cast
|
|
|
8
9
|
|
|
9
10
|
from klaude_code.trace import DebugType, log_debug
|
|
10
11
|
|
|
12
|
+
# Environment variable for tmux test signal channel
|
|
13
|
+
TMUX_SIGNAL_ENV = "KLAUDE_TEST_SIGNAL"
|
|
14
|
+
|
|
11
15
|
ST = "\033\\"
|
|
12
16
|
BEL = "\a"
|
|
13
17
|
|
|
@@ -39,7 +43,7 @@ class TerminalNotifierConfig:
|
|
|
39
43
|
stream: TextIO | None = None
|
|
40
44
|
|
|
41
45
|
@classmethod
|
|
42
|
-
def from_env(cls) ->
|
|
46
|
+
def from_env(cls) -> TerminalNotifierConfig:
|
|
43
47
|
env = os.getenv("KLAUDE_NOTIFY", "").strip().lower()
|
|
44
48
|
if env in {"0", "off", "false", "disable", "disabled"}:
|
|
45
49
|
return cls(enabled=False)
|
|
@@ -95,9 +99,7 @@ class TerminalNotifier:
|
|
|
95
99
|
if not getattr(stream, "isatty", lambda: False)():
|
|
96
100
|
return False
|
|
97
101
|
term = os.getenv("TERM", "")
|
|
98
|
-
|
|
99
|
-
return False
|
|
100
|
-
return True
|
|
102
|
+
return term.lower() not in {"", "dumb"}
|
|
101
103
|
|
|
102
104
|
|
|
103
105
|
def _compact(text: str, limit: int = 160) -> str:
|
|
@@ -105,3 +107,41 @@ def _compact(text: str, limit: int = 160) -> str:
|
|
|
105
107
|
if len(squashed) > limit:
|
|
106
108
|
return squashed[: limit - 3] + "…"
|
|
107
109
|
return squashed
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def emit_tmux_signal(channel: str | None = None) -> bool:
|
|
113
|
+
"""Send a tmux wait-for signal when a task completes.
|
|
114
|
+
|
|
115
|
+
This enables synchronous testing by allowing external scripts to block
|
|
116
|
+
until a task finishes, eliminating the need for polling or sleep.
|
|
117
|
+
|
|
118
|
+
Usage:
|
|
119
|
+
KLAUDE_TEST_SIGNAL=done klaude # In tmux session
|
|
120
|
+
tmux wait-for done # Blocks until task completes
|
|
121
|
+
|
|
122
|
+
Args:
|
|
123
|
+
channel: Signal channel name. If None, reads from KLAUDE_TEST_SIGNAL env var.
|
|
124
|
+
|
|
125
|
+
Returns:
|
|
126
|
+
True if signal was sent successfully, False otherwise.
|
|
127
|
+
"""
|
|
128
|
+
channel = channel or os.getenv(TMUX_SIGNAL_ENV)
|
|
129
|
+
if not channel:
|
|
130
|
+
return False
|
|
131
|
+
|
|
132
|
+
# Check if we're in a tmux session
|
|
133
|
+
if not os.getenv("TMUX"):
|
|
134
|
+
log_debug("tmux signal skipped: not in tmux session", debug_type=DebugType.TERMINAL)
|
|
135
|
+
return False
|
|
136
|
+
|
|
137
|
+
try:
|
|
138
|
+
subprocess.run(
|
|
139
|
+
["tmux", "wait-for", "-S", channel],
|
|
140
|
+
check=True,
|
|
141
|
+
capture_output=True,
|
|
142
|
+
)
|
|
143
|
+
log_debug(f"tmux signal sent: {channel}", debug_type=DebugType.TERMINAL)
|
|
144
|
+
return True
|
|
145
|
+
except (subprocess.CalledProcessError, FileNotFoundError) as e:
|
|
146
|
+
log_debug(f"tmux signal failed: {e}", debug_type=DebugType.TERMINAL)
|
|
147
|
+
return False
|