openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
978 lines (977 loc) • 39.7 kB
JavaScript
import { D as isRecord, S as resolveGlobalSingleton } from "./number-coercion-CmpLVzZ6.mjs";
import { R as isSqliteLockError, V as markSqliteNativeOpenFailure, a as StartupMaintenanceRequiredError, h as VERSION, o as isStartupMaintenanceKind, t as SqliteSchemaVersionError, z as isSqliteNativeOpenFailure } from "./sqlite-user-version-C7PVO8Wf.mjs";
import "./utils-BfTq4rUg.mjs";
import { t as OpenClawStateDatabaseSchemaMigrationRequiredError } from "./openclaw-state-db-schema-migration-required-DtltEO1E.mjs";
import { S as readOpenClawStateDatabaseFailurePath, T as GatewayStateOwnerContentionError, it as SqliteCoordinatorError, nt as OpenClawStateOwnershipError, rt as OpenClawStateOwnershipMetadataError, st as throwSqliteLifecycleErrors, tt as OpenClawStateExternalOwnershipError, w as OpenClawQuarantineReadCleanupError, x as markOpenClawStateDatabaseFailure } from "./sqlite-readonly-location-cleanup-CmRNKiuM.mjs";
import { deserialize, serialize } from "node:v8";
import "node:fs";
import path from "node:path";
import "node:os";
import "node:crypto";
import { isMainThread, threadId, workerData } from "node:worker_threads";
import fs from "node:fs/promises";
//#region src/state/session-metadata-unavailable-error.ts
var SessionMetadataUnavailableError = class extends Error {
constructor(reason, options, missingTables = []) {
super(`Session metadata unavailable (${[reason, ...missingTables].join(": ")}); retry after the agent store is ready.`, options);
this.reason = reason;
this.missingTables = missingTables;
this.name = "SessionMetadataUnavailableError";
}
};
//#endregion
//#region src/agents/agent-create-error.ts
var DuplicateAgentError = class extends Error {};
//#endregion
//#region src/agents/mcp-oauth-store-error.ts
var McpOAuthStoreCorruptionError = class extends Error {
constructor(storeKey, detail, options) {
super(`MCP OAuth store ${storeKey} is invalid: ${detail}`, options);
this.name = "McpOAuthStoreCorruptionError";
}
};
//#endregion
//#region src/agents/workspace-state-identity.ts
const WORKSPACE_ALIAS_REPOINTED_ERROR_CODE = "WORKSPACE_ALIAS_REPOINTED";
var WorkspaceAliasRepointedError = class extends Error {
constructor(params) {
super(`workspace path alias points to a different current target: ${params.aliasPath} now resolves to ${params.currentWorkspacePath}, but its stored workspace state belongs to ${params.storedWorkspacePath}. Run \`openclaw doctor --fix\` and confirm the move, or use \`openclaw doctor --fix --force\`.`);
this.code = WORKSPACE_ALIAS_REPOINTED_ERROR_CODE;
this.name = "WorkspaceAliasRepointedError";
this.aliasPath = params.aliasPath;
this.storedWorkspacePath = params.storedWorkspacePath;
this.currentWorkspacePath = params.currentWorkspacePath;
}
};
//#endregion
//#region src/config/sessions/goals-operations.types.ts
const SESSION_GOAL_OPERATION_ERROR_CODES = [
"expired",
"operation-conflict",
"session-rebound",
"goal-rebound",
"capacity",
"receipt-invalid",
"invalid"
];
var SessionGoalOperationError = class extends Error {
constructor(code, message) {
super(message);
this.code = code;
this.name = "SessionGoalOperationError";
}
};
//#endregion
//#region src/config/sessions/session-mutation-conflict-error.ts
var SqliteSessionMutationConflictError = class extends Error {
constructor(operationLabel) {
super(`SQLite session state changed while preparing ${operationLabel}`);
this.operationLabel = operationLabel;
this.name = "SqliteSessionMutationConflictError";
}
};
//#endregion
//#region src/config/sessions/session-pending-input-custody-error.ts
/** Custody refusal must not release already accepted input for another dispatch. */
var SessionPendingInputCustodyError = class extends Error {};
//#endregion
//#region src/gateway/worker-environments/session-attachment.ts
var WorkerSessionAlreadyAttachedError = class extends Error {
constructor(sessionId, environmentId) {
super(`Session ${sessionId} is already attached to worker environment ${environmentId}`);
this.sessionId = sessionId;
this.environmentId = environmentId;
}
};
//#endregion
//#region src/plugin-state/plugin-blob-store.types.ts
var PluginBlobStoreError = class extends Error {
constructor(message, options) {
super(message, { cause: options.cause });
this.name = "PluginBlobStoreError";
this.code = options.code;
this.operation = options.operation;
if (options.path) this.path = options.path;
}
};
//#endregion
//#region src/plugin-state/plugin-state-error-cause.ts
function capturePluginStateErrorCause(value, encodeCanonical, seen = /* @__PURE__ */ new Set()) {
if (value === void 0) return;
const canonical = encodeCanonical?.(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 : void 0;
const errcode = "errcode" in value ? value.errcode : void 0;
const errno = "errno" in value ? value.errno : void 0;
return {
name,
message,
...typeof code === "string" || typeof code === "number" ? { errorCode: code } : {},
...typeof errcode === "number" ? { errcode } : {},
...typeof errno === "number" ? { errno } : {},
..."cause" in value ? { cause: capturePluginStateErrorCause(value.cause, encodeCanonical, seen) } : {},
...value instanceof AggregateError ? { errors: value.errors.slice(0, 8).map((error) => capturePluginStateErrorCause(error, encodeCanonical, seen)) } : {}
};
}
//#endregion
//#region src/plugin-state/plugin-state-error.ts
/** Typed error thrown for plugin-state validation and sqlite failures. */
var PluginStateStoreError = class extends Error {
constructor(message, options) {
super(message, { cause: options.cause });
this.name = "PluginStateStoreError";
this.code = options.code;
this.operation = options.operation;
this.owner = options.owner ?? {
pid: process.pid,
threadId,
version: VERSION
};
if (options.path) this.path = options.path;
}
toJSON() {
return {
name: this.name,
message: this.message,
code: this.code,
operation: this.operation,
path: this.path,
owner: this.owner,
cause: capturePluginStateErrorCause(this.cause)
};
}
};
//#endregion
//#region src/secrets/store/secret-store-validation-error.ts
var SecretStoreValidationError = class extends Error {
constructor(code, message) {
super(message);
this.code = code;
this.name = "SecretStoreValidationError";
}
};
const SECRET_STORE_VALUE_MAX_BYTES = 65536;
function isSecretStoreValidationCode(value) {
return value === "SECRET_STORE_INVALID_NAME" || value === "SECRET_STORE_INVALID_ALLOWED_HOST" || value === "SECRET_STORE_VALUE_TOO_LARGE" || value === "SECRET_STORE_VALUE_IN_ARGV" || value === "SECRET_STORE_VALUE_REDACTED" || value === "SECRET_STORE_VALUE_CHANGED" || value === "SECRET_STORE_VALUE_EMPTY";
}
//#endregion
//#region src/skills/lifecycle/upload-store-error.ts
var SkillUploadRequestError = class extends Error {
constructor(..._args) {
super(..._args);
this.name = "SkillUploadRequestError";
}
};
//#endregion
//#region src/skills/skill-library-error.ts
var SkillLibraryError = class extends Error {
constructor(code, message, currentRevision, options) {
super(message, options);
this.code = code;
this.currentRevision = currentRevision;
this.name = "SkillLibraryError";
}
};
//#endregion
//#region src/state/openclaw-agent-db-migration-required.ts
var OpenClawAgentDatabaseMediaMigrationRequiredError = class extends StartupMaintenanceRequiredError {
constructor(pathname, schemaVersion) {
super("agent-media", `OpenClaw agent database ${pathname} uses schema version ${schemaVersion}; run openclaw doctor --fix to migrate persisted media before using it.`);
this.pathname = pathname;
this.schemaVersion = schemaVersion;
this.name = "OpenClawAgentDatabaseMediaMigrationRequiredError";
}
};
//#endregion
//#region src/state/openclaw-state-lease-error.ts
const leaseErrorCodes = [
"OPENCLAW_STATE_LEASE_INVALID_INPUT",
"OPENCLAW_STATE_LEASE_HELD",
"OPENCLAW_STATE_LEASE_ABORTED",
"OPENCLAW_STATE_LEASE_LOST",
"OPENCLAW_STATE_LEASE_STORAGE_FAILED"
];
function isOpenClawStateLeaseErrorCode(value) {
return leaseErrorCodes.some((code) => code === value);
}
var OpenClawStateLeaseError = class extends Error {
constructor(message, options) {
super(message, { cause: options.cause });
this.name = "OpenClawStateLeaseError";
this.code = options.code;
}
};
//#endregion
//#region src/state/openclaw-state-worker-error-identity.ts
const MESSAGE_ONLY_ERRORS = {
"duplicate-agent": DuplicateAgentError,
"session-pending-input-custody": SessionPendingInputCustodyError,
"skill-upload-request": SkillUploadRequestError,
coordinator: SqliteCoordinatorError,
ownership: OpenClawStateOwnershipError,
"newer-schema": SqliteSchemaVersionError,
"range-error": RangeError,
"syntax-error": SyntaxError,
"type-error": TypeError
};
function isMessageOnlyErrorIdentity(node) {
return typeof node.type === "string" && Object.hasOwn(MESSAGE_ONLY_ERRORS, node.type);
}
function identifyError(error) {
if (error instanceof PluginStateStoreError) return {
type: "plugin-state",
stateCode: error.code,
operation: error.operation,
path: error.path,
owner: error.owner
};
if (error instanceof SkillLibraryError) return {
type: "skill-library",
libraryCode: error.code,
...error.currentRevision === void 0 ? {} : { currentRevision: error.currentRevision }
};
if (error instanceof SecretStoreValidationError) return {
type: "secret-store-validation",
secretCode: error.code
};
if (error instanceof WorkerSessionAlreadyAttachedError) return {
type: "worker-session-already-attached",
sessionId: error.sessionId,
environmentId: error.environmentId
};
if (error instanceof PluginBlobStoreError) return {
type: "plugin-blob",
blobCode: error.code,
operation: error.operation,
...error.path === void 0 ? {} : { path: error.path }
};
if (error instanceof WorkspaceAliasRepointedError) return {
type: "workspace-alias-repointed",
aliasPath: error.aliasPath,
storedWorkspacePath: error.storedWorkspacePath,
currentWorkspacePath: error.currentWorkspacePath
};
if (error instanceof McpOAuthStoreCorruptionError) return { type: "mcp-oauth-corruption" };
if (error instanceof SessionGoalOperationError) return {
type: "session-goal-operation",
goalCode: error.code
};
if (error instanceof SqliteSessionMutationConflictError) return {
type: "session-mutation-conflict",
operationLabel: error.operationLabel
};
if (error instanceof SessionMetadataUnavailableError) return {
type: "session-metadata",
reason: error.reason,
missingTables: [...error.missingTables]
};
if (error instanceof GatewayStateOwnerContentionError) return {
type: "state-owner-contention",
databasePath: error.databasePath
};
if (error instanceof OpenClawStateLeaseError) return {
type: "state-lease",
leaseCode: error.code
};
if (error instanceof OpenClawStateOwnershipMetadataError) return {
type: "ownership-metadata",
databasePath: error.databasePath
};
if (error instanceof OpenClawStateExternalOwnershipError) return {
type: "external-ownership",
databasePath: error.databasePath,
managerId: error.managerId
};
if (error instanceof OpenClawStateDatabaseSchemaMigrationRequiredError) return {
type: "state-migration",
kind: error.kind,
pathname: error.pathname
};
if (error instanceof OpenClawAgentDatabaseMediaMigrationRequiredError) return {
type: "agent-media-migration",
pathname: error.pathname,
schemaVersion: error.schemaVersion
};
for (const [type, ErrorType] of Object.entries(MESSAGE_ONLY_ERRORS)) if (error instanceof ErrorType) return { type };
if (error instanceof StartupMaintenanceRequiredError) return {
type: "maintenance",
kind: error.kind
};
return { type: error instanceof AggregateError ? "aggregate" : "error" };
}
function isBlobCode(value) {
return value === "PLUGIN_BLOB_OPEN_FAILED" || value === "PLUGIN_BLOB_WRITE_FAILED" || value === "PLUGIN_BLOB_READ_FAILED" || value === "PLUGIN_BLOB_CORRUPT" || value === "PLUGIN_BLOB_LIMIT_EXCEEDED" || value === "PLUGIN_BLOB_INVALID_INPUT";
}
function isBlobOperation(value) {
return value === "open" || value === "register" || value === "lookup" || value === "delete" || value === "entries" || value === "clear" || value === "sweep";
}
function isSkillLibraryCode(value) {
return value === "IDENTITY_REQUIRED" || value === "FORBIDDEN" || value === "NOT_FOUND" || value === "CONFLICT" || value === "NAME_CONFLICT" || value === "INVALID_BUNDLE" || value === "POLICY_BLOCKED" || value === "AUTHORITY_EXPIRED" || value === "LIMIT";
}
function parseIdentity(node) {
if (isMessageOnlyErrorIdentity(node)) return { type: node.type };
switch (node.type) {
case "plugin-state": {
const codes = [
"PLUGIN_STATE_SQLITE_UNAVAILABLE",
"PLUGIN_STATE_OPEN_FAILED",
"PLUGIN_STATE_WRITE_FAILED",
"PLUGIN_STATE_READ_FAILED",
"PLUGIN_STATE_CORRUPT",
"PLUGIN_STATE_LIMIT_EXCEEDED",
"PLUGIN_STATE_INVALID_INPUT"
];
const operations = [
"load-sqlite",
"open",
"ensure-schema",
"register",
"lookup",
"consume",
"delete",
"entries",
"count",
"clear",
"sweep",
"probe",
"close"
];
const stateCode = codes.find((code) => code === node.stateCode && code === node.code);
const operation = operations.find((candidate) => candidate === node.operation);
const owner = node.owner;
return stateCode && operation && isRecord(owner) && typeof owner.pid === "number" && typeof owner.threadId === "number" && typeof owner.version === "string" && (node.path === void 0 || typeof node.path === "string") ? {
type: node.type,
stateCode,
operation,
owner: {
pid: owner.pid,
threadId: owner.threadId,
version: owner.version
},
...typeof node.path === "string" ? { path: node.path } : {}
} : void 0;
}
case "skill-library": return isSkillLibraryCode(node.libraryCode) && node.code === node.libraryCode && (node.currentRevision === void 0 || typeof node.currentRevision === "string") ? {
type: node.type,
libraryCode: node.libraryCode,
...typeof node.currentRevision === "string" ? { currentRevision: node.currentRevision } : {}
} : void 0;
case "secret-store-validation": return isSecretStoreValidationCode(node.secretCode) && node.code === node.secretCode ? {
type: node.type,
secretCode: node.secretCode
} : void 0;
case "worker-session-already-attached": return typeof node.sessionId === "string" && typeof node.environmentId === "string" ? {
type: node.type,
sessionId: node.sessionId,
environmentId: node.environmentId
} : void 0;
case "workspace-alias-repointed": return typeof node.aliasPath === "string" && typeof node.storedWorkspacePath === "string" && typeof node.currentWorkspacePath === "string" ? {
type: node.type,
aliasPath: node.aliasPath,
storedWorkspacePath: node.storedWorkspacePath,
currentWorkspacePath: node.currentWorkspacePath
} : void 0;
case "error":
case "aggregate":
case "mcp-oauth-corruption": return { type: node.type };
case "session-goal-operation": {
const goalCode = SESSION_GOAL_OPERATION_ERROR_CODES.find((code) => code === node.goalCode);
return goalCode && node.code === goalCode ? {
type: node.type,
goalCode
} : void 0;
}
case "session-mutation-conflict": return typeof node.operationLabel === "string" ? {
type: node.type,
operationLabel: node.operationLabel
} : void 0;
case "session-metadata": return (node.reason === "schema-missing" || node.reason === "table-missing") && Array.isArray(node.missingTables) && node.missingTables.every((table) => typeof table === "string") ? {
type: node.type,
reason: node.reason,
missingTables: [...node.missingTables]
} : void 0;
case "state-owner-contention":
case "ownership-metadata": return typeof node.databasePath === "string" ? {
type: node.type,
databasePath: node.databasePath
} : void 0;
case "external-ownership": return typeof node.databasePath === "string" && typeof node.managerId === "string" ? {
type: node.type,
databasePath: node.databasePath,
managerId: node.managerId
} : void 0;
case "plugin-blob": return isBlobCode(node.blobCode) && node.code === node.blobCode && isBlobOperation(node.operation) && (node.path === void 0 || typeof node.path === "string") ? {
type: node.type,
blobCode: node.blobCode,
operation: node.operation,
...typeof node.path === "string" ? { path: node.path } : {}
} : void 0;
case "state-lease": return isOpenClawStateLeaseErrorCode(node.leaseCode) && node.code === node.leaseCode ? {
type: node.type,
leaseCode: node.leaseCode
} : void 0;
case "maintenance": return isStartupMaintenanceKind(node.kind) ? {
type: node.type,
kind: node.kind
} : void 0;
case "state-migration": return (node.kind === "audit-events-v2" || node.kind === "legacy-cron-run-logs" || node.kind === "legacy-workshop-review-index") && typeof node.pathname === "string" ? {
type: node.type,
kind: node.kind,
pathname: node.pathname
} : void 0;
case "agent-media-migration": return typeof node.pathname === "string" && typeof node.schemaVersion === "number" && Number.isSafeInteger(node.schemaVersion) && node.schemaVersion >= 0 ? {
type: node.type,
pathname: node.pathname,
schemaVersion: node.schemaVersion
} : void 0;
default: return;
}
}
function unreachableErrorNode(node) {
throw new Error(`Unexpected shared-state worker error node: ${String(node)}`);
}
function createError(node) {
if (isMessageOnlyErrorIdentity(node)) {
const ErrorType = MESSAGE_ONLY_ERRORS[node.type];
return new ErrorType(node.message);
}
switch (node.type) {
case "plugin-state": return new PluginStateStoreError(node.message, {
code: node.stateCode,
operation: node.operation,
path: node.path,
owner: node.owner
});
case "skill-library": return new SkillLibraryError(node.libraryCode, node.message, node.currentRevision);
case "secret-store-validation": return new SecretStoreValidationError(node.secretCode, node.message);
case "worker-session-already-attached": return new WorkerSessionAlreadyAttachedError(node.sessionId, node.environmentId);
case "workspace-alias-repointed": return new WorkspaceAliasRepointedError(node);
case "session-goal-operation": return new SessionGoalOperationError(node.goalCode, node.message);
case "session-mutation-conflict": return new SqliteSessionMutationConflictError(node.operationLabel);
case "session-metadata": return new SessionMetadataUnavailableError(node.reason, void 0, node.missingTables);
case "error": return new Error(node.message);
case "mcp-oauth-corruption": return new McpOAuthStoreCorruptionError("", "");
case "aggregate": return new AggregateError([], node.message);
case "state-owner-contention": return new GatewayStateOwnerContentionError(node.databasePath);
case "ownership-metadata": return new OpenClawStateOwnershipMetadataError(node.databasePath, "");
case "external-ownership": return new OpenClawStateExternalOwnershipError(node.databasePath, node.managerId);
case "plugin-blob": return new PluginBlobStoreError(node.message, {
code: node.blobCode,
operation: node.operation,
...node.path === void 0 ? {} : { path: node.path }
});
case "state-lease": return new OpenClawStateLeaseError(node.message, { code: node.leaseCode });
case "maintenance": return new StartupMaintenanceRequiredError(node.kind, node.message);
case "state-migration": return new OpenClawStateDatabaseSchemaMigrationRequiredError(node.kind, node.pathname);
case "agent-media-migration": return new OpenClawAgentDatabaseMediaMigrationRequiredError(node.pathname, node.schemaVersion);
}
return unreachableErrorNode(node);
}
//#endregion
//#region src/state/openclaw-state-worker-error.ts
function isScalar(value) {
return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
}
function isNativeErrorCode(value) {
return typeof value === "number" && Number.isInteger(value) && value >= 0 && value <= 2147483647;
}
function encodeOpenClawStateWorkerError(error, options = {}) {
if (!(error instanceof Error)) return;
const nodes = [];
const errors = [];
const references = /* @__PURE__ */ new Map();
let canonical = false;
const encodeValue = (value) => {
if (!(value instanceof Error)) return isScalar(value) ? { value } : { undefined: true };
const known = references.get(value);
if (known !== void 0) return { ref: known };
const ref = errors.length;
references.set(value, ref);
errors.push(value);
return { ref };
};
try {
encodeValue(error);
for (const current of errors) {
const identity = identifyError(current);
const nativeOpen = isSqliteNativeOpenFailure(current);
const stateDatabasePath = readOpenClawStateDatabaseFailurePath(current);
canonical ||= stateDatabasePath !== void 0 || nativeOpen || isSqliteLockError(current) || current instanceof OpenClawQuarantineReadCleanupError || identity.type !== "error" && identity.type !== "aggregate";
const code = "code" in current ? current.code : void 0;
const errcode = "errcode" in current ? current.errcode : void 0;
const errno = "errno" in current ? current.errno : void 0;
nodes.push({
...identity,
name: current.name,
message: current.message,
...typeof code === "string" || typeof code === "number" && Number.isFinite(code) ? { code } : {},
...isNativeErrorCode(errcode) ? { errcode } : {},
...typeof errno === "number" && Number.isInteger(errno) ? { errno } : {},
...nativeOpen ? { nativeOpen: true } : {},
...stateDatabasePath === void 0 ? {} : { stateDatabasePath },
..."cause" in current ? { cause: encodeValue(current.cause) } : {},
...current instanceof AggregateError ? { errors: current.errors.map(encodeValue) } : {}
});
}
return canonical || options.includeOrdinary === true ? {
version: 1,
root: 0,
nodes
} : void 0;
} catch {
return;
}
}
function isErrorValue(value, count) {
if (!isRecord(value) || Object.keys(value).length !== 1) return false;
if ("ref" in value) return typeof value.ref === "number" && Number.isSafeInteger(value.ref) && value.ref >= 0 && value.ref < count;
return "value" in value ? isScalar(value.value) : value.undefined === true;
}
function parseNode(value, count) {
if (!isRecord(value) || typeof value.name !== "string" || typeof value.message !== "string") return;
const identity = parseIdentity(value);
if (!identity) return;
const allowed = /* @__PURE__ */ new Set([
...Object.keys(identity),
"name",
"message",
"code",
"errcode",
"errno",
"nativeOpen",
"stateDatabasePath",
"cause"
]);
const errors = [];
if (identity.type === "aggregate") {
allowed.add("errors");
if (!Array.isArray(value.errors)) return;
for (const entry of value.errors) {
if (!isErrorValue(entry, count)) return;
errors.push(entry);
}
}
if (Object.keys(value).some((key) => !allowed.has(key)) || "code" in value && typeof value.code !== "string" && !(typeof value.code === "number" && Number.isFinite(value.code)) || "errcode" in value && !isNativeErrorCode(value.errcode) || "errno" in value && (typeof value.errno !== "number" || !Number.isInteger(value.errno)) || "nativeOpen" in value && value.nativeOpen !== true || "stateDatabasePath" in value && typeof value.stateDatabasePath !== "string" || "cause" in value && !isErrorValue(value.cause, count)) return;
return {
...identity,
name: value.name,
message: value.message,
...typeof value.code === "string" || typeof value.code === "number" ? { code: value.code } : {},
...isNativeErrorCode(value.errcode) ? { errcode: value.errcode } : {},
...typeof value.errno === "number" ? { errno: value.errno } : {},
...value.nativeOpen === true ? { nativeOpen: true } : {},
...typeof value.stateDatabasePath === "string" ? { stateDatabasePath: value.stateDatabasePath } : {},
...isErrorValue(value.cause, count) ? { cause: value.cause } : {},
...identity.type === "aggregate" ? { errors } : {}
};
}
function decodeErrorGraph(value, options) {
try {
if (!isRecord(value) || Object.keys(value).some((key) => ![
"version",
"root",
"nodes"
].includes(key)) || value.version !== 1 || !Array.isArray(value.nodes) || typeof value.root !== "number" || !Number.isSafeInteger(value.root) || value.root < 0 || value.root >= value.nodes.length) return;
const nodes = [];
for (const valueNode of value.nodes) {
const node = parseNode(valueNode, value.nodes.length);
if (!node) return;
nodes.push(node);
}
const visited = /* @__PURE__ */ new Set();
const pending = [value.root];
let canonical = false;
for (const ref of pending) {
if (visited.has(ref)) continue;
visited.add(ref);
const node = nodes[ref];
canonical ||= node.stateDatabasePath !== void 0 || node.nativeOpen === true || isSqliteLockError(node) || node.type === "aggregate" && node.name === "OpenClawQuarantineReadCleanupError" || node.type !== "error" && node.type !== "aggregate";
for (const edge of [...node.cause ? [node.cause] : [], ...node.errors ?? []]) if ("ref" in edge) pending.push(edge.ref);
}
if (!canonical && options.includeOrdinary !== true || visited.size !== nodes.length) return;
const errors = nodes.map(createError);
const decodeValue = (entry) => "ref" in entry ? errors[entry.ref] : "value" in entry ? entry.value : void 0;
for (const [index, node] of nodes.entries()) {
const error = errors[index];
error.name = node.name;
error.message = node.message;
if (node.nativeOpen) markSqliteNativeOpenFailure(error);
if (node.stateDatabasePath !== void 0) markOpenClawStateDatabaseFailure(error, node.stateDatabasePath);
for (const [key, propertyValue] of Object.entries({
...node.code !== void 0 ? { code: node.code } : {},
...node.errcode !== void 0 ? { errcode: node.errcode } : {},
...node.errno !== void 0 ? { errno: node.errno } : {},
...node.cause ? { cause: decodeValue(node.cause) } : {}
})) Object.defineProperty(error, key, {
value: propertyValue,
configurable: true,
writable: true
});
if (error instanceof AggregateError) error.errors = (node.errors ?? []).map(decodeValue);
}
const group = Object.freeze({});
for (const [index, error] of errors.entries()) retainPayload(error, value, index, true, group);
return {
errors,
nodes,
root: value.root
};
} catch {
return;
}
}
const retainedPayloadKey = Symbol.for("openclaw.sharedStateWorkerErrorPayload");
function retainPayload(error, payload, node, materialized, group) {
Object.defineProperty(error, retainedPayloadKey, { value: Object.freeze({
payload,
node,
materialized,
group
}) });
}
/** Keep the closed wire graph without binding it to a process-global broker's classes. */
function retainOpenClawStateWorkerErrorPayload(error, payload) {
retainPayload(error, payload, 0, false, Object.freeze({}));
}
function hydrateOpenClawStateWorkerError(value, options = {}) {
if (!(value instanceof Error)) return value;
const groups = /* @__PURE__ */ new Map();
const nodes = /* @__PURE__ */ new Map();
const queue = [];
const add = (error) => {
const previous = nodes.get(error);
if (previous) return previous;
const node = {
source: error,
replacement: error,
parents: /* @__PURE__ */ new Set(),
changed: false,
opaque: false
};
nodes.set(error, node);
queue.push(node);
const retained = Object.getOwnPropertyDescriptor(error, retainedPayloadKey)?.value;
if (isRecord(retained) && typeof retained.node === "number" && Number.isSafeInteger(retained.node) && retained.node >= 0 && typeof retained.materialized === "boolean" && isRecord(retained.group)) {
if (!groups.has(retained.group)) groups.set(retained.group, decodeErrorGraph(retained.payload, options));
const graph = groups.get(retained.group);
const index = retained.materialized ? retained.node : graph?.root;
const replacement = index === void 0 ? void 0 : graph?.errors[index];
const identity = index === void 0 ? void 0 : graph?.nodes[index];
if (replacement && identity) {
node.replacement = replacement;
node.opaque = !retained.materialized;
node.changed = node.opaque || identifyError(error).type !== identity.type;
}
}
return node;
};
const root = add(value);
for (const node of queue) {
if (node.opaque) continue;
const edge = (child) => {
if (child instanceof Error) add(child).parents.add(node);
};
if ("cause" in node.source) {
node.cause = { value: node.source.cause };
edge(node.cause.value);
}
if (node.source instanceof AggregateError) {
node.errors = [...node.source.errors];
node.errors.forEach(edge);
}
}
const affected = queue.filter((node) => node.changed);
for (const node of affected) for (const parent of node.parents) if (!parent.changed) {
parent.changed = true;
affected.push(parent);
}
if (!root.changed) return value;
for (const node of affected) if (node.replacement === node.source) {
node.replacement = node.source instanceof AggregateError ? new AggregateError([], node.source.message) : new Error(node.source.message);
Object.setPrototypeOf(node.replacement, Object.getPrototypeOf(node.source));
}
const replace = (child) => {
const node = child instanceof Error ? nodes.get(child) : void 0;
return node?.changed ? node.replacement : child;
};
for (const node of affected) {
if (node.opaque) continue;
const descriptors = Object.getOwnPropertyDescriptors(node.source);
Reflect.deleteProperty(descriptors, retainedPayloadKey);
if (node.cause) descriptors.cause = {
configurable: descriptors.cause?.configurable ?? true,
enumerable: descriptors.cause?.enumerable ?? false,
writable: descriptors.cause?.writable ?? true,
value: replace(node.cause.value)
};
if (node.errors) descriptors.errors = {
configurable: descriptors.errors?.configurable ?? true,
enumerable: descriptors.errors?.enumerable ?? false,
writable: descriptors.errors?.writable ?? true,
value: node.errors.map(replace)
};
Object.defineProperties(node.replacement, descriptors);
}
return root.replacement;
}
//#endregion
//#region node-compile-cache.mjs
const MAX_BYTES = 536870912;
const MAX_AGE_MS = 6048e5;
const MAINTENANCE_INTERVAL_MS = 36e5;
const BUILD_MARKER_RE = /^(?:[a-f0-9]{16}|\d+-\d+|no-package-json|build-[A-Za-z0-9._-]+)$/;
const sanitize = (value) => {
const segment = value.replace(/[^A-Za-z0-9._-]+/g, "_").replace(/^_+|_+$/g, "");
return segment && segment !== "." && segment !== ".." ? segment : "unknown";
};
function resolveSafeNodeCompileCacheDirectory(directory) {
if (process.platform === "win32" && path.resolve(directory).length > 200) {
process.stderr.write("[openclaw] Compile cache disabled: Windows cache path exceeds 200 characters.\n");
return;
}
return directory;
}
async function maintain(directory) {
const root = path.dirname(path.dirname(directory));
const version = path.basename(path.dirname(directory));
if (path.basename(root) !== "openclaw" || sanitize(version) !== version || !BUILD_MARKER_RE.test(path.basename(directory))) return;
const now = Date.now();
const previous = await fs.lstat(root).catch(() => void 0);
for (const target of [
root,
path.dirname(directory),
directory
]) {
const stat = target === root ? previous : await fs.lstat(target).catch(() => void 0);
if (stat && !stat.isDirectory()) return;
}
await fs.mkdir(directory, { recursive: true });
let retired = false;
for (const entry of await fs.readdir(root, { withFileTypes: true })) {
if (!entry.isDirectory()) continue;
const versionRoot = path.join(root, entry.name);
for (const build of await fs.readdir(versionRoot, { withFileTypes: true })) {
const candidate = path.join(versionRoot, build.name);
if (build.isDirectory() && candidate !== directory) {
await fs.rm(candidate, {
recursive: true,
force: true
});
retired = true;
}
}
if (versionRoot !== path.dirname(directory)) await fs.rmdir(versionRoot).catch(() => {});
}
if (!retired && previous && now - previous.mtimeMs < MAINTENANCE_INTERVAL_MS) return;
await fs.utimes(root, new Date(now), new Date(now));
const files = [];
let bytes = 0;
async function visit(dir) {
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
const file = path.join(dir, entry.name);
if (entry.isDirectory()) await visit(file);
else if (entry.isFile()) {
const stat = await fs.lstat(file);
bytes += stat.size;
files.push({
file,
size: stat.size,
mtimeMs: stat.mtimeMs
});
}
}
}
await visit(directory);
files.sort((left, right) => left.mtimeMs - right.mtimeMs);
for (const file of files) if (bytes > MAX_BYTES || now - file.mtimeMs > MAX_AGE_MS) {
await fs.unlink(file.file);
bytes -= file.size;
}
}
if (!isMainThread && typeof workerData?.openclawCompileCacheDirectory === "string") maintain(workerData.openclawCompileCacheDirectory).catch(() => {});
//#endregion
//#region src/infra/node-compile-cache-env.ts
const COMPILE_CACHE_BASE_KEY = Symbol.for("openclaw.nodeCompileCacheBase");
function compileCacheOwner() {
return resolveGlobalSingleton(COMPILE_CACHE_BASE_KEY, () => ({}));
}
function resolveNodeCompileCacheEnv(env = process.env) {
if (env.NODE_DISABLE_COMPILE_CACHE !== void 0) return env;
const directory = env.NODE_COMPILE_CACHE ?? compileCacheOwner().baseDirectory;
if (directory && !resolveSafeNodeCompileCacheDirectory(directory)) {
const disabled = {
...env,
NODE_DISABLE_COMPILE_CACHE: "1"
};
delete disabled.NODE_COMPILE_CACHE;
return disabled;
}
if (env.NODE_COMPILE_CACHE !== void 0) return env;
return directory ? {
...env,
NODE_COMPILE_CACHE: directory
} : env;
}
//#endregion
//#region src/infra/sqlite-worker-transfer.ts
const SQLITE_WORKER_TRANSFER_FRAME_BYTES = 8388608;
/** One owned result cursor; callers supply records and any associated cleanup. */
function createSqliteWorkerTransferOwner() {
let nextId = 0;
let current;
const cleanup = (transfer) => {
const errors = [];
if (!transfer.iteratorClosed) try {
transfer.iterator.return?.();
transfer.iteratorClosed = true;
} catch (error) {
errors.push(error);
}
if (!transfer.cleaned) try {
transfer.cleanup?.();
transfer.cleaned = true;
} catch (error) {
errors.push(error);
}
throwSqliteLifecycleErrors(errors, "SQLite read transfer cleanup failed");
};
const cancel = () => {
if (current) {
cleanup(current);
current = void 0;
}
};
const requireTransfer = (id) => {
if (!current || current.id !== id) throw new Error("SQLite read transfer is no longer active");
return current;
};
return {
start(iterator, options) {
if (current) throw new Error("The preceding SQLite read transfer was not released");
current = {
id: ++nextId,
iterator,
cleanup: options.cleanup,
iteratorClosed: false,
cleaned: false,
counts: new Map(options.kinds.map((kind) => [kind, 0])),
sequence: 0,
finished: false
};
return {
id: current.id,
kinds: [...current.counts.keys()]
};
},
next(id) {
const transfer = requireTransfer(id);
if (transfer.finished) throw new Error("SQLite read transfer has already reached its end");
if (transfer.record && transfer.record.offset === transfer.record.bytes.byteLength) transfer.record = void 0;
if (!transfer.record) {
const next = transfer.iterator.next();
if (next.done) {
cleanup(transfer);
transfer.finished = true;
return {
id,
sequence: transfer.sequence++,
done: true,
counts: [...transfer.counts]
};
}
const { kind } = next.value;
const count = transfer.counts.get(kind);
if (count === void 0) throw new Error("SQLite read transfer returned an unexpected record kind");
transfer.record = {
kind,
bytes: "serialized" in next.value ? next.value.serialized : serialize(next.value.value),
offset: 0
};
transfer.counts.set(kind, count + 1);
}
const record = transfer.record;
const offset = record.offset;
const end = Math.min(record.bytes.byteLength, offset + SQLITE_WORKER_TRANSFER_FRAME_BYTES);
record.offset = end;
return {
id,
sequence: transfer.sequence++,
done: false,
kind: record.kind,
recordBytes: record.bytes.byteLength,
offset,
recordDone: end === record.bytes.byteLength,
bytes: new Uint8Array(record.bytes.subarray(offset, end))
};
},
end(id) {
if (!requireTransfer(id).finished) throw new Error("SQLite read transfer ended before its complete result");
cancel();
},
cancel,
close: cancel
};
}
/** Reassembles one transfer; its caller owns transport completion and cancellation. */
function createSqliteWorkerTransferReceiver(handle, consume) {
const counts = new Map(handle.kinds.map((kind) => [kind, 0]));
let sequence = 0;
let finished = false;
let record;
return { accept(frame) {
try {
if (finished || frame.id !== handle.id || frame.sequence !== sequence++) throw new Error("SQLite read transfer frame is out of order");
if (frame.done) {
if (record || frame.counts.length !== counts.size || frame.counts.some(([kind, count]) => counts.get(kind) !== count) || new Set(frame.counts.map(([kind]) => kind)).size !== counts.size) throw new Error("SQLite read transfer ended with an incomplete result");
finished = true;
return frame.counts;
}
const count = counts.get(frame.kind);
if (count === void 0 || !Number.isSafeInteger(frame.recordBytes) || frame.recordBytes < 1 || !Number.isSafeInteger(frame.offset) || frame.offset < 0 || frame.bytes.byteLength < 1 || frame.bytes.byteLength > 8388608) throw new Error("SQLite read transfer returned an invalid frame");
if (!record) {
if (frame.offset !== 0) throw new Error("SQLite read transfer omitted the start of a record");
record = {
kind: frame.kind,
bytes: new Uint8Array(frame.recordBytes),
offset: 0
};
}
const end = frame.offset + frame.bytes.byteLength;
if (record.kind !== frame.kind || record.bytes.byteLength !== frame.recordBytes || record.offset !== frame.offset || end > frame.recordBytes || frame.recordDone !== (end === frame.recordBytes)) throw new Error("SQLite read transfer returned a discontinuous record");
record.bytes.set(frame.bytes, frame.offset);
record.offset = end;
if (frame.recordDone) {
const value = deserialize(record.bytes);
const kind = record.kind;
record = void 0;
consume({
kind,
value
});
counts.set(kind, count + 1);
}
return;
} catch (error) {
record = void 0;
finished = true;
throw error;
}
} };
}
//#endregion
export { hydrateOpenClawStateWorkerError as a, SecretStoreValidationError as c, encodeOpenClawStateWorkerError as i, createSqliteWorkerTransferReceiver as n, retainOpenClawStateWorkerErrorPayload as o, resolveNodeCompileCacheEnv as r, SECRET_STORE_VALUE_MAX_BYTES as s, createSqliteWorkerTransferOwner as t };