Skip to content

Runtime steer-queue drain concatenates messages without separator, causing run-on tokenisation #2517

@simonferquel-clanker

Description

@simonferquel-clanker

Problem

When the runtime drains multiple queued steer messages and assembles them into user messages sent to the LLM, the messages are added back-to-back without any separator between them.

Because most LLM providers send the full conversation to the model as a continuous byte stream (or token sequence), adjacent words from separate messages are tokenised together as a single run. For example, three consecutive steer messages "to", "get", "her" produce the token "together" rather than three distinct words.

Root cause

In pkg/runtime/loop.go, every drain site iterates over the drained slice and calls appendSteerAndEmit for each message without appending any whitespace or newline between messages:

for _, sm := range steered {
    r.appendSteerAndEmit(sess, sm, events)
}

Fix

Append \n to the content of every non-last message in the drained batch before injecting it. Messages remain independent (not merged into one). For multi-content messages the \n is appended to the last text part; if no text part exists, a new one is appended.

Implemented in a new drainAndEmitSteered helper (replacing the three inline drain loops) with a pure helper appendNewlineToQueuedMessage.

Related: #2516 (trimming behaviour fix)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions