mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
refactor(renderer): fold activation mirroring and sort-order persistence off the deprecated owner resolver (#30484)
The eight mirroring callers (#23-#30) read the owner through runtimeEnvironmentIdWithLegacyFallbackUnlessTwin, so a twin is still not mirrored. Sort-order persistence (#2) leaves out ids that two hosts publish, and ids whose only server proof is a repo row (isUnprovenServerSshRoute), instead of writing them to this desktop's or a guessed server's meta. Deprecated importers 40 -> 31.
This commit is contained in:
@@ -9,8 +9,6 @@ src/renderer/src/components/native-chat/native-chat-runtime-owner.ts
|
||||
src/renderer/src/components/right-sidebar/file-explorer-operation-owner.ts
|
||||
src/renderer/src/components/right-sidebar/use-file-explorer-tree-pane-state.ts
|
||||
src/renderer/src/components/tab-bar/use-tab-bar-runtime-model.ts
|
||||
src/renderer/src/components/tab-bar/web-runtime-tab-move-mirror.ts
|
||||
src/renderer/src/components/tab-group/useTabGroupActivationCommands.ts
|
||||
src/renderer/src/components/tab-group/useTabGroupCreationCommands.ts
|
||||
src/renderer/src/components/terminal-pane/terminal-pane-menu-paste.ts
|
||||
src/renderer/src/components/terminal-pane/terminal-pane-paste-execution.ts
|
||||
@@ -26,18 +24,11 @@ src/renderer/src/lib/file-preview.ts
|
||||
src/renderer/src/lib/launch-agent-background-session.ts
|
||||
src/renderer/src/lib/launch-agent-in-new-tab.ts
|
||||
src/renderer/src/lib/launch-ai-vault-session.ts
|
||||
src/renderer/src/lib/structured-agent-session-tab-activation.ts
|
||||
src/renderer/src/lib/tab-number-shortcuts.ts
|
||||
src/renderer/src/lib/terminal-tab-owner-activation.ts
|
||||
src/renderer/src/lib/terminal-worktree-route.ts
|
||||
src/renderer/src/lib/web-runtime-worktree-terminal-after-wake.ts
|
||||
src/renderer/src/lib/workspace-tab-palette-activation.ts
|
||||
src/renderer/src/lib/worktree-activation.ts
|
||||
src/renderer/src/lib/worktree-creation-agent-seeds.ts
|
||||
src/renderer/src/lib/worktree-sort-order-host-split.ts
|
||||
src/renderer/src/store/slices/browser/browser-page-conversion-actions.ts
|
||||
src/renderer/src/store/slices/browser/browser-tab-actions.ts
|
||||
src/renderer/src/store/slices/tabs/tabs-host-mirroring.ts
|
||||
src/renderer/src/store/slices/terminal-tab-retirement.ts
|
||||
src/renderer/src/store/terminals/terminal-active-workspace-creation.ts
|
||||
src/renderer/src/store/terminals/terminal-pane-hibernation.ts
|
||||
|
||||
@@ -360,6 +360,7 @@
|
||||
1 src/renderer/src/lib/worktree-row-open-in-owner.ts # reads focus through resolveOwnerWithLegacyFallback, newly counted (round 3 F2); F8 nets it down
|
||||
9 src/renderer/src/lib/worktree-runtime-owner.ts # typed owner resolver, its null-collapsing wrapper, and the legacy-fallback adapter the folds move to (round 3 F0); deleting the deprecated pair (F8) nets it down
|
||||
1 src/renderer/src/lib/worktree-sort-order-host-split.ts
|
||||
1 src/renderer/src/lib/worktree-sort-order-persistence.ts # its split helper calls resolveOwnerWithLegacyFallback directly (round 3 F4); F8 nets it down
|
||||
1 src/renderer/src/runtime/local-structured-session-tabs-sync/snapshot-apply.ts
|
||||
17 src/renderer/src/runtime/runtime-jira-client.ts
|
||||
2 src/renderer/src/runtime/runtime-jira-summary-client.ts
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { RuntimeMobileSessionTabMove } from '../../../../shared/runtime-types'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from '@/lib/worktree-runtime-owner'
|
||||
import { useAppStore } from '../../store'
|
||||
import { isWebRuntimeSessionActive } from '../../runtime/web-runtime-session-environment'
|
||||
import { moveWebRuntimeSessionTab } from '../../runtime/web-runtime-session-tab-move'
|
||||
@@ -9,7 +9,10 @@ export function mirrorWebRuntimeTabMove(
|
||||
worktreeId: string
|
||||
}
|
||||
): void {
|
||||
const environmentId = getRuntimeEnvironmentIdForWorktree(useAppStore.getState(), args.worktreeId)
|
||||
const environmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(
|
||||
useAppStore.getState(),
|
||||
args.worktreeId
|
||||
)
|
||||
if (!isWebRuntimeSessionActive(environmentId)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import { focusTerminalTabSurface } from '../../lib/focus-terminal-tab-surface'
|
||||
import { TOGGLE_TERMINAL_PANE_EXPAND_EVENT } from '@/constants/terminal'
|
||||
import { activateWebRuntimeSessionTab } from '../../runtime/web-runtime-session-tab-lifecycle'
|
||||
import { isWebRuntimeSessionActive } from '../../runtime/web-runtime-session-environment'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from '@/lib/worktree-runtime-owner'
|
||||
import { browserWorkspaceHasRemoteOwner } from '@/runtime/remote-browser-tab-ownership'
|
||||
import { activateStructuredAgentSessionTab } from '@/lib/structured-agent-session-tab-activation'
|
||||
import type { TabGroupWorktreeSnapshot } from './useTabGroupItemProjections'
|
||||
@@ -38,7 +38,7 @@ export function useTabGroupActivationCommands({
|
||||
}
|
||||
focusGroup(worktreeId, groupId)
|
||||
activateTab(item.id)
|
||||
const runtimeEnvironmentId = getRuntimeEnvironmentIdForWorktree(
|
||||
const runtimeEnvironmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(
|
||||
useAppStore.getState(),
|
||||
worktreeId
|
||||
)
|
||||
@@ -117,7 +117,7 @@ export function useTabGroupActivationCommands({
|
||||
}
|
||||
focusGroup(worktreeId, groupId)
|
||||
activateTab(item.id)
|
||||
const runtimeEnvironmentId = getRuntimeEnvironmentIdForWorktree(
|
||||
const runtimeEnvironmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(
|
||||
useAppStore.getState(),
|
||||
worktreeId
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
import {
|
||||
getRepoSshConnectionId,
|
||||
parseExecutionHostId,
|
||||
toRuntimeExecutionHostId,
|
||||
toSshExecutionHostId,
|
||||
type ExecutionHostId
|
||||
@@ -250,3 +251,32 @@ export function runtimeEnvironmentIdUnlessTwin(
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* A server route to `ssh:X` that only a repo row proves: no worktree row names that server. The
|
||||
* row's `ssh:X` and the server's `connectionId: X` are different namespaces, so reads and spawn
|
||||
* may follow it but a host write could land on another machine with the same path.
|
||||
*/
|
||||
export function isUnprovenServerSshRoute(
|
||||
state: Pick<WorktreeOperationRouteState, 'worktreesByRepo' | 'detectedWorktreesByRepo'>,
|
||||
workspaceId: string,
|
||||
owner: HostAuthority
|
||||
): boolean {
|
||||
const { endpoint, at } = owner
|
||||
if (
|
||||
endpoint.kind !== 'environment' ||
|
||||
at === 'local' ||
|
||||
parseWorkspaceKey(workspaceId)?.type === 'folder'
|
||||
) {
|
||||
return false
|
||||
}
|
||||
const repoId = getRepoIdFromWorktreeId(workspaceId)
|
||||
const namesServer = (row: { id: string; hostId?: string; runtimeOwnerEnvironmentId?: string }) =>
|
||||
row.id === workspaceId &&
|
||||
parseExecutionHostId(row.hostId)?.id === at &&
|
||||
row.runtimeOwnerEnvironmentId?.trim() === endpoint.environmentId
|
||||
return !(
|
||||
state.worktreesByRepo?.[repoId]?.some(namesServer) ||
|
||||
state.detectedWorktreesByRepo?.[repoId]?.worktrees.some(namesServer)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -18,7 +18,9 @@ vi.mock('@/components/native-chat/use-native-chat-composer-reveal-focus', () =>
|
||||
requestNativeChatComposerFocus: mocks.requestNativeChatComposerFocus
|
||||
}))
|
||||
|
||||
vi.mock('./worktree-runtime-owner', () => ({ getRuntimeEnvironmentIdForWorktree: () => 'env-1' }))
|
||||
vi.mock('./worktree-runtime-owner', () => ({
|
||||
runtimeEnvironmentIdWithLegacyFallbackUnlessTwin: () => 'env-1'
|
||||
}))
|
||||
|
||||
vi.mock('@/runtime/runtime-rpc-client', () => ({ callRuntimeRpc: mocks.callRuntimeRpc }))
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getRuntimeEnvironmentIdForWorktree } from './worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from './worktree-runtime-owner'
|
||||
import { requestNativeChatComposerFocus } from '@/components/native-chat/use-native-chat-composer-reveal-focus'
|
||||
import { useAppStore } from '@/store'
|
||||
import { callRuntimeRpc } from '@/runtime/runtime-rpc-client'
|
||||
@@ -49,7 +49,7 @@ export function activateStructuredAgentSessionTab(args: {
|
||||
state.activateTab(tab.id, { worktreeId: args.worktreeId })
|
||||
state.setActiveTabType('agent-session', args.worktreeId)
|
||||
requestNativeChatComposerFocus(tab.id)
|
||||
const environmentId = getRuntimeEnvironmentIdForWorktree(state, args.worktreeId)
|
||||
const environmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(state, args.worktreeId)
|
||||
void callRuntimeRpc(
|
||||
args.target ?? runtimeTargetForOwnerEnvironment(environmentId),
|
||||
'session.tabs.activate',
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { focusTerminalTabSurface } from '@/lib/focus-terminal-tab-surface'
|
||||
import { useAppStore } from '@/store'
|
||||
import type { AppState } from '@/store/types'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from '@/lib/worktree-runtime-owner'
|
||||
import { dedupeTabOrder } from '../../../shared/workspace-layout/tab-order'
|
||||
import type { Tab } from '../../../shared/tab-types'
|
||||
import { activateWebRuntimeSessionTab } from '@/runtime/web-runtime-session-tab-lifecycle'
|
||||
@@ -60,7 +60,7 @@ export function activateTabNumberShortcut(index: number): boolean {
|
||||
}
|
||||
|
||||
const worktreeId = target.worktreeId
|
||||
const runtimeEnvironmentId = getRuntimeEnvironmentIdForWorktree(store, worktreeId)
|
||||
const runtimeEnvironmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(store, worktreeId)
|
||||
store.focusGroup(worktreeId, target.groupId)
|
||||
store.activateTab(target.id)
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
|
||||
const mocks = vi.hoisted(() => ({
|
||||
activateWebRuntimeSessionTab: vi.fn(),
|
||||
getRuntimeEnvironmentIdForWorktree: vi.fn(),
|
||||
runtimeEnvironmentIdWithLegacyFallbackUnlessTwin: vi.fn(),
|
||||
resolveWebSessionVisibleTabId: vi.fn()
|
||||
}))
|
||||
|
||||
vi.mock('@/store', () => ({ useAppStore: { getState: () => ({}) } }))
|
||||
vi.mock('@/lib/worktree-runtime-owner', () => ({
|
||||
getRuntimeEnvironmentIdForWorktree: mocks.getRuntimeEnvironmentIdForWorktree
|
||||
runtimeEnvironmentIdWithLegacyFallbackUnlessTwin:
|
||||
mocks.runtimeEnvironmentIdWithLegacyFallbackUnlessTwin
|
||||
}))
|
||||
vi.mock('@/runtime/web-runtime-session-tab-lifecycle', () => ({
|
||||
activateWebRuntimeSessionTab: mocks.activateWebRuntimeSessionTab
|
||||
@@ -30,12 +31,12 @@ describe('activateTerminalTabOnOwner', () => {
|
||||
})
|
||||
|
||||
it('tells the paired server that owns the workspace, not the focused one', () => {
|
||||
mocks.getRuntimeEnvironmentIdForWorktree.mockReturnValue('env-owner')
|
||||
mocks.runtimeEnvironmentIdWithLegacyFallbackUnlessTwin.mockReturnValue('env-owner')
|
||||
mocks.resolveWebSessionVisibleTabId.mockReturnValue('unified-visible')
|
||||
|
||||
activateTerminalTabOnOwner('wt-1', 'web-terminal-host-tab', 'leaf-b')
|
||||
|
||||
expect(mocks.getRuntimeEnvironmentIdForWorktree).toHaveBeenCalledWith({}, 'wt-1')
|
||||
expect(mocks.runtimeEnvironmentIdWithLegacyFallbackUnlessTwin).toHaveBeenCalledWith({}, 'wt-1')
|
||||
expect(mocks.activateWebRuntimeSessionTab).toHaveBeenCalledWith({
|
||||
worktreeId: 'wt-1',
|
||||
tabId: 'web-terminal-host-tab',
|
||||
@@ -47,7 +48,7 @@ describe('activateTerminalTabOnOwner', () => {
|
||||
})
|
||||
|
||||
it('makes no owner round trip for a workspace this client runs', () => {
|
||||
mocks.getRuntimeEnvironmentIdForWorktree.mockReturnValue(null)
|
||||
mocks.runtimeEnvironmentIdWithLegacyFallbackUnlessTwin.mockReturnValue(null)
|
||||
|
||||
activateTerminalTabOnOwner('wt-local', 'tab-1', null)
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAppStore } from '@/store'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from '@/lib/worktree-runtime-owner'
|
||||
import { activateWebRuntimeSessionTab } from '@/runtime/web-runtime-session-tab-lifecycle'
|
||||
import { isWebRuntimeSessionActive } from '@/runtime/web-runtime-session-environment'
|
||||
import { resolveWebSessionVisibleTabId } from '@/runtime/web-session-focus-intent'
|
||||
@@ -17,7 +17,7 @@ export function activateTerminalTabOnOwner(
|
||||
leafId: string | null
|
||||
): void {
|
||||
const state = useAppStore.getState()
|
||||
const environmentId = getRuntimeEnvironmentIdForWorktree(state, worktreeId)
|
||||
const environmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(state, worktreeId)
|
||||
if (!environmentId || !isWebRuntimeSessionActive(environmentId)) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -63,7 +63,7 @@ const mocks = vi.hoisted(() => {
|
||||
activateAndRevealWorkspace: vi.fn(),
|
||||
activateWebRuntimeSessionTab: vi.fn(),
|
||||
focusTerminalTabSurface: vi.fn(),
|
||||
getRuntimeEnvironmentIdForWorktree: vi.fn(),
|
||||
runtimeEnvironmentIdWithLegacyFallbackUnlessTwin: vi.fn(),
|
||||
isWebRuntimeSessionActive: vi.fn()
|
||||
}
|
||||
})
|
||||
@@ -79,7 +79,8 @@ vi.mock('@/lib/focus-terminal-tab-surface', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/worktree-runtime-owner', () => ({
|
||||
getRuntimeEnvironmentIdForWorktree: mocks.getRuntimeEnvironmentIdForWorktree
|
||||
runtimeEnvironmentIdWithLegacyFallbackUnlessTwin:
|
||||
mocks.runtimeEnvironmentIdWithLegacyFallbackUnlessTwin
|
||||
}))
|
||||
|
||||
vi.mock('@/runtime/web-runtime-session-tab-lifecycle', () => ({
|
||||
@@ -172,7 +173,7 @@ describe('activateWorkspaceTabPaletteResult', () => {
|
||||
.find((worktree) => worktree.id === worktreeId)
|
||||
)
|
||||
mocks.activateAndRevealWorkspace.mockReturnValue(true)
|
||||
mocks.getRuntimeEnvironmentIdForWorktree.mockReturnValue('runtime-1')
|
||||
mocks.runtimeEnvironmentIdWithLegacyFallbackUnlessTwin.mockReturnValue('runtime-1')
|
||||
mocks.isWebRuntimeSessionActive.mockReturnValue(false)
|
||||
})
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { focusTerminalTabSurface } from '@/lib/focus-terminal-tab-surface'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from '@/lib/worktree-runtime-owner'
|
||||
import { activateWebRuntimeSessionTab } from '@/runtime/web-runtime-session-tab-lifecycle'
|
||||
import { isWebRuntimeSessionActive } from '@/runtime/web-runtime-session-environment'
|
||||
import { useAppStore } from '@/store'
|
||||
@@ -119,7 +119,10 @@ export function activateWorkspaceTabPaletteResult(
|
||||
return { status: 'failed', reason: finalFailure }
|
||||
}
|
||||
|
||||
const runtimeEnvironmentId = getRuntimeEnvironmentIdForWorktree(state, result.worktreeId)
|
||||
const runtimeEnvironmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(
|
||||
state,
|
||||
result.worktreeId
|
||||
)
|
||||
state.focusGroup(result.worktreeId, result.groupId)
|
||||
state.activateTab(result.tabId, { worktreeId: result.worktreeId })
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import { registerWorktreeActivation } from '@/lib/worktree-activation-nav-regist
|
||||
import { workspaceHasSleepingAgentSessions } from '@/lib/worktree-agent-activation-gate'
|
||||
import { resumeSleepingAgentSessionsForWorktree } from '@/lib/resume-sleeping-agent-session'
|
||||
import { shouldAutoCreateInitialTerminal } from '@/components/terminal/initial-terminal'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from '@/lib/worktree-runtime-owner'
|
||||
import { folderWorkspaceKey, parseWorkspaceKey } from '../../../shared/workspace-scope'
|
||||
import {
|
||||
folderWorkspaceActivationBlocked,
|
||||
@@ -210,7 +210,10 @@ export function activateAndRevealWorktree(
|
||||
// 3. Core activation: setActiveWorktree also restores per-worktree state, clears unread, bumps dead PTY generations, refreshes GitHub
|
||||
state.setActiveWorktree(worktreeId, opts?.executionHostId)
|
||||
const postActivationState = useAppStore.getState()
|
||||
const ownerRuntimeEnvironmentId = getRuntimeEnvironmentIdForWorktree(postActivationState, wt.id)
|
||||
const ownerRuntimeEnvironmentId = runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(
|
||||
postActivationState,
|
||||
wt.id
|
||||
)
|
||||
if (opts?.notifyHostRuntime !== false && isWebRuntimeSessionActive(ownerRuntimeEnvironmentId)) {
|
||||
// Why: paired web clients own only local selection, so the desktop host publishes session surfaces without treating it as a nav command.
|
||||
void activateWebRuntimeSessionWorktree({
|
||||
|
||||
@@ -34,4 +34,42 @@ describe('splitWorktreeSortOrderByHost', () => {
|
||||
)
|
||||
expect(groups).toEqual([{ hostId: 'runtime:focused-env', orderedIds: ['legacy::wt'] }])
|
||||
})
|
||||
|
||||
it('leaves out a twin and a row only a repo row places on a server', () => {
|
||||
const groups = splitWorktreeSortOrderByHost(
|
||||
{
|
||||
settings: { activeRuntimeEnvironmentId: null },
|
||||
runtimeEnvironments: [{ id: 'hub-env' }],
|
||||
runtimeEnvironmentCatalogHydrated: true,
|
||||
repos: [
|
||||
{ id: 'local-repo', connectionId: null, executionHostId: 'local' },
|
||||
{ id: 'twin', connectionId: null, executionHostId: 'local' },
|
||||
{ id: 'twin', connectionId: 'box', executionHostId: 'ssh:box' },
|
||||
{ id: 'stale-hub', connectionId: 'target', executionHostId: 'runtime:hub-env' },
|
||||
{ id: 'hub', connectionId: 'box', executionHostId: 'runtime:hub-env' }
|
||||
],
|
||||
worktreesByRepo: {
|
||||
'local-repo': [{ id: 'local-repo::wt-a', repoId: 'local-repo' }],
|
||||
twin: [
|
||||
{ id: 'twin::wt', repoId: 'twin', hostId: 'local' },
|
||||
{ id: 'twin::wt', repoId: 'twin', hostId: 'ssh:box' }
|
||||
],
|
||||
'stale-hub': [{ id: 'stale-hub::wt', repoId: 'stale-hub', hostId: 'ssh:target' }],
|
||||
hub: [
|
||||
{
|
||||
id: 'hub::wt',
|
||||
repoId: 'hub',
|
||||
hostId: 'ssh:box',
|
||||
runtimeOwnerEnvironmentId: 'hub-env'
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
['twin::wt', 'stale-hub::wt', 'hub::wt', 'local-repo::wt-a']
|
||||
)
|
||||
expect(groups).toEqual([
|
||||
{ hostId: 'runtime:hub-env', orderedIds: ['hub::wt'] },
|
||||
{ hostId: 'local', orderedIds: ['local-repo::wt-a'] }
|
||||
])
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { LOCAL_EXECUTION_HOST_ID, toRuntimeExecutionHostId } from '../../../shared/execution-host'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from './worktree-runtime-owner'
|
||||
import { isUnprovenServerSshRoute } from './resolve-owner'
|
||||
import { resolveOwnerWithLegacyFallback } from './worktree-runtime-owner'
|
||||
import type { WorktreeRuntimeOwnerState } from './worktree-runtime-owner-state'
|
||||
|
||||
export type WorktreeSortOrderHostGroup = {
|
||||
@@ -13,7 +14,8 @@ export type WorktreeSortOrderHostGroup = {
|
||||
* Why: persisted `sortOrder` lives in each host's `worktreeMeta` and is enriched
|
||||
* onto worktrees from their owner host. Stamping the full cross-host id list on
|
||||
* only the focused host loses other hosts' ordering and pollutes the focused
|
||||
* host with foreign ids, so persist each host's ids on that host.
|
||||
* host with foreign ids, so persist each host's ids on that host. Ids no host can be
|
||||
* proven to own are left out.
|
||||
*/
|
||||
export function splitWorktreeSortOrderByHost(
|
||||
state: WorktreeRuntimeOwnerState,
|
||||
@@ -21,8 +23,16 @@ export function splitWorktreeSortOrderByHost(
|
||||
): WorktreeSortOrderHostGroup[] {
|
||||
const groups = new Map<string, string[]>()
|
||||
for (const id of orderedIds) {
|
||||
const environmentId = getRuntimeEnvironmentIdForWorktree(state, id)
|
||||
const hostId = environmentId ? toRuntimeExecutionHostId(environmentId) : LOCAL_EXECUTION_HOST_ID
|
||||
const owner = resolveOwnerWithLegacyFallback(state, { workspaceId: id })
|
||||
// Why: a twin names no host to write to, and an unproven server route may be another machine.
|
||||
if (owner.kind !== 'resolved' || isUnprovenServerSshRoute(state, id, owner.owner)) {
|
||||
continue
|
||||
}
|
||||
const { endpoint } = owner.owner
|
||||
const hostId =
|
||||
endpoint.kind === 'environment'
|
||||
? toRuntimeExecutionHostId(endpoint.environmentId)
|
||||
: LOCAL_EXECUTION_HOST_ID
|
||||
const existing = groups.get(hostId)
|
||||
if (existing) {
|
||||
existing.push(id)
|
||||
|
||||
@@ -76,7 +76,8 @@ vi.mock('@/lib/feature-education-telemetry', () => ({
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/worktree-runtime-owner', () => ({
|
||||
getRuntimeEnvironmentIdForWorktree: mocks.getRuntimeEnvironmentIdForWorktree
|
||||
getRuntimeEnvironmentIdForWorktree: mocks.getRuntimeEnvironmentIdForWorktree,
|
||||
runtimeEnvironmentIdWithLegacyFallbackUnlessTwin: mocks.getRuntimeEnvironmentIdForWorktree
|
||||
}))
|
||||
|
||||
vi.mock('@/lib/agent-launch-prompt-delivery', () => ({
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { AppState } from '../../types'
|
||||
import type { TerminalTab } from '../../../../../shared/terminal-tab-types'
|
||||
import { findTabAndWorktree } from '../tab-group-state'
|
||||
import { getRuntimeEnvironmentIdForWorktree } from '@/lib/worktree-runtime-owner'
|
||||
import { runtimeEnvironmentIdWithLegacyFallbackUnlessTwin } from '@/lib/worktree-runtime-owner'
|
||||
import { locateTerminalTab } from '../../terminals/terminal-tab-location'
|
||||
|
||||
/**
|
||||
@@ -33,7 +33,7 @@ export function mirrorTabPinnedToHost(state: AppState, tabId: string, isPinned:
|
||||
if (
|
||||
!found ||
|
||||
found.tab.contentType !== 'terminal' ||
|
||||
!getRuntimeEnvironmentIdForWorktree(state, found.worktreeId)
|
||||
!runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(state, found.worktreeId)
|
||||
) {
|
||||
return
|
||||
}
|
||||
@@ -55,7 +55,7 @@ export function mirrorTabViewModeToHost(
|
||||
if (
|
||||
!found ||
|
||||
found.tab.contentType !== 'terminal' ||
|
||||
!getRuntimeEnvironmentIdForWorktree(state, found.worktreeId)
|
||||
!runtimeEnvironmentIdWithLegacyFallbackUnlessTwin(state, found.worktreeId)
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user