Skip to content

feat(remote): complete typed mutation protocol - #419

Merged
Ziinc merged 7 commits into
mainfrom
cursor/typed-remote-mutation-protocol-40f6
Sep 6, 2026
Merged

Ziinc merged 7 commits into
mainfrom
cursor/typed-remote-mutation-protocol-40f6

Conversation

@Ziinc

@Ziinc Ziinc commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Summary

Closes the Phase 5 gap between Rust TreqCommandRequest and the TypeScript IPC union. SplitCommit is a non-interactive typed mutation (selected files/hunks). AgentInput writes to the VM-local supervisor FIFO. Arbitrary command strings stay out of frontend and IPC types.

Supported commands

Reads: InspectRepository, RepositoryStatus, ListBranches, ListWorkspaces, InspectWorkspace, ListChanges, DiffFile, ReadFile, ListCommits, ListConflicts, WorkspaceChangeMarker, ProbeRepo, AgentStatus, AgentLogs
Naturally idempotent mutations / ops (no key): UpdateWorkspace, DeleteWorkspace, RestoreFile, DescribeCommit, GitFetch, GitBookmarkTrack, AgentStop
Mutations that require an idempotency key: CloneRepo, InitRepo, CreateWorkspace, RenameWorkspace, MoveWorkspaceChanges, RebaseWorkspace, PatchFile, CreateCommit, SplitCommit, MoveCommit, AbandonCommit, ResolveConflict, GitPush, AgentStart, AgentInput

Idempotency

Non-naturally-idempotent mutations require a non-empty idempotency_key. Replay uses the existing in-process map (not durable storage). Empty keys are rejected.

SplitCommit

Request carries files and hunks. Execution unions those paths and calls existing jj_split. Empty files and hunks is invalid_arguments. No interactive hunk selector.

AgentInput

Start opens a Unix FIFO plus a keeper process so stdin survives CLI process exit. Missing record → agent_not_found. Stopped process → agent_not_running. Windows has no FIFO; input is written to a file while the process is alive.

Intentional limitations

  • No durable idempotency store.
  • No new visual mutation UI.
  • SSH connection, certificates, aliases, and PTY unchanged.
  • Hunk-level split still maps to file-level jj_split.
  • Windows AgentInput uses a file, not a FIFO.

Tests run

Command Result
Focused Rust split / AgentInput / CLI parse / kind parity / unknown-kind pass
npm run build:napi pass
vitest src/lib/remote-dispatch.test.ts 3 passed
Full cargo test --lib in this VM 485 passed; 12 failed because jj is missing (No such file or directory)
GitHub rust / test / ubuntu-22.04 and macos-latest pass
GitHub rust / test / windows-latest failed on send_agent_input_reaches_a_running_process (ping leak + no FIFO echo); fixed in follow-up commit
GitHub check-conventional-title failed on previous title; retitled to conventional format
Open in Web Open in Cursor 

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

@Ziinc
Ziinc marked this pull request as ready for review September 4, 2026 19:32
@cursor cursor Bot changed the title Complete typed remote mutation protocol feat(remote): complete typed mutation protocol Sep 4, 2026
cursoragent and others added 2 commits September 5, 2026 08:36
Expose matching TreqCommandRequest variants in Rust, CLI, Tauri IPC, and TypeScript for clone/init, workspace/file/commit/conflict/git/agent mutations. Require idempotency keys on non-naturally-idempotent mutations, implement non-interactive SplitCommit with explicit files/hunks, and send AgentInput through the VM-local supervisor FIFO.

Co-authored-by: ty <ty@tzeyiing.com>
Windows has no FIFO, so the stdin-echo assertion is Unix-only. Always stop the helper process on Drop so a failed assertion cannot leak ping.exe.

Co-authored-by: ty <ty@tzeyiing.com>
@Ziinc
Ziinc force-pushed the cursor/typed-remote-mutation-protocol-40f6 branch from 37781fb to e647875 Compare September 5, 2026 19:26
…_deref

PR 419 made idempotency_key a required String (validated at the CLI
boundary) rather than main's prior Option<String>. The 5-arg
with_idempotency_key call sites and two test fixtures still assumed the
old Option shape after the rebase.
…ype drift

main had advanced past this branch's rebase point with several more merged
PRs, including native SSH config alias resolution which added
clone_repo_native() still using the old Option<String> idempotency_key
shape. Updated it to the required String this branch introduced.
The merge with main left duplicate CloneRepo/InitRepo TypeScript union
members: an old shape with idempotency_key optional alongside the new
required-string shape this branch introduced. The optional variant let
callers (and the remote-ssh integration test) omit the field entirely,
which the Rust side now rejects with "missing field idempotency_key"
since the field is a required String there.
IdempotencyStore::open() eagerly creates <repo>/.treq/ when opened. Scoping
it at the clone destination itself meant that directory existed (non-empty)
by the time git clone ran, so git refused with "destination path already
exists and is not an empty directory" on every clone. The destination is
supposed to not exist yet; its parent is what's guaranteed to be there.
@Ziinc
Ziinc merged commit 1ed6414 into main Sep 6, 2026
15 checks passed
@Ziinc
Ziinc deleted the cursor/typed-remote-mutation-protocol-40f6 branch September 6, 2026 04:11
Ziinc pushed a commit that referenced this pull request Sep 6, 2026
main's typed mutation protocol (#419) removed isRemoteActionSupported and
wired SplitCommit/AgentInput end-to-end, so remote-capabilities.ts marks
them supported instead of reading a removed helper.
Ziinc pushed a commit that referenced this pull request Sep 6, 2026
PR #419 changed TreqCommandRequest's idempotency_key fields from
Option<String> to required String; update the native e2e test's
InitRepo/CreateWorkspace calls to match.
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.

3 participants