mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 08:03:12 +00:00
* fix(ai-vault): replace scanner internals with actionable panel copy Agent Session History painted the scanner's supervision errors verbatim: "AI Vault service restart circuit is open." and "AI Vault service timed out after 130000ms." Neither tells a user what happened or what to do. Add a shared mapper that rewrites the supervision family into copy tied to an action, passing anything unrecognized through so scanner-authored messages (host name, remote path, cap) keep their own wording. It also strips Electron's `Error invoking remote method` wrapper, which this path never handled. Applied at both surfaces the panel paints: the local leg's scan-issue row and the thrown-rejection banner. Humanizing in main covers remote clients too; the raw text moves to the main log. Also make "Refresh to try again" true. The relay path lets a forced refresh reopen the restart circuit, but on the local path `force` stopped at the cache layer and never reached the supervisor, so the refresh button was inert for the full 60s fault window. The client file sat at 299/300 lines, so extract the child-listener and init-frame wiring into `attachAiVaultServiceChild`, next to the ready-waiter and retirement helpers it belongs with, rather than bumping the max-lines ceiling. * fix(ai-vault): humanize runtime scanner errors * fix(ai-vault): preserve runtime error metadata * fix(ai-vault): normalize wrapped scan errors * fix(ai-vault): preserve non-scanner relay errors * fix(ai-vault): make forced retries cancel backoff
90 lines
3.7 KiB
TypeScript
90 lines
3.7 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { describeAiVaultScanError } from './ai-vault-scan-error-message'
|
|
|
|
describe('describeAiVaultScanError', () => {
|
|
it('replaces the restart-circuit wording with an actionable line', () => {
|
|
expect(describeAiVaultScanError('AI Vault service restart circuit is open.')).toBe(
|
|
'Session scanning paused after repeated failures. Refresh to try again.'
|
|
)
|
|
})
|
|
|
|
it('renders the scan timeout in seconds', () => {
|
|
expect(describeAiVaultScanError('AI Vault service timed out after 130000ms.')).toBe(
|
|
'Session scan timed out after 130s — the machine may be busy. Refresh to try again.'
|
|
)
|
|
})
|
|
|
|
it('keeps the SSH host in the timeout copy', () => {
|
|
expect(
|
|
describeAiVaultScanError(
|
|
'Agent Session History scan timed out after 130000ms on this SSH host.'
|
|
)
|
|
).toBe('Session scan timed out after 130s on this SSH host. Refresh to try again.')
|
|
})
|
|
|
|
it('humanizes the relay-hosted variant of the same fault', () => {
|
|
expect(describeAiVaultScanError('Relay AI Vault service restart circuit is open.')).toBe(
|
|
'Session scanning paused after repeated failures. Refresh to try again.'
|
|
)
|
|
})
|
|
|
|
it('strips the Electron invoke wrapper before matching', () => {
|
|
expect(
|
|
describeAiVaultScanError(
|
|
"Error invoking remote method 'aiVault:listSessions': Error: AI Vault service did not become ready."
|
|
)
|
|
).toBe('The session scanner stopped unexpectedly. Refresh to try again.')
|
|
})
|
|
|
|
it.each([
|
|
['AI Vault service disconnected.', 'The session scanner stopped unexpectedly.'],
|
|
['AI Vault service exited (null).', 'The session scanner stopped unexpectedly.'],
|
|
['AI Vault scanner worker exited with code 1.', 'The session scanner stopped unexpectedly.'],
|
|
['AI Vault service sent a malformed message.', 'The session scanner stopped unexpectedly.']
|
|
])('covers the supervision fault %s', (raw, expected) => {
|
|
expect(describeAiVaultScanError(raw)).toBe(`${expected} Refresh to try again.`)
|
|
})
|
|
|
|
it('routes a missing scanner entry to install guidance, not a retry', () => {
|
|
const described = describeAiVaultScanError('AI Vault service entry not found: /a/b.js')
|
|
expect(described).toBe(
|
|
'The session scanner is missing from this Orca install. Reinstalling Orca restores it.'
|
|
)
|
|
expect(described).not.toContain('Refresh')
|
|
})
|
|
|
|
it('never leaks internal vocabulary a user cannot act on', () => {
|
|
for (const raw of [
|
|
'AI Vault service restart circuit is open.',
|
|
'AI Vault service timed out after 130000ms.',
|
|
'AI Vault service queue is full.',
|
|
'AI Vault service cache invalidation timed out.',
|
|
'AI Vault service did not cancel within 2000ms.',
|
|
'AI Vault service client was disposed.'
|
|
]) {
|
|
const described = describeAiVaultScanError(raw)
|
|
expect(described).not.toMatch(/circuit|ms\.|AI Vault service|scanner worker/)
|
|
}
|
|
})
|
|
|
|
it('passes scanner-authored messages through untouched', () => {
|
|
const authored = 'Could not read /Users/x/.codex/sessions: EACCES'
|
|
expect(describeAiVaultScanError(authored)).toBe(authored)
|
|
expect(describeAiVaultScanError('SSH relay is not ready')).toBe('SSH relay is not ready')
|
|
})
|
|
|
|
it('removes transport wrappers before passing through an unknown message', () => {
|
|
expect(
|
|
describeAiVaultScanError(
|
|
"Error invoking remote method 'aiVault:listSessions': Error: SSH relay is not ready"
|
|
)
|
|
).toBe('SSH relay is not ready')
|
|
expect(describeAiVaultScanError('Relay AI Vault scanner is not ready')).toBe(
|
|
'AI Vault scanner is not ready'
|
|
)
|
|
expect(describeAiVaultScanError('Relay client is not connected')).toBe(
|
|
'Relay client is not connected'
|
|
)
|
|
})
|
|
})
|