Merge pull request 'Allow /stop without target argument' (#13) from feat/unify-start-stop-args into main

Reviewed-on: #13
This commit was merged in pull request #13.
This commit is contained in:
2026-02-17 06:19:47 +09:00
4 changed files with 35 additions and 18 deletions

View File

@@ -96,11 +96,10 @@ class Bridge:
def _handle_command(self, action: str, target: str, channel: str) -> None:
"""슬래시 커맨드를 처리한다."""
if target not in {"claude", "codex"}:
self.slack.send_message(channel, ":warning: 지원하지 않는 대상입니다.")
return
if action == "start":
if target not in {"claude", "codex"}:
self.slack.send_message(channel, ":warning: 지원하지 않는 대상입니다.")
return
self._start_session(channel, target)
elif action == "stop":
self._stop_session(channel)

View File

@@ -86,23 +86,12 @@ class SlackHandler:
ack()
user_id = body.get("user_id", "")
channel_id = body.get("channel_id", "")
target = self._parse_target(body.get("text", ""))
if not self._is_authorized(user_id, channel_id):
return
if target is None:
self.send_message(
channel_id,
(
":warning: 대상은 `claude` 또는 `codex`여야 합니다. "
"예: `/stop claude`"
),
)
return
if self._on_command_callback:
self._on_command_callback("stop", target, channel_id)
self._on_command_callback("stop", "", channel_id)
@staticmethod
def _parse_target(text: str) -> str | None:

View File

@@ -132,6 +132,21 @@ def test_unknown_target_is_rejected(monkeypatch) -> None:
)
def test_stop_command_ignores_empty_target(monkeypatch) -> None:
FakePtyManager.instances.clear()
bridge = _make_bridge(monkeypatch)
bridge._handle_command("start", "codex", "C1")
bridge._handle_command("stop", "", "C1")
assert bridge.pty is None
assert bridge._active_target is None
assert bridge.slack.sent_messages[-1] == (
"C1",
":electric_plug: 세션 연결이 해제되었습니다.",
)
def test_handle_message_resets_last_sent_output_after_input(monkeypatch) -> None:
FakePtyManager.instances.clear()
bridge = _make_bridge(monkeypatch)

View File

@@ -111,7 +111,7 @@ def test_start_command_normalizes_target(monkeypatch) -> None:
assert called == [("start", "claude", "C1")]
def test_stop_command_routes_target_from_text(monkeypatch) -> None:
def test_stop_command_ignores_target_text(monkeypatch) -> None:
handler = _build_handler(monkeypatch)
called = _capture_commands(handler)
@@ -121,7 +121,21 @@ def test_stop_command_routes_target_from_text(monkeypatch) -> None:
{"user_id": "U1", "channel_id": "C1", "text": "claude"},
)
assert called == [("stop", "claude", "C1")]
assert called == [("stop", "", "C1")]
def test_stop_command_without_target_routes_immediately(monkeypatch) -> None:
handler = _build_handler(monkeypatch)
called = _capture_commands(handler)
stop_handler = handler.app.command_handlers["/stop"]
stop_handler(
lambda: None,
{"user_id": "U1", "channel_id": "C1", "text": ""},
)
assert called == [("stop", "", "C1")]
assert handler.app.client.messages == []
def test_invalid_target_sends_warning_message(monkeypatch) -> None: