feat(agent): implement /clear and advertise it as a capability - #76942
Closed
haacked wants to merge 2 commits into
Closed
feat(agent): implement /clear and advertise it as a capability#76942haacked wants to merge 2 commits into
haacked wants to merge 2 commits into
Conversation
Intercept /clear in the Claude adapter instead of forwarding it to the SDK: retire the current query and swap in a brand-new SDK session (fresh id, no resume) under the same ACP session. A _posthog/conversation_cleared marker records the boundary in the append-only session log, and the rehydration paths (jsonl hydration, ResumeSaga) treat it as a conversation boundary so desktop reconnects and cloud resumes rebuild only the post-clear conversation. The UI renders a "Conversation cleared" divider and resets the context indicator. Session.clearing (a promise, claimed synchronously) serializes the swap: a second /clear is refused, cancel/interrupt is ignored mid-clear, refreshSession refuses, and a racing prompt waits for the clear to settle instead of pushing into the retired input stream. The "/clear" prompt is broadcast only once the new session is confirmed live, so a timeout leaves no orphaned entry in the log, and any error terminates the unproven replacement query, closes the session, and resolves the spinner with clearing_failed. The command is read off the ACP prompt rather than the converted SDK message, skipping blocks the host injected rather than the user: promptToClaude prepends detected-PR and local-skill context, and cloud prompts lead with hidden blocks (a resume preamble; on desktop, shell-execute recaps). Matching the first text block of either read host context as the user's command and missed the command entirely, which is why /clear never fired on a resumed cloud run. The adapter advertises conversationClear in its initialize capabilities and the cloud agent-server relays it on _posthog/run_started, so a host can tell whether the agent it is talking to honours the boundary. Hosts that record one without an agent gate on it; an agent that predates the marker ignores it on resume and would rebuild the conversation the boundary was meant to retire. Claude-Session: https://claude.ai/code/session_01HJQHhq27qXnKGj98x7UrXZ
|
Merging to
After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here |
1 task
applySessionMode updated the running query and session.permissionMode but left session.queryOptions.permissionMode at the value the session was created with. Both query rebuilds (/clear, refreshSession) seed the replacement from queryOptions, so a session that started in bypassPermissions and was later narrowed silently returned to bypassPermissions after a clear, with nothing on screen to say the mode had moved. Sync the mode into queryOptions when it changes, matching how effort and the 1M-context beta already do it, so every rebuild inherits the live value rather than each one re-rooting its own fields. Reported by veria-ai on #76457.
Contributor
Author
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.
Problem
/cleardidn't work in cloud, which was blocking the feature. Two independent reasons:The adapter read the leading slash command off the converted SDK message. In cloud that's almost never the user's text.
promptToClaudeprepends detected-PR and local-skill context, and the agent-server wraps a pending message in a hidden resume preamble. Since a finished cloud run turns every send into a new run, that resume shape is the common path, so/clearreached the model as literal text instead of clearing anything.Separately,
/clearwasn't advertised at all, so it never appeared in the composer's command menu.Changes
Command detection now reads the ACP prompt and skips blocks the host injected rather than the user (
_meta.ui.hidden, plus the local-skill chunkpromptToClaudeconsumes). That also fixes the desktop case where shell-execute recaps precede the prompt. The hidden-block predicate already existed in the codex adapter, so it moved to a sharedadapters/prompt-blocks.tsthat both use.The adapter also advertises a
conversationClearcapability in its initialize response, and the cloud agent-server relays it on_posthog/run_started.That capability exists because of how this ships. The agent is published as
@posthog/agentand baked into the sandbox image, on its own release, while the backend that records a clear boundary ships with PostHog. An agent predating the marker ignores it on resume and rebuilds the conversation the boundary was meant to retire. Without something to gate on, a user could be shown a cleared conversation that wasn't. The stacked PR consumes this.This is the bottom of a two-PR stack, and it has to ship first. It is also useful alone:
/clearon a live run works end to end once anagent-v*release lands.How did you test this code?
Automated, all run locally:
packages/agent(adapters + sagas), including 16 inclaude-agent.clear.test.tspackages/coresessionstypecheckclean on agent, core, ui, sharedNew tests, and the regression each catches:
claude-agent.clear.test.ts— a cloud-shaped prompt where/clearsits behind a hidden resume preamble still clears. This is the exact bug above; every existing clear test sent a bare/clearblock, so none of them caught it.resume-saga.test.ts— aconversation_clearedmarker naming no session resumes nothing.findSessionIdused to skip such an entry and keep scanning back to an earlierrun_started, which on a warm sandbox would natively resume the conversation the marker retired.I have not exercised
/clearagainst a live cloud run. That needs the agent published and the sandbox image rolled, neither of which can happen before this merges.Automatic notifications
Docs update
UPSTREAM.mdnotes that PostHog Code now implements/clearitself rather than forwarding the SDK's.