diff --git a/packages/components/src/components/ai-gui/view.tsx b/packages/components/src/components/ai-gui/view.tsx
index b6cbd832c..38f2e7fa7 100644
--- a/packages/components/src/components/ai-gui/view.tsx
+++ b/packages/components/src/components/ai-gui/view.tsx
@@ -3629,7 +3629,7 @@ const AssistantForkButton = ({
);
};
-const AssistantTurnFooter = ({
+export const AssistantTurnFooter = ({
message,
sessionId,
fileDiffOverride,
@@ -3737,7 +3737,7 @@ const AssistantTurnFooter = ({
'flex flex-wrap items-center justify-start text-[11px] text-muted-foreground',
isMobile ? 'min-h-6 gap-1' : 'min-h-7 gap-2',
!isMobile && 'opacity-0 transition-opacity duration-150 focus-within:opacity-100',
- !isMobile && isTurnHovered && 'opacity-100'
+ !isMobile && (isTurnHovered || isForking) && 'opacity-100'
)}
data-assistant-turn-actions
>
diff --git a/packages/components/src/stories/AssistantTurnAlignment.stories.tsx b/packages/components/src/stories/AssistantTurnAlignment.stories.tsx
index 042b75b39..688f61b9f 100644
--- a/packages/components/src/stories/AssistantTurnAlignment.stories.tsx
+++ b/packages/components/src/stories/AssistantTurnAlignment.stories.tsx
@@ -177,6 +177,24 @@ export const DesktopFinishedTurn: Story = {
),
};
+export const DesktopForkingTurn: Story = {
+ args: { sessionId, items: finishedItems, renderMessageRow },
+ globals: { theme: 'dark' },
+ render: () => (
+
+ undefined}
+ forkingAssistantMessageId={finishedTurn.id}
+ />
+
+ ),
+};
+
/**
* PLAN-MODE TURN — the widest set of top-level row shells in one column.
*
diff --git a/packages/components/tests/assistant-turn-action-inset.test.ts b/packages/components/tests/assistant-turn-action-inset.test.ts
index 930485c15..f4084b2e6 100644
--- a/packages/components/tests/assistant-turn-action-inset.test.ts
+++ b/packages/components/tests/assistant-turn-action-inset.test.ts
@@ -1,7 +1,21 @@
+// @vitest-environment jsdom
+
+import { act, createElement } from 'react';
+import { createRoot, type Root } from 'react-dom/client';
+import type { SessionHistoryParsed, SessionId } from '@lody/shared';
import { describe, expect, it } from 'vitest';
-import { MOBILE_TURN_ACTION_LEADING_INSET_PX } from '../src/components/ai-gui/view';
+import {
+ AssistantTurnFooter,
+ MOBILE_TURN_ACTION_LEADING_INSET_PX,
+} from '../src/components/ai-gui/view';
import { EDGE_ZONE_PX } from '../src/components/mobile/mobile-edge-back-swipe';
+import { ForceDesktopLayoutProvider } from '../src/hooks/use-mobile';
+import { initI18n } from '../src/i18n';
+
+(
+ globalThis as typeof globalThis & { IS_REACT_ACT_ENVIRONMENT?: boolean }
+).IS_REACT_ACT_ENVIRONMENT = true;
/*
* The mobile assistant-turn action bar puts the turn duration in front of the
@@ -29,3 +43,45 @@ describe('mobile assistant-turn action bar inset', () => {
expect(EDGE_ZONE_PX).toBeGreaterThan(0);
});
});
+
+describe('desktop assistant-turn action bar visibility', () => {
+ it('keeps the whole action group visible while a fork is pending', async () => {
+ await initI18n('en');
+ const container = document.createElement('div');
+ document.body.appendChild(container);
+ const root: Root = createRoot(container);
+ const message = {
+ id: 'assistant-turn-forking',
+ role: 'assistant',
+ timestamp: '2026-09-10T03:00:00.000Z',
+ endedAt: '2026-09-10T03:00:01.000Z',
+ finished: true,
+ items: [{ type: 'text', text: 'A completed response.' }],
+ } as unknown as SessionHistoryParsed;
+
+ await act(async () => {
+ root.render(
+ createElement(
+ ForceDesktopLayoutProvider,
+ null,
+ createElement(AssistantTurnFooter, {
+ message,
+ sessionId: 'session-forking' as SessionId,
+ showDuration: true,
+ isTurnHovered: false,
+ onFork: () => undefined,
+ isForking: true,
+ })
+ )
+ );
+ });
+
+ const actions = container.querySelector('[data-assistant-turn-actions]');
+ expect(actions?.classList.contains('opacity-100')).toBe(true);
+ expect(container.querySelector('[aria-label="Copy response"]')).not.toBeNull();
+ expect(container.querySelector('[aria-label="Fork session"] .animate-spin')).not.toBeNull();
+
+ await act(async () => root.unmount());
+ container.remove();
+ });
+});