Skip to content

Commit 181e25d

Browse files
CopilotByron
andcommitted
Add "Start Coding Agent session" menu item to BranchHeaderContextMenu
Co-authored-by: Byron <[email protected]>
1 parent 497fde1 commit 181e25d

File tree

3 files changed

+53
-0
lines changed

3 files changed

+53
-0
lines changed

apps/desktop/src/components/BranchHeaderContextMenu.svelte

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
import { PROMPT_SERVICE } from '$lib/ai/promptService';
1919
import { AI_SERVICE } from '$lib/ai/service';
2020
import { CLIPBOARD_SERVICE } from '$lib/backend/clipboard';
21+
import { CLAUDE_CODE_SERVICE } from '$lib/codegen/claude';
2122
import { projectAiGenEnabled } from '$lib/config/config';
2223
import { DEFAULT_FORGE_FACTORY } from '$lib/forge/forgeFactory.svelte';
24+
import { codegenPath } from '$lib/routes/routes.svelte';
2325
import { STACK_SERVICE } from '$lib/stacks/stackService.svelte';
2426
import { URL_SERVICE } from '$lib/utils/url';
2527
import { inject } from '@gitbutler/core/context';
@@ -33,6 +35,7 @@
3335
} from '@gitbutler/ui';
3436
3537
import { tick } from 'svelte';
38+
import { goto } from '$app/navigation';
3639
import type { AnchorPosition, BranchDetails } from '$lib/stacks/stack';
3740
3841
type Props = {
@@ -59,6 +62,7 @@
5962
const promptService = inject(PROMPT_SERVICE);
6063
const urlService = inject(URL_SERVICE);
6164
const clipboardService = inject(CLIPBOARD_SERVICE);
65+
const claudeCodeService = inject(CLAUDE_CODE_SERVICE);
6266
const [insertBlankCommitInBranch, commitInsertion] = stackService.insertBlankCommit;
6367
const [updateBranchNameMutation] = stackService.updateBranchName;
6468
const [createRef, refCreation] = stackService.createReference;
@@ -99,6 +103,12 @@
99103
aiConfigurationValid = await aiService.validateConfiguration();
100104
}
101105
106+
async function startCodingSession() {
107+
if (!stackId) return;
108+
goto(`${codegenPath(projectId)}?stackId=${stackId}`);
109+
close();
110+
}
111+
102112
async function generateBranchName(stackId: string, branchName: string) {
103113
if (!$aiGenEnabled || !aiConfigurationValid) return;
104114
@@ -265,6 +275,17 @@
265275
{/if}
266276
</ContextMenuSection>
267277
<ContextMenuSection>
278+
{#if $aiGenEnabled && aiConfigurationValid && stackId}
279+
<ContextMenuItem
280+
label="Start Coding Agent session"
281+
icon="ai"
282+
testId={TestId.BranchHeaderContextMenu_StartCodingSession}
283+
disabled={isReadOnly}
284+
onclick={() => {
285+
startCodingSession();
286+
}}
287+
/>
288+
{/if}
268289
{#if $aiGenEnabled && aiConfigurationValid && !branch.remoteTrackingBranch && stackId}
269290
<ContextMenuItem
270291
label="Generate branch name"

apps/desktop/src/routes/[projectId]/codegen/+page.svelte

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,47 @@
44
import CodegenPage from '$components/codegen/CodegenPage.svelte';
55
import { codegenEnabled } from '$lib/config/uiFeatureFlags';
66
import { workspacePath } from '$lib/routes/routes.svelte';
7+
import { UI_STATE } from '$lib/state/uiState.svelte';
8+
import { STACK_SERVICE } from '$lib/stacks/stackService.svelte';
9+
import { inject } from '@gitbutler/core/context';
710
811
// TODO: Refactor so we don't need non-null assertion.
912
const projectId = $derived(page.params.projectId!);
13+
14+
const uiState = inject(UI_STATE);
15+
const stackService = inject(STACK_SERVICE);
16+
const projectState = $derived(uiState.project(projectId));
17+
18+
// Check for stackId in URL query parameters
19+
const urlStackId = $derived(page.url.searchParams.get('stackId'));
20+
const stacks = $derived(stackService.stacks(projectId));
1021
1122
// Redirect users when feature is disabled
1223
$effect(() => {
1324
if (!$codegenEnabled) {
1425
goto(workspacePath(projectId));
1526
}
1627
});
28+
29+
// Handle stackId URL parameter to auto-select branch
30+
$effect(() => {
31+
if (urlStackId && stacks.current.data) {
32+
// Find the stack with the matching ID
33+
const targetStack = stacks.current.data.find(s => s.id === urlStackId);
34+
if (targetStack && targetStack.heads.length > 0) {
35+
// Set the selected Claude session to the first head of this stack
36+
projectState.selectedClaudeSession.set({
37+
stackId: urlStackId,
38+
head: targetStack.heads[0].name
39+
});
40+
41+
// Remove the stackId parameter from the URL to keep it clean
42+
const newUrl = new URL(page.url);
43+
newUrl.searchParams.delete('stackId');
44+
goto(newUrl.toString(), { replaceState: true });
45+
}
46+
}
47+
});
1748
</script>
1849

1950
{#if $codegenEnabled}

packages/ui/src/lib/utils/testIds.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export enum TestId {
1010
BranchHeaderContextMenu_OpenInBrowser = 'branch-header-context-menu-open-in-browser',
1111
BranchHeaderContextMenu_CopyBranchName = 'branch-header-context-menu-copy-branch-name',
1212
BranchHeaderContextMenu_AddRemoveDescription = 'branch-header-context-menu-add-remove-description',
13+
BranchHeaderContextMenu_StartCodingSession = 'branch-header-context-menu-start-coding-session',
1314
BranchHeaderContextMenu_GenerateBranchName = 'branch-header-context-menu-generate-branch-name',
1415
BranchHeaderContextMenu_Rename = 'branch-header-context-menu-rename',
1516
BranchHeaderContextMenu_Delete = 'branch-header-context-menu-delete',

0 commit comments

Comments
 (0)