mirror of
https://github.com/stablyai/orca.git
synced 2026-10-21 16:03:26 +00:00
fix(skills): accept mirrored SSH pane session
This commit is contained in:
@@ -1,5 +1,11 @@
|
||||
import { describe, expect, it } from 'vitest'
|
||||
import type { FolderWorkspace, ProjectGroup, Repo, WorkspaceSessionState } from '../../shared/types'
|
||||
import type {
|
||||
FolderWorkspace,
|
||||
ProjectGroup,
|
||||
Repo,
|
||||
WorktreeMeta,
|
||||
WorkspaceSessionState
|
||||
} from '../../shared/types'
|
||||
import { resolvePaneSkillDiscoveryWorkspace } from './pane-skill-discovery-workspace'
|
||||
|
||||
const EMPTY_SESSION = { tabsByWorktree: {} } as WorkspaceSessionState
|
||||
@@ -16,6 +22,22 @@ function repo(overrides: Partial<Repo> = {}): Repo {
|
||||
}
|
||||
}
|
||||
|
||||
function worktreeMeta(hostId: WorktreeMeta['hostId']): WorktreeMeta {
|
||||
return {
|
||||
hostId,
|
||||
displayName: 'repo',
|
||||
comment: '',
|
||||
linkedIssue: null,
|
||||
linkedPR: null,
|
||||
linkedLinearIssue: null,
|
||||
isArchived: false,
|
||||
isUnread: false,
|
||||
isPinned: false,
|
||||
sortOrder: 0,
|
||||
lastActivityAt: 1
|
||||
}
|
||||
}
|
||||
|
||||
function session(worktreeId: string, startupCwd?: string): WorkspaceSessionState {
|
||||
return {
|
||||
tabsByWorktree: {
|
||||
@@ -42,6 +64,63 @@ describe('resolvePaneSkillDiscoveryWorkspace', () => {
|
||||
).toEqual({ connectionId: 'target-1', cwd: '/remote/repo/packages/app' })
|
||||
})
|
||||
|
||||
it('accepts the legacy local mirror of an authoritative SSH pane session', () => {
|
||||
const worktreeId = 'repo-1::/work/demo-project'
|
||||
|
||||
expect(
|
||||
resolvePaneSkillDiscoveryWorkspace({
|
||||
worktreeId,
|
||||
terminalTabId: 'tab-1',
|
||||
repos: [repo({ path: '/work/demo-project' })],
|
||||
projectGroups: [],
|
||||
folderWorkspaces: [],
|
||||
worktreeMeta: worktreeMeta('ssh:target-1'),
|
||||
sessions: [
|
||||
{ hostId: 'local', session: session(worktreeId, '/work/demo-project') },
|
||||
{ hostId: 'ssh:target-1', session: session(worktreeId, '/work/demo-project') }
|
||||
]
|
||||
})
|
||||
).toEqual({ connectionId: 'target-1', cwd: '/work/demo-project' })
|
||||
})
|
||||
|
||||
it('rejects duplicate pane sessions on distinct non-local hosts', () => {
|
||||
const worktreeId = 'repo-1::/remote/repo'
|
||||
|
||||
expect(() =>
|
||||
resolvePaneSkillDiscoveryWorkspace({
|
||||
worktreeId,
|
||||
terminalTabId: 'tab-1',
|
||||
repos: [repo()],
|
||||
projectGroups: [],
|
||||
folderWorkspaces: [],
|
||||
worktreeMeta: worktreeMeta('ssh:target-1'),
|
||||
sessions: [
|
||||
{ hostId: 'ssh:target-1', session: session(worktreeId) },
|
||||
{ hostId: 'ssh:target-2', session: session(worktreeId) }
|
||||
]
|
||||
})
|
||||
).toThrow('pane_skill_discovery_owner_ambiguous')
|
||||
})
|
||||
|
||||
it('rejects a legacy local pane that does not mirror the SSH startup directory', () => {
|
||||
const worktreeId = 'repo-1::/remote/repo'
|
||||
|
||||
expect(() =>
|
||||
resolvePaneSkillDiscoveryWorkspace({
|
||||
worktreeId,
|
||||
terminalTabId: 'tab-1',
|
||||
repos: [repo()],
|
||||
projectGroups: [],
|
||||
folderWorkspaces: [],
|
||||
worktreeMeta: worktreeMeta('ssh:target-1'),
|
||||
sessions: [
|
||||
{ hostId: 'local', session: session(worktreeId, '/local/repo') },
|
||||
{ hostId: 'ssh:target-1', session: session(worktreeId, '/remote/repo') }
|
||||
]
|
||||
})
|
||||
).toThrow('pane_skill_discovery_owner_ambiguous')
|
||||
})
|
||||
|
||||
it('routes an executionHostId-only SSH repo instead of falling back locally', () => {
|
||||
expect(
|
||||
resolvePaneSkillDiscoveryWorkspace({
|
||||
|
||||
@@ -38,9 +38,9 @@ export function resolvePaneSkillDiscoveryWorkspace(
|
||||
): PaneSkillDiscoveryWorkspace {
|
||||
const scope = parseWorkspaceKey(args.worktreeId)
|
||||
const worktreeId = scope?.type === 'worktree' ? scope.worktreeId : args.worktreeId
|
||||
const sessionOwner = findPaneSession(args.sessions, worktreeId, args.terminalTabId)
|
||||
|
||||
if (scope?.type === 'folder') {
|
||||
const sessionOwner = findPaneSession(args.sessions, worktreeId, args.terminalTabId)
|
||||
const workspace = selectFolderWorkspace(
|
||||
args.folderWorkspaces.filter((candidate) => candidate.id === scope.folderWorkspaceId),
|
||||
sessionOwner?.hostId
|
||||
@@ -72,6 +72,7 @@ export function resolvePaneSkillDiscoveryWorkspace(
|
||||
throw new Error('pane_skill_discovery_workspace_not_found')
|
||||
}
|
||||
const metaHostId = parseOptionalHostId(args.worktreeMeta?.hostId)
|
||||
const sessionOwner = findPaneSession(args.sessions, worktreeId, args.terminalTabId, metaHostId)
|
||||
assertMatchingHost(sessionOwner?.hostId, metaHostId)
|
||||
const knownHostId = sessionOwner?.hostId ?? metaHostId
|
||||
const repo = selectPaneRepo(candidates, knownHostId)
|
||||
@@ -171,7 +172,8 @@ function declaredHostId(owner: {
|
||||
function findPaneSession(
|
||||
sessions: readonly HostSession[],
|
||||
worktreeId: string,
|
||||
terminalTabId: string | undefined
|
||||
terminalTabId: string | undefined,
|
||||
authoritativeHostId?: ExecutionHostId | null
|
||||
): { hostId: ExecutionHostId; tab: { startupCwd?: string } } | null {
|
||||
if (!terminalTabId) {
|
||||
return null
|
||||
@@ -186,11 +188,35 @@ function findPaneSession(
|
||||
)
|
||||
)
|
||||
if (matches.length > 1) {
|
||||
const authoritativeMatches = authoritativeHostId
|
||||
? matches.filter((match) => match.hostId === authoritativeHostId)
|
||||
: []
|
||||
const authoritativeMatch = authoritativeMatches.length === 1 ? authoritativeMatches[0] : null
|
||||
// Why: save compatibility mirrors remote tabs locally; only matching local rows yield to persisted ownership.
|
||||
if (
|
||||
authoritativeHostId !== LOCAL_EXECUTION_HOST_ID &&
|
||||
authoritativeMatch &&
|
||||
matches.every(
|
||||
(match) =>
|
||||
match === authoritativeMatch ||
|
||||
(match.hostId === LOCAL_EXECUTION_HOST_ID &&
|
||||
paneSessionsMirror(match.tab, authoritativeMatch.tab))
|
||||
)
|
||||
) {
|
||||
return authoritativeMatch
|
||||
}
|
||||
throw new Error('pane_skill_discovery_owner_ambiguous')
|
||||
}
|
||||
return matches[0] ?? null
|
||||
}
|
||||
|
||||
function paneSessionsMirror(
|
||||
left: { startupCwd?: string },
|
||||
right: { startupCwd?: string }
|
||||
): boolean {
|
||||
return (left.startupCwd?.trim() || null) === (right.startupCwd?.trim() || null)
|
||||
}
|
||||
|
||||
function selectPaneRepo(candidates: readonly Repo[], hostId: ExecutionHostId | null): Repo {
|
||||
if (!hostId) {
|
||||
if (candidates.length !== 1) {
|
||||
|
||||
Reference in New Issue
Block a user