fix(yolo): unblock AskUserQuestion; add orthogonal afk mode#2045
fix(yolo): unblock AskUserQuestion; add orthogonal afk mode#2045
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9e7fc734a6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if soul.runtime.approval.is_yolo_flag(): | ||
| soul.runtime.approval.set_yolo(False) | ||
| track("yolo_toggle", enabled=False) | ||
| wire_send(TextPart(text="You only die once! Actions will require approval.")) |
There was a problem hiding this comment.
Adjust
/yolo disable message when AFK remains enabled
The /yolo toggle always emits "Actions will require approval." when the explicit yolo flag is turned off, but that is incorrect when AFK is still on. In the yolo=true, afk=true state, this branch clears only the yolo flag; Approval.is_yolo() remains true via AFK, so tool calls are still auto-approved. This gives users a false safety signal and can lead to unexpected unprompted execution after they think approvals are restored.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Pull request overview
This PR fixes a behavioral regression where --yolo incorrectly made the model treat sessions as non-interactive (blocking AskUserQuestion), and it splits “auto-approve” vs “no user present” into two independent modes: YOLO and AFK.
Changes:
- Introduces AFK mode (
--afk,/afk) to represent “no user present”: auto-dismissAskUserQuestion+ auto-approve tool calls;--printnow implies--afk. - Updates YOLO semantics/prompting to keep
AskUserQuestionavailable in interactive sessions, and prevents YOLO injection when AFK is active or when running as a subagent. - Adds UI badges, approval state plumbing, and comprehensive regression tests for the new orthogonal state model.
Reviewed changes
Copilot reviewed 31 out of 31 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/tools/test_ask_user.py | Updates ask-user tests for AFK auto-dismiss + adds regression ensuring YOLO-only remains interactive. |
| tests/core/test_yolo_injection.py | Expands yolo injection tests for AFK/subagent suppression and prompt wording expectations. |
| tests/core/test_slash_afk.py | Adds coverage for /afk plus independence from /yolo and status snapshot behavior. |
| tests/core/test_approval_afk.py | Validates the Approval yolo/afk orthogonal state model + share() propagation + persistence rules. |
| tests/core/test_afk_injection.py | Adds tests for the new AFK injection provider (inject once, skip subagent, etc.). |
| src/kimi_cli/ui/theme.py | Adds AFK toolbar color token for the new status badge. |
| src/kimi_cli/ui/shell/prompt.py | Renders independent yolo and afk badges in the bottom toolbar. |
| src/kimi_cli/tools/plan/enter.py | Adjusts plan-mode messaging for auto-approved (yolo/afk) path. |
| src/kimi_cli/tools/plan/init.py | Adjusts ExitPlanMode auto-approved messaging similarly. |
| src/kimi_cli/tools/ask_user/init.py | Changes ask-user auto-dismiss from YOLO to AFK-only via late-bound bind_afk(). |
| src/kimi_cli/soul/slash.py | Makes /yolo toggle only the explicit yolo flag; adds /afk command. |
| src/kimi_cli/soul/kimisoul.py | Wires AFK into status snapshot, tool binding, injection providers; adds is_afk / is_subagent. |
| src/kimi_cli/soul/dynamic_injections/yolo_mode.py | Rewrites YOLO reminder to allow AskUserQuestion and suppresses injection under AFK/subagent. |
| src/kimi_cli/soul/dynamic_injections/afk_mode.py | New AFK reminder provider (no user present; don’t call AskUserQuestion). |
| src/kimi_cli/soul/approval.py | Adds runtime-only afk flag; is_yolo() becomes (yolo OR afk); adds is_yolo_flag() and is_afk(). |
| src/kimi_cli/soul/agent.py | Threads afk into ApprovalState construction at runtime creation. |
| src/kimi_cli/soul/init.py | Extends StatusSnapshot with afk_enabled and clarifies yolo flag semantics. |
| src/kimi_cli/cli/init.py | Adds --afk flag; makes --print imply AFK (not YOLO) and plumbs into app creation. |
| src/kimi_cli/app.py | Adds afk parameter, docs, and telemetry field. |
| docs/zh/release-notes/changelog.md | Adds Unreleased notes describing YOLO/AFK semantics and fixes. |
| docs/zh/reference/slash-commands.md | Documents /afk and clarifies /yolo semantics and independence. |
| docs/zh/reference/kimi-command.md | Updates CLI option docs: --print implies AFK; adds --afk. |
| docs/zh/guides/interaction.md | Adds AFK guide section and clarifies YOLO vs AFK behavior. |
| docs/zh/customization/print-mode.md | Updates print-mode docs to reflect implicit AFK. |
| docs/zh/configuration/overrides.md | Adds --afk override and updates YOLO description. |
| docs/en/release-notes/changelog.md | Adds Unreleased notes describing YOLO/AFK semantics and fixes. |
| docs/en/reference/slash-commands.md | Documents /afk and clarifies /yolo semantics and independence. |
| docs/en/reference/kimi-command.md | Updates CLI option docs: --print implies AFK; adds --afk. |
| docs/en/guides/interaction.md | Adds AFK guide section and clarifies YOLO vs AFK behavior. |
| docs/en/customization/print-mode.md | Updates print-mode docs to reflect implicit AFK. |
| docs/en/configuration/overrides.md | Adds --afk override and updates YOLO description. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - Core:修复 `--yolo` 模式意外阻止模型调用 `AskUserQuestion` 的问题——以前 yolo 会注入一段 system reminder,告诉模型当前处于“非交互模式”,不能向用户提问;同时 ask-user 工具在 yolo 下也会自动 dismiss。这两处都是错的:yolo 的真正语义只是“自动批准工具调用”,并不意味着“用户已离开”。现在 yolo 模式下用户仍然在线,prompt 措辞也更温和——明确告诉模型在关键决策点仍可以调用 `AskUserQuestion` 来澄清需求,只是不要滥用 | ||
| - CLI:把“自动审批”和“非交互”拆分为两个正交模式——`--yolo`(自动批准工具调用,但用户仍在终端前)和 `--afk` / `/afk`(away-from-keyboard:`AskUserQuestion` 会被自动 dismiss、工具调用也自动批准)。`--print` 现在隐式启用 `--afk` 而不是 `--yolo`(语义更准确:print 下没人坐在终端前)。状态栏独立显示 `yolo` 和 `afk`,`/yolo` 与 `/afk` 各自切换自身的 flag,互不干扰 | ||
| - Shell:修复 afk 开启时 `/yolo` 切换产生误导性 UI 文案的问题——以前 `/yolo` 读的是 yolo 和 afk 合并后的自动批准状态,afk 开着时按 `/yolo` 会说“现在需要审批”,但 afk 仍在继续自动批准。现在 `/yolo` 只读写 yolo 自身的 flag,不碰 afk |
There was a problem hiding this comment.
Per docs/AGENTS.md, the Chinese changelog should be translated from the English changelog, and the English changelog is auto-synced from root CHANGELOG.md. To avoid drift, update CHANGELOG.md, run npm run sync to regenerate docs/en/release-notes/changelog.md, then translate those entries into this file.
| - Core:修复 `--yolo` 模式意外阻止模型调用 `AskUserQuestion` 的问题——以前 yolo 会注入一段 system reminder,告诉模型当前处于“非交互模式”,不能向用户提问;同时 ask-user 工具在 yolo 下也会自动 dismiss。这两处都是错的:yolo 的真正语义只是“自动批准工具调用”,并不意味着“用户已离开”。现在 yolo 模式下用户仍然在线,prompt 措辞也更温和——明确告诉模型在关键决策点仍可以调用 `AskUserQuestion` 来澄清需求,只是不要滥用 | |
| - CLI:把“自动审批”和“非交互”拆分为两个正交模式——`--yolo`(自动批准工具调用,但用户仍在终端前)和 `--afk` / `/afk`(away-from-keyboard:`AskUserQuestion` 会被自动 dismiss、工具调用也自动批准)。`--print` 现在隐式启用 `--afk` 而不是 `--yolo`(语义更准确:print 下没人坐在终端前)。状态栏独立显示 `yolo` 和 `afk`,`/yolo` 与 `/afk` 各自切换自身的 flag,互不干扰 | |
| - Shell:修复 afk 开启时 `/yolo` 切换产生误导性 UI 文案的问题——以前 `/yolo` 读的是 yolo 和 afk 合并后的自动批准状态,afk 开着时按 `/yolo` 会说“现在需要审批”,但 afk 仍在继续自动批准。现在 `/yolo` 只读写 yolo 自身的 flag,不碰 afk | |
| - Core:修复 `--yolo` 模式下意外阻止模型调用 `AskUserQuestion` 的问题——此前,yolo 会注入一段 system reminder,告诉模型当前处于“非交互模式”、不能向用户提问;同时 ask-user 工具在 yolo 下也会被自动 dismiss。这两点都不正确:yolo 的真实语义只是“自动批准工具调用”,并不表示“用户已离开”。现在,在 yolo 模式下用户仍被视为在线,prompt 的措辞也更温和——明确说明模型在关键决策点仍可调用 `AskUserQuestion` 澄清需求,只是不要滥用 | |
| - CLI:将“自动批准”和“非交互”拆分为两个正交模式——`--yolo`(自动批准工具调用,但用户仍在终端前)以及 `--afk` / `/afk`(away-from-keyboard:`AskUserQuestion` 会被自动 dismiss,工具调用也会自动批准)。`--print` 现在会隐式启用 `--afk`,而不是 `--yolo`(语义更准确:print 模式下默认没人守在终端前)。状态栏会分别显示 `yolo` 和 `afk`,`/yolo` 与 `/afk` 也各自只切换自己的 flag,互不影响 | |
| - Shell:修复在启用 afk 时切换 `/yolo` 会产生误导性 UI 文案的问题——此前,`/yolo` 读取的是 yolo 与 afk 合并后的自动批准状态,所以在 afk 已开启时执行 `/yolo`,界面会提示“现在需要审批”,但实际上 afk 仍会继续自动批准。现在,`/yolo` 只读取并写入 yolo 自身的 flag,不再影响 afk |
| # Afk on, yolo flag off -> is_yolo() True via OR, but yolo_flag is False. | ||
| soul.runtime.approval._state.afk = True # pyright: ignore[reportPrivateUsage] | ||
| assert soul.runtime.approval.is_yolo() is True | ||
| assert soul.runtime.approval.is_yolo_flag() is False |
There was a problem hiding this comment.
This test sets AFK by mutating the private approval._state.afk. Since Approval.set_afk() is available, prefer the public setter to keep the test resilient to internal refactors.
| # Afk only -> afk_enabled True, yolo_enabled False. | ||
| soul.runtime.approval._state.afk = True # pyright: ignore[reportPrivateUsage] | ||
| snap = soul.status | ||
| assert snap.afk_enabled is True | ||
| assert snap.yolo_enabled is False |
There was a problem hiding this comment.
This test sets AFK by mutating the private approval._state.afk. Since Approval.set_afk() is available, prefer the public setter to keep the test resilient to internal refactors.
| async def yolo(soul: KimiSoul, args: str): | ||
| """Toggle YOLO mode (auto-approve all actions)""" | ||
| from kimi_cli.telemetry import track | ||
|
|
||
| if soul.runtime.approval.is_yolo(): | ||
| # Inspect only the yolo flag, not the OR-combined is_yolo(): afk is independent | ||
| # and is toggled by /afk. | ||
| if soul.runtime.approval.is_yolo_flag(): | ||
| soul.runtime.approval.set_yolo(False) | ||
| track("yolo_toggle", enabled=False) | ||
| wire_send(TextPart(text="You only die once! Actions will require approval.")) | ||
| else: | ||
| soul.runtime.approval.set_yolo(True) | ||
| track("yolo_toggle", enabled=True) | ||
| wire_send(TextPart(text="You only live once! All actions will be auto-approved.")) |
There was a problem hiding this comment.
/yolo toggling can still display a misleading toast when AFK is active. If both flags are on and the user runs /yolo to disable the YOLO flag, this branch will send "Actions will require approval" even though AFK keeps auto-approving tool calls. Consider tailoring the toast based on approval.is_afk() (and updating wording from "actions" to "tool calls") so the UI always reflects the effective approval behavior; add a regression test for the AFK+YOLO -> AFK-only toggle case.
| ## Unreleased | ||
|
|
||
| - Core: Fix `--yolo` mode unintentionally preventing the model from calling `AskUserQuestion` — yolo used to inject a system reminder telling the model it was in "non-interactive mode" and must not ask, and the ask-user tool auto-dismissed in yolo. Both were wrong: yolo only means "auto-approve tool calls", not "the user is gone". Yolo now keeps the user fully reachable, with a gentler prompt that tells the model it can still ask clarifying questions at meaningful decision points (just to use it sparingly) | ||
| - CLI: Split "auto-approve" and "non-interactive" into two orthogonal modes — `--yolo` (auto-approve tool calls while the user is still at the terminal) and `--afk` / `/afk` (away-from-keyboard: `AskUserQuestion` is auto-dismissed and tool calls are auto-approved). `--print` now implicitly enables `--afk` instead of `--yolo` (more accurate: print has no user at the terminal). The status bar shows `yolo` and `afk` independently, and `/yolo` and `/afk` toggle their own flag without disturbing the other | ||
| - Shell: Fix `/yolo` toggling producing misleading UI messages when afk is also active — `/yolo` used to read the combined auto-approve state, so pressing it under afk would claim approval was now required even though afk kept auto-approving everything. `/yolo` now reads and writes only the yolo flag, leaving afk alone |
There was a problem hiding this comment.
This file is auto-synced from the root CHANGELOG.md (see docs/AGENTS.md). Direct edits here will be overwritten by the sync script. Please move these Unreleased entries to CHANGELOG.md and run npm run sync (from docs/) to regenerate this page.
…er yolo yolo previously conflated two dimensions — auto-approving tool calls AND user non-interactive — and injected a system reminder telling the model it was "in non-interactive mode" and must not call AskUserQuestion. Even with the user sitting at the terminal, the model would make "best-effort" guesses instead of asking at genuinely ambiguous decision points. Split the axes: yolo is now strictly "auto-approve tool calls" (user still reachable); afk (away-from-keyboard) is strictly "no user at the terminal" and implies auto-approve. Approval exposes is_yolo_flag and is_afk for single-axis reads, and is_yolo() returns yolo OR afk so existing auto-approve call sites stay correct. Changes: - Rewrite the yolo system-reminder so the model knows the user is still present and may be asked sparingly for genuinely ambiguous decisions. - Add AfkModeInjectionProvider with a stricter prompt; yolo provider skips injection when afk is on (to avoid clashing instructions) and when running as a subagent (which does not expose AskUserQuestion). - AskUserQuestion auto-dismisses only under afk, not under yolo. - --print now implicitly enables --afk (previously --yolo); more accurate: print has no user at the terminal. - New --afk CLI flag and /afk slash command for runtime toggling. - /yolo now reads and writes only the yolo flag, so toggling it while afk is on no longer shows misleading "approval required" toasts. - Status bar shows yolo and afk independently, with distinct colors. - Plan-mode auto-approval messages no longer claim "non-interactive mode" (inaccurate when yolo is active while the user is present). afk is runtime-only and intentionally not persisted to session state.
Update the kimi command reference, slash commands reference, print mode guide, interaction guide, overrides table, and the unreleased changelog (both en and zh) to reflect the yolo/afk split: - --yolo and --afk documented side by side with clarified semantics. - /yolo and /afk slash commands documented with independence note. - --print description updated: implies --afk, not --yolo. - Interaction guide gains a dedicated AFK section with the distinction from YOLO. - Unreleased changelog entries describe the bug fix and the split.
9e7fc73 to
d2688f9
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2688f9744
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if soul.runtime.approval.is_yolo_flag(): | ||
| soul.runtime.approval.set_yolo(False) | ||
| track("yolo_toggle", enabled=False) | ||
| wire_send(TextPart(text="You only die once! Actions will require approval.")) |
There was a problem hiding this comment.
Fix
/yolo off toast when afk keeps auto-approval enabled
If both yolo and afk are enabled, running /yolo takes the is_yolo_flag() true branch, clears only the explicit yolo flag, and emits “Actions will require approval.”, but approvals are still auto-approved because Approval.is_yolo() remains true via afk. This gives a false safety signal and can lead to unprompted tool execution until /afk is also turned off.
Useful? React with 👍 / 👎.
- test_initialize_handshake / test_initialize_external_tool_conflict: the slash_commands list returned by wire handshake now includes the new /afk command. - test_manual_compact: expected post-compact context_tokens bumped from 118 to 199 — the rewritten yolo prompt is longer (~81 tokens) than the previous "non-interactive mode" reminder, so compaction leaves a slightly larger context.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f102fb9928
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if self._injected: | ||
| return [] | ||
| self._injected = True |
There was a problem hiding this comment.
Re-inject afk reminder when afk mode is re-enabled
This provider permanently latches _injected after the first afk turn, so later /afk toggles in the same session never add a fresh afk reminder. Because injections are appended into conversation history by KimiSoul._collect_injections, users who turn afk on and then off can leave a stale “no user is present / do NOT call AskUserQuestion” instruction in context, and turning afk back on later also gets no new reminder. In practice this can suppress clarifying questions even after returning to interactive mode, hurting response accuracy.
Useful? React with 👍 / 👎.
Python 3.12 preserves the leading indentation of multi-line
docstrings, while 3.13+ strips it via the compiler (PEP 257
enforcement). The original multi-line /afk docstring caused
test_initialize_handshake to fail only on 3.12 because the
handshake's slash_commands description carried "\n In afk mode..."
instead of the dedented form the snapshot expected.
Adopting the single-line style used by /yolo and /plan sidesteps the
version difference entirely while keeping the essential information
("auto-dismiss AskUserQuestion, auto-approve tool calls").
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cfa51fa97a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if soul.is_subagent: | ||
| # Subagents have no AskUserQuestion tool; repeating the rule | ||
| # just burns tokens on every subagent turn. | ||
| return [] |
There was a problem hiding this comment.
Gate AFK subagent skip on tool availability, not role
This early return suppresses the AFK reminder for every subagent, but subagent toolsets are spec-driven (the subagent type allowlist comes from agent spec loading), so custom subagent types can still expose AskUserQuestion. In AFK runs, those calls are auto-dismissed; without the reminder, the model can keep asking anyway and burn turn budget until max_steps_per_turn is hit. Please gate this on actual tool presence rather than is_subagent alone.
Useful? React with 👍 / 👎.
When both yolo and afk are on, toggling /yolo off used to emit "Actions will require approval", but is_yolo() stayed true via afk and tool calls kept being auto-approved — a false safety signal. Now the off branch checks the other flag and tells the user when auto-approval is still in effect. The /afk off branch gets the symmetric treatment: if yolo is still on, it says so.
…ction The config was originally introduced to suppress the non-interactive mode reminder for custom KimiSoul applications. After the yolo/afk split, --print now implies --afk instead of --yolo, and the afk prompt IS the non-interactive mode hint — but the config only gated the yolo provider, leaving afk injected unconditionally. That was a regression for consumers who set this flag specifically to avoid the hint. Gate both providers with the same config, and clarify the config docstring to mention both modes.
The root CHANGELOG.md is the source of truth per docs/AGENTS.md; docs/en/release-notes/changelog.md is auto-synced from it. The earlier doc commit bypassed that by writing docs/en directly, which would be overwritten by the next sync run. Mirror the three afk-related entries into CHANGELOG.md so the source of truth and the auto-synced page stay in lockstep. docs/zh/release-notes/changelog.md is manually translated from the English version and already carries the equivalent entries.
| if self._injected: | ||
| return [] | ||
| self._injected = True |
There was a problem hiding this comment.
🟡 AfkModeInjectionProvider never re-injects after /afk off→on toggle, leaving model with stale "user is back" instruction
When /afk is toggled off, the /afk slash command (src/kimi_cli/soul/slash.py:142-143) injects an _AFK_DISABLED_REMINDER into context that explicitly tells the model: "Afk mode is now disabled. The user is back… Ignore any earlier afk mode reminders… AskUserQuestion is available again." However, when /afk is re-enabled, the AfkModeInjectionProvider at src/kimi_cli/soul/dynamic_injections/afk_mode.py:46 has self._injected = True from the first activation and returns [], so no new afk injection is produced. The model's last context-level instruction about afk says the user is present and AskUserQuestion is available — which is now wrong. The model will likely call AskUserQuestion, which gets auto-dismissed (wasting a turn) before the model discovers from the tool response that afk is active again.
Toggle cycle trace
/afkon → provider fires once → model knows "no user"/afkoff →_AFK_DISABLED_REMINDERinjected → model told "user is back, ignore earlier afk reminders, AskUserQuestion available"/afkon again → provider_injected=True→ no injection → model still believes user is present- Model calls AskUserQuestion → auto-dismissed → wasted turn
Prompt for agents
The AfkModeInjectionProvider uses a one-shot _injected flag that is set to True on first injection and never reset. This interacts badly with the /afk slash command in src/kimi_cli/soul/slash.py, which injects an _AFK_DISABLED_REMINDER into context when afk is toggled OFF (telling the model the user is back and AskUserQuestion is available). When afk is toggled back ON, the provider does not re-inject because _injected is already True, leaving the model with a stale instruction that the user is present.
The simplest fix is to inject a context-level system_reminder in the /afk enable path (src/kimi_cli/soul/slash.py, the else branch of the afk function around line 154-164) similar to how the disable path injects _AFK_DISABLED_REMINDER. This would tell the model afk is back on and it must not call AskUserQuestion. Alternatively, the _injected flag could be reset to False when afk is disabled (though the provider instance is not directly accessible from the slash command).
Was this helpful? React with 👍 or 👎 to provide feedback.
Summary
--yolomode erroneously telling the model it's "non-interactive" and must not callAskUserQuestion, even when the user is sitting at the terminal.yolo(auto-approve) andafk/ away-from-keyboard (no user present → auto-dismissAskUserQuestion+ auto-approve).--afkCLI flag and/afkslash command; status bar now shows the two flags independently.What changed
--printnow implicitly enables--afk(previously--yolo) — more accurate:--printhas no user at the terminal./yoloand/afkeach toggle their own flag;/yolounder afk no longer shows misleading "approval required" toasts.AfkModeInjectionProvider; yolo provider skips injection when afk is on (to avoid clashing prompts) and when running as a subagent (which has noAskUserQuestiontool).Test plan
make check-kimi-clipassespytest tests/green (2560 passing)test_ask_user_yolo_only_does_not_dismiss— yolo-only keeps AskUserQuestion livetest_yolo_slash_under_afk_only_toggles_yolo_flag—/yolono longer lies about approval state when afk is ontest_slash_afk.py—/afktoggle + independence from/yolotest_approval_afk.py— all four yolo/afk combinations + share() propagationtest_afk_injection.py— afk prompt injected once; yolo provider skips when afk onkimi+/yolo→ ask something ambiguous → model should sendAskUserQuestionmodal (the reported bug)kimi --print -p "..."→AskUserQuestionauto-dismissed, no hangkimi+/afk→ status bar shows orange AFK badge; AskUserQuestion auto-dismissedkimi+/yolo+/afk→ both badges show, each toggles independently