Feature Request: expose conversation rewind over ACP (Droid already implements execute_rewind) · Issue #47 · Factory-AI/factory · GitHub
Skip to content

Feature Request: expose conversation rewind over ACP (Droid already implements execute_rewind) #47

Open

Description

@apple-ouyang

Summary

Droid has a working "rewind conversation" in the TUI (/rewind-conversation, backed by droid.execute_rewind), but it is not reachable from ACP, so ACP clients cannot offer it. Please advertise it over ACP:

"agentCapabilities": {
  "_meta": {
    "conversationRewind": { "method": "_paseo/session/revert", "target": "user-message-id" }
  }
}

plus one extMethod case that forks the session and returns the new session id. The namespace is yours to pick; clients read the method name out of _meta.

Current behavior (droid 0.232.0, macOS arm64)

  • ACP initialize returns loadSession, sessionCapabilities{list,resume}, promptCapabilities{image,embeddedContext} and _meta{terminal_output,terminal-auth}. Nothing about rewind.
  • The ACP agent's extMethod handles only session/list, session/resume, session/set_config_option; anything else is -32601.
  • rewind-conversation is not in available_commands_update (88 commands advertised on a loaded session), and it needs a TUI picker anyway — sending it as a prompt just goes to the model as text.
  • droid.execute_rewind{sessionId, messageId, filesToRestore, filesToDelete, forkTitle} → {newSessionId, restoredCount, deletedCount, failedRestoreCount, failedDeleteCount} already exists in daemon / stream-jsonrpc mode. Its semantics are exactly what a client wants: fork the conversation immediately before one user message. It is only the ACP exposure that is missing.

Suggested behavior

  1. Advertise the extension in initialize as shown above.
  2. Handle it in extMethod, taking { "sessionId": …, "messageId": … }.
  3. Resolve messageId to Droid's own message: clients identify the turn with the ACP prompt id. PromptRequest.messageId exists in the current ACP schema, and some clients also duplicate it as _meta.clientMessageId for older adapters.
  4. Echo messageId on the replayed user_message_chunk notifications during session/load. ContentChunk.messageId is already in the schema; without it a client cannot rewind a second time on the returned fork, because the replayed rows lose their identity.
  5. Return { "sessionId": "<forked session id>" }. The client then resumes that fork with session/load and the existing replay machinery shows the rewound conversation.

Conversation-only is enough for a first cut: filesToRestore / filesToDelete can be empty, so no file restoration is required.

Why it matters

Paseo already implements the client half generically for any ACP agent: it gates the rewind menu on _meta.conversationRewind, calls the advertised method, rebinds to the returned session id and replays it (getpaseo/paseo#5924, discussed in getpaseo/paseo#4578). Factory Droid would light up with no client change the moment the capability is advertised. Every other ACP client that adopts the same extension gets it for free too.

Workaround, to show the gap is only on the ACP surface

A local ACP proxy can fake the extension by copying <sessionId>.jsonl under ~/.factory/sessions/<cwd-slug>/, keeping the records before the target user message, rewriting session_start.id to a fresh UUID and copying the .settings.json alongside. Verified working: Droid accepts that fork and replays the truncated history through session/load. That is a lot of undocumented-format coupling for every client to carry, and it needs the proxy's own bookkeeping to map client prompt ids back to stored messages — which is the part that would be trivial inside Droid, where execute_rewind already does the fork.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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