Files
orca/src/relay/remote-cli-timeout.test.ts
T
Jinwoo HongandOrca 0784a7ea37 fix(ssh): bridge the full Orca CLI over the SSH relay instead of a hardcoded command switch (#7771)
The relay CLI shim on SSH remotes rejected every orchestration/mutation
command with 'Unsupported SSH Orca CLI command' because the host handled
relay CLI requests with a hand-rolled allowlist of five read-only-ish
commands. The host now runs the real bundled orca CLI entry (same entry
as the local shell command, via ELECTRON_RUN_AS_NODE) as a captured
subprocess, so remote invocations get the full command surface by
construction. Remote cwd is carried via ORCA_CLI_CWD so cwd-based
selectors (--worktree active) resolve against the caller's remote
directory; only Orca terminal-context env vars cross the bridge.

Host-interactive commands (serve, claude-teams, agent-teams-tmux) get a
targeted error, and the legacy in-process switch remains as a fallback
when the host CLI entry cannot be launched. Relay-side request timeouts
are raised to fit mutation and long-poll (--wait/--timeout-ms) commands,
and stdin forwarding now covers *-stdin payload flags.

Fixes #7716

Co-authored-by: Orca <help@stably.ai>
2026-07-08 13:59:42 -07:00

66 lines
2.2 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { remoteCliRequestTimeoutMs } from './remote-cli-timeout'
describe('remoteCliRequestTimeoutMs', () => {
it('gives Linear issue context reads the general CLI budget', () => {
expect(
remoteCliRequestTimeoutMs({
argv: ['linear', 'issue', 'ENG-123', '--json']
})
).toBe(300_000)
})
it('gives ordinary remote CLI requests the general CLI budget instead of the 30s relay default', () => {
// Why: mutation commands bridged through the full host CLI (worktree
// create, orchestration dispatch, ...) can legitimately exceed 30s.
expect(remoteCliRequestTimeoutMs({ argv: ['status'] })).toBe(300_000)
expect(remoteCliRequestTimeoutMs({ argv: ['worktree', 'create', '--repo', 'r'] })).toBe(300_000)
})
it('extends the timeout for wait-style commands', () => {
expect(remoteCliRequestTimeoutMs({ argv: ['terminal', 'wait', '--for', 'exit'] })).toBe(600_000)
expect(
remoteCliRequestTimeoutMs({
argv: ['orchestration', 'check', '--wait', '--json']
})
).toBe(600_000)
expect(
remoteCliRequestTimeoutMs({
argv: ['orchestration', 'ask', '--to', 'term_x', '--question', 'ok?']
})
).toBe(600_000)
})
it('extends past an explicit --timeout-ms waiter budget', () => {
expect(
remoteCliRequestTimeoutMs({
argv: ['terminal', 'wait', '--for', 'exit', '--timeout-ms', '1800000']
})
).toBe(1_860_000)
expect(
remoteCliRequestTimeoutMs({
argv: ['orchestration', 'check', '--wait', '--timeout-ms=1800000']
})
).toBe(1_860_000)
})
it('keeps the wait base budget when --timeout-ms is small', () => {
expect(
remoteCliRequestTimeoutMs({
argv: ['terminal', 'wait', '--for', 'exit', '--timeout-ms', '5000']
})
).toBe(600_000)
})
it('does not treat a flag value named wait as a command path element', () => {
expect(remoteCliRequestTimeoutMs({ argv: ['terminal', 'read', '--terminal', 'wait'] })).toBe(
300_000
)
})
it('falls back to the relay default for malformed argv', () => {
expect(remoteCliRequestTimeoutMs({ argv: 'status' })).toBeUndefined()
expect(remoteCliRequestTimeoutMs({})).toBeUndefined()
})
})