mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 16:02:32 +00:00
* 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>
55 lines
2.4 KiB
TypeScript
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 }
|
|
}
|