Skip to content
2 changes: 2 additions & 0 deletions .storybook/mocks/orpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,8 @@ export function createMockORPCClient(options: MockORPCClientOptions = {}): APICl
pickDirectory: async () => null,
listBranches: async () => ({
branches: ["main", "develop", "feature/new-feature"],
remoteBranches: [],
remoteBranchGroups: [],
recommendedTrunk: "main",
}),
remove: async (input: { projectPath: string }) => {
Expand Down
33 changes: 32 additions & 1 deletion src/browser/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { migrateGatewayModel } from "@/browser/hooks/useGatewayModels";
import { enforceThinkingPolicy } from "@/common/utils/thinking/policy";
import { getDefaultModel } from "@/browser/hooks/useModelsFromSettings";
import type { BranchListResult } from "@/common/orpc/types";
import type { ExistingBranchSelection } from "@/common/types/branchSelection";
import { useTelemetry } from "./hooks/useTelemetry";
import { getRuntimeTypeForTelemetry } from "@/common/telemetry";
import { useStartWorkspaceCreation, getFirstProjectPath } from "./hooks/useStartWorkspaceCreation";
Expand Down Expand Up @@ -390,23 +391,52 @@ function AppInner() {
[startWorkspaceCreation]
);

const openBranchAsWorkspaceFromPalette = useCallback(
(projectPath: string, selection: ExistingBranchSelection) => {
startWorkspaceCreation(projectPath, { projectPath, existingBranch: selection });
},
[startWorkspaceCreation]
);

const getBranchesForProject = useCallback(
async (projectPath: string): Promise<BranchListResult> => {
if (!api) {
return { branches: [], recommendedTrunk: null };
return { branches: [], remoteBranches: [], remoteBranchGroups: [], recommendedTrunk: null };
}
const branchResult = await api.projects.listBranches({ projectPath });
const sanitizedBranches = branchResult.branches.filter(
(branch): branch is string => typeof branch === "string"
);

const sanitizedRemoteBranches = branchResult.remoteBranches.filter(
(branch): branch is string => typeof branch === "string"
);

const sanitizedRemoteBranchGroups = Array.isArray(branchResult.remoteBranchGroups)
? branchResult.remoteBranchGroups
.filter(
(group): group is { remote: string; branches: string[]; truncated: boolean } =>
typeof group?.remote === "string" &&
Array.isArray(group.branches) &&
typeof group.truncated === "boolean"
)
.map((group) => ({
remote: group.remote,
branches: group.branches.filter((b): b is string => typeof b === "string"),
truncated: group.truncated,
}))
.filter((group) => group.remote.length > 0 && group.branches.length > 0)
: [];

const recommended =
branchResult.recommendedTrunk && sanitizedBranches.includes(branchResult.recommendedTrunk)
? branchResult.recommendedTrunk
: (sanitizedBranches[0] ?? null);

return {
branches: sanitizedBranches,
remoteBranches: sanitizedRemoteBranches,
remoteBranchGroups: sanitizedRemoteBranchGroups,
recommendedTrunk: recommended,
};
},
Expand Down Expand Up @@ -460,6 +490,7 @@ function AppInner() {
getThinkingLevel: getThinkingLevelForWorkspace,
onSetThinkingLevel: setThinkingLevelFromPalette,
onStartWorkspaceCreation: openNewWorkspaceFromPalette,
onStartWorkspaceCreationWithBranch: openBranchAsWorkspaceFromPalette,
getBranchesForProject,
onSelectWorkspace: selectWorkspaceFromPalette,
onRemoveWorkspace: removeWorkspaceFromPalette,
Expand Down
Loading
Loading