514 lines
16 KiB
Protocol Buffer
514 lines
16 KiB
Protocol Buffer
// Diff state protocol messages for communication between
|
||
// the Warp client and the remote server binary.
|
||
//
|
||
// These messages are used by the diff state subsystem to synchronize
|
||
// code review diff data between a remote daemon and the Warp client.
|
||
|
||
syntax = "proto3";
|
||
|
||
package remote_server;
|
||
|
||
// ── Diff state sub-messages ───────────────────────────────────────
|
||
// Mirror the Rust domain types in code_review/diff_state.rs.
|
||
|
||
// Mirrors DiffMode in Rust.
|
||
message DiffMode {
|
||
oneof mode {
|
||
DiffModeHead head = 1;
|
||
DiffModeMainBranch main_branch = 2;
|
||
DiffModeOtherBranch other_branch = 3;
|
||
}
|
||
}
|
||
message DiffModeHead {}
|
||
message DiffModeMainBranch {}
|
||
message DiffModeOtherBranch {
|
||
string branch_name = 1;
|
||
}
|
||
|
||
// Mirrors DiffState in Rust. After the wrapper split (§1), Loaded is a
|
||
// unit variant — the diff payload is carried separately in
|
||
// DiffStateSnapshot.diffs.
|
||
message DiffState {
|
||
oneof state {
|
||
DiffStateNotInRepository not_in_repository = 1;
|
||
DiffStateLoading loading = 2;
|
||
DiffStateErrorValue error = 3;
|
||
DiffStateLoaded loaded = 4;
|
||
}
|
||
}
|
||
message DiffStateNotInRepository {}
|
||
message DiffStateLoading {}
|
||
message DiffStateErrorValue {
|
||
string message = 1;
|
||
}
|
||
message DiffStateLoaded {}
|
||
|
||
// Mirrors DiffLineType in Rust.
|
||
enum DiffLineType {
|
||
DIFF_LINE_TYPE_UNSPECIFIED = 0;
|
||
DIFF_LINE_TYPE_CONTEXT = 1;
|
||
DIFF_LINE_TYPE_ADD = 2;
|
||
DIFF_LINE_TYPE_DELETE = 3;
|
||
DIFF_LINE_TYPE_HUNK_HEADER = 4;
|
||
}
|
||
|
||
// Represents a single line in a diff hunk, as rendered by `git diff`. Mirrors DiffLine in Rust.
|
||
message DiffLine {
|
||
DiffLineType line_type = 1;
|
||
optional uint64 old_line_number = 2;
|
||
optional uint64 new_line_number = 3;
|
||
string text = 4;
|
||
bool no_trailing_newline = 5;
|
||
}
|
||
|
||
// Represents a hunk of changes in a file diff, as rendered by `git diff`. Mirrors DiffHunk in Rust.
|
||
message DiffHunk {
|
||
uint64 old_start_line = 1;
|
||
uint64 old_line_count = 2;
|
||
uint64 new_start_line = 3;
|
||
uint64 new_line_count = 4;
|
||
repeated DiffLine lines = 5;
|
||
uint64 unified_diff_start = 6;
|
||
uint64 unified_diff_end = 7;
|
||
}
|
||
|
||
// Represents the status of a file in the git working directory. Mirrors GitFileStatus in Rust.
|
||
message GitFileStatus {
|
||
oneof status {
|
||
GitFileStatusNew new_file = 1;
|
||
GitFileStatusModified modified = 2;
|
||
GitFileStatusDeleted deleted = 3;
|
||
GitFileStatusRenamed renamed = 4;
|
||
GitFileStatusCopied copied = 5;
|
||
GitFileStatusUntracked untracked = 6;
|
||
GitFileStatusConflicted conflicted = 7;
|
||
}
|
||
}
|
||
message GitFileStatusNew {}
|
||
message GitFileStatusModified {}
|
||
message GitFileStatusDeleted {}
|
||
message GitFileStatusRenamed {
|
||
string old_path = 1;
|
||
}
|
||
message GitFileStatusCopied {
|
||
string old_path = 1;
|
||
}
|
||
message GitFileStatusUntracked {}
|
||
message GitFileStatusConflicted {}
|
||
|
||
// Mirrors DiffSize in Rust (diff_size_limits.rs).
|
||
enum DiffSize {
|
||
DIFF_SIZE_UNSPECIFIED = 0;
|
||
DIFF_SIZE_NORMAL = 1;
|
||
DIFF_SIZE_LARGE = 2;
|
||
// The diff/patch itself is too large to render. (Was DIFF_SIZE_UNRENDERABLE;
|
||
// value 3 is preserved for wire compatibility.)
|
||
DIFF_SIZE_UNRENDERABLE_DIFF_TOO_LARGE = 3;
|
||
// The base file content was withheld because it exceeded the per-file wire
|
||
// budget; the client renders a "file too large" placeholder.
|
||
DIFF_SIZE_UNRENDERABLE_FILE_TOO_LARGE = 4;
|
||
}
|
||
|
||
// Mirrors FileDiff + FileDiffAndContent in Rust.
|
||
// The two types are collapsed into a single message with an optional content_at_base field,
|
||
// since every wire context that sends a FileDiff also needs base content for editor rendering.
|
||
message FileDiff {
|
||
string file_path = 1;
|
||
GitFileStatus status = 2;
|
||
repeated DiffHunk hunks = 3;
|
||
bool is_binary = 4;
|
||
bool is_autogenerated = 5;
|
||
uint64 max_line_number = 6;
|
||
bool has_hidden_bidi_chars = 7;
|
||
DiffSize size = 8;
|
||
// File content at HEAD or merge-base, used by the code review editor to
|
||
// render inline diff decorations (set_base). Absent for binary files, for
|
||
// files whose content exceeds the per-file wire budget (size =
|
||
// DIFF_SIZE_UNRENDERABLE_FILE_TOO_LARGE), or when git show fails.
|
||
optional string content_at_base = 9;
|
||
// Number of complete conflict-marker blocks in the working-tree file.
|
||
uint64 conflict_count = 10;
|
||
}
|
||
|
||
// Represents the complete git diff information for a repository. Mirrors GitDiffData in Rust.
|
||
message GitDiffData {
|
||
repeated FileDiff files = 1;
|
||
uint64 total_additions = 2;
|
||
uint64 total_deletions = 3;
|
||
uint64 files_changed = 4;
|
||
}
|
||
|
||
// Mirrors DiffStats in Rust.
|
||
message DiffStats {
|
||
uint64 files_changed = 1;
|
||
uint64 total_additions = 2;
|
||
uint64 total_deletions = 3;
|
||
}
|
||
|
||
// Mirrors DiffMetadataAgainstBase in Rust.
|
||
message DiffMetadataAgainstBase {
|
||
DiffStats aggregate_stats = 1;
|
||
// Per-file change entries for this base, captured from the same numstat that
|
||
// produces aggregate_stats so the git dialog's Changes box can render
|
||
// without a working-tree read (lets the box populate for remote repos).
|
||
repeated FileChangeEntry files = 2;
|
||
}
|
||
|
||
// Mirrors Commit in Rust (util/git.rs).
|
||
message Commit {
|
||
string hash = 1;
|
||
string subject = 2;
|
||
uint64 files_changed = 3;
|
||
uint64 additions = 4;
|
||
uint64 deletions = 5;
|
||
// Per-file changes in this commit, captured up front so the push dialog can
|
||
// render a commit's file list on expansion without a follow-up RPC.
|
||
repeated FileChangeEntry files = 6;
|
||
}
|
||
|
||
// Mirrors FileChangeEntry in Rust (util/git.rs).
|
||
message FileChangeEntry {
|
||
string path = 1;
|
||
uint64 additions = 2;
|
||
uint64 deletions = 3;
|
||
}
|
||
|
||
// Mirrors PrInfo in Rust (util/git.rs).
|
||
message PrInfo {
|
||
uint64 number = 1;
|
||
string url = 2;
|
||
string state = 3;
|
||
bool draft = 4;
|
||
string base_branch = 5;
|
||
}
|
||
|
||
// Mirrors DiffMetadata in Rust.
|
||
message DiffMetadata {
|
||
string main_branch_name = 1;
|
||
string current_branch_name = 2;
|
||
DiffMetadataAgainstBase against_head = 3;
|
||
optional DiffMetadataAgainstBase against_base_branch = 4;
|
||
bool has_head_commit = 5;
|
||
repeated Commit unpushed_commits = 6;
|
||
optional string upstream_ref = 7;
|
||
}
|
||
|
||
// Mirrors FileStatusInfo in Rust. Identifies a file and its git status
|
||
// for discard operations (git restore / git stash / git rm).
|
||
message FileStatusInfo {
|
||
string path = 1;
|
||
GitFileStatus status = 2;
|
||
}
|
||
|
||
// ── Diff state client → server ────────────────────────────────────
|
||
|
||
// Client → server: subscribe to diff state for a (repo, mode) pair.
|
||
// The server responds with GetDiffStateResponse, then pushes subsequent changes.
|
||
message GetDiffState {
|
||
string repo_path = 1;
|
||
DiffMode mode = 2;
|
||
}
|
||
|
||
// Client → server: unsubscribe from diff state updates for a (repo, mode) pair.
|
||
// Fire-and-forget — the server does not send a response.
|
||
message UnsubscribeDiffState {
|
||
string repo_path = 1;
|
||
DiffMode mode = 2;
|
||
}
|
||
|
||
// Client → server: discard changes for one or more files.
|
||
// Runs git restore/stash/rm on the remote filesystem.
|
||
message DiscardFilesRequest {
|
||
string repo_path = 1;
|
||
repeated FileStatusInfo files = 2;
|
||
bool should_stash = 3;
|
||
// Branch to restore against. Absent means HEAD.
|
||
optional string branch_name = 4;
|
||
// The diff mode identifying which DiffStateModel to use.
|
||
DiffMode mode = 5;
|
||
}
|
||
|
||
// ── Diff state server → client ────────────────────────────────────
|
||
|
||
// Error payload for GetDiffStateResponse.
|
||
message DiffStateError {
|
||
string message = 1;
|
||
}
|
||
|
||
// Full diff state snapshot for a (repo, mode) pair.
|
||
// Pushed on structural changes (NewDiffsComputed events).
|
||
message DiffStateSnapshot {
|
||
string repo_path = 1;
|
||
DiffMode mode = 2;
|
||
DiffMetadata metadata = 3;
|
||
DiffState state = 4;
|
||
// Present when state is Loaded.
|
||
optional GitDiffData diffs = 5;
|
||
}
|
||
|
||
// Response to GetDiffState.
|
||
message GetDiffStateResponse {
|
||
oneof result {
|
||
DiffStateSnapshot snapshot = 1;
|
||
DiffStateError error = 2;
|
||
}
|
||
}
|
||
|
||
// Metadata-only update pushed for MetadataRefreshed and
|
||
// CurrentBranchChanged events. Avoids re-serializing the entire diff
|
||
// payload on every throttled refresh.
|
||
message DiffStateMetadataUpdate {
|
||
string repo_path = 1;
|
||
DiffMode mode = 2;
|
||
DiffMetadata metadata = 3;
|
||
}
|
||
|
||
// Single-file diff delta pushed for SingleFileUpdated events.
|
||
// Carries one FileDiff + file path + updated metadata.
|
||
// Debounced at 2s on the server.
|
||
message DiffStateFileDelta {
|
||
string repo_path = 1;
|
||
DiffMode mode = 2;
|
||
string file_path = 3;
|
||
optional FileDiff diff = 4;
|
||
optional DiffMetadata metadata = 5;
|
||
}
|
||
|
||
// Server → client: result of a DiscardFilesRequest.
|
||
message DiscardFilesResponse {
|
||
oneof result {
|
||
DiscardFilesSuccess success = 1;
|
||
DiscardFilesError error = 2;
|
||
}
|
||
}
|
||
|
||
message DiscardFilesSuccess {}
|
||
|
||
message DiscardFilesError {
|
||
string message = 1;
|
||
}
|
||
|
||
// ── Branch listing ────────────────────────────────────────────────
|
||
|
||
// Client → server: list branches for a repository.
|
||
message GetBranches {
|
||
string repo_path = 1;
|
||
// Maximum number of branches to return. Absent = server default (100).
|
||
optional uint32 max_branch_count = 2;
|
||
// Whether to include remote-tracking branches (refs/remotes).
|
||
bool include_remotes = 3;
|
||
}
|
||
|
||
// A single branch entry.
|
||
message BranchInfo {
|
||
string name = 1;
|
||
bool is_main = 2;
|
||
}
|
||
|
||
// Server → client: result of a GetBranches request.
|
||
message GetBranchesResponse {
|
||
oneof result {
|
||
GetBranchesSuccess success = 1;
|
||
GetBranchesError error = 2;
|
||
}
|
||
}
|
||
|
||
message GetBranchesSuccess {
|
||
repeated BranchInfo branches = 1;
|
||
}
|
||
|
||
message GetBranchesError {
|
||
string message = 1;
|
||
}
|
||
|
||
// ── Git operations (commit / push / create-PR) ────────────────────
|
||
// Run git / gh on the remote filesystem. These mirror the local code
|
||
// review git dialog operations in app/src/code_review/git_dialog/*.
|
||
|
||
// Shared error payload for git operation responses. The message is the
|
||
// raw git/gh error, mapped to user-facing copy on the client.
|
||
message GitOpError {
|
||
string message = 1;
|
||
}
|
||
|
||
// Post-operation delta applied to DiffMetadata so the client refreshes the
|
||
// header immediately, without waiting for the next watcher-driven snapshot.
|
||
message GitOpDelta {
|
||
repeated Commit unpushed_commits = 1;
|
||
optional string upstream_ref = 2;
|
||
}
|
||
|
||
// Client → server: run the commit chain (commit, then optionally push, then
|
||
// optionally create-PR) host-local in a single round trip. The daemon
|
||
// sequences the underlying git / gh subprocesses (see handle_git_commit_chain), so
|
||
// the SSH link carries one request/response instead of the 2–3 a client-side
|
||
// chain would send.
|
||
message GitCommitChainRequest {
|
||
string repo_path = 1;
|
||
string message = 2;
|
||
bool include_unstaged = 3;
|
||
// Branch to push / open the PR against. Ignored for COMMIT_ONLY.
|
||
string branch = 4;
|
||
GitCommitChainMode mode = 5;
|
||
// When mode is COMMIT_AND_CREATE_PR, generate the PR title/body via AI on the
|
||
// daemon (get_diff_for_pr + generate_code_review_content), falling back to
|
||
// `gh pr create --fill`. Ignored for the other modes.
|
||
bool autogenerate_pr_content = 6;
|
||
}
|
||
|
||
// What to run after the commit succeeds.
|
||
enum GitCommitChainMode {
|
||
GIT_COMMIT_CHAIN_MODE_COMMIT_ONLY = 0;
|
||
GIT_COMMIT_CHAIN_MODE_COMMIT_AND_PUSH = 1;
|
||
GIT_COMMIT_CHAIN_MODE_COMMIT_AND_CREATE_PR = 2;
|
||
}
|
||
|
||
message GitCommitChainResponse {
|
||
oneof result {
|
||
GitCommitChainSuccess success = 1;
|
||
GitOpError error = 2;
|
||
}
|
||
}
|
||
|
||
// Final post-chain delta plus the PR when one was created (absent for
|
||
// COMMIT_ONLY / COMMIT_AND_PUSH).
|
||
message GitCommitChainSuccess {
|
||
GitOpDelta delta = 1;
|
||
optional PrInfo pr_info = 2;
|
||
}
|
||
|
||
// Client → server: push `branch` to origin, setting upstream tracking.
|
||
message GitPushRequest {
|
||
string repo_path = 1;
|
||
string branch = 2;
|
||
}
|
||
|
||
message GitPushResponse {
|
||
oneof result {
|
||
GitOpDelta success = 1;
|
||
GitOpError error = 2;
|
||
}
|
||
}
|
||
|
||
// Client → server: create a PR for the current branch (must be pushed).
|
||
// Absent title/body => `gh pr create --fill`, unless autogenerate_content is
|
||
// set (then the daemon generates the title/body via AI first).
|
||
message GitCreatePrRequest {
|
||
string repo_path = 1;
|
||
// Current branch name, passed as context to daemon-side AI generation.
|
||
string branch = 2;
|
||
// When true and title/body are both absent, the daemon generates the PR
|
||
// title + body via AI (get_diff_for_pr + generate_code_review_content)
|
||
// before running `gh pr create`, falling back to `--fill` on failure.
|
||
bool autogenerate_content = 3;
|
||
}
|
||
|
||
message GitCreatePrResponse {
|
||
oneof result {
|
||
PrInfo success = 1;
|
||
GitOpError error = 2;
|
||
}
|
||
}
|
||
|
||
|
||
// Client → server: list the committed file changes for the current branch's
|
||
// PR-ready diff (merge_base(HEAD, main)..HEAD). Backs the Create PR dialog's
|
||
// Changes box; deliberately committed-only (no working-tree edits, no
|
||
// untracked files) so it matches what `gh pr create` would include.
|
||
message GitGetCommittedBranchFilesRequest {
|
||
string repo_path = 1;
|
||
}
|
||
|
||
message GitGetCommittedBranchFilesResponse {
|
||
oneof result {
|
||
GitGetCommittedBranchFilesSuccess success = 1;
|
||
GitOpError error = 2;
|
||
}
|
||
}
|
||
|
||
message GitGetCommittedBranchFilesSuccess {
|
||
repeated FileChangeEntry files = 1;
|
||
}
|
||
|
||
// Client → server: generate a commit message via AI on the remote host.
|
||
// The daemon computes the working-tree diff locally and calls the Warp
|
||
// server's code-review content endpoint, returning the message string. Sent
|
||
// at commit-dialog open time, mirroring the local open-time autogen.
|
||
message GitGenerateCommitMessageRequest {
|
||
string repo_path = 1;
|
||
// Whether to include unstaged changes in the diff sent to AI (mirrors the
|
||
// commit dialog's include-unstaged toggle).
|
||
bool include_unstaged = 2;
|
||
// Current branch name, passed as context to the AI request.
|
||
string branch_name = 3;
|
||
}
|
||
|
||
message GitGenerateCommitMessageResponse {
|
||
oneof result {
|
||
// The generated commit message (already trimmed, non-empty).
|
||
string message = 1;
|
||
GitOpError error = 2;
|
||
}
|
||
}
|
||
|
||
// ── Git and GitHub info ──────────────────────────────────────────────────
|
||
|
||
// Mirrors RepositoryInfo in Rust (util/git.rs). Returned by `gh repo view`.
|
||
message RepositoryInfo {
|
||
string name = 1;
|
||
optional string owner = 2;
|
||
}
|
||
|
||
// Mirrors GitStatusMetadata in Rust (code_review/git_repo_model/mod.rs).
|
||
message GitStatusMetadata {
|
||
string current_branch_name = 1;
|
||
string main_branch_name = 2;
|
||
DiffStats stats_against_head = 3;
|
||
optional string tracking_upstream = 4;
|
||
uint32 tracking_ahead = 5;
|
||
uint32 tracking_behind = 6;
|
||
bool tracking_counts_available = 7;
|
||
}
|
||
|
||
// Server -> client push: aggregate git status for a repo. Sent on every
|
||
// watcher tick, opportunistically after navigation resolves a git root, and
|
||
// when a client requests a current snapshot.
|
||
message GitStatusPush {
|
||
string repo_path = 1;
|
||
GitStatusMetadata metadata = 2;
|
||
}
|
||
|
||
// Client -> server notification: ask the daemon to create the per-repo git
|
||
// status model if needed and push the current GitStatusPush snapshot when
|
||
// available. Fire-and-forget; no response is sent.
|
||
message UpdateGitStatus {
|
||
string repo_path = 1;
|
||
}
|
||
|
||
// Server -> client push: PR info for a repo's current branch. Sent when the
|
||
// daemon's `GitHubRepoModel` recomputes PR info.
|
||
message GitHubPrInfoPush {
|
||
string repo_path = 1;
|
||
optional PrInfo pr_info = 2;
|
||
}
|
||
// Server -> client push: repository name/owner info for a repo. Sent when the
|
||
// daemon's `GitHubRepoModel` recomputes repository info.
|
||
message GitHubRepositoryInfoPush {
|
||
string repo_path = 1;
|
||
optional RepositoryInfo repository_info = 2;
|
||
}
|
||
// Client -> server notification: ask the daemon to create the per-repo
|
||
// GitHubRepoModel if needed and refresh PR info for the current branch. The
|
||
// result is delivered as a `GitHubPrInfoPush` broadcast (single source of
|
||
// truth: the daemon's `GitHubRepoModel`). Fire-and-forget; no response.
|
||
message UpdateGitHubPrInfo {
|
||
string repo_path = 1;
|
||
}
|
||
// Client -> server notification: ask the daemon to create the per-repo
|
||
// GitHubRepoModel if needed and refresh repository name/owner. The result is
|
||
// delivered as a `GitHubRepositoryInfoPush` broadcast. Fire-and-forget; no
|
||
// response.
|
||
message UpdateGitHubRepoInfo {
|
||
string repo_path = 1;
|
||
}
|