mirror of
https://github.com/QwenLM/qwen-code.git
synced 2026-07-19 05:54:13 +00:00
* feat(web-shell): queue prompts while turns are running * fix(web-shell): address pending prompt review feedback * fix(web-shell): tighten queued prompt event handling * fix(web-shell): avoid showing active prompt as queued * fix(web-shell): address queued prompt review follow-ups * fix(web-shell): address pending prompt review issues * fix(web-shell): reconcile queued prompt actions from server * fix(daemon): address pending prompt critical review * test(webui): expect submit abort signal forwarding * fix(web-shell): avoid duplicate queued prompt sync * fix(web-shell): keep local slash commands out of queue * fix(webui): avoid aborting prompt admission * fix(daemon): avoid queued prompt cancel cascades * fix(webui): avoid stale client id for queue cleanup * test(webui): update stale session queue cleanup expectation * fix(web-shell): preserve queue reconciliation identity * fix(web-shell): guard queue clear session writes --------- Co-authored-by: ytahdn <ytahdn@gmail.com> Co-authored-by: qwen-code-dev-bot <qwen-code-dev-bot@users.noreply.github.com>
60 lines
2.4 KiB
TypeScript
60 lines
2.4 KiB
TypeScript
import type { PromptImage } from '../adapters/promptTypes';
|
|
|
|
/**
|
|
* Single choke point for echoing a local slash command into the transcript.
|
|
*
|
|
* Some local commands "echo": they append a local user message
|
|
* (`store.appendLocalUserMessage`) and render their result inline. If one runs
|
|
* while a turn is streaming, the injected user row acts as a turn boundary in
|
|
* `applyTurnCollapse` (a turn spans one user message up to the next) and splits
|
|
* the active turn into two — its tool/thinking/token counters are then computed
|
|
* per fragment and come out wrong.
|
|
*
|
|
* Routing every echo through this helper means a command can never append to the
|
|
* transcript mid-turn. While a turn is in flight the command is suppressed
|
|
* instead of being added to the daemon pending-prompt queue, because local
|
|
* commands must not be replayed as model-facing prompt text.
|
|
*
|
|
* The only call sites that should bypass this and append mid-stream are the
|
|
* deliberate "busy acknowledgement" paths (e.g. clearing a goal while a turn
|
|
* runs), which opt in by calling `append` directly.
|
|
*/
|
|
export interface LocalEchoSink {
|
|
/** Append the command as a local user message (renders inline immediately). */
|
|
append: (text: string) => void;
|
|
}
|
|
|
|
/**
|
|
* Append a local command's echo, or suppress it if a turn is streaming.
|
|
*
|
|
* @returns `true` if the command was suppressed — the caller must stop and not
|
|
* run its inline side effects. `false` if it was appended and the caller
|
|
* should proceed.
|
|
*/
|
|
export function appendOrDeferLocalUserMessage(
|
|
isStreaming: boolean,
|
|
text: string,
|
|
_images: PromptImage[] | undefined,
|
|
sink: LocalEchoSink,
|
|
): boolean {
|
|
if (isStreaming) {
|
|
return true;
|
|
}
|
|
sink.append(text);
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Whether a queued prompt is a slash (`/…`) or shell (`!…`) command rather than
|
|
* model-facing prose.
|
|
*
|
|
* The queue's "insert" action injects the raw text into the running turn via
|
|
* `enqueueMidTurnMessage` — it is NOT re-dispatched as a command, so a command
|
|
* inserted this way reaches the model as the literal string "/context …" and
|
|
* never runs. Callers use this to disable "insert" for command entries that may
|
|
* still exist from daemon/custom command paths or from older sessions.
|
|
*/
|
|
export function isCommandPrompt(text: string): boolean {
|
|
const trimmed = text.trimStart();
|
|
return trimmed.startsWith('/') || trimmed.startsWith('!');
|
|
}
|