From c48c808d1c4127506d82e5205ad2a9fcf1d4ddf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20M=C3=BCller?= Date: Tue, 19 May 2026 01:26:33 +0000 Subject: [PATCH] Support plain fast Codex toggle --- agent/telegram_bot.py | 26 +++++++++++++++++++------- agent/test_telegram_bot.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 7 deletions(-) diff --git a/agent/telegram_bot.py b/agent/telegram_bot.py index 5785cc1..785b2a2 100644 --- a/agent/telegram_bot.py +++ b/agent/telegram_bot.py @@ -1456,9 +1456,20 @@ def label(text: str, active: bool) -> str: "text": label(model.replace("gpt-", ""), current_model == model), "callback_data": f"codex_model:model:{model}", }) + effort_labels = { + "low": "Fast", + "medium": "Medium", + "high": "High", + "xhigh": "XHigh", + } effort_row = [ { - "text": label(effort.title(), current_effort == effort), + "text": label("Default", not current_effort), + "callback_data": "codex_model:effort:default", + } + ] + [ + { + "text": label(effort_labels[effort], current_effort == effort), "callback_data": f"codex_model:effort:{effort}", } for effort in CODEX_REASONING_EFFORTS @@ -5524,6 +5535,8 @@ def handle(self, msg: dict) -> None: thread_id, ) cmd, arg = _parse_command(text) + if not cmd and text.strip().lower() == "fast": + cmd = "/fast" # `/terminal` — owner-only mode switch. Spawns a persistent bash # in this lane; from this point on plain-text messages route to @@ -5708,7 +5721,7 @@ def handle(self, msg: dict) -> None: # are stdin for it (codex login codes, gh auth login codes, `read` # answers, `y/n` prompts, …). Slash commands fall through below # so the user can still `/cancel`, `/queue`, etc. - if not text.startswith("/"): + if not text.startswith("/") and cmd not in {"/fast"}: goal_entry = _goal_state_for(self.state, slug) if goal_entry is None and _is_owner(sender, owner) and _wait_for_goal_start(slug): goal_entry = _goal_state_for(self.state, slug) @@ -6035,7 +6048,6 @@ def handle(self, msg: dict) -> None: reply_to=mid, thread_id=thread_id, markdown=True, - reply_markup=_codex_model_picker_markup(settings), ) return if cmd == "/model": @@ -6475,7 +6487,6 @@ def _cmd_codex_model( reply_to=reply_to, thread_id=thread_id, markdown=True, - reply_markup=_codex_model_picker_markup(settings), ) return @@ -7459,9 +7470,10 @@ def _handle_codex_model_callback(self, cb: dict, data: str) -> None: model = "" if value == "default" else value settings = _set_codex_settings(key, self.state, model=model) toast = "Model updated" - elif action == "effort" and value in CODEX_REASONING_EFFORTS: - settings = _set_codex_settings(key, self.state, reasoning_effort=value) - toast = f"Effort: {value}" + elif action == "effort" and (value == "default" or value in CODEX_REASONING_EFFORTS): + effort = "" if value == "default" else value + settings = _set_codex_settings(key, self.state, reasoning_effort=effort) + toast = "Effort default" if value == "default" else f"Effort: {value}" else: self.call( "answerCallbackQuery", diff --git a/agent/test_telegram_bot.py b/agent/test_telegram_bot.py index 0b97f6b..e9598b6 100644 --- a/agent/test_telegram_bot.py +++ b/agent/test_telegram_bot.py @@ -76,6 +76,7 @@ def test_model_picker_marks_current_choices(self) -> None: ] self.assertIn("✓ 5.4", labels) self.assertIn("✓ High", labels) + self.assertIn("Fast", labels) self.assertIn("Reset Codex defaults", labels) def test_model_picker_callback_updates_effort_in_place(self) -> None: @@ -116,6 +117,39 @@ def fake_call(method: str, **kwargs): self.assertEqual(bot.state["agents"]["100_123"], "codex") self.assertTrue(any(method == "editMessageText" for method, _ in calls)) + def test_plain_fast_switches_codex_effort(self) -> None: + sent: list[tuple[str, dict]] = [] + bot = telegram_bot.Bot.__new__(telegram_bot.Bot) + bot.state = {"offset": 0, "agents": {}, "codex_settings": {}, "owners": {}} + bot.setup_token = None + bot._username = "bux_bot" + bot.react = lambda *_args, **_kwargs: None # type: ignore[method-assign] + bot.typing = lambda *_args, **_kwargs: None # type: ignore[method-assign] + bot.send = lambda _chat, text, **kwargs: sent.append((text, kwargs)) # type: ignore[method-assign] + + with ( + mock.patch.object(telegram_bot, "load_allow", return_value={100}), + mock.patch.object(telegram_bot, "save_state"), + mock.patch.object(telegram_bot, "_get_shell_session", return_value=None), + mock.patch.object(telegram_bot, "_goal_state_for", return_value=None), + ): + bot.handle( + { + "chat": {"id": 100, "type": "private"}, + "from": {"id": 55, "username": "Magnus_Mueller"}, + "message_id": 123, + "text": "fast", + } + ) + + self.assertEqual(bot.state["agents"]["100_main"], "codex") + self.assertEqual( + bot.state["codex_settings"]["100_main"], + {"reasoning_effort": "low"}, + ) + self.assertIn("Fast mode on.", sent[-1][0]) + self.assertNotIn("reply_markup", sent[-1][1]) + def test_codex_goal_feature_enablement_is_idempotent(self) -> None: with tempfile.TemporaryDirectory() as tmp: config = Path(tmp) / "config.toml"