Iostream-Li's picture
Add files using upload-large-folder tool
ff78003 verified
Raw
History Blame Contribute Delete
3.27 kB
/**
* 显式错误类型 — 上层调用方(B4 reviewer / B5 evolution / B6 mutator)
* **必须**显式 catch 以下类型,不允许 generic try/catch 后默默走 NEUTRAL/0.5
* fallback。这是反欺骗的硬约束:LLM 离线、超预算、输出违约 都必须让
* 上层"看见",由上层 自行决定 是否走 heuristic fallback、是否登记
* lifecycle 事件。
*
* 不要在调用 `llmRoleClient` 的地方写:
* ```ts
* try { ... } catch { return NEUTRAL; } // ❌ 静默,违反反欺骗
* ```
*
* 应当写:
* ```ts
* try {
* const r = await llmRoleClient(...);
* ...
* } catch (e) {
* if (e instanceof LlmRoleDisabled) { ... 走 heuristic 并 logAlert ... }
* if (e instanceof LlmRoleBudgetExceeded) { ... 同上 ... }
* throw e; // 其他错误必须冒泡
* }
* ```
*/
abstract class LlmRoleErrorBase extends Error {
abstract readonly status: string;
constructor(message: string) {
super(message);
this.name = new.target.name;
}
}
/** `CAPABILITY_LLM_ENABLED=false` 时所有角色调用都抛此错。 */
export class LlmRoleDisabled extends LlmRoleErrorBase {
readonly status = "disabled";
constructor(reason = "CAPABILITY_LLM_ENABLED is false") {
super(reason);
}
}
/** 该 (capability, role) 当日花销已达 / 超过 daily_limit_usd。 */
export class LlmRoleBudgetExceeded extends LlmRoleErrorBase {
readonly status = "budget_exceeded";
constructor(
public readonly capabilityId: string | null,
public readonly role: string,
public readonly spent: number,
public readonly limit: number,
) {
super(
`Daily LLM budget exceeded for capability=${capabilityId ?? "global"} role=${role}: spent=$${spent.toFixed(4)} limit=$${limit.toFixed(4)}`,
);
}
}
/** Zod validate 输出失败,1 次重试后仍失败。 */
export class LlmRoleResponseInvalid extends LlmRoleErrorBase {
readonly status = "invalid_response";
constructor(
public readonly role: string,
public readonly zodIssues: unknown,
public readonly rawText: string,
) {
super(`LLM role=${role} response did not validate after retry`);
}
}
/** 单次调用 timeout(role-specific timeout 触发)。 */
export class LlmRoleTimeout extends LlmRoleErrorBase {
readonly status = "timeout";
constructor(
public readonly role: string,
public readonly timeoutMs: number,
) {
super(`LLM role=${role} timed out after ${timeoutMs}ms`);
}
}
/** Gateway 熔断中或没 provider — 上层应走 heuristic fallback。 */
export class LlmRoleProviderUnavailable extends LlmRoleErrorBase {
readonly status = "provider_unavailable";
constructor(
public readonly role: string,
public readonly providerErrorCode: string,
detail = "",
) {
super(
`LLM role=${role} provider unavailable: ${providerErrorCode}${detail ? " — " + detail : ""}`,
);
}
}
/** 共用类型守卫 — 让上层一行判断"这是 plumbing 层抛的可处理错误"。 */
export function isLlmRoleError(err: unknown): err is LlmRoleErrorBase {
return err instanceof LlmRoleErrorBase;
}
export type LlmRoleErrorStatus =
| "disabled"
| "budget_exceeded"
| "invalid_response"
| "timeout"
| "provider_unavailable";