Skip to content

fix(yolo): unblock AskUserQuestion; add orthogonal afk mode#2045

Open
RealKai42 wants to merge 8 commits intomainfrom
kaiyi/las-vegas-v4
Open

fix(yolo): unblock AskUserQuestion; add orthogonal afk mode#2045
RealKai42 wants to merge 8 commits intomainfrom
kaiyi/las-vegas-v4

Conversation

@RealKai42
Copy link
Copy Markdown
Collaborator

@RealKai42 RealKai42 commented Apr 23, 2026

Summary

  • Fixes --yolo mode erroneously telling the model it's "non-interactive" and must not call AskUserQuestion, even when the user is sitting at the terminal.
  • Splits the conflated "auto-approve" and "non-interactive" semantics into two orthogonal modes: yolo (auto-approve) and afk / away-from-keyboard (no user present → auto-dismiss AskUserQuestion + auto-approve).
  • Adds --afk CLI flag and /afk slash command; status bar now shows the two flags independently.

What changed

  • --print now implicitly enables --afk (previously --yolo) — more accurate: --print has no user at the terminal.
  • /yolo and /afk each toggle their own flag; /yolo under afk no longer shows misleading "approval required" toasts.
  • Yolo system-reminder rewritten: explicitly tells the model it can still ask clarifying questions sparingly.
  • New AfkModeInjectionProvider; yolo provider skips injection when afk is on (to avoid clashing prompts) and when running as a subagent (which has no AskUserQuestion tool).

Test plan

  • make check-kimi-cli passes
  • pytest tests/ green (2560 passing)
  • New regression: test_ask_user_yolo_only_does_not_dismiss — yolo-only keeps AskUserQuestion live
  • New regression: test_yolo_slash_under_afk_only_toggles_yolo_flag/yolo no longer lies about approval state when afk is on
  • New: test_slash_afk.py/afk toggle + independence from /yolo
  • New: test_approval_afk.py — all four yolo/afk combinations + share() propagation
  • New: test_afk_injection.py — afk prompt injected once; yolo provider skips when afk on
  • Manual: kimi + /yolo → ask something ambiguous → model should send AskUserQuestion modal (the reported bug)
  • Manual: kimi --print -p "..."AskUserQuestion auto-dismissed, no hang
  • Manual: kimi + /afk → status bar shows orange AFK badge; AskUserQuestion auto-dismissed
  • Manual: kimi + /yolo + /afk → both badges show, each toggles independently

Open in Devin Review

Copilot AI review requested due to automatic review settings April 23, 2026 17:07
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 5 additional findings.

Open in Devin Review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/kimi_cli/soul/slash.py Outdated
Comment on lines 102 to 105
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."))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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-dismiss AskUserQuestion + auto-approve tool calls; --print now implies --afk.
  • Updates YOLO semantics/prompting to keep AskUserQuestion available 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.

Comment on lines +7 to +9
- 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
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Suggested change
- 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

Copilot uses AI. Check for mistakes.
Comment on lines +79 to +82
# 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
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines +126 to +130
# 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
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
Comment on lines 96 to 109
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."))
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/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.

Copilot uses AI. Check for mistakes.
Comment on lines 5 to +9
## 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
Copy link

Copilot AI Apr 23, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
…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.
@RealKai42 RealKai42 force-pushed the kaiyi/las-vegas-v4 branch from 9e7fc73 to d2688f9 Compare April 23, 2026 17:18
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread src/kimi_cli/soul/slash.py Outdated
Comment on lines 102 to 105
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."))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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 👍 / 👎.

devin-ai-integration[bot]

This comment was marked as resolved.

- 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.
devin-ai-integration[bot]

This comment was marked as resolved.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +46 to +48
if self._injected:
return []
self._injected = True
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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").
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment on lines +42 to +45
if soul.is_subagent:
# Subagents have no AskUserQuestion tool; repeating the rule
# just burns tokens on every subagent turn.
return []
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge 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.
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 new potential issue.

View 10 additional findings in Devin Review.

Open in Devin Review

Comment on lines +46 to +48
if self._injected:
return []
self._injected = True
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 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
  1. /afk on → provider fires once → model knows "no user"
  2. /afk off → _AFK_DISABLED_REMINDER injected → model told "user is back, ignore earlier afk reminders, AskUserQuestion available"
  3. /afk on again → provider _injected=True → no injection → model still believes user is present
  4. 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).
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants