Skip to content

Cancel run agent - #2714

Draft
tlokeshrao wants to merge 5 commits into
feat-cancel-llm-streamfrom
feat-cancel-run-agent
Draft

Cancel run agent#2714
tlokeshrao wants to merge 5 commits into
feat-cancel-llm-streamfrom
feat-cancel-run-agent

Conversation

@tlokeshrao

Copy link
Copy Markdown
Contributor

Description

Changes Made

How to Test

  1. Steps to reproduce/test the behavior
  2. Expected outcomes

Notes

…-commit

Adds Room.ask(msg, engine, parentId, prebuiltResponse). When prebuiltResponse
is non-null, the LLM call is skipped and the caller-supplied response is
slotted in as the assistant turn -- everything else matches the live ask
tail (mutation lock, latest projection refresh, orphan-tool normalize,
parent-id resolution, append, room-name inference, persist) so the
persisted turn is indistinguishable from an LLM-generated one. When null,
delegates to the existing 3-arg ask.

Mirrors the null-passthrough convention already established on the 10-arg
Room.addToolExecutionResult overload. Hoists the cancel-commit tail out of
AskPlaygroundReactor.commitPrebuiltTurn (removed in the follow-up commit)
so RunAgent can share it.
…Playground uses Room.ask overload

Hoists appendHiddenPair from both playground reactors into PlaygroundUtils.
The shared helper acquires its own mutation lock and persists, matching the
existing AddPlaygroundToolExecution flow (the AskPlayground flow used to
piggy-back on commitPrebuiltTurn's persist; a second persist is a small
extra cost and keeps Room-level code hidden-message-unaware).

AskPlaygroundReactor drops its inline commitPrebuiltTurn and calls the new
Room.ask(msg, engine, parentId, prebuiltResponse) overload instead. Same
persisted output; centralizes the cancel-commit tail so RunAgent can share
it.

AddPlaygroundToolExecutionReactor points at the shared helper.
…k cancel-commit

Extends the cancel-persistence pattern from AskPlayground /
AddPlaygroundToolExecution to RunAgent so a stream cancelled during the
initial ask of a RunAgent turn can still commit the partial response the
FE saw.

Two new optional reactor keys:
- responseParts: when present, the agent loop is skipped entirely; the FE-
  supplied THINKING/TEXT parts are assembled into a ResponseMessage and
  persisted as the assistant response for a single input+response turn.
  Uses Room.ask(msg, engine, parentId, prebuiltResponse) so the persisted
  turn is indistinguishable from a live initial ask.
- hiddenMessage: paired with responseParts. Appends a hidden user note +
  assistant ack after the visible turn so the next turn's provider payload
  signals the model was cut short. Ignored on live runs.

Also added: parentMessageId reactor key (matches AskPlayground) so the FE
can anchor the persisted turn to the right point in the message tree.

Scope: initial-ask cancel only. Reflection cancels are behind a non-default
toggle (maxReflections defaults to 0) and would require the BE-owned
REFLECTION_PROMPT as the input text -- deferred until FE needs it.
Tool-followup cancels (mid-tool-batch or on the follow-up LLM call) are
also deferred; they have a different room-tail shape (aggregating
tool_result InputMessage vs. a fresh input) and warrant their own plumbing.

Return map on the cancel path uses the playground shape
{inputMessage, responseMessage, extraMessages} that the FE cancel flow
already consumes from AskPlayground, plus runId=null / status=CANCELLED_COMMIT
so callers can distinguish it from a live-run RunAgentResult return.

engine (engineIdFallback) is required on the cancel path -- the harness
normally resolves it from room options but the cancel-commit path does not
run the harness. Live path is unchanged.

FE will need to update: after cancelling a RunAgent stream on the initial
ask, call RunAgent again with responseParts=[...] + hiddenMessage=...
+ engine + roomId + command, matching the AskPlayground cancel flow.
@snyk-io

snyk-io Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Snyk checks have passed. No issues have been found so far.

Status Scan Engine Critical High Medium Low Total (0)
Open Source Security 0 0 0 0 0 issues

💻 Catch issues earlier using the plugins for VS Code, JetBrains IDEs, Visual Studio, and Eclipse.

@tlokeshrao
tlokeshrao changed the base branch from dev to feat-cancel-llm-stream July 8, 2026 14:06
…uiltTurn

Removes the four-arg ask(..., ResponseMessage prebuiltResponse) overload —
that shape conflated two very different code paths (live LLM call vs.
persist-only slot-in) behind one method name and forced callers/readers
to route on a null prebuiltResponse. ask now only asks the model.

Introduces commitPrebuiltTurn(msg, engine, parentId, prebuiltResponse) as
its own public method on Room, with prebuiltResponse required. Body is
unchanged — same mutation-lock/refresh/normalize/parent-id/append/
room-name/persist scaffold that used to be the private helper.

AskPlaygroundReactor and RunAgentReactor switch from
room.ask(msg, engine, parentId, prebuilt) to
room.commitPrebuiltTurn(msg, engine, parentId, prebuilt).
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.

1 participant