Change a worktree workspace base from Changes (#8642)

Change a worktree workspace's base from the Changes pane. The choice persists and diffs, counts, commits and Git actions follow it.

Supersedes #6872.

Co-authored-by: Tianyu Yang <yangtianyu.cl@bytedance.com>
This commit is contained in:
Mohamed Boudra
2026-11-05 22:30:14 +07:00
committed by GitHub
co-authored by Tianyu Yang
parent e9f897a66a
commit 3ed57e9dd7
41 changed files with 1192 additions and 46 deletions
+18 -1
View File
@@ -3582,6 +3582,22 @@ export class DaemonClient {
return { pinnedAt: payload.pinnedAt };
}
async setWorkspaceBaseBranch(options: {
workspaceId: string;
baseRef: string;
requestId?: string;
}): Promise<{ baseRef: string | null }> {
const { requestId, workspaceId, baseRef } = options;
const payload =
await this.sendNamespacedCorrelatedSessionRequest<"workspace.base_branch.set.response">({
requestId,
message: { type: "workspace.base_branch.set.request", workspaceId, baseRef },
});
if (!payload.accepted)
throw new Error(payload.error ?? "Changing the workspace base branch failed");
return { baseRef: payload.baseRef };
}
async inspectWorkspaceRecovery(
workspaceId: string,
requestId?: string,
@@ -5134,7 +5150,7 @@ export class DaemonClient {
}
async getBranchSuggestions(
options: { cwd: string; query?: string; limit?: number },
options: { cwd: string; query?: string; limit?: number; refMode?: "exact" },
requestId?: string,
): Promise<BranchSuggestionsPayload> {
return this.sendCorrelatedSessionRequest({
@@ -5144,6 +5160,7 @@ export class DaemonClient {
cwd: options.cwd,
query: options.query,
limit: options.limit,
refMode: options.refMode,
},
responseType: "branch_suggestions_response",
});
+23
View File
@@ -607,6 +607,29 @@ test("workspace handles keep identity and refresh snapshots through existing dri
}),
);
await expect(titlePromise).resolves.toEqual({ title: "SDK review" });
const basePromise = workspace.setBaseBranch({
baseRef: "refs/heads/release",
requestId: "workspace-base-request",
});
expect(parseSentSessionMessage(ws.sent.at(-1))).toMatchObject({
type: "workspace.base_branch.set.request",
workspaceId: "workspace_sdk",
baseRef: "refs/heads/release",
requestId: "workspace-base-request",
});
ws.message(
sessionMessage({
type: "workspace.base_branch.set.response",
payload: {
requestId: "workspace-base-request",
workspaceId: "workspace_sdk",
accepted: true,
baseRef: "refs/heads/release",
error: null,
},
}),
);
await expect(basePromise).resolves.toEqual({ baseRef: "refs/heads/release" });
unsubscribe();
ws.message(
+6
View File
@@ -189,6 +189,10 @@ export interface PaseoWorkspaceHandle {
current(): PaseoWorkspace | null;
refresh(options?: { requestId?: string }): Promise<PaseoWorkspace | null>;
setTitle(title: string | null, requestId?: string): Promise<{ title: string | null }>;
setBaseBranch(options: {
baseRef: string;
requestId?: string;
}): Promise<{ baseRef: string | null }>;
archive(requestId?: string): Promise<PaseoWorkspaceArchiveResult>;
/**
* Subscribes to already-emitted daemon workspace_update events for this id.
@@ -862,6 +866,8 @@ function createWorkspaceHandleFactory(
current: () => current,
refresh,
setTitle: (title, requestId) => daemonClient.setWorkspaceTitle(id, title, requestId),
setBaseBranch: (options) =>
daemonClient.setWorkspaceBaseBranch({ ...options, workspaceId: id }),
archive: async (requestId) => {
const result = await daemonClient.archiveWorkspace(id, requestId);
if (current) {