mirror of
https://github.com/stablyai/orca.git
synced 2026-10-23 08:03:39 +00:00
fix(ai-vault): humanize runtime scanner errors
This commit is contained in:
@@ -79,6 +79,14 @@ function makeDispatcher(): RpcDispatcher {
|
||||
return new RpcDispatcher({ runtime, methods: AI_VAULT_METHODS })
|
||||
}
|
||||
|
||||
function makeFailingDispatcher(error: Error): RpcDispatcher {
|
||||
const runtime = {
|
||||
getRuntimeId: () => 'test-runtime',
|
||||
listAiVaultSessions: vi.fn().mockRejectedValue(error)
|
||||
} as unknown as OrcaRuntimeService
|
||||
return new RpcDispatcher({ runtime, methods: AI_VAULT_METHODS })
|
||||
}
|
||||
|
||||
describe('aiVault.resolveSessionTitles handler', () => {
|
||||
beforeEach(() => {
|
||||
resolveAiVaultSessionTitlesInWorker.mockReset()
|
||||
@@ -229,6 +237,17 @@ describe('aiVault.listSessions handler + shared cache', () => {
|
||||
expect(response).toMatchObject({ ok: true, result: makeResult() })
|
||||
})
|
||||
|
||||
it('humanizes scanner supervision errors for remote clients', async () => {
|
||||
const dispatcher = makeFailingDispatcher(new Error('AI Vault service restart circuit is open.'))
|
||||
|
||||
await expect(
|
||||
dispatcher.dispatch(makeRequest('aiVault.listSessions', { limit: 500 }))
|
||||
).resolves.toMatchObject({
|
||||
ok: false,
|
||||
error: { message: 'Session scanning paused after repeated failures. Refresh to try again.' }
|
||||
})
|
||||
})
|
||||
|
||||
it('passes only the first 64 scopePaths to the scanner when a request exceeds the cap', async () => {
|
||||
const dispatcher = makeDispatcher()
|
||||
const scopePaths = Array.from({ length: 65 }, (_, index) => `/p/${index}`)
|
||||
|
||||
@@ -5,6 +5,7 @@ import { restampAiVaultListResult } from '../../../ai-vault/session-list-results
|
||||
import { AI_VAULT_AGENTS, AI_VAULT_SCOPE_PATHS_MAX_COUNT } from '../../../../shared/ai-vault-types'
|
||||
import { AI_VAULT_SESSION_TITLE_REQUEST_MAX_COUNT } from '../../../../shared/ai-vault-session-title'
|
||||
import { LOCAL_EXECUTION_HOST_ID, parseExecutionHostId } from '../../../../shared/execution-host'
|
||||
import { describeAiVaultScanError } from '../../../../shared/ai-vault-scan-error-message'
|
||||
|
||||
// Why: bound limit + scopePaths so a client cannot force an unbounded scan.
|
||||
// Each scopePath is a host-local match prefix (validated/capped, never used for
|
||||
@@ -83,12 +84,18 @@ export const AI_VAULT_METHODS: RpcMethod[] = [
|
||||
name: 'aiVault.listSessions',
|
||||
params: AiVaultListSessionsParams,
|
||||
handler: async (params, { runtime }) => {
|
||||
const result = await runtime.listAiVaultSessions({
|
||||
limit: params.unlimited ? undefined : params.limit,
|
||||
unlimited: params.unlimited,
|
||||
force: params.force,
|
||||
scopePaths: params.scopePaths
|
||||
})
|
||||
let result
|
||||
try {
|
||||
result = await runtime.listAiVaultSessions({
|
||||
limit: params.unlimited ? undefined : params.limit,
|
||||
unlimited: params.unlimited,
|
||||
force: params.force,
|
||||
scopePaths: params.scopePaths
|
||||
})
|
||||
} catch (error) {
|
||||
const raw = error instanceof Error ? error.message : String(error)
|
||||
throw new Error(describeAiVaultScanError(raw))
|
||||
}
|
||||
// Why: web clients consume this response directly (no parent-side retag),
|
||||
// so sessions must come back stamped as the runtime host they addressed.
|
||||
return params.executionHostId
|
||||
|
||||
Reference in New Issue
Block a user