refactor(memory): localize host SDK internals (#101508)

This commit is contained in:
Vincent Koc 2026-07-07 01:50:53 -07:00 committed by GitHub
parent c1f9087e8e
commit 2e4e982ff0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 31 additions and 42 deletions

View file

@ -8,14 +8,14 @@ export const LOCAL_EMBEDDING_WORKER_ERROR_CODES = {
} as const;
/** Error code union for local embedding worker failures. */
export type LocalEmbeddingWorkerFailureCode =
type LocalEmbeddingWorkerFailureCode =
(typeof LOCAL_EMBEDDING_WORKER_ERROR_CODES)[keyof typeof LOCAL_EMBEDDING_WORKER_ERROR_CODES];
/** Cause category for local embedding worker failures. */
type LocalEmbeddingWorkerFailureReason = "exit" | "signal" | "process-error" | "ipc";
/** Error shape used by callers that need retry/status decisions. */
export type LocalEmbeddingWorkerFailureError = Error & {
/** Error shape returned by the local embedding worker failure factory. */
type LocalEmbeddingWorkerFailureError = Error & {
code: LocalEmbeddingWorkerFailureCode;
reason: LocalEmbeddingWorkerFailureReason;
exitCode?: number | null;

View file

@ -8,7 +8,6 @@ export {
assertNoSymlinkParents,
readRegularFile,
statRegularFile,
type RegularFileStatResult,
} from "@openclaw/fs-safe/advanced";
export { walkDirectory, type WalkDirectoryEntry } from "@openclaw/fs-safe/walk";

View file

@ -1,7 +1,7 @@
// Minimal node-llama-cpp type facade used by the local embedding provider.
/** Embedding vector returned by node-llama-cpp. */
export type LlamaEmbedding = {
type LlamaEmbedding = {
vector: Float32Array | number[];
};
@ -21,7 +21,7 @@ export type LlamaModel = {
};
/** Options accepted by node-llama-cpp model file resolution. */
export type ResolveModelFileOptions = {
type ResolveModelFileOptions = {
directory?: string;
signal?: AbortSignal;
};

View file

@ -1,37 +1,12 @@
// Memory Host SDK tests cover retry utils behavior.
import { afterEach, describe, expect, it, vi } from "vitest";
import { MAX_SAFE_TIMEOUT_DELAY_MS } from "../../../gateway-client/src/timeouts.js";
import { resolveRetryConfig, retryAsync } from "./retry-utils.js";
import { retryAsync } from "./retry-utils.js";
afterEach(() => {
vi.restoreAllMocks();
});
describe("resolveRetryConfig", () => {
const defaults = {
attempts: 4,
minDelayMs: 0,
maxDelayMs: 0,
jitter: 0,
};
it("does not round malformed attempt counts", () => {
expect(resolveRetryConfig(defaults, { attempts: 1.5 }).attempts).toBe(4);
expect(resolveRetryConfig(defaults, { attempts: Number.POSITIVE_INFINITY }).attempts).toBe(4);
expect(resolveRetryConfig(defaults, { attempts: Number.NaN }).attempts).toBe(4);
});
it("caps oversized retry delays at the timer-safe ceiling", () => {
const config = resolveRetryConfig(defaults, {
minDelayMs: Number.MAX_SAFE_INTEGER,
maxDelayMs: Number.MAX_SAFE_INTEGER,
});
expect(config.minDelayMs).toBe(MAX_SAFE_TIMEOUT_DELAY_MS);
expect(config.maxDelayMs).toBe(MAX_SAFE_TIMEOUT_DELAY_MS);
});
});
describe("retryAsync", () => {
it("falls back to the default attempt count for malformed numeric counts", async () => {
const run = vi.fn(async () => {
@ -43,6 +18,22 @@ describe("retryAsync", () => {
expect(run).toHaveBeenCalledTimes(3);
});
it("falls back to the default attempt count for malformed option counts", async () => {
const run = vi.fn(async () => {
throw new Error("boom");
});
await expect(
retryAsync(run, {
attempts: 1.5,
minDelayMs: 0,
maxDelayMs: 0,
}),
).rejects.toThrow("boom");
expect(run).toHaveBeenCalledTimes(3);
});
it("caps legacy numeric retry sleeps at the timer-safe ceiling", async () => {
const run = vi
.fn<() => Promise<string>>()

View file

@ -2,7 +2,7 @@
import { resolveSafeTimeoutDelayMs } from "../../../gateway-client/src/timeouts.js";
/** Retry timing configuration with optional jitter. */
export type RetryConfig = {
type RetryConfig = {
attempts?: number;
minDelayMs?: number;
maxDelayMs?: number;
@ -10,7 +10,7 @@ export type RetryConfig = {
};
/** Retry callback payload. */
export type RetryInfo = {
type RetryInfo = {
attempt: number;
maxAttempts: number;
delayMs: number;
@ -19,7 +19,7 @@ export type RetryInfo = {
};
/** Retry options for retryAsync. */
export type RetryOptions = RetryConfig & {
type RetryOptions = RetryConfig & {
label?: string;
shouldRetry?: (err: unknown, attempt: number) => boolean;
retryAfterMs?: (err: unknown) => number | undefined;
@ -64,7 +64,7 @@ function resolveAttempts(value: unknown, fallback: number): number {
}
/** Resolve retry settings with clamped positive timeout values. */
export function resolveRetryConfig(
function resolveRetryConfig(
defaults: Required<RetryConfig> = DEFAULT_RETRY_CONFIG,
overrides?: RetryConfig,
): Required<RetryConfig> {

View file

@ -1,10 +1,10 @@
// Secret input parsing shared by memory provider config and gateway-resolved snapshots.
/** Supported secret reference backing stores. */
export type SecretRefSource = "env" | "file" | "exec";
type SecretRefSource = "env" | "file" | "exec";
/** Canonical secret reference shape used after gateway resolution. */
export type SecretRef = {
type SecretRef = {
source: SecretRefSource;
provider: string;
id: string;

View file

@ -34,7 +34,6 @@ import type { MemorySessionSyncTarget } from "./types.js";
export {
listSessionTranscriptCorpusEntriesForAgent,
type SessionTranscriptCorpusArtifactKind,
type SessionTranscriptCorpusEntry,
} from "./session-transcript-corpus.js";
@ -241,7 +240,7 @@ function isCanonicalSessionsDirForAgent(sessionsDir: string, agentId: string): b
);
}
export function loadSessionTranscriptClassificationForSessionsDir(
function loadSessionTranscriptClassificationForSessionsDir(
sessionsDir: string,
): SessionTranscriptClassification {
const agentId = extractAgentIdFromSessionsDir(sessionsDir);

View file

@ -18,7 +18,7 @@ import {
type SessionEntry,
} from "./openclaw-runtime-session.js";
export type SessionTranscriptCorpusArtifactKind =
type SessionTranscriptCorpusArtifactKind =
| "active-session"
| "archive-artifact"
| "orphan-file-artifact";

View file

@ -1,7 +1,7 @@
// Small string normalization helpers kept local to memory-host-sdk for package
// builds that should not depend on the full normalization package graph.
/** Normalize a non-empty string or return null. */
export function normalizeNullableString(value: unknown): string | null {
function normalizeNullableString(value: unknown): string | null {
if (typeof value !== "string") {
return null;
}