File size: 3,901 Bytes
76289e7 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 | import {
encodeOpenClawStateWorkerError,
hydrateOpenClawStateWorkerError,
retainOpenClawStateWorkerErrorPayload,
type OpenClawStateWorkerErrorPayload,
} from "../state/openclaw-state-worker-error.js";
import {
PluginStateStoreError,
type PluginStateStoreErrorCode,
type PluginStateStoreOperation,
} from "./plugin-state-store.types.js";
type PluginStateWorkerCause =
| { canonical: OpenClawStateWorkerErrorPayload }
| {
name: string;
message: string;
code?: string | number;
errcode?: number;
cause?: PluginStateWorkerCause;
};
export type PluginStateWorkerFailure = {
message: string;
code: PluginStateStoreErrorCode;
operation: PluginStateStoreOperation;
path?: string;
cause?: PluginStateWorkerCause;
};
// Preserve classification fields and causal messages, not arbitrary error properties or stacks.
function captureCause(
value: unknown,
seen = new Set<object>(),
): PluginStateWorkerCause | undefined {
if (value === undefined) {
return undefined;
}
const canonical = encodeOpenClawStateWorkerError(value);
if (canonical) {
return { canonical };
}
if (
value === null ||
typeof value === "string" ||
typeof value === "number" ||
typeof value === "boolean" ||
typeof value === "bigint" ||
typeof value === "symbol"
) {
return { name: "Error", message: String(value) };
}
if (typeof value !== "object") {
return { name: "Error", message: "Unknown SQLite error cause" };
}
if (seen.has(value) || seen.size >= 8) {
return { name: "Error", message: "Additional SQLite error cause omitted" };
}
seen.add(value);
const name = "name" in value && typeof value.name === "string" ? value.name : "Error";
const message = "message" in value && typeof value.message === "string" ? value.message : name;
const code = "code" in value ? value.code : undefined;
const errcode = "errcode" in value ? value.errcode : undefined;
const cause = "cause" in value ? captureCause(value.cause, seen) : undefined;
return {
name,
message,
...(typeof code === "string" || typeof code === "number" ? { code } : {}),
...(typeof errcode === "number" ? { errcode } : {}),
...(cause ? { cause } : {}),
};
}
const errorConstructors = new Map<string, ErrorConstructor>([
["Error", Error],
["TypeError", TypeError],
["SyntaxError", SyntaxError],
["RangeError", RangeError],
["ReferenceError", ReferenceError],
["URIError", URIError],
["EvalError", EvalError],
]);
function restoreCause(value: PluginStateWorkerCause | undefined): Error | undefined {
if (value && "canonical" in value) {
const retained = new Error("SQLite worker error cause");
retainOpenClawStateWorkerErrorPayload(retained, value.canonical);
return hydrateOpenClawStateWorkerError(retained);
}
const Constructor = value ? (errorConstructors.get(value.name) ?? Error) : Error;
return value
? Object.assign(new Constructor(value.message, { cause: restoreCause(value.cause) }), {
name: value.name,
...(value.code === undefined ? {} : { code: value.code }),
...(value.errcode === undefined ? {} : { errcode: value.errcode }),
})
: undefined;
}
export function capturePluginStateWorkerFailure(
error: PluginStateStoreError,
): PluginStateWorkerFailure {
const cause = captureCause(error.cause);
return {
message: error.message,
code: error.code,
operation: error.operation,
...(error.path === undefined ? {} : { path: error.path }),
...(cause ? { cause } : {}),
};
}
export function restorePluginStateWorkerFailure(
error: PluginStateWorkerFailure,
): PluginStateStoreError {
return new PluginStateStoreError(error.message, {
code: error.code,
operation: error.operation,
...(error.path === undefined ? {} : { path: error.path }),
cause: restoreCause(error.cause),
});
}
|