mirror of
https://github.com/stablyai/orca.git
synced 2026-10-30 16:47:34 +00:00
fix(mimo): keep MiMo's login and sessions by injecting the status plugin via MIMOCODE_CONFIG_DIR (#33668)
Co-authored-by: BluesYoung-web <55608642+BluesYoung-web@users.noreply.github.com>
This commit is contained in:
@@ -42,7 +42,7 @@ if [[ -n "${ORCA_DATA_ACCOUNT_DATA_HOME:-}" ]]; then
|
||||
export OPENCODE_DB="opencode.db"
|
||||
fi
|
||||
fi
|
||||
[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
# Why: OMP does not auto-load Orca's managed status extension; wrap only
|
||||
# interactive launch invocations so subcommands such as `omp config` keep
|
||||
# their normal argv shape.
|
||||
|
||||
@@ -118,7 +118,7 @@ __orca_deferred_init() {
|
||||
export OPENCODE_DB="opencode.db"
|
||||
fi
|
||||
fi
|
||||
[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
# Why: OMP does not auto-load Orca's managed status extension; wrap only
|
||||
# interactive launch invocations so subcommands such as `omp config` keep
|
||||
# their normal argv shape.
|
||||
|
||||
@@ -50,7 +50,7 @@ if [[ -n "${ORCA_DATA_ACCOUNT_DATA_HOME:-}" ]]; then
|
||||
export OPENCODE_DB="opencode.db"
|
||||
fi
|
||||
fi
|
||||
[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
# Why: OMP does not auto-load Orca's managed status extension; wrap only
|
||||
# interactive launch invocations so subcommands such as `omp config` keep
|
||||
# their normal argv shape.
|
||||
|
||||
@@ -125,7 +125,7 @@ __orca_deferred_init() {
|
||||
export OPENCODE_DB="opencode.db"
|
||||
fi
|
||||
fi
|
||||
[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
# Why: OMP does not auto-load Orca's managed status extension; wrap only
|
||||
# interactive launch invocations so subcommands such as `omp config` keep
|
||||
# their normal argv shape.
|
||||
|
||||
@@ -24,7 +24,7 @@ fi
|
||||
[[ $- == *i* ]] && bind 'set enable-bracketed-paste on' 2>/dev/null
|
||||
# Why: remote startup files can re-export user defaults after relay spawn.
|
||||
[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}"
|
||||
[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
[[ -n "${ORCA_REMOTE_CLI_BIN_DIR:-}" ]] && case ":$PATH:" in *:"${ORCA_REMOTE_CLI_BIN_DIR}":*) ;; *) export PATH="${ORCA_REMOTE_CLI_BIN_DIR}:$PATH" ;; esac
|
||||
if [ -n "${ORCA_CLI_BIN_DIR:-}" ]; then
|
||||
case "${PATH:-}" in
|
||||
|
||||
@@ -100,7 +100,7 @@ __orca_deferred_init() {
|
||||
export OPENCODE_DB="opencode.db"
|
||||
fi
|
||||
fi
|
||||
[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
[[ -n "${ORCA_REMOTE_CLI_BIN_DIR:-}" ]] && case ":$PATH:" in *:"${ORCA_REMOTE_CLI_BIN_DIR}":*) ;; *) export PATH="${ORCA_REMOTE_CLI_BIN_DIR}:$PATH" ;; esac
|
||||
# Why: OMP does not auto-load Orca's managed status extension; wrap only
|
||||
# interactive launch invocations so subcommands such as `omp config` keep
|
||||
|
||||
@@ -37,7 +37,7 @@ ${ORCA_CLI_POSIX_PATH_RESTORE}
|
||||
# Restore the managed OpenCode config after user profiles may have replaced it.
|
||||
[[ -n "\${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="\${ORCA_OPENCODE_CONFIG_DIR}"
|
||||
${MANAGED_DATA_ACCOUNT_POSIX_RESTORE}
|
||||
[[ -n "\${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="\${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "\${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="\${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
${getPosixOmpShellWrapper()}
|
||||
# Preserve the managed CODEX_HOME after user profiles.
|
||||
[[ -n "\${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="\${ORCA_CODEX_HOME}"
|
||||
|
||||
@@ -151,8 +151,8 @@ describe('createPtySubprocess', () => {
|
||||
rows: 24,
|
||||
env: {
|
||||
SHELL: '/bin/zsh',
|
||||
MIMOCODE_HOME: '/tmp/orca-mimocode-overlay',
|
||||
ORCA_MIMOCODE_HOME: '/tmp/orca-mimocode-overlay'
|
||||
MIMOCODE_CONFIG_DIR: '/tmp/orca-mimocode-overlay',
|
||||
ORCA_MIMOCODE_CONFIG_DIR: '/tmp/orca-mimocode-overlay'
|
||||
}
|
||||
})
|
||||
} finally {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { join } from 'node:path'
|
||||
|
||||
const ORCA_SHELL_WRAPPER_ENV = [
|
||||
'ORCA_OPENCODE_CONFIG_DIR',
|
||||
'ORCA_MIMOCODE_HOME',
|
||||
'ORCA_MIMOCODE_CONFIG_DIR',
|
||||
'ORCA_PI_CODING_AGENT_DIR',
|
||||
'ORCA_OMP_CODING_AGENT_DIR',
|
||||
'ORCA_OMP_STATUS_EXTENSION',
|
||||
|
||||
@@ -552,7 +552,7 @@ describePosix('daemon shell-ready launch config', () => {
|
||||
const restoreLine =
|
||||
'[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}"'
|
||||
const mimoRestoreLine =
|
||||
'[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"'
|
||||
'[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"'
|
||||
const codexRestoreLine =
|
||||
'[[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}"'
|
||||
const agentTeamsPathRestoreLine = '[[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0'
|
||||
|
||||
@@ -123,9 +123,10 @@ export const openCodeHookServiceModuleMock = () => ({
|
||||
})
|
||||
|
||||
export const mimoHookServiceModuleMock = (): {
|
||||
mimoCodeHookService: { buildPtyEnv: Mock }
|
||||
mimoCodeHookService: { carryOverLegacyAuth: Mock; buildPtyEnv: Mock }
|
||||
} => ({
|
||||
mimoCodeHookService: {
|
||||
carryOverLegacyAuth: vi.fn(),
|
||||
buildPtyEnv: mimoCodeBuildPtyEnvMock
|
||||
}
|
||||
})
|
||||
|
||||
@@ -221,8 +221,10 @@ export function createPtyIpcSuiteEnvironment(): PtyIpcSuiteEnvironment {
|
||||
? '/tmp/orca-opencode2-overlay'
|
||||
: '/tmp/orca-opencode2-config'
|
||||
}))
|
||||
mimoCodeBuildPtyEnvMock.mockImplementation((_ptyId: string, existingHome?: string) => ({
|
||||
MIMOCODE_HOME: existingHome ? '/tmp/orca-mimocode-overlay' : '/tmp/orca-mimocode-shared'
|
||||
mimoCodeBuildPtyEnvMock.mockImplementation((_ptyId: string, existingConfigDir?: string) => ({
|
||||
MIMOCODE_CONFIG_DIR: existingConfigDir
|
||||
? '/tmp/orca-mimocode-overlay'
|
||||
: '/tmp/orca-mimocode-shared'
|
||||
}))
|
||||
buildAgentHookEnvMock.mockReturnValue({
|
||||
ORCA_AGENT_HOOK_PORT: '5678',
|
||||
|
||||
@@ -26,7 +26,7 @@ import {
|
||||
clearPiAgentShadowEnv,
|
||||
exposePiManagedExtensionEnv,
|
||||
isMimoLaunchCommand,
|
||||
resolveMimocodeSourceHome,
|
||||
resolveMimocodeSourceConfigDir,
|
||||
resolvePiAgentSourceDir,
|
||||
resolveScopedPiAgentSourceDir
|
||||
} from './pi-agent'
|
||||
@@ -100,25 +100,29 @@ export function buildPtyHostEnv(
|
||||
opts,
|
||||
launchCommandHint
|
||||
)
|
||||
if (opts.agentStatusHooksEnabled) {
|
||||
if (isMimoLaunchCommand(launchCommandHint)) {
|
||||
const preexistingMimocodeHome = resolveMimocodeSourceHome(baseEnv)
|
||||
Object.assign(baseEnv, mimoCodeHookService.buildPtyEnv(id, preexistingMimocodeHome))
|
||||
if (baseEnv.MIMOCODE_HOME) {
|
||||
baseEnv.ORCA_MIMOCODE_HOME = baseEnv.MIMOCODE_HOME
|
||||
if (preexistingMimocodeHome) {
|
||||
baseEnv.ORCA_MIMOCODE_SOURCE_HOME = preexistingMimocodeHome
|
||||
} else {
|
||||
delete baseEnv.ORCA_MIMOCODE_SOURCE_HOME
|
||||
}
|
||||
// Older builds redirected MIMOCODE_HOME; a nested pane must not inherit that overlay.
|
||||
restoreOrStripOverlayEnv(baseEnv, {
|
||||
primary: 'MIMOCODE_HOME',
|
||||
overlay: 'ORCA_MIMOCODE_HOME',
|
||||
source: 'ORCA_MIMOCODE_SOURCE_HOME'
|
||||
})
|
||||
restoreOrStripOverlayEnv(baseEnv, {
|
||||
primary: 'MIMOCODE_CONFIG_DIR',
|
||||
overlay: 'ORCA_MIMOCODE_CONFIG_DIR',
|
||||
source: 'ORCA_MIMOCODE_SOURCE_CONFIG_DIR',
|
||||
preserveExplicitPrimary: true
|
||||
})
|
||||
const mimoSourceConfigDir = resolveMimocodeSourceConfigDir(baseEnv)
|
||||
if (opts.agentStatusHooksEnabled && isMimoLaunchCommand(launchCommandHint)) {
|
||||
mimoCodeHookService.carryOverLegacyAuth({ ...process.env, ...baseEnv })
|
||||
const overlay = mimoCodeHookService.buildPtyEnv(id, mimoSourceConfigDir).MIMOCODE_CONFIG_DIR
|
||||
if (overlay && overlay !== mimoSourceConfigDir) {
|
||||
baseEnv.MIMOCODE_CONFIG_DIR = overlay
|
||||
baseEnv.ORCA_MIMOCODE_CONFIG_DIR = overlay
|
||||
if (mimoSourceConfigDir) {
|
||||
baseEnv.ORCA_MIMOCODE_SOURCE_CONFIG_DIR = mimoSourceConfigDir
|
||||
}
|
||||
}
|
||||
} else {
|
||||
restoreOrStripOverlayEnv(baseEnv, {
|
||||
primary: 'MIMOCODE_HOME',
|
||||
overlay: 'ORCA_MIMOCODE_HOME',
|
||||
source: 'ORCA_MIMOCODE_SOURCE_HOME'
|
||||
})
|
||||
}
|
||||
|
||||
// Remove inherited hook coordinates before injecting the owning pane's receiver.
|
||||
|
||||
@@ -136,7 +136,9 @@ export function getInheritedAgentHookEnvKeysToDelete(
|
||||
'ORCA_CLAUDE_CONFIG_DIR',
|
||||
'ORCA_OPENCODE_AGENT',
|
||||
'ORCA_OPENCODE_CONFIG_DIR',
|
||||
'ORCA_OPENCODE_SOURCE_CONFIG_DIR'
|
||||
'ORCA_OPENCODE_SOURCE_CONFIG_DIR',
|
||||
'ORCA_MIMOCODE_CONFIG_DIR',
|
||||
'ORCA_MIMOCODE_SOURCE_CONFIG_DIR'
|
||||
].filter((key) => env[key] === undefined)
|
||||
}
|
||||
|
||||
@@ -155,17 +157,19 @@ export function isMimoLaunchCommand(launchCommand: string | undefined): boolean
|
||||
return getAgentLaunchExecutableName(launchCommand) === 'mimo'
|
||||
}
|
||||
|
||||
export function resolveMimocodeSourceHome(baseEnv: Record<string, string>): string | undefined {
|
||||
const sourceHome = baseEnv.ORCA_MIMOCODE_SOURCE_HOME ?? process.env.ORCA_MIMOCODE_SOURCE_HOME
|
||||
if (sourceHome) {
|
||||
return sourceHome
|
||||
/** Call after the overlay env is restored: an explicit pane value wins over inherited markers. */
|
||||
export function resolveMimocodeSourceConfigDir(
|
||||
baseEnv: Record<string, string>,
|
||||
inheritedEnv: NodeJS.ProcessEnv = process.env
|
||||
): string | undefined {
|
||||
if (baseEnv.MIMOCODE_CONFIG_DIR) {
|
||||
return baseEnv.MIMOCODE_CONFIG_DIR
|
||||
}
|
||||
const configHome = baseEnv.MIMOCODE_HOME ?? process.env.MIMOCODE_HOME
|
||||
const orcaHome = baseEnv.ORCA_MIMOCODE_HOME ?? process.env.ORCA_MIMOCODE_HOME
|
||||
if (configHome && orcaHome && configHome === orcaHome) {
|
||||
return undefined
|
||||
if (inheritedEnv.ORCA_MIMOCODE_SOURCE_CONFIG_DIR) {
|
||||
return inheritedEnv.ORCA_MIMOCODE_SOURCE_CONFIG_DIR
|
||||
}
|
||||
return configHome
|
||||
const configDir = inheritedEnv.MIMOCODE_CONFIG_DIR
|
||||
return configDir && configDir === inheritedEnv.ORCA_MIMOCODE_CONFIG_DIR ? undefined : configDir
|
||||
}
|
||||
|
||||
export function resolveOpenCodeSourceConfigDir(
|
||||
|
||||
@@ -264,9 +264,9 @@ describe('registerPtyHandlers', () => {
|
||||
const env = await spawnAndGetEnv(undefined, undefined, undefined, undefined, 'mimo')
|
||||
|
||||
expect(mimoCodeBuildPtyEnvMock).toHaveBeenCalledTimes(1)
|
||||
expect(env.MIMOCODE_HOME).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_HOME).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_SOURCE_HOME).toBeUndefined()
|
||||
expect(env.MIMOCODE_CONFIG_DIR).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_CONFIG_DIR).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_SOURCE_CONFIG_DIR).toBeUndefined()
|
||||
})
|
||||
it.each([
|
||||
'/usr/local/bin/mimo --prompt hi',
|
||||
@@ -276,8 +276,8 @@ describe('registerPtyHandlers', () => {
|
||||
const env = await spawnAndGetEnv(undefined, undefined, undefined, undefined, launchCommand)
|
||||
|
||||
expect(mimoCodeBuildPtyEnvMock).toHaveBeenCalledTimes(1)
|
||||
expect(env.MIMOCODE_HOME).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_HOME).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.MIMOCODE_CONFIG_DIR).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_CONFIG_DIR).toBe('/tmp/orca-mimocode-shared')
|
||||
})
|
||||
it('uses sequenced startup env as the MiMo launch hint when command is a wrapper', async () => {
|
||||
const env = await spawnAndGetEnv(
|
||||
@@ -289,20 +289,20 @@ describe('registerPtyHandlers', () => {
|
||||
)
|
||||
|
||||
expect(mimoCodeBuildPtyEnvMock).toHaveBeenCalledTimes(1)
|
||||
expect(env.MIMOCODE_HOME).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_HOME).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.MIMOCODE_CONFIG_DIR).toBe('/tmp/orca-mimocode-shared')
|
||||
expect(env.ORCA_MIMOCODE_CONFIG_DIR).toBe('/tmp/orca-mimocode-shared')
|
||||
})
|
||||
it('does not inject MiMo overlay for non-mimo launches', async () => {
|
||||
await spawnAndGetEnv()
|
||||
|
||||
expect(mimoCodeBuildPtyEnvMock).not.toHaveBeenCalled()
|
||||
})
|
||||
it('restores user MiMo home when agent status hooks are disabled in a nested Orca shell', async () => {
|
||||
it('restores user MiMo config dir when agent status hooks are disabled in a nested Orca shell', async () => {
|
||||
const env = await spawnAndGetEnv(
|
||||
{
|
||||
MIMOCODE_HOME: '/tmp/parent-orca-mimocode-overlay',
|
||||
ORCA_MIMOCODE_HOME: '/tmp/parent-orca-mimocode-overlay',
|
||||
ORCA_MIMOCODE_SOURCE_HOME: '/tmp/user-mimocode-home'
|
||||
MIMOCODE_CONFIG_DIR: '/tmp/parent-orca-mimocode-overlay',
|
||||
ORCA_MIMOCODE_CONFIG_DIR: '/tmp/parent-orca-mimocode-overlay',
|
||||
ORCA_MIMOCODE_SOURCE_CONFIG_DIR: '/tmp/user-mimocode-config'
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
@@ -311,9 +311,27 @@ describe('registerPtyHandlers', () => {
|
||||
)
|
||||
|
||||
expect(mimoCodeBuildPtyEnvMock).not.toHaveBeenCalled()
|
||||
expect(env.MIMOCODE_CONFIG_DIR).toBe('/tmp/user-mimocode-config')
|
||||
expect(env.ORCA_MIMOCODE_CONFIG_DIR).toBeUndefined()
|
||||
expect(env.ORCA_MIMOCODE_SOURCE_CONFIG_DIR).toBeUndefined()
|
||||
})
|
||||
it("leaves MiMo's home alone and drops an older build's MIMOCODE_HOME overlay", async () => {
|
||||
const env = await spawnAndGetEnv(
|
||||
{
|
||||
MIMOCODE_HOME: '/tmp/parent-orca-mimocode-home',
|
||||
ORCA_MIMOCODE_HOME: '/tmp/parent-orca-mimocode-home',
|
||||
ORCA_MIMOCODE_SOURCE_HOME: '/tmp/user-mimocode-home'
|
||||
},
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'mimo'
|
||||
)
|
||||
|
||||
expect(env.MIMOCODE_HOME).toBe('/tmp/user-mimocode-home')
|
||||
expect(env.ORCA_MIMOCODE_HOME).toBeUndefined()
|
||||
expect(env.ORCA_MIMOCODE_SOURCE_HOME).toBeUndefined()
|
||||
expect(env.MIMOCODE_CONFIG_DIR).toBe('/tmp/orca-mimocode-shared')
|
||||
})
|
||||
posixOnlyIt(
|
||||
'reproduces issue #1534: GUI-launched Orca mirrors zshrc-only OpenCode config',
|
||||
|
||||
@@ -1,5 +1,15 @@
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
|
||||
import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
|
||||
import {
|
||||
existsSync,
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readFileSync,
|
||||
readdirSync,
|
||||
rmSync,
|
||||
statSync,
|
||||
symlinkSync,
|
||||
writeFileSync
|
||||
} from 'node:fs'
|
||||
import { tmpdir } from 'node:os'
|
||||
import { join } from 'node:path'
|
||||
import { setAppEnvironment } from '../../shared/app-environment'
|
||||
@@ -12,7 +22,7 @@ import { MimoCodeHookService } from './hook-service'
|
||||
|
||||
describe('MimoCodeHookService buildPtyEnv', () => {
|
||||
let userDataDir: string
|
||||
let mimocodeHome: string
|
||||
let userConfigDir: string
|
||||
|
||||
beforeEach(() => {
|
||||
userDataDir = mkdtempSync(join(tmpdir(), 'orca-mimocode-userdata-'))
|
||||
@@ -32,53 +42,109 @@ describe('MimoCodeHookService buildPtyEnv', () => {
|
||||
getAppMetrics: () => []
|
||||
})
|
||||
|
||||
mimocodeHome = mkdtempSync(join(tmpdir(), 'orca-mimocode-home-'))
|
||||
const configDir = join(mimocodeHome, 'config')
|
||||
mkdirSync(join(configDir, 'plugins'), { recursive: true })
|
||||
writeFileSync(join(configDir, 'mimocode.json'), '{"theme":"dark"}')
|
||||
writeFileSync(join(configDir, 'plugins', 'user-plugin.js'), 'export default () => {}')
|
||||
writeFileSync(join(configDir, 'plugins', 'orca-mimocode-status.js'), 'USER PLUGIN')
|
||||
userConfigDir = mkdtempSync(join(tmpdir(), 'orca-mimocode-config-'))
|
||||
mkdirSync(join(userConfigDir, 'plugins'), { recursive: true })
|
||||
writeFileSync(join(userConfigDir, 'mimocode.json'), '{"theme":"dark"}')
|
||||
writeFileSync(join(userConfigDir, 'plugins', 'user-plugin.js'), 'export default () => {}')
|
||||
writeFileSync(join(userConfigDir, 'plugins', 'orca-mimocode-status.js'), 'USER PLUGIN')
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
rmSync(userDataDir, { recursive: true, force: true })
|
||||
rmSync(mimocodeHome, { recursive: true, force: true })
|
||||
rmSync(userConfigDir, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
it('mirrors user config into shared overlay and installs Orca status plugin', () => {
|
||||
const service = new MimoCodeHookService()
|
||||
const env = service.buildPtyEnv('pty-1', mimocodeHome)
|
||||
// MIMOCODE_HOME also moves auth.json, sessions and state (#9132); only add a config layer.
|
||||
it('sets only MIMOCODE_CONFIG_DIR to a directory holding just the Orca plugin', () => {
|
||||
const env = new MimoCodeHookService().buildPtyEnv('pty-1')
|
||||
|
||||
const overlayHome = join(userDataDir, 'mimocode-hooks', 'shared')
|
||||
expect(env.MIMOCODE_HOME).toBe(overlayHome)
|
||||
expect(readFileSync(join(overlayHome, 'config', 'mimocode.json'), 'utf8')).toBe(
|
||||
'{"theme":"dark"}'
|
||||
)
|
||||
expect(readFileSync(join(overlayHome, 'config', 'plugins', 'user-plugin.js'), 'utf8')).toBe(
|
||||
'export default () => {}'
|
||||
)
|
||||
|
||||
const orcaPlugin = join(overlayHome, 'config', 'plugins', 'orca-mimocode-status.js')
|
||||
expect(existsSync(orcaPlugin)).toBe(true)
|
||||
const pluginSource = readFileSync(orcaPlugin, 'utf8')
|
||||
const overlay = join(userDataDir, 'mimocode-hooks', 'config')
|
||||
expect(env).toEqual({ MIMOCODE_CONFIG_DIR: overlay })
|
||||
expect(readdirSync(overlay)).toEqual(['plugins'])
|
||||
const pluginSource = readFileSync(join(overlay, 'plugins', 'orca-mimocode-status.js'), 'utf8')
|
||||
expect(pluginSource).toContain('/hook/mimo-code')
|
||||
expect(pluginSource).not.toContain('post("SessionStart"')
|
||||
|
||||
expect(
|
||||
readFileSync(join(mimocodeHome, 'config', 'plugins', 'orca-mimocode-status.js'), 'utf8')
|
||||
).toBe('USER PLUGIN')
|
||||
})
|
||||
|
||||
it('reuses the overlay home on a second buildPtyEnv call', () => {
|
||||
const service = new MimoCodeHookService()
|
||||
const first = service.buildPtyEnv('pty-1', mimocodeHome)
|
||||
const second = service.buildPtyEnv('pty-2', mimocodeHome)
|
||||
it("layers the user's own MIMOCODE_CONFIG_DIR into the overlay without touching it", () => {
|
||||
const env = new MimoCodeHookService().buildPtyEnv('pty-1', userConfigDir)
|
||||
|
||||
const overlayHome = join(userDataDir, 'mimocode-hooks', 'shared')
|
||||
expect(first.MIMOCODE_HOME).toBe(overlayHome)
|
||||
expect(second.MIMOCODE_HOME).toBe(overlayHome)
|
||||
expect(
|
||||
readFileSync(join(overlayHome, 'config', 'plugins', 'orca-mimocode-status.js'), 'utf8')
|
||||
).toContain('/hook/mimo-code')
|
||||
const overlay = env.MIMOCODE_CONFIG_DIR ?? ''
|
||||
expect(overlay).toContain(join(userDataDir, 'mimocode-hooks', 'config-overlays'))
|
||||
expect(readFileSync(join(overlay, 'mimocode.json'), 'utf8')).toBe('{"theme":"dark"}')
|
||||
expect(readFileSync(join(overlay, 'plugins', 'user-plugin.js'), 'utf8')).toBe(
|
||||
'export default () => {}'
|
||||
)
|
||||
expect(readFileSync(join(overlay, 'plugins', 'orca-mimocode-status.js'), 'utf8')).toContain(
|
||||
'/hook/mimo-code'
|
||||
)
|
||||
expect(readFileSync(join(userConfigDir, 'plugins', 'orca-mimocode-status.js'), 'utf8')).toBe(
|
||||
'USER PLUGIN'
|
||||
)
|
||||
})
|
||||
|
||||
it.skipIf(process.platform === 'win32')(
|
||||
"never writes the Orca plugin through a user's linked plugins folder",
|
||||
() => {
|
||||
const linkedPlugins = mkdtempSync(join(tmpdir(), 'orca-mimocode-linked-plugins-'))
|
||||
writeFileSync(join(linkedPlugins, 'user-plugin.js'), 'export default () => {}')
|
||||
rmSync(join(userConfigDir, 'plugins'), { recursive: true })
|
||||
symlinkSync(linkedPlugins, join(userConfigDir, 'plugins'))
|
||||
try {
|
||||
const env = new MimoCodeHookService().buildPtyEnv('pty-1', userConfigDir)
|
||||
|
||||
expect(existsSync(join(env.MIMOCODE_CONFIG_DIR ?? '', 'plugins', 'user-plugin.js'))).toBe(
|
||||
true
|
||||
)
|
||||
expect(readdirSync(linkedPlugins)).toEqual(['user-plugin.js'])
|
||||
} finally {
|
||||
rmSync(linkedPlugins, { recursive: true, force: true })
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
it('carries a login made under the old Orca MIMOCODE_HOME over once, owner-only', () => {
|
||||
const legacyData = join(userDataDir, 'mimocode-hooks', 'shared', 'data')
|
||||
mkdirSync(legacyData, { recursive: true })
|
||||
writeFileSync(join(legacyData, 'auth.json'), '{"legacy":true}')
|
||||
const xdgData = join(userDataDir, 'xdg-data')
|
||||
const service = new MimoCodeHookService()
|
||||
|
||||
service.carryOverLegacyAuth({ XDG_DATA_HOME: xdgData })
|
||||
const auth = join(xdgData, 'mimocode', 'auth.json')
|
||||
expect(readFileSync(auth, 'utf8')).toBe('{"legacy":true}')
|
||||
if (process.platform !== 'win32') {
|
||||
expect(statSync(auth).mode & 0o777).toBe(0o600)
|
||||
}
|
||||
|
||||
expect(existsSync(join(legacyData, 'auth.json'))).toBe(false)
|
||||
expect(existsSync(join(legacyData, 'auth.json.migrated'))).toBe(true)
|
||||
|
||||
rmSync(auth)
|
||||
service.carryOverLegacyAuth({ XDG_DATA_HOME: xdgData })
|
||||
expect(existsSync(auth)).toBe(false)
|
||||
})
|
||||
|
||||
it('never overwrites an existing login or follows a relative MIMOCODE_HOME', () => {
|
||||
const legacyData = join(userDataDir, 'mimocode-hooks', 'shared', 'data')
|
||||
mkdirSync(legacyData, { recursive: true })
|
||||
writeFileSync(join(legacyData, 'auth.json'), '{"legacy":true}')
|
||||
const xdgData = join(userDataDir, 'xdg-data')
|
||||
mkdirSync(join(xdgData, 'mimocode'), { recursive: true })
|
||||
const auth = join(xdgData, 'mimocode', 'auth.json')
|
||||
writeFileSync(auth, '{"canonical":true}')
|
||||
const service = new MimoCodeHookService()
|
||||
|
||||
service.carryOverLegacyAuth({ MIMOCODE_HOME: 'relative-mimo-home' })
|
||||
expect(existsSync(join(process.cwd(), 'relative-mimo-home'))).toBe(false)
|
||||
expect(existsSync(join(legacyData, 'auth.json'))).toBe(true)
|
||||
|
||||
service.carryOverLegacyAuth({ XDG_DATA_HOME: xdgData })
|
||||
expect(readFileSync(auth, 'utf8')).toBe('{"canonical":true}')
|
||||
expect(existsSync(join(legacyData, 'auth.json.migrated'))).toBe(true)
|
||||
|
||||
rmSync(auth)
|
||||
service.carryOverLegacyAuth({ XDG_DATA_HOME: xdgData })
|
||||
expect(existsSync(auth)).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
+115
-46
@@ -1,81 +1,150 @@
|
||||
import { getAppEnvironment } from '../../shared/app-environment'
|
||||
import { join } from 'node:path'
|
||||
import { existsSync, mkdirSync, readdirSync, writeFileSync } from 'node:fs'
|
||||
import { isAbsolute, join } from 'node:path'
|
||||
import { homedir } from 'node:os'
|
||||
import {
|
||||
chmodSync,
|
||||
constants,
|
||||
copyFileSync,
|
||||
existsSync,
|
||||
lstatSync,
|
||||
mkdirSync,
|
||||
readdirSync,
|
||||
renameSync,
|
||||
statSync,
|
||||
writeFileSync
|
||||
} from 'node:fs'
|
||||
import { getOpenCodeFamilyPluginSource } from '../opencode/hook-service'
|
||||
import { mirrorEntry, safeRemoveTree } from '../pty/overlay-mirror'
|
||||
import { sourceOverlayDirName } from '../opencode/overlay-dir-names'
|
||||
import {
|
||||
clearOpenCodeOverlayManifestEntries,
|
||||
readOpenCodeOverlayManifest,
|
||||
writeOpenCodeOverlayManifest,
|
||||
type OpenCodeOverlayManifest
|
||||
} from '../opencode/opencode-overlay-manifest'
|
||||
import { isSafeDescendCandidate, mirrorEntry, safeRemoveOverlay } from '../pty/overlay-mirror'
|
||||
|
||||
const ORCA_MIMOCODE_PLUGIN_FILE = 'orca-mimocode-status.js'
|
||||
const MIMOCODE_HOOKS_DIR = 'mimocode-hooks'
|
||||
const MIMOCODE_SHARED_HOME = 'shared'
|
||||
const PLUGIN_ONLY_CONFIG_DIR = 'config'
|
||||
const SOURCE_CONFIG_OVERLAYS_DIR = 'config-overlays'
|
||||
const LEGACY_SHARED_HOME = 'shared'
|
||||
|
||||
function defaultMimocodeConfigDir(): string {
|
||||
return join(homedir(), '.config', 'mimocode')
|
||||
}
|
||||
|
||||
function resolveSourceConfigDir(existingHome: string | undefined): string | undefined {
|
||||
if (existingHome) {
|
||||
const fromHome = join(existingHome, 'config')
|
||||
if (existsSync(fromHome)) {
|
||||
return fromHome
|
||||
}
|
||||
function isDirectoryFollowingLinks(path: string): boolean {
|
||||
try {
|
||||
return statSync(path).isDirectory()
|
||||
} catch {
|
||||
return false
|
||||
}
|
||||
const xdg = defaultMimocodeConfigDir()
|
||||
return existsSync(xdg) ? xdg : undefined
|
||||
}
|
||||
|
||||
function mirrorInto(sourcePath: string, targetDir: string, name: string): void {
|
||||
// MiMo may have created a same-named file in the overlay since the last launch.
|
||||
safeRemoveOverlay(join(targetDir, name), targetDir)
|
||||
mirrorEntry(sourcePath, join(targetDir, name))
|
||||
}
|
||||
|
||||
// Keep MiMo-written overlay files (installed plugin deps); replace only what was mirrored last time.
|
||||
function mirrorConfigDir(sourceConfigDir: string, targetConfigDir: string): void {
|
||||
mkdirSync(targetConfigDir, { recursive: true })
|
||||
clearOpenCodeOverlayManifestEntries(
|
||||
targetConfigDir,
|
||||
readOpenCodeOverlayManifest(targetConfigDir),
|
||||
ORCA_MIMOCODE_PLUGIN_FILE
|
||||
)
|
||||
const manifest: OpenCodeOverlayManifest = {
|
||||
topLevelEntries: [],
|
||||
pluginEntries: [],
|
||||
sourceConfigDir
|
||||
}
|
||||
for (const entry of readdirSync(sourceConfigDir, { withFileTypes: true })) {
|
||||
if (entry.name === 'plugins' && entry.isDirectory()) {
|
||||
const sourcePath = join(sourceConfigDir, entry.name)
|
||||
// A linked plugins dir must not be linked through, or Orca's plugin lands in the user's folder.
|
||||
if (entry.name === 'plugins' && isDirectoryFollowingLinks(sourcePath)) {
|
||||
const overlayPlugins = join(targetConfigDir, 'plugins')
|
||||
mkdirSync(overlayPlugins, { recursive: true })
|
||||
for (const pluginEntry of readdirSync(join(sourceConfigDir, 'plugins'), {
|
||||
withFileTypes: true
|
||||
})) {
|
||||
if (pluginEntry.name === ORCA_MIMOCODE_PLUGIN_FILE) {
|
||||
continue
|
||||
if (!ensureRealDirectory(overlayPlugins)) {
|
||||
throw new Error('MiMo overlay plugins folder is not a real directory')
|
||||
}
|
||||
for (const pluginName of readdirSync(sourcePath)) {
|
||||
if (pluginName !== ORCA_MIMOCODE_PLUGIN_FILE) {
|
||||
mirrorInto(join(sourcePath, pluginName), overlayPlugins, pluginName)
|
||||
manifest.pluginEntries.push(pluginName)
|
||||
}
|
||||
mirrorEntry(
|
||||
join(sourceConfigDir, 'plugins', pluginEntry.name),
|
||||
join(overlayPlugins, pluginEntry.name)
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
mirrorEntry(join(sourceConfigDir, entry.name), join(targetConfigDir, entry.name))
|
||||
mirrorInto(sourcePath, targetConfigDir, entry.name)
|
||||
manifest.topLevelEntries.push(entry.name)
|
||||
}
|
||||
writeOpenCodeOverlayManifest(targetConfigDir, manifest)
|
||||
}
|
||||
|
||||
function ensureRealDirectory(path: string): boolean {
|
||||
mkdirSync(path, { recursive: true })
|
||||
return isSafeDescendCandidate(lstatSync(path))
|
||||
}
|
||||
|
||||
export class MimoCodeHookService {
|
||||
clearPty(_ptyId: string): void {}
|
||||
|
||||
buildPtyEnv(_ptyId: string, existingMimocodeHome?: string): Record<string, string> {
|
||||
const home = join(
|
||||
getAppEnvironment().getPath('userData'),
|
||||
MIMOCODE_HOOKS_DIR,
|
||||
MIMOCODE_SHARED_HOME
|
||||
)
|
||||
/** MIMOCODE_CONFIG_DIR adds a config layer; MIMOCODE_HOME would also move auth and session data. */
|
||||
buildPtyEnv(_ptyId: string, existingConfigDir?: string): { MIMOCODE_CONFIG_DIR?: string } {
|
||||
const fallback = { MIMOCODE_CONFIG_DIR: existingConfigDir }
|
||||
const root = join(getAppEnvironment().getPath('userData'), MIMOCODE_HOOKS_DIR)
|
||||
const overlay = existingConfigDir
|
||||
? join(root, SOURCE_CONFIG_OVERLAYS_DIR, sourceOverlayDirName(existingConfigDir))
|
||||
: join(root, PLUGIN_ONLY_CONFIG_DIR)
|
||||
try {
|
||||
for (const sub of ['config', 'data', 'cache', 'state'] as const) {
|
||||
mkdirSync(join(home, sub), { recursive: true })
|
||||
if (!ensureRealDirectory(root) || !ensureRealDirectory(overlay)) {
|
||||
return fallback
|
||||
}
|
||||
const overlayConfig = join(home, 'config')
|
||||
const sourceConfig = resolveSourceConfigDir(existingMimocodeHome)
|
||||
if (sourceConfig) {
|
||||
safeRemoveTree(overlayConfig)
|
||||
mirrorConfigDir(sourceConfig, overlayConfig)
|
||||
if (existingConfigDir && existsSync(existingConfigDir)) {
|
||||
mirrorConfigDir(existingConfigDir, overlay)
|
||||
}
|
||||
const pluginsDir = join(overlay, 'plugins')
|
||||
if (!ensureRealDirectory(pluginsDir)) {
|
||||
return fallback
|
||||
}
|
||||
const pluginsDir = join(home, 'config', 'plugins')
|
||||
mkdirSync(pluginsDir, { recursive: true })
|
||||
writeFileSync(
|
||||
join(pluginsDir, ORCA_MIMOCODE_PLUGIN_FILE),
|
||||
getOpenCodeFamilyPluginSource('/hook/mimo-code', { emitSessionStart: false })
|
||||
)
|
||||
} catch {
|
||||
return existingMimocodeHome ? { MIMOCODE_HOME: existingMimocodeHome } : {}
|
||||
return fallback
|
||||
}
|
||||
return { MIMOCODE_CONFIG_DIR: overlay }
|
||||
}
|
||||
|
||||
/** Older builds kept MiMo data under Orca's MIMOCODE_HOME; move a login made there over once, then mark it migrated. */
|
||||
carryOverLegacyAuth(env: Record<string, string | undefined>): void {
|
||||
const legacyAuth = join(
|
||||
getAppEnvironment().getPath('userData'),
|
||||
MIMOCODE_HOOKS_DIR,
|
||||
LEGACY_SHARED_HOME,
|
||||
'data',
|
||||
'auth.json'
|
||||
)
|
||||
// MiMo rejects a relative MIMOCODE_HOME; Orca would otherwise write relative to its own cwd.
|
||||
if (env.MIMOCODE_HOME && !isAbsolute(env.MIMOCODE_HOME)) {
|
||||
return
|
||||
}
|
||||
// Mirrors MiMo's Global.Path.data resolution (xdg-basedir, or MIMOCODE_HOME/data).
|
||||
const dataDir = env.MIMOCODE_HOME
|
||||
? join(env.MIMOCODE_HOME, 'data')
|
||||
: join(env.XDG_DATA_HOME || join(homedir(), '.local', 'share'), 'mimocode')
|
||||
const auth = join(dataDir, 'auth.json')
|
||||
try {
|
||||
if (!existsSync(legacyAuth)) {
|
||||
return
|
||||
}
|
||||
if (!existsSync(auth)) {
|
||||
mkdirSync(dataDir, { recursive: true })
|
||||
copyFileSync(legacyAuth, auth, constants.COPYFILE_EXCL)
|
||||
chmodSync(auth, 0o600)
|
||||
}
|
||||
// Never restore the Orca-only login later, e.g. after the user deletes the canonical one.
|
||||
renameSync(legacyAuth, `${legacyAuth}.migrated`)
|
||||
} catch {
|
||||
// A failed carry-over leaves MiMo logged out, as before; never block the launch.
|
||||
}
|
||||
return { MIMOCODE_HOME: home }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('PowerShell OSC 133 bootstrap', () => {
|
||||
|
||||
expect(script).toContain('[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()')
|
||||
expect(script).toContain('ORCA_OPENCODE_CONFIG_DIR')
|
||||
expect(script).toContain('ORCA_MIMOCODE_HOME')
|
||||
expect(script).toContain('ORCA_MIMOCODE_CONFIG_DIR')
|
||||
expect(script).not.toContain('ORCA_PI_CODING_AGENT_DIR')
|
||||
expect(script).not.toContain('ORCA_OMP_CODING_AGENT_DIR')
|
||||
expect(script).toContain('ORCA_OMP_STATUS_EXTENSION')
|
||||
|
||||
@@ -10,7 +10,7 @@ const POWERSHELL_OSC133_BOOTSTRAP = `# Orca OSC 133 shell integration for PowerS
|
||||
# Restore managed ownership before the shell-integration compatibility guard.
|
||||
if ($env:ORCA_OPENCODE_CONFIG_DIR) { $env:OPENCODE_CONFIG_DIR = $env:ORCA_OPENCODE_CONFIG_DIR }
|
||||
${MANAGED_DATA_ACCOUNT_POWERSHELL_RESTORE}
|
||||
if ($env:ORCA_MIMOCODE_HOME) { $env:MIMOCODE_HOME = $env:ORCA_MIMOCODE_HOME }
|
||||
if ($env:ORCA_MIMOCODE_CONFIG_DIR) { $env:MIMOCODE_CONFIG_DIR = $env:ORCA_MIMOCODE_CONFIG_DIR }
|
||||
if ($env:ORCA_CODEX_HOME) { $env:CODEX_HOME = $env:ORCA_CODEX_HOME }
|
||||
|
||||
if ($ExecutionContext.SessionState.LanguageMode -eq "FullLanguage" -and
|
||||
|
||||
@@ -522,8 +522,8 @@ describe('LocalPtyProvider', () => {
|
||||
it('uses shell wrapper when MiMo home must survive shell startup', async () => {
|
||||
provider.configure({
|
||||
buildSpawnEnv: (_id, env) => {
|
||||
env.MIMOCODE_HOME = '/tmp/orca-mimocode-overlay'
|
||||
env.ORCA_MIMOCODE_HOME = '/tmp/orca-mimocode-overlay'
|
||||
env.MIMOCODE_CONFIG_DIR = '/tmp/orca-mimocode-overlay'
|
||||
env.ORCA_MIMOCODE_CONFIG_DIR = '/tmp/orca-mimocode-overlay'
|
||||
return env
|
||||
}
|
||||
})
|
||||
|
||||
@@ -43,7 +43,7 @@ ${WSL_MANAGED_CLI_PATH_RESTORE}
|
||||
# Restore Orca-managed config after user startup files may override it.
|
||||
[[ -n "\${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="\${ORCA_OPENCODE_CONFIG_DIR}"
|
||||
${MANAGED_DATA_ACCOUNT_POSIX_RESTORE}
|
||||
[[ -n "\${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="\${ORCA_MIMOCODE_HOME}"
|
||||
[[ -n "\${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="\${ORCA_MIMOCODE_CONFIG_DIR}"
|
||||
${getPosixOmpShellWrapper()}
|
||||
# Profile scripts must not replace Orca's runtime CODEX_HOME.
|
||||
[[ -n "\${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="\${ORCA_CODEX_HOME}"
|
||||
|
||||
@@ -299,7 +299,7 @@ describePosix('local PTY shell-ready launch config', () => {
|
||||
const restoreLine =
|
||||
'[[ -n "${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="${ORCA_OPENCODE_CONFIG_DIR}"'
|
||||
const mimoRestoreLine =
|
||||
'[[ -n "${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="${ORCA_MIMOCODE_HOME}"'
|
||||
'[[ -n "${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="${ORCA_MIMOCODE_CONFIG_DIR}"'
|
||||
const codexRestoreLine =
|
||||
'[[ -n "${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="${ORCA_CODEX_HOME}"'
|
||||
const agentTeamsPathRestoreLine = '[[ -n "${ORCA_AGENT_TEAMS_SHIM_DIR:-}" ]] || return 0'
|
||||
|
||||
@@ -125,7 +125,9 @@ describe('resolveWindowsShellLaunchArgs', () => {
|
||||
const opencodeRestoreIndex = command.indexOf(
|
||||
'$env:OPENCODE_CONFIG_DIR = $env:ORCA_OPENCODE_CONFIG_DIR'
|
||||
)
|
||||
const mimocodeRestoreIndex = command.indexOf('$env:MIMOCODE_HOME = $env:ORCA_MIMOCODE_HOME')
|
||||
const mimocodeRestoreIndex = command.indexOf(
|
||||
'$env:MIMOCODE_CONFIG_DIR = $env:ORCA_MIMOCODE_CONFIG_DIR'
|
||||
)
|
||||
const duplicateStateGuardIndex = command.indexOf('Test-Path variable:global:__OrcaOsc133State')
|
||||
const languageModeGuardIndex = command.indexOf('LanguageMode -eq "FullLanguage"')
|
||||
const ompWrapperIndex = command.indexOf('function Global:omp')
|
||||
|
||||
@@ -16,7 +16,7 @@ export type ShellStartupFeature = (typeof SHELL_STARTUP_FEATURES)[number]
|
||||
const OVERLAY_ENV_KEYS = [
|
||||
'ORCA_DATA_ACCOUNT_DATA_HOME',
|
||||
'ORCA_OPENCODE_CONFIG_DIR',
|
||||
'ORCA_MIMOCODE_HOME',
|
||||
'ORCA_MIMOCODE_CONFIG_DIR',
|
||||
'ORCA_OMP_STATUS_EXTENSION',
|
||||
'ORCA_CODEX_HOME',
|
||||
'ORCA_AGENT_TEAMS_SHIM_DIR',
|
||||
|
||||
@@ -50,7 +50,7 @@ const CONTRACT_GLOBALS = new Set([
|
||||
// Exported only in the claude function's subshell.
|
||||
'CLAUDE_CONFIG_DIR',
|
||||
'HISTFILE',
|
||||
'MIMOCODE_HOME',
|
||||
'MIMOCODE_CONFIG_DIR',
|
||||
'OPENCODE_CONFIG_DIR',
|
||||
'OPENCODE_AUTH_CONTENT',
|
||||
'OPENCODE_DB',
|
||||
|
||||
@@ -49,7 +49,7 @@ const AGENT_TEAMS_PATH_RESTORE_BLOCK = `__orca_restore_agent_teams_path() {
|
||||
__orca_restore_agent_teams_path`
|
||||
|
||||
const OPENCODE_CONFIG_DIR_RESTORE = `[[ -n "\${ORCA_OPENCODE_CONFIG_DIR:-}" ]] && export OPENCODE_CONFIG_DIR="\${ORCA_OPENCODE_CONFIG_DIR}"`
|
||||
const MIMOCODE_HOME_RESTORE = `[[ -n "\${ORCA_MIMOCODE_HOME:-}" ]] && export MIMOCODE_HOME="\${ORCA_MIMOCODE_HOME}"`
|
||||
const MIMOCODE_CONFIG_DIR_RESTORE = `[[ -n "\${ORCA_MIMOCODE_CONFIG_DIR:-}" ]] && export MIMOCODE_CONFIG_DIR="\${ORCA_MIMOCODE_CONFIG_DIR}"`
|
||||
const REMOTE_CLI_BIN_DIR_RESTORE = `[[ -n "\${ORCA_REMOTE_CLI_BIN_DIR:-}" ]] && case ":$PATH:" in *:"\${ORCA_REMOTE_CLI_BIN_DIR}":*) ;; *) export PATH="\${ORCA_REMOTE_CLI_BIN_DIR}:$PATH" ;; esac`
|
||||
const CODEX_HOME_RESTORE = `# Restore the runtime CODEX_HOME after user rc files.
|
||||
[[ -n "\${ORCA_CODEX_HOME:-}" ]] && export CODEX_HOME="\${ORCA_CODEX_HOME}"`
|
||||
@@ -93,7 +93,7 @@ function getOverlayRestoreBlocks(spec: ZshStartupHookSpec): (string | null)[] {
|
||||
spec.restores.agentTeamsPath ? AGENT_TEAMS_PATH_RESTORE_BLOCK : null,
|
||||
OPENCODE_CONFIG_DIR_RESTORE,
|
||||
MANAGED_DATA_ACCOUNT_POSIX_RESTORE,
|
||||
MIMOCODE_HOME_RESTORE,
|
||||
MIMOCODE_CONFIG_DIR_RESTORE,
|
||||
spec.restores.remoteCliBinDir ? REMOTE_CLI_BIN_DIR_RESTORE : null,
|
||||
getPosixOmpShellWrapper(),
|
||||
spec.restores.codexHome ? CODEX_HOME_RESTORE : null
|
||||
|
||||
Reference in New Issue
Block a user