mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 00:02:31 +00:00
* feat(agents): add OpenCode 2 beta support Co-authored-by: Xiro The Dev <lethanhtrung.trungle@gmail.com> * fix(opencode2): support current plugin lifecycle and session storage * fix(opencode2): preserve lifecycle ordering and full session capture * test(opencode2): cover setup event bridge * test(opencode2): cover setup event bridge * test(browser): satisfy anti-slop naming check * test(opencode2): cover live form lifecycle * fix(relay): preserve OMP config directory selection * test(opencode2): avoid assertions in bridge fixture * fix(rebase): retain OMP resume and fresh launch behavior * test: align upstream OMP resume expectations * test(opencode2): verify rejected form closes waiting state --------- Co-authored-by: Xiro The Dev <lethanhtrung.trungle@gmail.com>
433 lines
18 KiB
TypeScript
433 lines
18 KiB
TypeScript
import { afterEach, beforeEach, describe, expect, it } from 'vitest'
|
|
import {
|
|
existsSync,
|
|
mkdirSync,
|
|
mkdtempSync,
|
|
readFileSync,
|
|
readdirSync,
|
|
rmSync,
|
|
symlinkSync,
|
|
writeFileSync
|
|
} from 'node:fs'
|
|
import { tmpdir } from 'node:os'
|
|
import { basename, join } from 'node:path'
|
|
import { PluginOverlayManager } from './plugin-overlay'
|
|
import { resolvePiSourceAgentDir } from './plugin-overlay-env'
|
|
|
|
describe('PluginOverlayManager', () => {
|
|
let homeDir: string
|
|
let manager: PluginOverlayManager
|
|
|
|
beforeEach(() => {
|
|
homeDir = mkdtempSync(join(tmpdir(), 'plugin-overlay-'))
|
|
manager = new PluginOverlayManager({ homeDir })
|
|
})
|
|
|
|
afterEach(() => {
|
|
rmSync(homeDir, { recursive: true, force: true })
|
|
})
|
|
|
|
it('reports no source until install runs', () => {
|
|
expect(manager.hasOpenCodeSource()).toBe(false)
|
|
expect(manager.hasPiSource()).toBe(false)
|
|
expect(manager.materializeOpenCode('tab-1:0')).toBeNull()
|
|
expect(manager.materializePi('tab-1:0')).toBeNull()
|
|
})
|
|
|
|
it('materializes OpenCode plugin into <overlay>/plugins/<file>', () => {
|
|
manager.setSources({ opencodePluginSource: 'export const X = 1' })
|
|
const dir = manager.materializeOpenCode('tab-1:0')
|
|
expect(dir).not.toBeNull()
|
|
const expected = join(dir!, 'plugins', 'orca-opencode-status.js')
|
|
expect(existsSync(expected)).toBe(true)
|
|
expect(readFileSync(expected, 'utf8')).toBe('export const X = 1')
|
|
})
|
|
|
|
it('keeps the OpenCode 2 plugin in a separate overlay and filename', () => {
|
|
manager.setSources({ opencode2PluginSource: 'export const V2 = 1' })
|
|
expect(manager.hasOpenCodeSource('opencode2')).toBe(true)
|
|
const dir = manager.materializeOpenCode('tab-2:0', undefined, 'opencode2')
|
|
expect(dir).not.toBeNull()
|
|
expect(readFileSync(join(dir!, 'plugins', 'orca-opencode2-status.js'), 'utf8')).toBe(
|
|
'export const V2 = 1'
|
|
)
|
|
expect(existsSync(join(dir!, 'plugins', 'orca-opencode-status.js'))).toBe(false)
|
|
})
|
|
|
|
it('mirrors a preexisting remote OpenCode config dir before adding Orca plugin', () => {
|
|
const userConfigDir = join(homeDir, 'company-opencode')
|
|
mkdirSync(join(userConfigDir, 'plugins'), { recursive: true })
|
|
writeFileSync(join(userConfigDir, 'opencode.json'), '{"provider":"custom"}')
|
|
writeFileSync(join(userConfigDir, 'plugins', 'user-plugin.js'), 'user plugin')
|
|
writeFileSync(join(userConfigDir, 'plugins', 'orca-opencode-status.js'), 'user same-name')
|
|
|
|
manager.setSources({ opencodePluginSource: 'orca plugin' })
|
|
const dir = manager.materializeOpenCode('tab-opencode:0', userConfigDir)
|
|
|
|
expect(dir).not.toBeNull()
|
|
expect(readFileSync(join(dir!, 'opencode.json'), 'utf8')).toBe('{"provider":"custom"}')
|
|
expect(readFileSync(join(dir!, 'plugins', 'user-plugin.js'), 'utf8')).toBe('user plugin')
|
|
expect(readFileSync(join(dir!, 'plugins', 'orca-opencode-status.js'), 'utf8')).toBe(
|
|
'orca plugin'
|
|
)
|
|
expect(readFileSync(join(userConfigDir, 'plugins', 'orca-opencode-status.js'), 'utf8')).toBe(
|
|
'user same-name'
|
|
)
|
|
})
|
|
|
|
it('does not override a missing preexisting OpenCode config dir', () => {
|
|
manager.setSources({ opencodePluginSource: 'orca plugin' })
|
|
|
|
expect(manager.materializeOpenCode('tab-missing:0', join(homeDir, 'missing'))).toBeNull()
|
|
})
|
|
|
|
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)
|
|
expect(existsSync(file)).toBe(true)
|
|
expect(readFileSync(file, 'utf8')).toContain('@orca-managed-pi-extension')
|
|
})
|
|
|
|
it("does not overwrite a user's same-named remote Pi extension file", () => {
|
|
const piAgentDir = join(homeDir, '.pi', 'agent')
|
|
const extensionFile = join(piAgentDir, 'extensions', 'orca-agent-status.ts')
|
|
mkdirSync(join(piAgentDir, 'extensions'), { recursive: true })
|
|
writeFileSync(extensionFile, 'user-owned remote status extension')
|
|
|
|
manager.setSources({ piExtensionSource: '// pi extension' })
|
|
expect(manager.materializePi('tab-user-owned-pi:0')).toBeNull()
|
|
expect(readFileSync(extensionFile, 'utf8')).toBe('user-owned remote status extension')
|
|
})
|
|
|
|
it('uses the kind-specific Pi-compatible extension source when available', () => {
|
|
manager.setSources({
|
|
piExtensionSource: '// pi extension',
|
|
ompExtensionSource: '// omp extension'
|
|
})
|
|
|
|
const piResult = manager.materializePi('tab-kind-pi:0', undefined, 'pi')
|
|
const ompResult = 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')
|
|
})
|
|
|
|
it('uses only the Prime-specific source in the default Prime agent dir', () => {
|
|
manager.setSources({ piExtensionSource: '// pi extension' })
|
|
expect(manager.materializePi('tab-prime-missing:0', undefined, 'prime-agent')).toBeNull()
|
|
|
|
manager.setSources({ primeAgentExtensionSource: '// prime extension' })
|
|
const result = manager.materializePi('tab-prime:0', undefined, 'prime-agent')
|
|
expect(result?.sourceAgentDir).toBe(join(homeDir, '.prime', 'agent'))
|
|
expect(readFileSync(result!.statusExtensionPath!, 'utf8')).toContain('// prime extension')
|
|
expect(readFileSync(result!.statusExtensionPath!, 'utf8')).not.toContain('// pi extension')
|
|
})
|
|
|
|
it('installs Orca status extension into the remote default Pi agent dir', () => {
|
|
const piAgentDir = join(homeDir, '.pi', 'agent')
|
|
mkdirSync(join(piAgentDir, 'skills', 'my-skill'), { recursive: true })
|
|
mkdirSync(join(piAgentDir, 'extensions', 'user-ext'), { recursive: true })
|
|
writeFileSync(join(piAgentDir, 'auth.json'), 'secret token')
|
|
writeFileSync(join(piAgentDir, 'skills', 'my-skill', 'SKILL.md'), 'critical user skill')
|
|
writeFileSync(join(piAgentDir, 'extensions', 'user-ext', 'ext.ts'), 'user extension')
|
|
writeFileSync(
|
|
join(piAgentDir, 'settings.json'),
|
|
JSON.stringify({
|
|
defaultProvider: 'amazon-bedrock',
|
|
hideThinkingBlock: false,
|
|
terminal: {
|
|
showImages: false,
|
|
clearOnShrink: false
|
|
}
|
|
})
|
|
)
|
|
|
|
manager.setSources({ piExtensionSource: '// pi extension' })
|
|
const result = manager.materializePi('tab-pi:0')
|
|
const dir = result?.sourceAgentDir
|
|
|
|
expect(dir).toBeDefined()
|
|
expect(readFileSync(join(dir!, 'auth.json'), 'utf8')).toBe('secret token')
|
|
expect(readFileSync(join(dir!, 'skills', 'my-skill', 'SKILL.md'), 'utf8')).toBe(
|
|
'critical user skill'
|
|
)
|
|
expect(readFileSync(join(dir!, 'extensions', 'user-ext', 'ext.ts'), 'utf8')).toBe(
|
|
'user extension'
|
|
)
|
|
expect(readdirSync(join(dir!, 'extensions')).sort()).toEqual([
|
|
'orca-agent-status.ts',
|
|
'user-ext'
|
|
])
|
|
expect(JSON.parse(readFileSync(join(dir!, 'settings.json'), 'utf8'))).toEqual({
|
|
defaultProvider: 'amazon-bedrock',
|
|
hideThinkingBlock: false,
|
|
terminal: {
|
|
showImages: false,
|
|
clearOnShrink: false
|
|
}
|
|
})
|
|
expect(JSON.parse(readFileSync(join(piAgentDir, 'settings.json'), 'utf8'))).toEqual({
|
|
defaultProvider: 'amazon-bedrock',
|
|
hideThinkingBlock: false,
|
|
terminal: {
|
|
showImages: false,
|
|
clearOnShrink: false
|
|
}
|
|
})
|
|
})
|
|
|
|
it('mirrors a preexisting remote Pi agent dir instead of the default', () => {
|
|
const defaultAgentDir = join(homeDir, '.pi', 'agent')
|
|
const customAgentDir = join(homeDir, 'custom-pi-agent')
|
|
mkdirSync(defaultAgentDir, { recursive: true })
|
|
mkdirSync(join(customAgentDir, 'extensions'), { recursive: true })
|
|
writeFileSync(join(defaultAgentDir, 'auth.json'), 'default token')
|
|
writeFileSync(join(customAgentDir, 'auth.json'), 'custom token')
|
|
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
|
|
|
|
expect(dir).toBeDefined()
|
|
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(
|
|
'// pi extension'
|
|
)
|
|
})
|
|
|
|
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')
|
|
|
|
expect(first?.sourceAgentDir).toBe(sourceDir)
|
|
const sourcePath = join(sourceDir, 'agent.db')
|
|
const content = 'agent.db relay credentials'
|
|
|
|
expect(existsSync(sourcePath)).toBe(false)
|
|
expect(existsSync(join(homeDir, '.orca-relay', 'omp-overlays'))).toBe(false)
|
|
expect(existsSync(join(sourceDir, 'history.db'))).toBe(false)
|
|
writeFileSync(sourcePath, content)
|
|
|
|
expect(readFileSync(sourcePath, 'utf8')).toBe(content)
|
|
|
|
const second = 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)
|
|
})
|
|
|
|
// Why: per-agent source dir. The renderer picks Pi or OMP per
|
|
// launch, and the relay must use the right `~/.<kind>/agent` source —
|
|
// disk-presence guessing (always-Pi or first-exists) shadows the other
|
|
// agent's user extensions when both dirs exist on the remote disk.
|
|
describe('per-agent default source dir (no cross-agent fallback)', () => {
|
|
function seedAgentDir(dotDir: '.pi' | '.omp', tag: string): string {
|
|
const agentDir = join(homeDir, dotDir, 'agent')
|
|
mkdirSync(join(agentDir, 'extensions', `${tag}-ext`), { recursive: true })
|
|
writeFileSync(join(agentDir, 'extensions', `${tag}-ext`, 'ext.ts'), `${tag} extension`)
|
|
writeFileSync(join(agentDir, 'auth.json'), `${tag} token`)
|
|
return agentDir
|
|
}
|
|
|
|
it('launching pi with both ~/.pi/agent and ~/.omp/agent present installs into ~/.pi/agent', () => {
|
|
seedAgentDir('.pi', 'pi')
|
|
seedAgentDir('.omp', 'omp')
|
|
|
|
manager.setSources({ piExtensionSource: '// pi extension' })
|
|
const result = manager.materializePi('tab-relay-pi-both:0', undefined, 'pi')
|
|
const dir = result?.sourceAgentDir
|
|
|
|
expect(dir).toBe(join(homeDir, '.pi', 'agent'))
|
|
expect(readFileSync(join(dir!, 'auth.json'), 'utf8')).toBe('pi token')
|
|
const extensions = readdirSync(join(dir!, 'extensions')).sort()
|
|
expect(extensions).toContain('pi-ext')
|
|
expect(extensions).toContain('orca-agent-status.ts')
|
|
expect(extensions).not.toContain('omp-ext')
|
|
})
|
|
|
|
it('launching omp with both ~/.pi/agent and ~/.omp/agent present installs into ~/.omp/agent', () => {
|
|
seedAgentDir('.pi', 'pi')
|
|
seedAgentDir('.omp', 'omp')
|
|
|
|
manager.setSources({ piExtensionSource: '// pi extension' })
|
|
const result = manager.materializePi('tab-relay-omp-both:0', undefined, 'omp')
|
|
const dir = result?.sourceAgentDir
|
|
|
|
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
|
|
// OMP extensions on the remote.
|
|
expect(readFileSync(join(dir!, 'auth.json'), 'utf8')).toBe('omp token')
|
|
const extensions = readdirSync(join(dir!, 'extensions')).sort()
|
|
expect(extensions).toContain('omp-ext')
|
|
expect(extensions).toContain('orca-agent-status.ts')
|
|
expect(extensions).not.toContain('pi-ext')
|
|
})
|
|
|
|
it('launching omp when only ~/.pi/agent exists does NOT mirror Pi state', () => {
|
|
// Why: missing OMP source dir on the remote must create only OMP's
|
|
// own extension dir. Pi state must never cross-pollinate in.
|
|
seedAgentDir('.pi', 'pi')
|
|
expect(existsSync(join(homeDir, '.omp'))).toBe(false)
|
|
expect(existsSync(join(homeDir, '.prime'))).toBe(false)
|
|
|
|
manager.setSources({ piExtensionSource: '// pi extension' })
|
|
const result = manager.materializePi('tab-relay-omp-empty:0', undefined, 'omp')
|
|
const dir = result?.sourceAgentDir
|
|
|
|
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',
|
|
primeAgentExtensionSource: '// prime 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
|
|
})
|
|
// Why: bare OMP keeps status via ~/.orca-relay/… without SOURCE_AGENT_DIR or ~/.omp.
|
|
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)
|
|
expect(
|
|
manager.materializePi('tab-bare-prime:0', undefined, 'prime-agent', {
|
|
materializeDefaultHome: false
|
|
})
|
|
).toBeNull()
|
|
expect(existsSync(join(homeDir, '.prime'))).toBe(false)
|
|
})
|
|
})
|
|
|
|
it('does not override a missing preexisting Pi agent dir', () => {
|
|
manager.setSources({ piExtensionSource: '// pi extension' })
|
|
|
|
expect(manager.materializePi('tab-missing-pi:0', join(homeDir, 'missing-pi'))).toBeNull()
|
|
})
|
|
|
|
it('clearOverlay removes OpenCode overlays without deleting real Pi/OMP homes', () => {
|
|
manager.setSources({
|
|
opencodePluginSource: 'opencode',
|
|
opencode2PluginSource: 'opencode2',
|
|
piExtensionSource: 'pi',
|
|
ompExtensionSource: 'omp'
|
|
})
|
|
const opencodeDir = manager.materializeOpenCode('tab-3:0')!
|
|
const opencode2Dir = manager.materializeOpenCode('tab-3:0', undefined, 'opencode2')!
|
|
const piDir = manager.materializePi('tab-3:0', undefined, 'pi')!.sourceAgentDir!
|
|
const ompDir = manager.materializePi('tab-3:0', undefined, 'omp')!.sourceAgentDir!
|
|
expect(piDir).not.toBe(ompDir)
|
|
expect(existsSync(opencodeDir)).toBe(true)
|
|
expect(existsSync(opencode2Dir)).toBe(true)
|
|
expect(existsSync(piDir)).toBe(true)
|
|
expect(existsSync(ompDir)).toBe(true)
|
|
|
|
manager.clearOverlay('tab-3:0')
|
|
|
|
expect(existsSync(opencodeDir)).toBe(false)
|
|
expect(existsSync(opencode2Dir)).toBe(false)
|
|
expect(existsSync(piDir)).toBe(true)
|
|
expect(existsSync(ompDir)).toBe(true)
|
|
})
|
|
|
|
it.skipIf(process.platform === 'win32')(
|
|
'clearOverlay removes OpenCode overlay symlinks without deleting their targets',
|
|
() => {
|
|
const userConfigDir = join(homeDir, 'company-opencode')
|
|
const linkedTarget = join(homeDir, 'linked-plugin-target')
|
|
mkdirSync(join(userConfigDir, 'plugins'), { recursive: true })
|
|
mkdirSync(linkedTarget, { recursive: true })
|
|
writeFileSync(join(linkedTarget, 'keep.js'), 'do not delete')
|
|
symlinkSync(linkedTarget, join(userConfigDir, 'plugins', 'linked-plugin'), 'dir')
|
|
|
|
manager.setSources({ opencodePluginSource: 'orca plugin' })
|
|
const dir = manager.materializeOpenCode('tab-opencode-symlink:0', userConfigDir)!
|
|
expect(existsSync(join(dir, 'plugins', 'linked-plugin'))).toBe(true)
|
|
|
|
manager.clearOverlay('tab-opencode-symlink:0')
|
|
|
|
expect(existsSync(dir)).toBe(false)
|
|
expect(readFileSync(join(linkedTarget, 'keep.js'), 'utf8')).toBe('do not delete')
|
|
}
|
|
)
|
|
|
|
it('produces stable overlay dirs for a given id (idempotent re-materialization)', () => {
|
|
manager.setSources({ opencodePluginSource: 'first' })
|
|
const dirA = manager.materializeOpenCode('tab-stable:0')!
|
|
manager.setSources({ opencodePluginSource: 'second' })
|
|
const dirB = manager.materializeOpenCode('tab-stable:0')!
|
|
expect(dirA).toBe(dirB)
|
|
expect(readFileSync(join(dirA, 'plugins', 'orca-opencode-status.js'), 'utf8')).toBe('second')
|
|
})
|
|
|
|
it('hashes unsafe pane ids into portable overlay directory names', () => {
|
|
manager.setSources({ opencodePluginSource: 'plugin' })
|
|
const dir = manager.materializeOpenCode('tab/with\\unsafe:chars\n0')
|
|
|
|
expect(dir).not.toBeNull()
|
|
expect(basename(dir!)).toMatch(/^[a-f0-9]{32}$/)
|
|
expect(dir).not.toContain('tab/with')
|
|
expect(existsSync(join(dir!, 'plugins', 'orca-opencode-status.js'))).toBe(true)
|
|
})
|
|
})
|
|
|
|
describe('resolvePiSourceAgentDir', () => {
|
|
it('uses only the selected kind source shadow when resolving inherited overlays', () => {
|
|
const env = {
|
|
HOME: mkdtempSync(join(tmpdir(), 'plugin-overlay-env-')),
|
|
PI_CODING_AGENT_DIR: '/tmp/parent-orca-pi-overlay',
|
|
ORCA_PI_CODING_AGENT_DIR: '/tmp/parent-orca-pi-overlay',
|
|
ORCA_PI_SOURCE_AGENT_DIR: '/user/.pi/agent'
|
|
}
|
|
try {
|
|
expect(resolvePiSourceAgentDir(env, undefined, 'pi')).toBe('/user/.pi/agent')
|
|
expect(resolvePiSourceAgentDir(env, undefined, 'omp')).toBeUndefined()
|
|
} finally {
|
|
rmSync(env.HOME, { recursive: true, force: true })
|
|
}
|
|
})
|
|
|
|
it('keeps explicit PI_CODING_AGENT_DIR values when they are not Orca overlays', () => {
|
|
const env = {
|
|
HOME: mkdtempSync(join(tmpdir(), 'plugin-overlay-env-')),
|
|
PI_CODING_AGENT_DIR: '/user/custom-omp-agent',
|
|
ORCA_PI_SOURCE_AGENT_DIR: '/user/.pi/agent'
|
|
}
|
|
try {
|
|
expect(resolvePiSourceAgentDir(env, undefined, 'omp')).toBe('/user/custom-omp-agent')
|
|
} finally {
|
|
rmSync(env.HOME, { recursive: true, force: true })
|
|
}
|
|
})
|
|
})
|