perf(cli): use packaged Node for ordinary Mac commands

This commit is contained in:
Brennan Benson
2026-11-13 18:59:36 -08:00
parent a6b2a0803a
commit f40646ebf8
11 changed files with 265 additions and 15 deletions
+45 -1
View File
@@ -20,7 +20,6 @@ fi
CONTENTS="$APP_PATH/Contents"
ELECTRON="$CONTENTS/MacOS/Orca"
# The unpacked entrypoint runs directly in Electron's Node mode.
CLI="$CONTENTS/Resources/app.asar.unpacked/out/cli/index.js"
export ORCA_NODE_OPTIONS="${NODE_OPTIONS-}"
@@ -28,4 +27,49 @@ export ORCA_NODE_REPL_EXTERNAL_MODULE="${NODE_REPL_EXTERNAL_MODULE-}"
unset NODE_OPTIONS
unset NODE_REPL_EXTERNAL_MODULE
function plist_version() {
local file=$1 key=$2 line found=0 remaining=256
REPLY=
[ -r "$file" ] || return 1
while IFS= read -r line; do
[ "$remaining" -gt 0 ] || return 1
remaining=$((remaining - 1))
if [[ $line == *"<key>$key</key>"* ]]; then
found=1
line=${line#*</key>}
fi
if [ "$found" -eq 1 ]; then
if [[ $line =~ ^[[:space:]]*\<string\>([0-9]{1,3}\.[0-9]{1,3}(\.[0-9]{1,3})?)\</string\>[[:space:]]*$ ]]; then
REPLY=${BASH_REMATCH[1]}
return 0
fi
[[ $line =~ ^[[:space:]]*$ ]] || return 1
fi
done < "$file"
return 1
}
function supports_packaged_node() {
local minimum current index required actual
plist_version "$NODE_CONTENTS/Info.plist" LSMinimumSystemVersion || return 1
IFS=. read -r -a minimum <<< "$REPLY"
plist_version /System/Library/CoreServices/SystemVersion.plist ProductVersion || return 1
IFS=. read -r -a current <<< "$REPLY"
for index in 0 1 2; do
required=$((10#${minimum[$index]:-0}))
actual=$((10#${current[$index]:-0}))
[ "$actual" -gt "$required" ] && return 0
[ "$actual" -lt "$required" ] && return 1
done
return 0
}
NODE_CONTENTS="$CONTENTS/Helpers/Orca Agents.app/Contents"
NODE="$NODE_CONTENTS/MacOS/Orca Agents"
if [ -x "$NODE" ] && supports_packaged_node; then
export ORCA_CLI_ELECTRON_EXECUTABLE="$ELECTRON"
unset ELECTRON_RUN_AS_NODE
exec "$NODE" "$CLI" "$@"
fi
ELECTRON_RUN_AS_NODE=1 exec "$ELECTRON" "$CLI" "$@"
+1
View File
@@ -1,4 +1,5 @@
#!/usr/bin/env node
import './runtime/packaged-cli-interpreter'
import {
findCommandSpec,
isCommandGroup,
@@ -1,7 +1,20 @@
import { describe, expect, it } from 'vitest'
import { afterEach, describe, expect, it, vi } from 'vitest'
import type { ProcessResult, ProcessSpec } from '@orca/process-host/process-spec'
import { selectPluginTestNode } from './plugin-test-node'
const { runDefault, packaged } = vi.hoisted(() => {
const packaged: { path: string | null } = { path: null }
return { runDefault: vi.fn(), packaged }
})
vi.mock('@orca/process-host', () => ({ runProcess: runDefault }))
vi.mock('../../runtime/packaged-cli-interpreter', () => ({
getPackagedElectronExecutable: () => packaged.path
}))
afterEach(() => {
packaged.path = null
vi.clearAllMocks()
})
const ORCA = { execPath: '/Applications/Orca.app/Contents/MacOS/Orca', version: 'v22.9.0' }
function answering(stdout: string | Error, code = 0) {
@@ -17,9 +30,19 @@ function answering(stdout: string | Error, code = 0) {
}
describe('selectPluginTestNode', () => {
it('uses root Electron for the fallback child while the packaged CLI runs on Node', async () => {
packaged.path = '/Applications/Orca.app/Contents/MacOS/Orca'
runDefault.mockRejectedValue(new Error('spawn node ENOENT'))
expect(await selectPluginTestNode()).toMatchObject({
program: '/Applications/Orca.app/Contents/MacOS/Orca',
env: { ELECTRON_RUN_AS_NODE: '1' },
source: 'orca'
})
})
it('uses a new enough system node by the absolute path it reports, probed outside the plugin', async () => {
const probe = answering('v20.6.0 /usr/local/bin/node\n')
const node = await selectPluginTestNode({ ...ORCA, electron: '38.0.0', run: probe.run })
const node = await selectPluginTestNode({ ...ORCA, electron: true, run: probe.run })
expect(node).toEqual({
program: '/usr/local/bin/node',
env: {},
@@ -32,7 +55,7 @@ describe('selectPluginTestNode', () => {
it('keeps a Windows path with spaces whole', async () => {
const probe = answering('v22.1.0 C:\\Program Files\\nodejs\\node.exe\r\n')
const node = await selectPluginTestNode({ ...ORCA, electron: '38.0.0', run: probe.run })
const node = await selectPluginTestNode({ ...ORCA, electron: true, run: probe.run })
expect(node.program).toBe('C:\\Program Files\\nodejs\\node.exe')
})
@@ -42,7 +65,7 @@ describe('selectPluginTestNode', () => {
['failing', answering('', 1)],
['answering garbage', answering('nope')]
])('falls back to Orca as Node when the system node is %s', async (_reason, probe) => {
const node = await selectPluginTestNode({ ...ORCA, electron: '38.0.0', run: probe.run })
const node = await selectPluginTestNode({ ...ORCA, electron: true, run: probe.run })
expect(node).toEqual({
program: ORCA.execPath,
env: { ELECTRON_RUN_AS_NODE: '1' },
@@ -53,7 +76,7 @@ describe('selectPluginTestNode', () => {
it('needs no Electron switch when the CLI itself runs on plain Node', async () => {
const probe = answering(new Error('spawn node ENOENT'))
const node = await selectPluginTestNode({ ...ORCA, electron: undefined, run: probe.run })
const node = await selectPluginTestNode({ ...ORCA, electron: false, run: probe.run })
expect(node.env).toEqual({})
})
})
+11 -7
View File
@@ -1,3 +1,4 @@
import { getPackagedElectronExecutable } from '../../runtime/packaged-cli-interpreter'
import { mkdtemp, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
@@ -21,15 +22,18 @@ type Dependencies = {
/** The runtime this CLI runs on: Electron as Node in a packaged app, or Node in development. */
execPath: string
version: string
electron: string | undefined
electron: boolean
}
const defaults = (): Dependencies => ({
run: runProcess,
execPath: process.execPath,
version: process.version,
electron: process.versions.electron
})
const defaults = (): Dependencies => {
const packagedElectron = getPackagedElectronExecutable()
return {
run: runProcess,
execPath: packagedElectron ?? process.execPath,
version: process.version,
electron: Boolean(packagedElectron || process.versions.electron)
}
}
function supports(version: string): boolean {
const [major = 0, minor = 0] = version.replace(/^v/, '').split('.').map(Number)
+2
View File
@@ -1,3 +1,4 @@
import { reenterPackagedElectron } from '../runtime/packaged-cli-interpreter'
import { z } from 'zod'
import type { CommandHandler } from '../dispatch/dispatch'
import { printResult } from '../output/command-result-output'
@@ -119,6 +120,7 @@ export const PROFILE_STATE_HANDLERS: Record<string, CommandHandler> = {
rejectProfileStateRemoteSelection(flags)
const selector = parseSelector(flags)
const profileId = parseProfileId(flags)
reenterPackagedElectron()
const userDataPath = getDefaultUserDataPath()
let result: ProfileStateRollbackResult
if (canLaunchProfileStateRecovery()) {
@@ -1,3 +1,4 @@
import { reenterPackagedElectron } from './packaged-cli-interpreter'
import { spawn } from 'node:child_process'
import { resolve } from 'node:path'
import type { CommandHandler } from '../dispatch/dispatch'
@@ -138,6 +139,7 @@ export const CORE_HANDLERS: Record<string, CommandHandler> = {
}
const port = getOptionalServePort(flags)
const pairingAddressValue = flags.get('pairing-address')
reenterPackagedElectron()
const exitCode = await serveOrcaApp({
json,
port,
+2
View File
@@ -1,3 +1,4 @@
import { reenterPackagedElectron } from './packaged-cli-interpreter'
import { randomUUID } from 'node:crypto'
import type { CliStatusResult, RuntimeStatus } from '../../shared/runtime-types'
import { runtimeHostConnectionState } from '../../shared/remote-runtime/host-status/runtime-host-connection-state'
@@ -307,6 +308,7 @@ export class RuntimeClient {
if (this.remote) {
return this.getCliStatus()
}
reenterPackagedElectron()
return openLocalOrca(
() => this.getCliStatus(),
(options) => this.call<{ requested: boolean }>('desktop.openWindowInBackground', {}, options),
@@ -0,0 +1,59 @@
import { afterEach, expect, it, vi } from 'vitest'
import { accessSync } from 'node:fs'
import type * as Fs from 'node:fs'
vi.mock('node:fs', async (importOriginal) => ({
...(await importOriginal<typeof Fs>()),
accessSync: vi.fn()
}))
const platform = process.platform
const argv = process.argv
afterEach(() => {
Object.defineProperty(process, 'platform', { value: platform })
process.argv = argv
vi.unstubAllEnvs()
vi.restoreAllMocks()
vi.mocked(accessSync).mockReset()
vi.resetModules()
})
it('consumes the shim marker before replacing a lifecycle command with root Electron', async () => {
Object.defineProperty(process, 'platform', { value: 'darwin' })
process.argv = ['/helper/node', '/app/cli.js', 'open', '--json']
vi.stubEnv('ORCA_CLI_ELECTRON_EXECUTABLE', '/Applications/Orca.app/Contents/MacOS/Orca')
vi.stubEnv('ORCA_NODE_OPTIONS', '--max-old-space-size=2048')
const replaced = new Error('Process replaced')
let invocation:
| { file: string; args: readonly string[] | undefined; env: NodeJS.ProcessEnv | undefined }
| undefined
vi.spyOn(process, 'execve').mockImplementation((file, args, env) => {
invocation = { file, args, env }
throw replaced
})
vi.resetModules()
const { reenterPackagedElectron } = await import('./packaged-cli-interpreter')
expect(process.env.ORCA_CLI_ELECTRON_EXECUTABLE).toBeUndefined()
expect(reenterPackagedElectron).toThrow(replaced)
expect(invocation).toMatchObject({
file: '/Applications/Orca.app/Contents/MacOS/Orca',
args: ['/Applications/Orca.app/Contents/MacOS/Orca', '/app/cli.js', 'open', '--json'],
env: { ELECTRON_RUN_AS_NODE: '1', ORCA_NODE_OPTIONS: '--max-old-space-size=2048' }
})
expect(invocation?.env).not.toHaveProperty('ORCA_CLI_ELECTRON_EXECUTABLE')
})
it('reports an unavailable app before attempting native process replacement', async () => {
Object.defineProperty(process, 'platform', { value: 'darwin' })
process.argv = ['/helper/node', '/app/cli.js', 'open']
vi.stubEnv('ORCA_CLI_ELECTRON_EXECUTABLE', '/missing/Orca')
vi.mocked(accessSync).mockImplementation(() => {
throw new Error('ENOENT')
})
vi.spyOn(process, 'execve').mockImplementation(() => {
throw new Error('Native replacement attempted')
})
vi.resetModules()
const { reenterPackagedElectron } = await import('./packaged-cli-interpreter')
expect(reenterPackagedElectron).toThrow('The installed Orca app is unavailable')
})
@@ -0,0 +1,32 @@
import { isAbsolute } from 'node:path'
import { accessSync, constants } from 'node:fs'
import { RuntimeClientError } from './types'
const electron = process.env.ORCA_CLI_ELECTRON_EXECUTABLE
delete process.env.ORCA_CLI_ELECTRON_EXECUTABLE
const packagedElectron =
process.platform === 'darwin' && electron && isAbsolute(electron) ? electron : null
export function getPackagedElectronExecutable(): string | null {
return packagedElectron
}
/** App-owned operations retain the root app's update and process identity. */
export function reenterPackagedElectron(): void {
if (!packagedElectron) {
return
}
try {
accessSync(packagedElectron, constants.X_OK)
accessSync(process.argv[1], constants.R_OK)
} catch {
throw new RuntimeClientError(
'app_not_found',
'The installed Orca app is unavailable. Reinstall Orca and try again.'
)
}
process.execve(packagedElectron, [packagedElectron, ...process.argv.slice(1)], {
...process.env,
ELECTRON_RUN_AS_NODE: '1'
})
}
+5 -2
View File
@@ -1,3 +1,4 @@
import { reenterPackagedElectron } from '../runtime/packaged-cli-interpreter'
import { existsSync, mkdirSync, rmSync, writeFileSync } from 'node:fs'
import { homedir } from 'node:os'
import { dirname } from 'node:path'
@@ -268,7 +269,7 @@ export const SERVE_SERVICE_HANDLERS: Record<string, CommandHandler> = {
'Use either --allow-public or --refuse-public, not both.'
)
}
const result = await installServeService({
const options = {
command: optionalString(flags.get('command')),
// Validate before launchd can loop on a bad value and trip the supervisor brake.
port: getOptionalServePort(flags),
@@ -277,7 +278,9 @@ export const SERVE_SERVICE_HANDLERS: Record<string, CommandHandler> = {
allowPublic: flags.get('allow-public') === true,
refusePublic: flags.get('refuse-public') === true,
dryRun: flags.get('dry-run') === true
})
}
reenterPackagedElectron()
const result = await installServeService(options)
emit(result, json, formatServeServiceInstall)
},
'serve service status': async ({ json }) => {
@@ -0,0 +1,78 @@
import { execFile } from 'node:child_process'
import { chmod, mkdir, mkdtemp, readFile, realpath, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { promisify } from 'node:util'
import { afterEach, expect, it } from 'vitest'
const run = promisify(execFile)
let root: string | undefined
afterEach(async () => {
if (root) {
await rm(root, { recursive: true, force: true })
root = undefined
}
})
it.skipIf(process.platform === 'win32').each([
['13.5', 'node', true],
['13.4', 'electron', true],
['27.2', 'node', true],
['unknown', 'electron', true],
['13.5', 'electron', false]
] as const)(
'runs the packaged CLI on %s with %s (helper executable: %s)',
async (version, runtime, executable) => {
root = await realpath(await mkdtemp(join(tmpdir(), 'orca-mac-cli-')))
const contents = join(root, 'Test.app', 'Contents')
const bin = join(contents, 'Resources', 'bin')
const helper = join(contents, 'Helpers', 'Orca Agents.app', 'Contents')
await Promise.all([
mkdir(bin, { recursive: true }),
mkdir(join(contents, 'MacOS'), { recursive: true }),
mkdir(join(helper, 'MacOS'), { recursive: true })
])
const systemVersion = join(root, 'SystemVersion.plist')
await writeFile(
systemVersion,
`<plist><dict>\n<key>ProductVersion</key>\n<string>${version}</string>\n</dict></plist>\n`
)
await writeFile(
join(helper, 'Info.plist'),
'<plist><dict>\n<key>LSMinimumSystemVersion</key>\n<string>13.5</string>\n</dict></plist>\n'
)
const shim = await readFile(join(__dirname, '../../../../resources/darwin/bin/orca'), 'utf8')
const launcher = join(bin, 'orca')
await writeFile(
launcher,
shim.replace('/System/Library/CoreServices/SystemVersion.plist', systemVersion)
)
for (const [path, name] of [
[join(contents, 'MacOS', 'Orca'), 'electron'],
[join(helper, 'MacOS', 'Orca Agents'), 'node']
]) {
await writeFile(
path,
`#!/bin/sh\nprintf '%s\\n' '${name}' "$@" "NODE_OPTIONS:\${NODE_OPTIONS-unset}" "ORCA_NODE_OPTIONS:\${ORCA_NODE_OPTIONS-unset}"\n`
)
await chmod(path, name === 'node' && !executable ? 0o644 : 0o755)
}
const result = await run('/bin/bash', [launcher, 'status', '--json'], {
env: {
PATH: '/usr/bin:/bin',
HOME: root,
NODE_OPTIONS: '--max-old-space-size=2048',
ORCA_BACKGROUND_LAUNCH: '1'
}
})
expect(result.stdout.split('\n')).toEqual([
runtime,
join(contents, 'Resources', 'app.asar.unpacked', 'out', 'cli', 'index.js'),
'status',
'--json',
'NODE_OPTIONS:unset',
'ORCA_NODE_OPTIONS:--max-old-space-size=2048',
''
])
}
)