diff --git a/src/main/ipc/pty.test.ts b/src/main/ipc/pty.test.ts index a4ff2845b32..b04550084cc 100644 --- a/src/main/ipc/pty.test.ts +++ b/src/main/ipc/pty.test.ts @@ -18,8 +18,8 @@ import { PtyWriteUnavailableError } from '../providers/pty-write-unavailable-err const isWindowsHost = process.platform === 'win32' const posixOnlyIt = isWindowsHost ? it.skip : it const expectedOmpStatusExtension = posix.join( - '/tmp/orca-user-data', - 'omp-managed-status-extension', + '/tmp/default-omp-agent', + 'extensions', 'orca-agent-status.ts' ) function expectedAttributionShimDir(): string { @@ -413,31 +413,15 @@ describe('registerPtyHandlers', () => { ORCA_AGENT_HOOK_TOKEN: 'agent-token' }) piBuildPtyEnvMock.mockImplementation( - ( - _ptyId: string, - existingAgentDir?: string, - kind?: string, - options?: { materializeDefaultHome?: boolean } - ) => { - if (kind === 'omp') { - if (!existingAgentDir && options?.materializeDefaultHome === false) { - return { - ORCA_OMP_STATUS_EXTENSION: - '/tmp/orca-user-data/omp-managed-status-extension/orca-agent-status.ts' + (_ptyId: string, existingAgentDir?: string, kind?: string) => + kind === 'omp' + ? { + ORCA_OMP_SOURCE_AGENT_DIR: existingAgentDir ?? '/tmp/default-omp-agent', + ORCA_OMP_STATUS_EXTENSION: `${existingAgentDir ?? '/tmp/default-omp-agent'}/extensions/orca-agent-status.ts` + } + : { + ORCA_PI_SOURCE_AGENT_DIR: existingAgentDir ?? '/tmp/default-pi-agent' } - } - return { - ORCA_OMP_SOURCE_AGENT_DIR: existingAgentDir ?? '/tmp/default-omp-agent', - ORCA_OMP_STATUS_EXTENSION: `${existingAgentDir ?? '/tmp/default-omp-agent'}/extensions/orca-agent-status.ts` - } - } - if (!existingAgentDir && options?.materializeDefaultHome === false) { - return {} - } - return { - ORCA_PI_SOURCE_AGENT_DIR: existingAgentDir ?? '/tmp/default-pi-agent' - } - } ) isPwshAvailableMock.mockReturnValue(false) spawnMock.mockReturnValue({ @@ -2440,21 +2424,15 @@ describe('registerPtyHandlers', () => { it('installs Pi managed extensions without redirecting Orca terminal PTY homes', async () => { const env = await spawnAndGetEnv(undefined, { PI_CODING_AGENT_DIR: '/tmp/user-pi-agent' }) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith( - expect.any(String), - '/tmp/user-pi-agent', - 'pi', - { materializeDefaultHome: false } - ) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'omp', { - materializeDefaultHome: false - }) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), '/tmp/user-pi-agent', 'pi') + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'omp') expect(env.PI_CODING_AGENT_DIR).toBe('/tmp/user-pi-agent') expect(env.ORCA_PI_CODING_AGENT_DIR).toBeUndefined() expect(env.ORCA_PI_SOURCE_AGENT_DIR).toBe('/tmp/user-pi-agent') expect(env.ORCA_OMP_CODING_AGENT_DIR).toBeUndefined() - expect(env.ORCA_OMP_STATUS_EXTENSION).toBe(expectedOmpStatusExtension) - expect(env.ORCA_OMP_SOURCE_AGENT_DIR).toBeUndefined() + expect(env.ORCA_OMP_STATUS_EXTENSION).toBe( + '/tmp/default-omp-agent/extensions/orca-agent-status.ts' + ) }) it('threads command: "omp" through to piBuildPtyEnv and emits OMP status metadata', async () => { @@ -2469,8 +2447,7 @@ describe('registerPtyHandlers', () => { expect(piBuildPtyEnvMock).toHaveBeenCalledWith( expect.any(String), '/tmp/user-omp-agent', - 'omp', - { materializeDefaultHome: true } + 'omp' ) expect(env.PI_CODING_AGENT_DIR).toBe('/tmp/user-omp-agent') expect(env.ORCA_OMP_CODING_AGENT_DIR).toBeUndefined() @@ -2498,8 +2475,7 @@ describe('registerPtyHandlers', () => { expect(piBuildPtyEnvMock).toHaveBeenCalledWith( expect.any(String), '/tmp/user-omp-agent', - 'omp', - { materializeDefaultHome: true } + 'omp' ) expect(env.ORCA_OMP_STATUS_EXTENSION).toBe( '/tmp/user-omp-agent/extensions/orca-agent-status.ts' @@ -2512,12 +2488,7 @@ describe('registerPtyHandlers', () => { PI_CODING_AGENT_DIR: '/tmp/parent-orca-pi-overlay', ORCA_PI_SOURCE_AGENT_DIR: '/tmp/user-pi-agent' }) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith( - expect.any(String), - '/tmp/user-pi-agent', - 'pi', - { materializeDefaultHome: false } - ) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), '/tmp/user-pi-agent', 'pi') expect(env.PI_CODING_AGENT_DIR).toBe('/tmp/parent-orca-pi-overlay') expect(env.ORCA_PI_CODING_AGENT_DIR).toBeUndefined() expect(env.ORCA_PI_SOURCE_AGENT_DIR).toBe('/tmp/user-pi-agent') @@ -2536,9 +2507,7 @@ describe('registerPtyHandlers', () => { 'omp' ) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'omp', { - materializeDefaultHome: true - }) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'omp') expect(env.ORCA_OMP_CODING_AGENT_DIR).toBeUndefined() expect(env.ORCA_OMP_SOURCE_AGENT_DIR).toBe('/tmp/default-omp-agent') expect(env.ORCA_PI_CODING_AGENT_DIR).toBeUndefined() @@ -2558,9 +2527,7 @@ describe('registerPtyHandlers', () => { 'pi' ) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'pi', { - materializeDefaultHome: true - }) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'pi') expect(env.ORCA_PI_CODING_AGENT_DIR).toBeUndefined() expect(env.ORCA_PI_SOURCE_AGENT_DIR).toBe('/tmp/default-pi-agent') expect(env.ORCA_OMP_CODING_AGENT_DIR).toBeUndefined() @@ -2602,8 +2569,7 @@ describe('registerPtyHandlers', () => { expect(piBuildPtyEnvMock).toHaveBeenCalledWith( expect.any(String), '/home/tester/.config/pi-agent', - 'pi', - { materializeDefaultHome: false } + 'pi' ) expect(env.PI_CODING_AGENT_DIR).toBeUndefined() expect(env.ORCA_PI_CODING_AGENT_DIR).toBeUndefined() @@ -3005,15 +2971,8 @@ describe('registerPtyHandlers', () => { it('installs Pi managed extensions without redirecting homes on the daemon path', async () => { const env = await daemonSpawnAndGetEnv({ PI_CODING_AGENT_DIR: '/user/.pi/agent' }) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith( - expect.any(String), - '/user/.pi/agent', - 'pi', - { materializeDefaultHome: false } - ) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'omp', { - materializeDefaultHome: false - }) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), '/user/.pi/agent', 'pi') + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(expect.any(String), undefined, 'omp') expect(env.PI_CODING_AGENT_DIR).toBe('/user/.pi/agent') expect(env.ORCA_PI_CODING_AGENT_DIR).toBeUndefined() expect(env.ORCA_PI_SOURCE_AGENT_DIR).toBe('/user/.pi/agent') @@ -3033,8 +2992,7 @@ describe('registerPtyHandlers', () => { expect(piBuildPtyEnvMock).toHaveBeenCalledWith( expect.any(String), '/user/.omp/agent', - 'omp', - { materializeDefaultHome: true } + 'omp' ) expect(env.PI_CODING_AGENT_DIR).toBe('/user/.omp/agent') expect(env.ORCA_OMP_CODING_AGENT_DIR).toBeUndefined() @@ -3061,8 +3019,7 @@ describe('registerPtyHandlers', () => { expect(piBuildPtyEnvMock).toHaveBeenCalledWith( expect.any(String), '/user/.omp/agent', - 'omp', - { materializeDefaultHome: true } + 'omp' ) expect(env.ORCA_OMP_STATUS_EXTENSION).toBe( '/user/.omp/agent/extensions/orca-agent-status.ts' @@ -4003,9 +3960,7 @@ describe('registerPtyHandlers', () => { expect(sessionId).toEqual(expect.any(String)) expect((sessionId ?? '').length).toBeGreaterThan(0) expect(spawnOpts.isNewSession).toBe(true) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith(sessionId, undefined, 'pi', { - materializeDefaultHome: false - }) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(sessionId, undefined, 'pi') }) it('respects a caller-provided sessionId instead of minting a new one', async () => { @@ -4020,9 +3975,7 @@ describe('registerPtyHandlers', () => { }) expect(daemonSpawn.mock.calls.at(-1)![0].sessionId).toBe('user-session-42') expect(daemonSpawn.mock.calls.at(-1)![0].isNewSession).toBeUndefined() - expect(piBuildPtyEnvMock).toHaveBeenCalledWith('user-session-42', undefined, 'pi', { - materializeDefaultHome: false - }) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith('user-session-42', undefined, 'pi') }) it('prefixes a minted sessionId with the worktreeId when provided', async () => { @@ -4038,9 +3991,7 @@ describe('registerPtyHandlers', () => { }) const sessionId = daemonSpawn.mock.calls.at(-1)![0].sessionId ?? '' expect(sessionId).toMatch(/^wt-alpha@@[0-9a-f]{8}$/) - expect(piBuildPtyEnvMock).toHaveBeenCalledWith(sessionId, undefined, 'pi', { - materializeDefaultHome: false - }) + expect(piBuildPtyEnvMock).toHaveBeenCalledWith(sessionId, undefined, 'pi') }) it('reuses one attach-style daemon session for fresh-agent operation retries', async () => { @@ -4119,8 +4070,7 @@ describe('registerPtyHandlers', () => { expect(piBuildPtyEnvMock).toHaveBeenCalledWith( expect.any(String), '/ambient/pi/agent', - 'pi', - { materializeDefaultHome: false } + 'pi' ) expect(env.PI_CODING_AGENT_DIR).toBeUndefined() expect(env.ORCA_PI_CODING_AGENT_DIR).toBeUndefined() @@ -8906,13 +8856,11 @@ describe('registerPtyHandlers', () => { 'ORCA_CLI_COMMAND/u', 'ORCA_AGENT_HOOK_PORT/u', 'ORCA_AGENT_HOOK_TOKEN/u', + 'ORCA_OMP_SOURCE_AGENT_DIR/p', 'ORCA_OMP_STATUS_EXTENSION/p', 'POWERLEVEL9K_DISABLE_CONFIGURATION_WIZARD' ]) ) - expect(env.WSLENV?.split(':')).not.toEqual( - expect.arrayContaining(['ORCA_OMP_SOURCE_AGENT_DIR/p']) - ) }) it('forces managed ORCA_USER_DATA_PATH for WSL spawns even when the caller provides a stale root', async () => { diff --git a/src/main/ipc/pty.ts b/src/main/ipc/pty.ts index fdaa2c69f37..3d3c4811747 100644 --- a/src/main/ipc/pty.ts +++ b/src/main/ipc/pty.ts @@ -1166,17 +1166,13 @@ export function buildPtyHostEnv( clearPiAgentShadowEnv(baseEnv, 'pi') clearPiAgentShadowEnv(baseEnv, 'omp') if (piAgentKind === 'pi') { - const piEnv = piTitlebarExtensionService.buildPtyEnv(id, preexistingPiAgentDir, 'pi', { - materializeDefaultHome: hasLaunchCommand - }) + const piEnv = piTitlebarExtensionService.buildPtyEnv(id, preexistingPiAgentDir, 'pi') Object.assign(baseEnv, piEnv) exposePiManagedExtensionEnv(baseEnv, 'pi', piEnv) } if (shouldPrepareOmpShadow) { - const ompEnv = piTitlebarExtensionService.buildPtyEnv(id, preexistingOmpAgentDir, 'omp', { - materializeDefaultHome: piAgentKind === 'omp' - }) + const ompEnv = piTitlebarExtensionService.buildPtyEnv(id, preexistingOmpAgentDir, 'omp') Object.assign(baseEnv, ompEnv) exposePiManagedExtensionEnv(baseEnv, 'omp', ompEnv) } diff --git a/src/main/pi/titlebar-extension-service.test.ts b/src/main/pi/titlebar-extension-service.test.ts index 43af655aa1f..7516f04dad9 100644 --- a/src/main/pi/titlebar-extension-service.test.ts +++ b/src/main/pi/titlebar-extension-service.test.ts @@ -643,35 +643,6 @@ describe('PiTitlebarExtensionService', () => { rmSync(fakeHome, { recursive: true, force: true }) } }) - - it('bare-shell prep does not create missing ~/.pi or ~/.omp homes (#10196)', () => { - const fakeHome = mkdtempSync(join(tmpdir(), 'orca-no-eager-agent-home-')) - expect(existsSync(join(fakeHome, '.pi'))).toBe(false) - expect(existsSync(join(fakeHome, '.omp'))).toBe(false) - - homedirOverride.current = fakeHome - try { - const svc = new PiTitlebarExtensionService() - const piEnv = svc.buildPtyEnv('pty-bare-pi', undefined, 'pi', { - materializeDefaultHome: false - }) - const ompEnv = svc.buildPtyEnv('pty-bare-omp', undefined, 'omp', { - materializeDefaultHome: false - }) - - expect(piEnv).toEqual({}) - expect(existsSync(join(fakeHome, '.pi'))).toBe(false) - expect(existsSync(join(fakeHome, '.omp'))).toBe(false) - expect(ompEnv.ORCA_OMP_SOURCE_AGENT_DIR).toBeUndefined() - expect(ompEnv.ORCA_OMP_STATUS_EXTENSION).toEqual( - expect.stringContaining('omp-managed-status-extension') - ) - expect(existsSync(ompEnv.ORCA_OMP_STATUS_EXTENSION!)).toBe(true) - } finally { - homedirOverride.current = '' - rmSync(fakeHome, { recursive: true, force: true }) - } - }) }) describe('isSafeDescendCandidate (Windows junction regression guard)', () => { diff --git a/src/main/pi/titlebar-extension-service.ts b/src/main/pi/titlebar-extension-service.ts index 4012e219c26..37d030b5e31 100644 --- a/src/main/pi/titlebar-extension-service.ts +++ b/src/main/pi/titlebar-extension-service.ts @@ -169,8 +169,7 @@ export class PiTitlebarExtensionService { buildPtyEnv( ptyId: string, existingAgentDir: string | undefined, - kind: PiAgentKind, - options?: { materializeDefaultHome?: boolean } + kind: PiAgentKind ): Record { const sourceAgentDir = existingAgentDir || getDefaultPiAgentDir(kind) try { @@ -181,15 +180,6 @@ export class PiTitlebarExtensionService { // directory should not prevent the terminal from starting. } - if (!existsSync(sourceAgentDir) && options?.materializeDefaultHome === false) { - if (kind === 'omp') { - const statusSource = withOrcaManagedExtensionMarker(getPiAgentStatusExtensionSource(kind)) - const statusExtensionPath = this.writeOmpFallbackStatusExtension(statusSource) - return statusExtensionPath ? { ORCA_OMP_STATUS_EXTENSION: statusExtensionPath } : {} - } - return {} - } - if (kind === 'omp') { migrateLegacyOmpOverlayState(sourceAgentDir, this.getSourceOverlayDir(sourceAgentDir, 'omp')) } diff --git a/src/relay/plugin-overlay.test.ts b/src/relay/plugin-overlay.test.ts index 8ebec60aed2..9b90692cd28 100644 --- a/src/relay/plugin-overlay.test.ts +++ b/src/relay/plugin-overlay.test.ts @@ -72,10 +72,9 @@ describe('PluginOverlayManager', () => { it('installs Pi extension into the real agent extensions dir', () => { manager.setSources({ piExtensionSource: '// pi extension' }) - const result = manager.materializePi('tab-2:0') - expect(result?.sourceAgentDir).toBeDefined() - const file = join(result!.sourceAgentDir!, 'extensions', 'orca-agent-status.ts') - expect(result?.statusExtensionPath).toBe(file) + const dir = manager.materializePi('tab-2:0') + expect(dir).not.toBeNull() + const file = join(dir!, 'extensions', 'orca-agent-status.ts') expect(existsSync(file)).toBe(true) expect(readFileSync(file, 'utf8')).toContain('@orca-managed-pi-extension') }) @@ -97,17 +96,17 @@ describe('PluginOverlayManager', () => { ompExtensionSource: '// omp extension' }) - const piResult = manager.materializePi('tab-kind-pi:0', undefined, 'pi') - const ompResult = manager.materializePi('tab-kind-omp:0', undefined, 'omp') + const piDir = manager.materializePi('tab-kind-pi:0', undefined, 'pi') + const ompDir = manager.materializePi('tab-kind-omp:0', undefined, 'omp') - expect(piResult?.sourceAgentDir).toBeDefined() - expect(ompResult?.sourceAgentDir).toBeDefined() - expect( - readFileSync(join(piResult!.sourceAgentDir!, 'extensions', 'orca-agent-status.ts'), 'utf8') - ).toContain('// pi extension') - expect( - readFileSync(join(ompResult!.sourceAgentDir!, 'extensions', 'orca-agent-status.ts'), 'utf8') - ).toContain('// omp extension') + expect(piDir).not.toBeNull() + expect(ompDir).not.toBeNull() + expect(readFileSync(join(piDir!, 'extensions', 'orca-agent-status.ts'), 'utf8')).toContain( + '// pi extension' + ) + expect(readFileSync(join(ompDir!, 'extensions', 'orca-agent-status.ts'), 'utf8')).toContain( + '// omp extension' + ) }) it('installs Orca status extension into the remote default Pi agent dir', () => { @@ -130,10 +129,9 @@ describe('PluginOverlayManager', () => { ) manager.setSources({ piExtensionSource: '// pi extension' }) - const result = manager.materializePi('tab-pi:0') - const dir = result?.sourceAgentDir + const dir = manager.materializePi('tab-pi:0') - expect(dir).toBeDefined() + expect(dir).not.toBeNull() expect(readFileSync(join(dir!, 'auth.json'), 'utf8')).toBe('secret token') expect(readFileSync(join(dir!, 'skills', 'my-skill', 'SKILL.md'), 'utf8')).toBe( 'critical user skill' @@ -173,10 +171,9 @@ describe('PluginOverlayManager', () => { writeFileSync(join(customAgentDir, 'extensions', 'custom.ts'), 'custom extension') manager.setSources({ piExtensionSource: '// pi extension' }) - const result = manager.materializePi('tab-custom-pi:0', customAgentDir) - const dir = result?.sourceAgentDir + const dir = manager.materializePi('tab-custom-pi:0', customAgentDir) - expect(dir).toBeDefined() + expect(dir).not.toBeNull() expect(readFileSync(join(dir!, 'auth.json'), 'utf8')).toBe('custom token') expect(readFileSync(join(dir!, 'extensions', 'custom.ts'), 'utf8')).toBe('custom extension') expect(readFileSync(join(dir!, 'extensions', 'orca-agent-status.ts'), 'utf8')).toContain( @@ -187,9 +184,10 @@ describe('PluginOverlayManager', () => { it('leaves lazy OMP agent.db in the real remote home on the relay', () => { manager.setSources({ piExtensionSource: '// pi extension' }) const sourceDir = join(homeDir, '.omp', 'agent') - const first = manager.materializePi('tab-relay-omp-sqlite:0', undefined, 'omp') + const firstDir = manager.materializePi('tab-relay-omp-sqlite:0', undefined, 'omp') - expect(first?.sourceAgentDir).toBe(sourceDir) + expect(firstDir).not.toBeNull() + expect(firstDir).toBe(sourceDir) const sourcePath = join(sourceDir, 'agent.db') const content = 'agent.db relay credentials' @@ -200,10 +198,10 @@ describe('PluginOverlayManager', () => { expect(readFileSync(sourcePath, 'utf8')).toBe(content) - const second = manager.materializePi('tab-relay-omp-sqlite:0', undefined, 'omp') + const secondDir = manager.materializePi('tab-relay-omp-sqlite:0', undefined, 'omp') - expect(second?.sourceAgentDir).toBe(first?.sourceAgentDir) - expect(readFileSync(join(second!.sourceAgentDir!, 'agent.db'), 'utf8')).toBe(content) + expect(secondDir).toBe(firstDir) + expect(readFileSync(join(secondDir!, 'agent.db'), 'utf8')).toBe(content) }) // Why: per-agent source dir. The renderer picks Pi or OMP per @@ -224,9 +222,9 @@ describe('PluginOverlayManager', () => { seedAgentDir('.omp', 'omp') manager.setSources({ piExtensionSource: '// pi extension' }) - const result = manager.materializePi('tab-relay-pi-both:0', undefined, 'pi') - const dir = result?.sourceAgentDir + const dir = manager.materializePi('tab-relay-pi-both:0', undefined, 'pi') + expect(dir).not.toBeNull() expect(dir).toBe(join(homeDir, '.pi', 'agent')) expect(readFileSync(join(dir!, 'auth.json'), 'utf8')).toBe('pi token') const extensions = readdirSync(join(dir!, 'extensions')).sort() @@ -240,9 +238,9 @@ describe('PluginOverlayManager', () => { seedAgentDir('.omp', 'omp') manager.setSources({ piExtensionSource: '// pi extension' }) - const result = manager.materializePi('tab-relay-omp-both:0', undefined, 'omp') - const dir = result?.sourceAgentDir + const dir = manager.materializePi('tab-relay-omp-both:0', undefined, 'omp') + expect(dir).not.toBeNull() expect(dir).toBe(join(homeDir, '.omp', 'agent')) // Even though ~/.pi/agent exists, the OMP launch MUST mirror OMP's // source dir. Cross-agent fallback would silently shadow the user's @@ -261,41 +259,15 @@ describe('PluginOverlayManager', () => { expect(existsSync(join(homeDir, '.omp'))).toBe(false) manager.setSources({ piExtensionSource: '// pi extension' }) - const result = manager.materializePi('tab-relay-omp-empty:0', undefined, 'omp') - const dir = result?.sourceAgentDir + const dir = manager.materializePi('tab-relay-omp-empty:0', undefined, 'omp') + expect(dir).not.toBeNull() expect(dir).toBe(join(homeDir, '.omp', 'agent')) // Pi-only home must NOT leak into the OMP home. expect(existsSync(join(dir!, 'auth.json'))).toBe(false) const extensions = readdirSync(join(dir!, 'extensions')).sort() expect(extensions).toEqual(['orca-agent-status.ts']) }) - - it('bare-shell prep does not create missing remote agent homes (#10196)', () => { - expect(existsSync(join(homeDir, '.pi'))).toBe(false) - expect(existsSync(join(homeDir, '.omp'))).toBe(false) - manager.setSources({ - piExtensionSource: '// pi extension', - ompExtensionSource: '// omp extension' - }) - - expect( - manager.materializePi('tab-bare-pi:0', undefined, 'pi', { - materializeDefaultHome: false - }) - ).toBeNull() - const bareOmp = manager.materializePi('tab-bare-omp:0', undefined, 'omp', { - materializeDefaultHome: false - }) - expect(bareOmp?.sourceAgentDir).toBeUndefined() - expect(bareOmp?.statusExtensionPath).toEqual( - expect.stringContaining(join('.orca-relay', 'omp-managed-status-extension')) - ) - expect(existsSync(bareOmp!.statusExtensionPath!)).toBe(true) - expect(readFileSync(bareOmp!.statusExtensionPath!, 'utf8')).toContain('// omp extension') - expect(existsSync(join(homeDir, '.pi'))).toBe(false) - expect(existsSync(join(homeDir, '.omp'))).toBe(false) - }) }) it('does not override a missing preexisting Pi agent dir', () => { @@ -311,8 +283,8 @@ describe('PluginOverlayManager', () => { ompExtensionSource: 'omp' }) const opencodeDir = manager.materializeOpenCode('tab-3:0')! - const piDir = manager.materializePi('tab-3:0', undefined, 'pi')!.sourceAgentDir! - const ompDir = manager.materializePi('tab-3:0', undefined, 'omp')!.sourceAgentDir! + const piDir = manager.materializePi('tab-3:0', undefined, 'pi')! + const ompDir = manager.materializePi('tab-3:0', undefined, 'omp')! expect(piDir).not.toBe(ompDir) expect(existsSync(opencodeDir)).toBe(true) expect(existsSync(piDir)).toBe(true) diff --git a/src/relay/plugin-overlay.ts b/src/relay/plugin-overlay.ts index 49e2799e5ed..ada88830bda 100644 --- a/src/relay/plugin-overlay.ts +++ b/src/relay/plugin-overlay.ts @@ -41,7 +41,6 @@ const PI_OVERLAY_SUBDIR_BY_KIND: Record = { const OPENCODE_PLUGIN_FILE = 'orca-opencode-status.js' const PI_EXTENSION_FILE = 'orca-agent-status.ts' const PI_AGENT_SUBDIR = 'agent' -const OMP_MANAGED_STATUS_EXTENSION_DIR = 'omp-managed-status-extension' const ORCA_MANAGED_EXTENSION_MARKER = '@orca-managed-pi-extension' function withOrcaManagedPiExtensionMarker(source: string): string { @@ -80,9 +79,8 @@ export type PluginSources = { ompExtensionSource?: string } -export type MaterializePiResult = { - sourceAgentDir?: string - statusExtensionPath?: string +export function getRelayPiStatusExtensionPath(agentDir: string): string { + return join(agentDir, 'extensions', PI_EXTENSION_FILE) } /** Presence of this file is what makes an overlay usable — a rebuild that failed @@ -238,30 +236,10 @@ export class PluginOverlayManager { } } - private writeOmpManagedStatusExtension(extensionSource: string): string | null { - const fallbackDir = join(this.homeDir, RELAY_HOOKS_DIR, OMP_MANAGED_STATUS_EXTENSION_DIR) - try { - mkdirSync(fallbackDir, { recursive: true }) - const fallbackPath = join(fallbackDir, PI_EXTENSION_FILE) - if (!this.canOverwritePiExtension(fallbackPath)) { - return null - } - writeFileSync(fallbackPath, extensionSource) - return fallbackPath - } catch (err) { - process.stderr.write( - `[plugin-overlay] failed to write OMP managed status extension: ${err instanceof Error ? err.message : String(err)}\n` - ) - return null - } - } - - materializePi( - id: string, - existingAgentDir?: string, - kind: PiAgentKind = 'pi', - options?: { materializeDefaultHome?: boolean } - ): MaterializePiResult | null { + /** Install the Pi/OMP status extension into the remote real agent dir and + * return that directory. `kind` selects which Pi-compatible agent's default + * dir to use when `existingAgentDir` is not supplied. */ + materializePi(id: string, existingAgentDir?: string, kind: PiAgentKind = 'pi'): string | null { const extensionSource = this.getPiExtensionSource(kind) if (!extensionSource || !isUsableId(id)) { return null @@ -271,17 +249,6 @@ export class PluginOverlayManager { if (existingAgentDir && !existsSync(existingAgentDir)) { return null } - if ( - !existingAgentDir && - !existsSync(sourceAgentDir) && - options?.materializeDefaultHome === false - ) { - if (kind === 'omp') { - const statusExtensionPath = this.writeOmpManagedStatusExtension(extensionSource) - return statusExtensionPath ? { statusExtensionPath } : null - } - return null - } const extensionsDir = join(sourceAgentDir, 'extensions') mkdirSync(extensionsDir, { recursive: true }) const extensionPath = join(extensionsDir, PI_EXTENSION_FILE) @@ -289,10 +256,7 @@ export class PluginOverlayManager { return null } writeFileSync(extensionPath, extensionSource) - return { - sourceAgentDir, - statusExtensionPath: extensionPath - } + return sourceAgentDir } catch (err) { process.stderr.write( `[plugin-overlay] failed to install ${kind} extension: ${err instanceof Error ? err.message : String(err)}\n` diff --git a/src/relay/relay.ts b/src/relay/relay.ts index 716641b2dc0..6daf87b309c 100644 --- a/src/relay/relay.ts +++ b/src/relay/relay.ts @@ -33,7 +33,7 @@ import { PortScanHandler } from './port-scan-handler' import { AgentExecHandler } from './agent-exec-handler' import { WorkspaceSessionHandler } from './workspace-session-handler' import { endpointDirForRelaySocket, RelayAgentHookServer } from './agent-hook-server' -import { PluginOverlayManager } from './plugin-overlay' +import { PluginOverlayManager, getRelayPiStatusExtensionPath } from './plugin-overlay' import { AGENT_HOOK_INSTALL_PLUGINS_METHOD, AGENT_HOOK_NOTIFICATION_METHOD, @@ -585,11 +585,9 @@ async function main(): Promise { const shouldPrepareOmpShadow = kind === 'omp' || !hasLaunchCommand if (kind === 'pi') { const sourceDir = resolvePiSourceAgentDir(ctx.env, ctx.shell, 'pi') - const result = pluginOverlay.materializePi(overlayId, sourceDir, 'pi', { - materializeDefaultHome: hasLaunchCommand - }) - if (result?.sourceAgentDir) { - env.ORCA_PI_SOURCE_AGENT_DIR = result.sourceAgentDir + const dir = pluginOverlay.materializePi(overlayId, sourceDir, 'pi') + if (dir) { + env.ORCA_PI_SOURCE_AGENT_DIR = dir } } if (shouldPrepareOmpShadow) { @@ -598,14 +596,10 @@ async function main(): Promise { kind === 'omp' ? resolvePiSourceAgentDir(ctx.env, ctx.shell, 'omp') : ctx.env.ORCA_OMP_SOURCE_AGENT_DIR - const result = pluginOverlay.materializePi(overlayId, sourceDir, 'omp', { - materializeDefaultHome: kind === 'omp' - }) - if (result?.statusExtensionPath) { - env.ORCA_OMP_STATUS_EXTENSION = result.statusExtensionPath - } - if (result?.sourceAgentDir) { - env.ORCA_OMP_SOURCE_AGENT_DIR = result.sourceAgentDir + const dir = pluginOverlay.materializePi(overlayId, sourceDir, 'omp') + if (dir) { + env.ORCA_OMP_STATUS_EXTENSION = getRelayPiStatusExtensionPath(dir) + env.ORCA_OMP_SOURCE_AGENT_DIR = dir } } }