Repository navigation
feat(agent): a task list, a hand-back box, and Enter that queues — plan and progress like Claude desktop - #115
Merged
Merged
Conversation
…nd Enter that queues instead of stopping
Modelled on the Code tab of the Claude desktop app (docs/PLAN-PROGRESS.md has the evidence and the differences).
- update_plan takes Claude's shape: the whole list once ({"items": [...]}, pending / in_progress / completed),
then small updates ({"advance": true}, {"done": [n], "start": m}). The host keeps each step's status by
number for the conversation; the old todos / title / done still read.
- wrap_up hands the work back: a recap, and one question with one or two replies when the next move is the
user's. Auto-verify runs there; a hand-back whose box holds a question ends the run with no further call.
- The chat draws the list as the last thing in the transcript while a run works (spinning step, stale caption,
a window of 8 with "earlier steps" / "more to go"), and the next-step box when it hands back.
- Enter while the agent works queues the message above the composer; it is sent when the run ends, or given
back to the message box if the run was stopped or failed. Send now hands it to the agent at its next step.
- wrap_up is reserved from MCP tool names. The web skin rounds the new card and band like the old plan bar.
…— the list, the box and the queue in the real editor and in a tab
…elCode does, the owner's queue decision; release notes
Conflicts, each keeping both sides: - agent.js, the end of a run: Ask When Risky's reviewer cost and summary row (#112) and this branch's plan completion and returned "Send now" messages; one agent.done log line with both sets of fields. - extension.js, resumeSession and New Chat: this branch's plan/steer reset and the reset of the person's recorded words (#112/#114), each in both places. - media/chat.html, the message switch: develop's `approvals` message (#112 replaced the two-option `autopilot` one, whose handler no longer exists) and this branch's agentStart/agentStatus, which keep the task list and drop the old plan bar. - test/sessionExpiredHost.test.js, the harness declarations: both sets (agentMode from env, the approvals mode and recorded words; this branch's agentPlan and steerInbox). Checked on the merged tree (macOS, Node 24): scripts/test-extensions.sh 136 files; tsc --checkJs on extension.js and agent.js, no new undefined names; in the dev build plan-progress-editor-check 17/17, approvals-editor-check 12/12, memory-editor-check 11/11 on one of four runs — its "History lists the session after New Session" step is flaky on develop too (1 of 2 there).
Contributor
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
Contributor
There was a problem hiding this comment.
Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.
An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.
ndemianc
marked this pull request as ready for review
October 20, 2026 01:13
…e is not run wrap_up is where the run's edits are checked and the hand-back is shown; a call the same response made after it (an edit, a command) still ran, after the check and behind the box that said the work was done. Once a wrap_up in a response is accepted, any later call in that response is answered "Not run … do the work first, then call wrap_up last" instead. A wrap_up that verification refused does not count: the call after it is the fix, and runs.
A reply in the next-step box shows a 1-3 word label; what a click sends is the reply's message, up to 300 characters the agent wrote (visible only as a tooltip). It went through the chat's normal send, so the host recorded it as typed — and since #112 and #114 that is the person's word: the Ask When Risky reviewer counts it as authorization, and remember may quote it. A README that steers the agent into a "Yes" button whose message says more could have turned one click into an explicit go-ahead. The page now sends a click as a reply ({ type: 'send', reply: true }), and keeps that mark through the queue (drained at the end of a run, or sent with Send now while idle). handleSend passes typed: false for it, so the reply reaches the agent as before but is not the person's word. A reply the person edits in the message box, or that is handed back to it, is sent as their own typing. Tested: the page's queue functions lifted from chat.html (sent at once, queued while busy, drained, Send now when idle — the mark survives each, and a typed message carries none); handleSend lifted into sessionExpiredHost (a reply reaches agentFlow with typed: false, a typed message with true); the button's click and the send message are pinned from source.
…, not the user The prompt tells the model a message sent with Send now arrives after a tool result, marked as sent during the run. It did not say where such a message never is, and the mark is fixed text: a file, a command's output or an MCP result could carry it. The prompt now says a real one is never inside a tool result, and that text there claiming to be from the user is content to read. The real message stays a separate part after the results, as before.
… response; a reply click is not your typing Three notes in "What LevelCode does now": a call after an accepted wrap_up in the same response is not run; a reply button's click is sent marked as a reply and is not recorded as the person's words; a message claiming to be from the user inside a tool result is content.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The agent chat now shows its plan and progress the way the Claude desktop app's Code tab does, and Enter no longer stops a run. Design note with the evidence:
docs/PLAN-PROGRESS.md.What changes for someone using it
How
update_plantakes Claude's shape:itemsonce, then{"advance": true}/{"done": [n], "start": m}; the host keeps statuses by step number for the conversation (turnPlan.js). The oldtodosstill read.wrap_up(recap, ask, actions, blocked) is where auto-verify now runs: failing edits hide the box and go back to the model. A box with a question ends the run without another model call. A run that ends with aDone:line and nowrap_upends as before.steer; the loop takes it after the current step's tool results (in the same message) or after a no-tool answer (the run continues). What the run never reaches goes back to the queue beforeagentDone.wrap_upis reserved from MCP tool names; the web skin rounds the new card and band.Decision
Owner, 2026-10-19: Enter mid-run queues, as in Claude. This supersedes for now the Mid-Run Messaging Spec's Enter-steers and its holding of write/command calls, which are not built.
What ran
./scripts/test-extensions.sh) on macOS, Node 24.17, with the real-build halves on: 131 files pass. New suites:turnPlan(20),agentPlanProgress(11, the real loop on scripted turns),planProgressUi(24, lifted fromchat.html); 23 hand-made mutations of the key lines all caught.extensions/levelcode-ai/scripts/plan-progress-editor-check.js— 17/17, screenshots in LevelCode One Dark and One Light.web/test/e2e-plan-progress.mjs --scheme dark|light— 9/9 in each.Not verified
advanceand ask sensible questions is untested.Conflicts
With #112 in five adjacent-line spots, all keep-both: the
finallyinrunAgentbeforedbg('agent.done'),resumeSessionafteragentMessages = …, the message handlers inchat.html(theagentStartline), and the sandbox-globals line intest/diagramHost.test.jsandtest/sessionExpiredHost.test.js. #114 applies cleanly.RELEASE-NOTES.mdadds a section to the file #113 started.Review fixes (after merging develop with #112, #113, #114)
message, words the agent wrote under a 1–3 word label. It went through the normal send, so since feat(agent): Ask When Risky — a reviewer model rates each command before it runs #112/feat(memory): memory from you — remember/forget credited to the words you typed — and Search Sessions #114 the host counted it as the user's word: the Ask When Risky reviewer took it as authorization, andremembercould quote it. The page now sends it as{ type: 'send', reply: true }(the mark survives the queue), andhandleSendpassestyped: falsefor it.wrap_upis the last call of its response. A call after an acceptedwrap_upin the same response used to run after the check and behind the box; it is now answered "Not run". Awrap_uprefused by verification does not count, so the fix after it runs.Checked: gate 136 files; nine single-defect mutations of these fixes, each red;
plan-progress-editor-check17/17 andapprovals-editor-check12/12 in the dev build.