OmniVoice-Studio / frontend /src /utils /errorDocsMap.ts
Lê Phi Nam
Deploy to HF Space
94004a2
Raw
History Blame Contribute Delete
2.97 kB
// MIRROR OF backend/core/error_docs_map.py — keep in sync.
// The Python test_keys_match_python_map / test_keys_match_taxonomy guards
// the 4-class taxonomy on the backend; the `_KEYS` array below is the
// TS-side anchor (the keys-sync test imports it and asserts equality).
//
// This `BASE` constant is the SECOND hardcoded URL drift site: the
// canonical Python-side resolver is `backend/core/links.py`
// (`PROJECT_REPO_BLOB_MAIN`). The TS half runs in the browser and can't
// read `pyproject.toml`, so it gets a hand-maintained mirror. Centralising
// the URL on the TS side is a v0.4 concern — the milestone accepts the
// drift risk and relies on the keys-sync test + threat-model T-02-01
// to bound the blast radius.
import { openExternal } from '../api/external';
const BASE = 'https://github.com/debpalash/OmniVoice-Studio/blob/main';
export const ERROR_DOCS: Record<string, string> = {
GATEKEEPER_QUARANTINE: `${BASE}/docs/install/macos.md#gatekeeper-quarantine`,
APPIMAGE_WEBKIT_WHITESCREEN: `${BASE}/docs/install/linux.md#appimage-white-screen-on-fedora-44--ubuntu-2404`,
PKG_RESOURCES_MISSING: `${BASE}/docs/install/troubleshooting.md#pkg_resources-missing`,
HF_AUTH_FAILED: `${BASE}/docs/setup/huggingface-token.md`,
};
export const DEFAULT_DOCS = `${BASE}/docs/install/troubleshooting.md`;
// Locked taxonomy keys — Phase 5 bug reporter consumes this exact set.
// Adding a 5th class is a contract change; update the Python map at the
// same time (`backend/core/error_docs_map.py`).
export const ERROR_CLASS_KEYS = [
'GATEKEEPER_QUARANTINE',
'APPIMAGE_WEBKIT_WHITESCREEN',
'PKG_RESOURCES_MISSING',
'HF_AUTH_FAILED',
] as const;
export type ErrorClass = (typeof ERROR_CLASS_KEYS)[number];
/**
* Heuristic error message → ErrorClass classifier. ErrorBoundary uses this
* when the thrown Error doesn't carry an explicit `errorClass` property.
*/
export function classifyError(error: unknown): ErrorClass | null {
const message =
(error as { message?: string } | null | undefined)?.message ?? String(error ?? '');
const lower = message.toLowerCase();
if (/pkg_resources/.test(lower)) return 'PKG_RESOURCES_MISSING';
if (/\b401\b/.test(lower) || /hfhub|hfhubhttp/.test(lower) || /unauthorized/.test(lower)) {
return 'HF_AUTH_FAILED';
}
if (/webkit/.test(lower) || /white\s*screen/.test(lower)) {
return 'APPIMAGE_WEBKIT_WHITESCREEN';
}
if (/quarantine/.test(lower) || /gatekeeper/.test(lower)) return 'GATEKEEPER_QUARANTINE';
return null;
}
export function urlFor(errorClass: ErrorClass | null | undefined): string {
if (!errorClass) return DEFAULT_DOCS;
return ERROR_DOCS[errorClass] ?? DEFAULT_DOCS;
}
/** Open the docs URL for `errorClass` in the user's default browser. */
export async function openDocsFor(
errorClass: ErrorClass | string | null | undefined,
): Promise<void> {
const url = ERROR_DOCS[errorClass as string] ?? DEFAULT_DOCS;
await openExternal(url);
}