mirror of
https://github.com/stablyai/orca.git
synced 2026-10-03 16:02:11 +00:00
* fix(memory): bound session and lifecycle registries * fix(memory): bound transient filesystem registries * fix(memory): cap path and locale caches * fix(memory): bound runtime recovery registries * fix(memory): bound host mirror gap verdicts * fix(memory): bound shell startup env cache * fix(memory): bound gitlab host context cache * fix(memory): release removed ssh generations * fix(memory): expire cloud refresh replay guards * fix(memory): release retired plugin generations * fix(memory): bound plugin log key retention * fix(memory): bound automation authority generations * fix(memory): bound native chat enrichment cache * fix(memory): bound web session tracking generations * fix(memory): bound codex credential absence paths * fix(memory): bound WSL canonical path cache * fix(memory): bound sparse checkout cache * fix(memory): bound shared directory cache * fix(memory): bound advertised URL scan snapshots * fix(memory): bound automation manager cache * fix(memory): bound web session reorder intents * fix(memory): bound web session focus intents * fix(memory): bound web session handoffs * fix(memory): bound automation dispatch tokens * fix(memory): bound host mirror waiters * fix(memory): bound retained session activity * fix(memory): bound retained session activity * fix(memory): bound web session close intents * fix(memory): bound cloud session cache * fix(memory): bound WSL home cache * fix(memory): bound SSH capability cache * fix(memory): bound trust grant cooldowns * fix(memory): bound WSL auth drain state * fix(memory): bound Linear workspace credential cache * fix(memory): bound local Git capability cache * fix(memory): bound WSL Git environment cache * fix(memory): bound WSL Git environment cache * fix(memory): bound WSL preflight cache * fix(memory): keep hot cache entries warm * fix(memory): preserve generation fences across eviction * fix(memory): close remaining eviction fences * fix(memory): align evicted upstream generations * fix(memory): trim successful capability probes * fix(auth): retain expired refresh replay evidence --------- Co-authored-by: m4air <m4air@Mac.localdomain>
224 lines
7.2 KiB
TypeScript
224 lines
7.2 KiB
TypeScript
import { describe, expect, it, vi } from 'vitest'
|
|
import {
|
|
CODEX_APP_SERVER_CAPABILITY_MAX_ENTRIES,
|
|
CODEX_APP_SERVER_CAPABILITY_RETRY_INTERVAL_MS,
|
|
CodexAppServerCapabilityCache,
|
|
getCodexAppServerHostKey
|
|
} from './codex-app-server-capability-cache'
|
|
|
|
const unsupportedError = new Error('unsupported')
|
|
const isUnsupported = (error: unknown): boolean => error === unsupportedError
|
|
|
|
describe('CodexAppServerCapabilityCache', () => {
|
|
it('retries a host after the compatibility interval', () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
cache.rememberUnsupported('native', 1_000)
|
|
|
|
expect(
|
|
cache.shouldTry('native', 1_000 + CODEX_APP_SERVER_CAPABILITY_RETRY_INTERVAL_MS - 1)
|
|
).toBe(false)
|
|
expect(cache.shouldTry('native', 1_000 + CODEX_APP_SERVER_CAPABILITY_RETRY_INTERVAL_MS)).toBe(
|
|
true
|
|
)
|
|
})
|
|
|
|
it('falls back on the first unsupported probe and skips the probe on later calls', async () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
const firstPreferred = vi.fn(() => Promise.reject(unsupportedError))
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
firstPreferred,
|
|
() => Promise.resolve('first-fallback'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('first-fallback')
|
|
expect(firstPreferred).toHaveBeenCalledTimes(1)
|
|
|
|
const laterPreferred = vi.fn(() => Promise.resolve('unexpected-preferred'))
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
laterPreferred,
|
|
() => Promise.resolve('cached-fallback'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('cached-fallback')
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
laterPreferred,
|
|
() => Promise.resolve('cached-fallback'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('cached-fallback')
|
|
expect(laterPreferred).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('isolates capability state per execution host', async () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
cache.rememberUnsupported('wsl:Ubuntu', 1_000)
|
|
|
|
expect(cache.shouldTry('wsl:Ubuntu', 1_001)).toBe(false)
|
|
expect(cache.shouldTry('native', 1_001)).toBe(true)
|
|
expect(cache.shouldTry('wsl:Debian', 1_001)).toBe(true)
|
|
|
|
const nativePreferred = vi.fn(() => Promise.resolve('native-result'))
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
nativePreferred,
|
|
() => Promise.resolve('unexpected'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('native-result')
|
|
expect(nativePreferred).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('bounds host capability state during WSL distro churn', () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
cache.rememberUnsupported('native', 1_000)
|
|
for (let index = 0; index < CODEX_APP_SERVER_CAPABILITY_MAX_ENTRIES + 4; index += 1) {
|
|
cache.rememberUnsupported(`wsl:distro-${index}`, 1_000)
|
|
}
|
|
|
|
expect(cache.shouldTry('native', 1_001)).toBe(true)
|
|
})
|
|
|
|
it('drops known support when a later call reports the capability unsupported', async () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
() => Promise.resolve('supported'),
|
|
() => Promise.resolve('unexpected'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('supported')
|
|
expect(cache.isKnownSupported('native')).toBe(true)
|
|
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
() => Promise.reject(unsupportedError),
|
|
() => Promise.resolve('fallback'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('fallback')
|
|
expect(cache.isKnownSupported('native')).toBe(false)
|
|
|
|
const laterPreferred = vi.fn(() => Promise.resolve('unexpected-preferred'))
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
laterPreferred,
|
|
() => Promise.resolve('cached-fallback'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('cached-fallback')
|
|
expect(laterPreferred).not.toHaveBeenCalled()
|
|
})
|
|
|
|
it('rethrows transient errors without marking the host unsupported', async () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
const transient = new Error('spawn ETIMEDOUT')
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'native',
|
|
() => Promise.reject(transient),
|
|
() => Promise.resolve('unexpected-fallback'),
|
|
isUnsupported
|
|
)
|
|
).rejects.toBe(transient)
|
|
expect(cache.shouldTry('native', 2)).toBe(true)
|
|
})
|
|
|
|
// Why (#16441): grants no longer block the main thread, so two pane launches
|
|
// can reach a cold host at once. Without dedupe each one pays its own
|
|
// app-server session against a codex that has no such RPC surface.
|
|
it('dedupes concurrent probes on one host to a single app-server session', async () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
let releaseProbe!: (error: unknown) => void
|
|
const preferred = vi.fn(
|
|
() =>
|
|
new Promise<string>((_resolve, reject) => {
|
|
releaseProbe = reject
|
|
})
|
|
)
|
|
const first = cache.runWithFallback(
|
|
'native',
|
|
preferred,
|
|
() => Promise.resolve('fallback'),
|
|
isUnsupported
|
|
)
|
|
const second = cache.runWithFallback(
|
|
'native',
|
|
preferred,
|
|
() => Promise.resolve('fallback'),
|
|
isUnsupported
|
|
)
|
|
await Promise.resolve()
|
|
releaseProbe(unsupportedError)
|
|
|
|
await expect(first).resolves.toBe('fallback')
|
|
await expect(second).resolves.toBe('fallback')
|
|
expect(preferred).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('lets a waiter run its own work once the in-flight probe reports support', async () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
let releaseProbe!: (value: string) => void
|
|
const firstPreferred = vi.fn(
|
|
() =>
|
|
new Promise<string>((resolve) => {
|
|
releaseProbe = resolve
|
|
})
|
|
)
|
|
const secondPreferred = vi.fn(() => Promise.resolve('second'))
|
|
const first = cache.runWithFallback(
|
|
'native',
|
|
firstPreferred,
|
|
() => Promise.resolve('fallback'),
|
|
isUnsupported
|
|
)
|
|
const second = cache.runWithFallback(
|
|
'native',
|
|
secondPreferred,
|
|
() => Promise.resolve('fallback'),
|
|
isUnsupported
|
|
)
|
|
await Promise.resolve()
|
|
releaseProbe('first')
|
|
|
|
await expect(first).resolves.toBe('first')
|
|
await expect(second).resolves.toBe('second')
|
|
expect(secondPreferred).toHaveBeenCalledTimes(1)
|
|
})
|
|
|
|
it('isolates in-flight probes per host so a cold WSL distro never waits on native', async () => {
|
|
const cache = new CodexAppServerCapabilityCache()
|
|
const nativePreferred = vi.fn(() => new Promise<string>(() => {}))
|
|
void cache.runWithFallback(
|
|
'native',
|
|
nativePreferred,
|
|
() => Promise.resolve('fallback'),
|
|
isUnsupported
|
|
)
|
|
const wslPreferred = vi.fn(() => Promise.resolve('wsl-result'))
|
|
await expect(
|
|
cache.runWithFallback(
|
|
'wsl:Ubuntu',
|
|
wslPreferred,
|
|
() => Promise.resolve('fallback'),
|
|
isUnsupported
|
|
)
|
|
).resolves.toBe('wsl-result')
|
|
})
|
|
|
|
it('builds host keys that keep WSL distros apart', () => {
|
|
expect(getCodexAppServerHostKey({ kind: 'native' })).toBe('native')
|
|
expect(getCodexAppServerHostKey({ kind: 'wsl', distro: 'Ubuntu' })).toBe('wsl:Ubuntu')
|
|
expect(getCodexAppServerHostKey({ kind: 'wsl', distro: 'Debian' })).toBe('wsl:Debian')
|
|
})
|
|
})
|