Files
openclaw/packages/memory-host-sdk/src/host/embedding-worker-errors.ts
Onur Solmaz 7ff29a9e6d Fix local embedding worker safety (#85348)
Summary:
- The PR routes local GGUF memory embeddings through a bundled worker sidecar, adds structured degradation and fallback handling, updates memory tests/build output, and keeps the local config contract unchanged.
- PR surface: Source +831, Tests +503, Docs +1, Other +2. Total +1337 across 23 files.
- Reproducibility: Do we have a high-confidence way to reproduce the issue? Source and report evidence are str ... cludes native crash logs; the exact Metal teardown abort was not reproduced in this review or the PR proof.

Automerge notes:
- PR branch already contained follow-up commit before automerge: fix(memory): keep local embedding config unchanged
- PR branch already contained follow-up commit before automerge: fix(memory): type local embedding degradation
- PR branch already contained follow-up commit before automerge: fix(memory): refresh keywords after embedding fallback
- PR branch already contained follow-up commit before automerge: fix(memory): keep worker errors internal
- PR branch already contained follow-up commit before automerge: test: satisfy memory provider lifecycle harnesses
- PR branch already contained follow-up commit before automerge: fix: harden local embedding worker fallback

Validation:
- ClawSweeper review passed for head 1d1fe41c4e.
- Required merge gates passed before the squash merge.

Prepared head SHA: 1d1fe41c4e
Review: https://github.com/openclaw/openclaw/pull/85348#issuecomment-4518516047

Co-authored-by: Onur Solmaz <onur@Onurs-MacBook-Pro.local>
Co-authored-by: clawsweeper <274271284+clawsweeper[bot]@users.noreply.github.com>
Co-authored-by: clawsweeper[bot] <274271284+clawsweeper[bot]@users.noreply.github.com>
Approved-by: osolmaz
Co-authored-by: osolmaz <2453968+osolmaz@users.noreply.github.com>
2026-05-25 11:03:04 +00:00

48 lines
1.6 KiB
TypeScript

export const LOCAL_EMBEDDING_WORKER_ERROR_CODES = {
exited: "LOCAL_EMBEDDING_WORKER_EXITED",
processError: "LOCAL_EMBEDDING_WORKER_PROCESS_ERROR",
ipcError: "LOCAL_EMBEDDING_WORKER_IPC_ERROR",
} as const;
export type LocalEmbeddingWorkerFailureCode =
(typeof LOCAL_EMBEDDING_WORKER_ERROR_CODES)[keyof typeof LOCAL_EMBEDDING_WORKER_ERROR_CODES];
export type LocalEmbeddingWorkerFailureReason = "exit" | "signal" | "process-error" | "ipc";
export type LocalEmbeddingWorkerFailureError = Error & {
code: LocalEmbeddingWorkerFailureCode;
reason: LocalEmbeddingWorkerFailureReason;
exitCode?: number | null;
signal?: NodeJS.Signals | null;
};
const LOCAL_EMBEDDING_WORKER_FAILURE_CODES = new Set<string>(
Object.values(LOCAL_EMBEDDING_WORKER_ERROR_CODES),
);
export function createLocalEmbeddingWorkerFailureError(params: {
message: string;
code: LocalEmbeddingWorkerFailureCode;
reason: LocalEmbeddingWorkerFailureReason;
exitCode?: number | null;
signal?: NodeJS.Signals | null;
cause?: unknown;
}): LocalEmbeddingWorkerFailureError {
return Object.assign(new Error(params.message), {
code: params.code,
reason: params.reason,
...(params.exitCode !== undefined ? { exitCode: params.exitCode } : {}),
...(params.signal !== undefined ? { signal: params.signal } : {}),
...(params.cause !== undefined ? { cause: params.cause } : {}),
});
}
export function isLocalEmbeddingWorkerFailure(
err: unknown,
): err is LocalEmbeddingWorkerFailureError {
return (
err instanceof Error &&
LOCAL_EMBEDDING_WORKER_FAILURE_CODES.has(String((err as { code?: unknown }).code))
);
}