mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
* Keep terminal workspace root links on their execution host * Resolve terminal root-link source host from the owner, not a missing connection id A direct SSH pane whose worktree id also exists on the desktop has no connectionId (ambiguous owner), which was read as local and offered the desktop workspace. Resolve the source via the owner-route resolver and skip the root shortcut when the source host is unknown. * Resolve terminal file links against the source owner's host A same-id SSH workspace left connectionId unset, so a rejected root link, the default-app row and Shift-click fell through to this machine's files. The terminal file context now names the resolved direct SSH host and refuses file access when no owner can be determined. * Keep an ambiguous terminal link owner unresolved instead of local The connection lookup ignores detected worktree rows, so a registered local row could override an owner the full resolver found ambiguous (registered local, detected SSH) and send link stat/open to this machine. Only a missing route may now defer to the connection lookup. * Re-resolve a held chat link's owner before rechecking it Native chat rechecks held link targets when a turn ends. A target resolved while its owner was local kept that context after a same-id worktree was detected on an SSH host, so the recheck still asked this machine. Each existence ask now re-resolves the workspace owner and refuses when it is unresolved or names a different host. --------- Co-authored-by: m4air <m4air@Mac.localdomain>
177 lines
7.7 KiB
JavaScript
177 lines
7.7 KiB
JavaScript
import { pathToFileURL } from 'node:url'
|
|
|
|
export const DOCKER_SSH_E2E_SPECS = [
|
|
'tests/e2e/local-ssh-browser-routing.spec.ts',
|
|
'tests/e2e/ssh-client-hosted-browser-drop-reconnect.spec.ts',
|
|
'tests/e2e/pty-input-write-queue-ssh.spec.ts',
|
|
'tests/e2e/ssh-ai-vault-session-history.spec.ts',
|
|
'tests/e2e/ssh-codex-display-artifacts-repro.spec.ts',
|
|
'tests/e2e/ssh-cold-activation-restore.spec.ts',
|
|
'tests/e2e/ssh-cold-hydration-gap-tab-seeding.spec.ts',
|
|
'tests/e2e/ssh-emptied-worktree-reactivation.spec.ts',
|
|
'tests/e2e/ssh-docker-five-pane-input-under-flood.spec.ts',
|
|
'tests/e2e/ssh-docker-bulk-open-freeze-repro.spec.ts',
|
|
'tests/e2e/ssh-docker-half-open-link.spec.ts',
|
|
'tests/e2e/ssh-docker-quick-open-large-listing.spec.ts',
|
|
'tests/e2e/ssh-docker-reconnect-pane-restore.spec.ts',
|
|
'tests/e2e/ssh-docker-relay-stall-credential.spec.ts',
|
|
'tests/e2e/ssh-docker-resource-accumulation.spec.ts',
|
|
'tests/e2e/ssh-docker-transport-drop-recovery.spec.ts',
|
|
'tests/e2e/ssh-external-image-preview.spec.ts',
|
|
'tests/e2e/ssh-lost-kill-tab-resurrection.spec.ts',
|
|
'tests/e2e/ssh-pi-compatible-agent-title.spec.ts',
|
|
'tests/e2e/ssh-port-forward-lifecycle.spec.ts',
|
|
'tests/e2e/ssh-reattach-home-partition.spec.ts',
|
|
'tests/e2e/ssh-reconnect-tab-destruction.spec.ts',
|
|
'tests/e2e/ssh-restart-tab-accumulation.spec.ts',
|
|
'tests/e2e/ssh-skill-installation.spec.ts',
|
|
'tests/e2e/ssh-stale-resume-execution-host-scope.spec.ts',
|
|
'tests/e2e/ssh-startup-local-shadow.spec.ts',
|
|
'tests/e2e/ssh-terminal-window-wake-stale-grid-repro.spec.ts',
|
|
'tests/e2e/terminal-inline-images-ssh.spec.ts',
|
|
'tests/e2e/ssh-docker-watcher-isolation.spec.ts',
|
|
'tests/e2e/ssh-terminal-parking.spec.ts',
|
|
'tests/e2e/terminal-retention-budget.spec.ts',
|
|
'tests/e2e/ssh-startup-exec-readiness.spec.ts',
|
|
'tests/e2e/paired-startup-exec-readiness.spec.ts',
|
|
'tests/e2e/workspace-layout-oracle-ssh.spec.ts'
|
|
]
|
|
|
|
export const NODE_NETWORK_E2E_SPEC =
|
|
'tests/e2e/ssh-browser-network-execution-route.docker.unit.test.ts'
|
|
export const LOCALHOST_SSH_E2E_SPEC = 'tests/e2e/ssh-localhost.spec.ts'
|
|
export const NATIVE_IME_E2E_SPEC = 'tests/e2e/terminal-ibus-hangul-native.spec.ts'
|
|
// Needs the packaged orcad slot, which only its own job builds.
|
|
export const ORCAD_SERVE_MODE_SWITCH_E2E_SPEC = 'tests/e2e/orcad-serve-mode-switch.spec.ts'
|
|
// Needs the orcad template for its host's target, which only its own job builds.
|
|
export const ORCAD_AUTO_CONVERT_E2E_SPEC = 'tests/e2e/ssh-orcad-auto-convert.spec.ts'
|
|
// Windows-only; its own job runs it on a Windows runner.
|
|
export const WINDOWS_MISSING_APPDATA_E2E_SPEC = 'tests/e2e/windows-missing-appdata-startup.spec.ts'
|
|
// Needs out/orcad, which only the mode-switch job builds; it runs there beside that spec.
|
|
export const LAYOUT_ORACLE_HEADLESS_E2E_SPEC = 'tests/e2e/workspace-layout-oracle-headless.spec.ts'
|
|
// Runs in the auto-convert job, which builds the template it needs.
|
|
export const ORCAD_IDLE_EXIT_E2E_SPEC = 'tests/e2e/ssh-orcad-idle-exit.spec.ts'
|
|
export const ORCAD_BROWSER_CAPABILITIES_E2E_SPEC =
|
|
'tests/e2e/ssh-orcad-browser-capabilities.spec.ts'
|
|
export const ORCAD_BROWSER_SERVICE_STATUS_E2E_SPEC =
|
|
'tests/e2e/ssh-orcad-browser-service-status.spec.ts'
|
|
export const ORCAD_BROWSER_ROUTING_E2E_SPEC = 'tests/e2e/ssh-orcad-browser-routing.spec.ts'
|
|
export const ORCAD_EDITOR_OWNERSHIP_E2E_SPEC = 'tests/e2e/ssh-orcad-editor-ownership.spec.ts'
|
|
export const ORCAD_MARKDOWN_CONVERSION_E2E_SPEC = 'tests/e2e/ssh-orcad-markdown-conversion.spec.ts'
|
|
export const ORCAD_MARKDOWN_LINK_REFRESH_E2E_SPEC =
|
|
'tests/e2e/ssh-orcad-markdown-link-refresh.spec.ts'
|
|
export const ORCAD_MARKDOWN_LIVE_DOCUMENTS_E2E_SPEC =
|
|
'tests/e2e/ssh-orcad-markdown-live-documents.spec.ts'
|
|
export const ORCAD_BROWSER_DROP_OWNER_E2E_SPEC = 'tests/e2e/ssh-orcad-browser-drop-owner.spec.ts'
|
|
export const ORCAD_OPEN_IN_OWNER_E2E_SPEC = 'tests/e2e/ssh-orcad-open-in-owner.spec.ts'
|
|
export const ORCAD_EDITOR_WATCH_RECOVERY_E2E_SPEC =
|
|
'tests/e2e/ssh-orcad-editor-watch-recovery.spec.ts'
|
|
export const ORCAD_EXPLORER_WATCH_RECOVERY_E2E_SPEC =
|
|
'tests/e2e/ssh-orcad-explorer-watch-recovery.spec.ts'
|
|
export const ORCAD_EXPLORER_SELECTED_HOST_E2E_SPEC =
|
|
'tests/e2e/ssh-orcad-explorer-selected-host.spec.ts'
|
|
export const ORCAD_TERMINAL_ROOT_OWNER_E2E_SPEC = 'tests/e2e/ssh-orcad-terminal-root-owner.spec.ts'
|
|
export const DEDICATED_E2E_SPECS = [
|
|
...DOCKER_SSH_E2E_SPECS,
|
|
NODE_NETWORK_E2E_SPEC,
|
|
LOCALHOST_SSH_E2E_SPEC,
|
|
NATIVE_IME_E2E_SPEC,
|
|
ORCAD_SERVE_MODE_SWITCH_E2E_SPEC,
|
|
LAYOUT_ORACLE_HEADLESS_E2E_SPEC,
|
|
ORCAD_AUTO_CONVERT_E2E_SPEC,
|
|
WINDOWS_MISSING_APPDATA_E2E_SPEC,
|
|
ORCAD_IDLE_EXIT_E2E_SPEC,
|
|
ORCAD_BROWSER_CAPABILITIES_E2E_SPEC,
|
|
ORCAD_BROWSER_SERVICE_STATUS_E2E_SPEC,
|
|
ORCAD_BROWSER_ROUTING_E2E_SPEC,
|
|
ORCAD_EDITOR_OWNERSHIP_E2E_SPEC,
|
|
ORCAD_MARKDOWN_CONVERSION_E2E_SPEC,
|
|
ORCAD_MARKDOWN_LINK_REFRESH_E2E_SPEC,
|
|
ORCAD_MARKDOWN_LIVE_DOCUMENTS_E2E_SPEC,
|
|
ORCAD_OPEN_IN_OWNER_E2E_SPEC,
|
|
ORCAD_EDITOR_WATCH_RECOVERY_E2E_SPEC,
|
|
ORCAD_EXPLORER_WATCH_RECOVERY_E2E_SPEC,
|
|
ORCAD_EXPLORER_SELECTED_HOST_E2E_SPEC,
|
|
ORCAD_BROWSER_DROP_OWNER_E2E_SPEC,
|
|
ORCAD_TERMINAL_ROOT_OWNER_E2E_SPEC
|
|
]
|
|
const dedicatedSpecs = new Set(DEDICATED_E2E_SPECS)
|
|
const dockerSpecs = new Set(DOCKER_SSH_E2E_SPECS)
|
|
|
|
export function selectGeneralE2eSpecs(specs) {
|
|
return specs.filter((spec) => !dedicatedSpecs.has(spec))
|
|
}
|
|
|
|
function parseSpecs(input) {
|
|
const specs = JSON.parse(input)
|
|
if (!Array.isArray(specs) || specs.some((spec) => typeof spec !== 'string' || !spec)) {
|
|
throw new Error('Expected a JSON array of nonempty E2E spec paths')
|
|
}
|
|
return specs
|
|
}
|
|
|
|
export function classifyE2eJobs(input, sshSourceChanged = 'false') {
|
|
const conservative = { e2e_run_changed: true, e2e_needs_build: true }
|
|
let specs
|
|
try {
|
|
specs = parseSpecs(input)
|
|
} catch {
|
|
return conservative
|
|
}
|
|
// Empty evidence keeps allocations; the consumer still validates its input.
|
|
if (specs.length === 0) {
|
|
return conservative
|
|
}
|
|
const runChanged = selectGeneralE2eSpecs(specs).length > 0
|
|
return {
|
|
e2e_run_changed: runChanged,
|
|
e2e_needs_build:
|
|
runChanged ||
|
|
sshSourceChanged !== 'false' ||
|
|
specs.some(
|
|
(spec) =>
|
|
dockerSpecs.has(spec) ||
|
|
spec === LOCALHOST_SSH_E2E_SPEC ||
|
|
spec === ORCAD_SERVE_MODE_SWITCH_E2E_SPEC ||
|
|
spec === LAYOUT_ORACLE_HEADLESS_E2E_SPEC ||
|
|
spec === ORCAD_AUTO_CONVERT_E2E_SPEC ||
|
|
spec === ORCAD_IDLE_EXIT_E2E_SPEC ||
|
|
spec === ORCAD_BROWSER_CAPABILITIES_E2E_SPEC ||
|
|
spec === ORCAD_BROWSER_SERVICE_STATUS_E2E_SPEC ||
|
|
spec === ORCAD_BROWSER_ROUTING_E2E_SPEC ||
|
|
spec === ORCAD_EDITOR_OWNERSHIP_E2E_SPEC ||
|
|
spec === ORCAD_MARKDOWN_CONVERSION_E2E_SPEC ||
|
|
spec === ORCAD_MARKDOWN_LINK_REFRESH_E2E_SPEC ||
|
|
spec === ORCAD_MARKDOWN_LIVE_DOCUMENTS_E2E_SPEC ||
|
|
spec === ORCAD_OPEN_IN_OWNER_E2E_SPEC ||
|
|
spec === ORCAD_EDITOR_WATCH_RECOVERY_E2E_SPEC ||
|
|
spec === ORCAD_EXPLORER_WATCH_RECOVERY_E2E_SPEC ||
|
|
spec === ORCAD_EXPLORER_SELECTED_HOST_E2E_SPEC ||
|
|
spec === ORCAD_BROWSER_DROP_OWNER_E2E_SPEC ||
|
|
spec === ORCAD_TERMINAL_ROOT_OWNER_E2E_SPEC
|
|
)
|
|
}
|
|
}
|
|
|
|
if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
|
|
let input = ''
|
|
process.stdin.setEncoding('utf8')
|
|
for await (const chunk of process.stdin) {
|
|
input += chunk
|
|
}
|
|
if (process.argv.includes('--job-outputs')) {
|
|
for (const [name, value] of Object.entries(
|
|
classifyE2eJobs(input, process.env.E2E_SSH_SOURCE_CHANGED ?? 'false')
|
|
)) {
|
|
process.stdout.write(`${name}=${value}\n`)
|
|
}
|
|
} else {
|
|
for (const spec of selectGeneralE2eSpecs(parseSpecs(input))) {
|
|
if (/[\r\n]/.test(spec)) {
|
|
throw new Error('E2E spec paths cannot contain newlines')
|
|
}
|
|
process.stdout.write(`${spec}\n`)
|
|
}
|
|
}
|
|
}
|