mirror of
https://github.com/stablyai/orca.git
synced 2026-09-30 16:02:56 +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
51 lines
2.2 KiB
TypeScript
51 lines
2.2 KiB
TypeScript
/**
|
|
* Maps the session scanner's internal supervision errors onto copy a user can
|
|
* act on. Applied at both surfaces the panel paints: the local leg's scan-issue
|
|
* row and the thrown-rejection banner. Anything unrecognized passes through, so
|
|
* scanner-authored messages (host name, remote path, cap) keep their own wording.
|
|
*/
|
|
const RETRY = 'Refresh to try again.'
|
|
|
|
/** Electron wraps every rejected `ipcMain.handle` before the renderer sees it. */
|
|
const IPC_INVOKE_PREFIX = /^Error invoking remote method '[^']*': (?:\w*Error: )?/
|
|
/** Relay-hosted scanner errors carry a transport-only `Relay ` prefix. */
|
|
const RELAY_PREFIX = /^Relay (?=AI Vault )/
|
|
/** Both the fork-based service and the legacy worker thread emit this family. */
|
|
const SCANNER = String.raw`AI Vault (?:service|scanner worker)`
|
|
|
|
function toSeconds(ms: string): number {
|
|
return Math.max(1, Math.round(Number(ms) / 1000))
|
|
}
|
|
|
|
function humanize(text: string): string | null {
|
|
const sshTimeout = /^Agent Session History scan timed out after (\d+)ms on this SSH host\.$/.exec(
|
|
text
|
|
)
|
|
if (sshTimeout) {
|
|
return `Session scan timed out after ${toSeconds(sshTimeout[1]!)}s on this SSH host. ${RETRY}`
|
|
}
|
|
const timeout = new RegExp(String.raw`^${SCANNER} timed out after (\d+)ms\.$`).exec(text)
|
|
if (timeout) {
|
|
return `Session scan timed out after ${toSeconds(timeout[1]!)}s — the machine may be busy. ${RETRY}`
|
|
}
|
|
if (text === 'AI Vault service restart circuit is open.') {
|
|
return `Session scanning paused after repeated failures. ${RETRY}`
|
|
}
|
|
if (new RegExp(String.raw`^${SCANNER} (?:client )?queue is full\.$`).test(text)) {
|
|
return 'Too many session scans in flight. Wait a moment, then refresh.'
|
|
}
|
|
if (new RegExp(String.raw`^${SCANNER} entry not found: `).test(text)) {
|
|
return 'The session scanner is missing from this Orca install. Reinstalling Orca restores it.'
|
|
}
|
|
if (new RegExp(String.raw`^${SCANNER}\b`).test(text)) {
|
|
return `The session scanner stopped unexpectedly. ${RETRY}`
|
|
}
|
|
return null
|
|
}
|
|
|
|
/** Returns user-facing copy, or the original text when it is already meaningful. */
|
|
export function describeAiVaultScanError(raw: string): string {
|
|
const text = raw.replace(IPC_INVOKE_PREFIX, '').replace(RELAY_PREFIX, '')
|
|
return humanize(text) ?? text
|
|
}
|