Skip to content

Follow-up message typed while a Bot is working is postponed instead of being delivered at its next step #707

Closed

Description

@hsliuustc0106

环境

DSH Desktop (macOS arm64, nightly channel),Bot 私聊(Docs Keeper)。

复现步骤

  1. 向一个正在工作的 Bot 发消息 A,Bot 开始处理
  2. 在 Bot 仍未结束时继续输入消息 B("他那边信息更多")并发送
  3. 观察消息 B 的状态

实际行为

消息 B 被推迟(postponed),显示为挂起/排队状态,没有按 message 语义"working Bot 在其下一个 step 读到该消息"立即进入当前 turn。

期望行为

按 Bot 通信语义,工作中 Bot 应在其下一个 step 读到新消息(可改变方向),当前工作完成后再统一作答;即消息 B 应被投递进进行中的 turn,而不是推迟成独立排队项。

相关

备注

用户视角的原始记录:Bot 回复"有道理……我先找到它"并 Messaged 后,用户第二条输入停留在 postpone 状态。

Activity

  1. Birfy commented on Oct 22, 2026

    @Birfy
    Collaborator

    Triage (2026-10-22): the report is accurate about what happens, but whether it is a defect depends on a decision we already made once — so this waits on that decision instead of being handed to a Bot.

    Why it is not obviously a bug. #642 ("a burst of messages opens one turn per message") fixed the burst case and, in the same design, decided what happens to a line that arrives while a turn is running: it is queued and the Bot sees it in its next turn, in arrival order. That is the behaviour this issue reports as "postponed". In other words the code is doing what the design asked; the question is whether the design still holds for a user's mid-turn correction.

    The decision (one sentence from the user).

    • A — keep queueing (status quo). A user's line typed during a run always lands in the next turn; nothing interrupts a running turn. Then the fix is presentation only: the composer shows the line as queued for the next turn (not a vague "postponed"), and the docs say so. Cost: one UI label plus one page of docs, no core change.
    • B — deliver at the Bot's next step. The running turn reads the new line between steps, the way a Bot-to-Bot message does today, and the answer covers both. This is what the reporter expects, and it is the semantics the team already relies on for Bot-to-Bot delivery — but it is a core delivery change (core/src/host/{delivery,channel}.js), it interacts with the 1500 ms settle window from A burst of messages opens one turn per message; there is no receive buffer #642, and it needs a rule for "the turn already answered before the line arrived".

    Why B is not free. A turn is a sequence of model steps with tool calls; injecting mid-turn means the transcript changes under the running loop, so the same line can be read twice or not at all depending on where the step boundary falls. That is why it was not part of #642.

    What happens after the decision. A is a small agent-ready (UI label + doc sentence); B becomes a design issue of its own with the delivery contract written down first.

    No label change beyond needs-human; the problem statement stands as written.

  2. added
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 22, 2026
  3. Birfy commented on Oct 24, 2026

    @Birfy
    Collaborator

    Keeping needs-human, and writing down why so it is not re-triaged every week:

    1. The mechanism is not in this repository: postponed has 0 matches across the whole tree. The delivery queue it describes is the DSH host's, not FlyBot's room code — FlyBot's side of that queue is inbox.nextStep/nextTurn (core/src/host/groups.js), which already delivers at the next step for group turns.
    2. What is left is a product choice, not a bug to derive: should a follow-up typed at a working Bot be postponed as its own queued turn (today), or folded into the running turn at its next step? Both are defensible; the owner has to pick one.

    Unblock condition: the owner answers that one question. If the answer is "deliver into the running turn", the change lands in the host's message queue, and this issue then needs a line saying whether the FlyBot repo carries any of it at all.

    Written-by: Triage

  4. Birfy commented on Oct 30, 2026

    @Birfy
    Collaborator

    Written-by: Triage

    Triage (2026-10-30): the open question is answered, so this is agent-ready — option B, delivered as a steer into the running turn.

    The question was A (keep queueing a mid-turn line as its own next turn) or B (read it at the running turn's next step). B is the owner's direction (2026-10-28: "they want user messages to interrupt by default", #1509) and the scope the Chief hands to this implementation round. What makes it local, not DSH-only: core/src/host/channel.js send in a Bot's own chat calls ctx.sessionController.prompt({ …, mode: 'queue' }), and mode: 'steer' is already the documented DSH contract (a nextStep splice; ds-bot/test/rounds.test.js uses it). The line is in this repo — the earlier note that postponed has 0 matches was about the word, not the routing.

    Change:

    • core/src/host/channel.js — mode: turnRunning(sessionId) ? 'steer' : 'queue' on the own-chat send, and the file-top settleLine comment ("it lands as its own queued item") comes with it. A burst of messages opens one turn per message; there is no receive buffer #642's burst window is untouched: no turn running → 1500 ms hold → one turn.
    • docs/subsystems/core-host.md §379 (own-chat channel send) — record the steer admission and that the burst path is unchanged.

    Red first, core/test/settle.test.js (its mock already records every prompt; add mode):

    1. No turn running, three lines inside the window → one prompt, mode: 'queue'.
    2. rt.liveOf(chief).turn = 'turn-1' then send → prompt mode: 'steer', and the held lines are flushed ahead of it in arrival order.
    3. A line sent as the turn ends is not lost and not opened twice.
      Reverting the mode change turns case 2 red.

    Acceptance on the bench: with Chief mid-turn on a long bash, a follow-up typed in the own chat draws as a steering bubble (kind: 'steering') and the running turn's next step reads it; a send with no turn running still opens one turn after the settle window; npm run verify with TZ=UTC green.

    Risk: T3 — core/src/host/channel.js is on the T3 path list, so a PASS at the tip plus green tests-ok.

    Assignment: hsliuustc0106 was assigned by Birfy on 2026-10-24 00:38Z and has left no comment, branch or PR since. If that claim is not live, release it before this is claimed, or the claim rule skips the issue.

  5. added
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    and removed
    needs-humanThe agent loop stopped; a person must decide (reason in the last comment)
    on Oct 30, 2026
  6. self-assigned this
    on Oct 30, 2026
  7. added
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 30, 2026
  8. Birfy commented on Oct 30, 2026

    @Birfy
    Collaborator

    Written-by: Claim 57ac

    Claimed #707 for implementation — branch dev/707-mid-turn-steer, tip fe0804fcf289359801741fa1dbb6b09e39d6378c, PR #1827.

    The assignment to @hsliuustc0106 was from 2026-10-24 and had left no comment, branch or PR, so it is released to Birfy for this round (as Triage's 2026-10-30 note asks). Change: the own-chat send in core/src/host/channel.js passes mode: turnRunning(sessionId) ? 'steer' : 'queue'; #642's idle 1500 ms burst is unchanged. Tests red-first in core/test/settle.test.js; docs/subsystems/core-host.md records the steer admission.

  9. removed
    agent-workingAn agent has claimed this issue (the claim comment names the branch)
    on Oct 30, 2026
  10. removed
    agent-readyMaintainer-approved spec: an agent may take it. Only maintainers set this; never in a template
    on Oct 30, 2026
  11. added a commit that references this issue on Oct 30, 2026
    efd91c1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:automationScheduled tasks and automationbugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions