mirror of
https://github.com/stablyai/orca.git
synced 2026-11-04 19:17:28 +00:00
All hosts gave every Orca server a 3 s scan, including the managed servers Orca reaches through an SSH tunnel, which now serve every SSH host. A healthy SSH host walking a large home timed out and showed up empty. The saved environment's connectionDependency now picks the 15 s budget for tunnelled servers; direct LAN/Tailscale servers keep 3 s. Reported, with the proposed approach, by @quzard in #31139.
This commit is contained in:
@@ -33,12 +33,16 @@ describe('runtime AI Vault session scanner', () => {
|
||||
it('lists saved runtime environments as runtime execution hosts', () => {
|
||||
mocks.listEnvironments.mockReturnValue([
|
||||
{ id: 'env-1', name: 'Server 1' },
|
||||
{ id: 'env-2', name: 'Server 2' }
|
||||
{ id: 'env-2', name: 'Server 2', connectionDependency: 'ssh-tunnel' }
|
||||
])
|
||||
|
||||
expect(getSavedRuntimeAiVaultHostInfos('/user-data')).toEqual([
|
||||
{ environmentId: 'env-1', executionHostId: 'runtime:env-1' },
|
||||
{ environmentId: 'env-2', executionHostId: 'runtime:env-2' }
|
||||
{
|
||||
environmentId: 'env-2',
|
||||
executionHostId: 'runtime:env-2',
|
||||
connectionDependency: 'ssh-tunnel'
|
||||
}
|
||||
])
|
||||
})
|
||||
|
||||
|
||||
@@ -21,11 +21,7 @@ import type {
|
||||
import { parseAiVaultListResult } from './session-list-result-validation'
|
||||
import { parseAiVaultSessionTitlesResult } from './session-title-result-validation'
|
||||
import { isGatedOffWslHost } from '../wsl/wsl-host-gate'
|
||||
|
||||
export type RuntimeAiVaultHostInfo = {
|
||||
environmentId: string
|
||||
executionHostId: `runtime:${string}`
|
||||
}
|
||||
import type { RuntimeAiVaultHostInfo } from '../ipc/ai-vault-runtime-scan'
|
||||
|
||||
export type RuntimeAiVaultScanOptions = {
|
||||
timeoutMs?: number
|
||||
@@ -53,7 +49,10 @@ export function getSavedRuntimeAiVaultHostInfos(
|
||||
.filter((environment) => !isGatedOffWslHost(environment))
|
||||
.map((environment) => ({
|
||||
environmentId: environment.id,
|
||||
executionHostId: toRuntimeExecutionHostId(environment.id)
|
||||
executionHostId: toRuntimeExecutionHostId(environment.id),
|
||||
...(environment.connectionDependency
|
||||
? { connectionDependency: environment.connectionDependency }
|
||||
: {})
|
||||
}))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
import type { RuntimeAiVaultHostInfo } from './ai-vault-runtime-scan'
|
||||
|
||||
// Per-leg bounds for the all-hosts fan-outs, so one slow host cannot hold a merge open.
|
||||
export const AI_VAULT_ALL_HOST_TIMEOUT_MS = {
|
||||
runtimeScan: 3_000,
|
||||
// Why: a remote home with many agent roots routinely needs seconds to walk,
|
||||
// stat and parse. The old shared 3s bound emptied healthy SSH hosts in the
|
||||
// all-hosts view; the relay gets a real scan budget and the whole leg (relay
|
||||
// attempt plus any legacy crawl) stays bounded.
|
||||
sshScanRelay: 15_000,
|
||||
sshScan: 20_000,
|
||||
// A search reads an index rather than walking a home, but it shares the relay
|
||||
// with the scans, so it gets the relay budget rather than one of its own.
|
||||
// all-hosts view; a server reached over an SSH tunnel walks the same home
|
||||
// plus the tunnel's latency, so it gets a real scan budget.
|
||||
sshTunneledRuntimeScan: 15_000,
|
||||
// A search reads an index rather than walking a home, but it shares the
|
||||
// connection with the scans, so it gets the SSH scan budget.
|
||||
search: 15_000
|
||||
} as const
|
||||
|
||||
export function allHostsRuntimeScanTimeoutMs(
|
||||
hostInfo: Pick<RuntimeAiVaultHostInfo, 'connectionDependency'>
|
||||
): number {
|
||||
return hostInfo.connectionDependency === 'ssh-tunnel'
|
||||
? AI_VAULT_ALL_HOST_TIMEOUT_MS.sshTunneledRuntimeScan
|
||||
: AI_VAULT_ALL_HOST_TIMEOUT_MS.runtimeScan
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@ import { aiVaultScanIssueResult } from '../ai-vault/session-list-results'
|
||||
export type RuntimeAiVaultHostInfo = {
|
||||
environmentId: string
|
||||
executionHostId: `runtime:${string}`
|
||||
/** The saved environment's own record of how it is reached; picks the all-hosts scan budget. */
|
||||
connectionDependency?: 'ssh-tunnel'
|
||||
}
|
||||
|
||||
export type RuntimeAiVaultScanOptions = {
|
||||
|
||||
@@ -96,6 +96,27 @@ describe('listAiVaultSessions host routing', () => {
|
||||
)
|
||||
})
|
||||
|
||||
it('gives servers reached over an SSH tunnel the longer all-hosts scan budget', async () => {
|
||||
registerAiVaultHandlers({
|
||||
getActiveRuntimeAiVaultHostInfos: () => [
|
||||
{ environmentId: 'lan-server', executionHostId: 'runtime:lan-server' },
|
||||
{
|
||||
environmentId: 'ssh-server',
|
||||
executionHostId: 'runtime:ssh-server',
|
||||
connectionDependency: 'ssh-tunnel'
|
||||
}
|
||||
],
|
||||
scanRuntimeAiVaultSessions: mocks.scanRuntimeAiVaultSessions
|
||||
})
|
||||
|
||||
await _internals.listAiVaultSessions({ executionHostScope: 'all', force: true })
|
||||
|
||||
const timeoutFor = (environmentId: string): unknown =>
|
||||
mocks.scanRuntimeAiVaultSessions.mock.calls.find(([id]) => id === environmentId)?.[2]
|
||||
expect(timeoutFor('lan-server')).toEqual({ timeoutMs: 3_000 })
|
||||
expect(timeoutFor('ssh-server')).toEqual({ timeoutMs: 15_000 })
|
||||
})
|
||||
|
||||
it('keeps direct runtime host scans on the normal runtime timeout', async () => {
|
||||
registerAiVaultHandlers({
|
||||
getActiveRuntimeAiVaultHostInfos: () => [],
|
||||
|
||||
@@ -59,7 +59,7 @@ import {
|
||||
OPENS_EVERY_STRUCTURED_CHAT,
|
||||
projectStructuredAiVaultSessions
|
||||
} from '../ai-vault/structured-session-ownership'
|
||||
import { AI_VAULT_ALL_HOST_TIMEOUT_MS } from './ai-vault-all-host-timeouts'
|
||||
import { allHostsRuntimeScanTimeoutMs } from './ai-vault-all-host-timeouts'
|
||||
import { registerAiVaultScanProgressBroadcast } from './ai-vault-scan-progress-broadcast'
|
||||
|
||||
type AiVaultHandlerOptions = AiVaultSessionSources &
|
||||
@@ -156,7 +156,7 @@ async function scanAiVaultSessionsByHostScope(
|
||||
listArgs: args ? { ...args, afterFingerprint: undefined } : undefined,
|
||||
options: {
|
||||
signal,
|
||||
timeoutMs: AI_VAULT_ALL_HOST_TIMEOUT_MS.runtimeScan
|
||||
timeoutMs: allHostsRuntimeScanTimeoutMs(hostInfo)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user