mirror of
https://github.com/binaricat/Netcatty.git
synced 2026-11-13 18:21:00 +00:00
Phase 2 of #4098: every remaining positional fallback in the workspace AI scope is replaced with id-based resolution. - Workspace gains anchorChatId: pinned by the AI side panel whenever a chat becomes active in the workspace scope, persisted through the session restore snapshot, and validated lazily by consumers. - resolveDisplayedPanelView: the auto-resume fallback now resolves the anchored chat first, then the most recently updated chat (updatedAt), else draft; sessions[0] is gone. - retargetWorkspaceActiveChatAfterMemberLoss: when the focused member did not survive, the retarget lands on the most-recently-active survivor by chat recency, not the first positional member. - plugin keybinding context: focused member, then the terminal member owning the anchored chat, then the most-recently-active member; a single-member workspace uses its only member. - New domain/aiSessionRecency helper shared by all survivor rankings. - /rebind and session_recover semantics (#4019) are unchanged.
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
import React, { useMemo } from 'react';
|
|
|
|
import { PluginContributionHost } from '../../components/plugins/PluginContributionHost';
|
|
import type { TerminalSession, Workspace } from '../../types';
|
|
import { useActiveTabId } from '../state/activeTabStore';
|
|
import { resolveActivePluginKeybindingContext } from '../state/pluginContributionContexts';
|
|
import { getAISessionsSnapshot } from '../state/aiSessionsStore';
|
|
import { getPersistedAiSessionsSnapshot } from '../state/aiStateSnapshots';
|
|
|
|
/**
|
|
* Leaf host for plugin keybindings so AppView does not subscribe to activeTabId.
|
|
* Tab switches only re-render this small surface (and plugin lifecycle), not the shell.
|
|
*/
|
|
export function AppPluginKeybindingHost({
|
|
locale,
|
|
theme,
|
|
themeTokens,
|
|
sessions,
|
|
workspaces,
|
|
}: {
|
|
locale: string;
|
|
theme: string;
|
|
themeTokens?: Record<string, string>;
|
|
sessions: TerminalSession[];
|
|
workspaces: Workspace[];
|
|
}) {
|
|
const activeTabId = useActiveTabId();
|
|
const keybindingContext = useMemo(() => {
|
|
// AI chat recency drives the workspace anchor fallback (#4098 phase 2).
|
|
// Read without subscribing: keybinding context is best-effort and refreshes
|
|
// on every tab/session/workspaces change that matters here.
|
|
const live = getAISessionsSnapshot().sessions;
|
|
const aiSessions = live.length > 0 ? live : getPersistedAiSessionsSnapshot();
|
|
return resolveActivePluginKeybindingContext({
|
|
activeTabId,
|
|
sessions,
|
|
workspaces,
|
|
aiSessions,
|
|
});
|
|
}, [activeTabId, sessions, workspaces]);
|
|
|
|
return (
|
|
<PluginContributionHost
|
|
locale={locale}
|
|
theme={theme}
|
|
themeTokens={themeTokens}
|
|
keybindingContext={keybindingContext}
|
|
/>
|
|
);
|
|
}
|