Files
orca/tests/e2e/helpers/nested-runtime-same-id-pairing.ts
T
afbd98d8a4 Support Windows drives in the remote host filesystem picker (#7439)
* Support Windows drives in the remote host filesystem picker

The remote picker was locked to the system drive on Windows hosts: the
breadcrumb root resolved to C:\ and typed drive paths (M:\dev) were
treated as filter text, so projects could only ever be created on C:.

- Server: answer host-root browses ('/') on win32 with the mounted
  drives instead of resolving to C:\.
- Client: recognize drive-anchored input (M:\, M:/, m:) as path mode,
  resolve segments from the normalized drive root, and make
  joinPath/parentPath/breadcrumbs drive-aware. Up from a drive root
  returns to the host root (the drive list).

Fixes #7438

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Document why joinDrivePath uses a literal backslash

Review feedback suggested path.win32.join, but the renderer bundle
imports no Node builtins anywhere and runs sandboxed, so path.win32 is
not available here. The backslash targets the remote Windows host
regardless of client OS; say so at the call site.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* Complete Windows drive browsing over SSH

* fix remote Windows drive browsing

* fix(ui): key remote breadcrumbs by path

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: OrcaWin <293788423+OrcaWin@users.noreply.github.com>
2026-07-28 20:51:14 -07:00

55 lines
2.4 KiB
TypeScript

import type { Page } from '@stablyai/playwright-test'
import { updateEnvironmentFromPairingCode } from '../../../src/shared/runtime-environment-store'
export type SameIdPairingReplacement = {
environmentId: string
previousPairingRevision: number
nextPairingRevision: number
}
export async function replaceRuntimePairingInPlace(args: {
environmentId: string
page: Page
pairingUrl: string
userDataDir: string
}): Promise<SameIdPairingReplacement> {
const previous = await args.page.evaluate((selector) => {
return window.api.runtimeEnvironments.resolve({ selector })
}, args.environmentId)
await args.page.evaluate(async (selector) => {
await window.api.runtimeEnvironments.disconnect({ selector })
}, args.environmentId)
const updated = updateEnvironmentFromPairingCode(args.userDataDir, args.environmentId, {
pairingCode: args.pairingUrl
})
const hydrated = await args.page.evaluate(async (selector) => {
const store = window.__store
if (!store) {
throw new Error('Paired desktop store is unavailable during same-ID re-pair')
}
const environments = await window.api.runtimeEnvironments.list()
store.getState().setRuntimeEnvironments(environments)
if (!(await store.getState().refreshRuntimeEnvironmentStatus(selector))) {
throw new Error('Same-ID re-paired desktop could not reach the HUB runtime')
}
if (!(await store.getState().setActiveRuntimeEnvironmentPreference(selector))) {
throw new Error('Same-ID re-paired desktop could not select the HUB runtime')
}
// Why: same-ID selection is a no-op, so explicitly rehydrate the graph from the replacement transport.
await store.getState().fetchRepos()
await store.getState().fetchAllWorktrees()
await store.getState().fetchWorktreeLineage()
return window.api.runtimeEnvironments.resolve({ selector })
}, args.environmentId)
const previousPairingRevision = previous.pairingRevision ?? previous.createdAt
const nextPairingRevision = hydrated.pairingRevision ?? hydrated.createdAt
if (updated.id !== args.environmentId || hydrated.id !== args.environmentId) {
throw new Error('Same-ID re-pair unexpectedly changed the environment identity')
}
if (nextPairingRevision <= previousPairingRevision) {
throw new Error('Same-ID re-pair did not advance the pairing revision')
}
return { environmentId: args.environmentId, previousPairingRevision, nextPairingRevision }
}