mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-17 01:19:40 +02:00
Adding an app to a workbench scene threw DataCloneError. scenesState is a $state array, so current.openApps was a Svelte 5 proxy and spreading it into a new array left proxy entries inside; IndexedDB's structured clone refuses to serialise those. Snapshot before handing the array to patchScene / createScene so Dexie sees plain objects. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
80 lines
2.4 KiB
TypeScript
80 lines
2.4 KiB
TypeScript
/**
|
|
* Typed error classes for the LLM orchestrator. UI code can `instanceof`
|
|
* these to render task-appropriate failure states (retry button, switch
|
|
* tier prompt, "blocked by safety filter" notice, etc.).
|
|
*/
|
|
|
|
import type { LlmTier } from './tiers';
|
|
|
|
export class LlmError extends Error {
|
|
constructor(message: string) {
|
|
super(message);
|
|
this.name = 'LlmError';
|
|
}
|
|
}
|
|
|
|
/** No tier from the user's preference list was able to run the task. */
|
|
export class NoTierAvailableError extends LlmError {
|
|
constructor(
|
|
public readonly taskName: string,
|
|
public readonly attempted: LlmTier[]
|
|
) {
|
|
super(`No tier could run task '${taskName}' (attempted: ${attempted.join(', ') || 'none'})`);
|
|
this.name = 'NoTierAvailableError';
|
|
}
|
|
}
|
|
|
|
/** The user's chosen tier is below the task's declared minimum tier. */
|
|
export class TierTooLowError extends LlmError {
|
|
constructor(
|
|
public readonly taskName: string,
|
|
public readonly requiredTier: LlmTier,
|
|
public readonly userTier: LlmTier
|
|
) {
|
|
super(
|
|
`Task '${taskName}' requires tier '${requiredTier}' but user is on '${userTier}'. Activate the higher tier in settings.`
|
|
);
|
|
this.name = 'TierTooLowError';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The upstream provider blocked the content (e.g. Gemini safety filter,
|
|
* OpenAI moderation). The UI should offer "retry" + "switch to another
|
|
* provider" options to the user — this is NOT auto-recoverable because
|
|
* a different provider might allow the same content (or might not).
|
|
*/
|
|
export class ProviderBlockedError extends LlmError {
|
|
constructor(
|
|
public readonly tier: LlmTier,
|
|
public readonly providerMessage: string
|
|
) {
|
|
super(`Provider '${tier}' blocked the request: ${providerMessage}`);
|
|
this.name = 'ProviderBlockedError';
|
|
}
|
|
}
|
|
|
|
/** Network/server error from a remote tier (mana-server, cloud). */
|
|
export class BackendUnreachableError extends LlmError {
|
|
constructor(
|
|
public readonly tier: LlmTier,
|
|
public readonly httpStatus?: number,
|
|
details?: string
|
|
) {
|
|
super(
|
|
`Backend '${tier}' is unreachable${httpStatus ? ` (HTTP ${httpStatus})` : ''}${details ? `: ${details}` : ''}`
|
|
);
|
|
this.name = 'BackendUnreachableError';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The browser tier specifically failed to load — model download
|
|
* interrupted, WebGPU adapter request failed, OOM, etc.
|
|
*/
|
|
export class EdgeLoadFailedError extends LlmError {
|
|
constructor(public readonly cause: string) {
|
|
super(`Edge LLM failed to load: ${cause}`);
|
|
this.name = 'EdgeLoadFailedError';
|
|
}
|
|
}
|