openclaw
Version:
Multi-channel AI gateway with extensible messaging integrations
127 lines (126 loc) • 5.65 kB
JavaScript
import { t as resolveIdentityPathViaExistingAncestorSync } from "./boundary-path-DMNeww4q.js";
import { f as resolveConfigPath, w as resolveStateDir } from "./paths-D2sRr1a_.js";
import { t as ADMIN_SCOPE } from "./operator-scopes-Dw7Gu2cA.js";
import { o as isLoopbackGatewayUrl } from "./net-DbNPs6Xm.js";
import { o as resolveGatewayService } from "./service-Cc6NX6Jm.js";
import { r as projectGatewayUrlForDiagnostics } from "./connection-details-dzrfNKN8.js";
import { i as buildGatewayConnectionDetails, o as callGateway, p as isGatewayCredentialsRequiredError } from "./call-BWR5pPgw.js";
import "./method-scopes-K6J_UQGL.js";
import { n as probeGateway } from "./probe-BllKXy3J.js";
import { t as quoteCliArg } from "./quote-cli-arg-BEt71TUh.js";
import path from "node:path";
//#region src/cli/state-dir-gateway-check.ts
const STATE_DIR_CHECK_TIMEOUT_MS = 3e3;
const GATEWAY_SERVICE_PATHS_UNVERIFIED = "Installed Gateway service state and config paths could not be verified. Inspect the service environment with `openclaw gateway status --deep` before repairing plugin state.";
async function inspectInstalledGatewayStatePaths(timeoutMs = STATE_DIR_CHECK_TIMEOUT_MS) {
try {
const serviceEnv = { ...process.env };
delete serviceEnv.OPENCLAW_STATE_DIR;
delete serviceEnv.OPENCLAW_CONFIG_PATH;
delete serviceEnv.OPENCLAW_HOME;
const command = await resolveGatewayService().readCommand(serviceEnv, {
timeoutMs,
requireEffective: true
});
if (!command) return { kind: "absent" };
const environment = command.environment;
if (!environment || ![
"OPENCLAW_STATE_DIR",
"OPENCLAW_HOME",
"HOME",
"USERPROFILE"
].some((key) => environment[key]?.trim())) return { kind: "unknown" };
return {
kind: "known",
stateDir: resolveStateDir(environment),
configPath: resolveConfigPath(environment)
};
} catch {
return { kind: "unknown" };
}
}
function compareCliGatewayStateDirs(params) {
const cliStateDir = resolveIdentityPathViaExistingAncestorSync(params.cliStateDir);
const cliConfigPath = resolveIdentityPathViaExistingAncestorSync(params.cliConfigPath);
const gatewayStateDir = resolveIdentityPathViaExistingAncestorSync(params.gatewayStateDir);
const gatewayConfigPath = resolveIdentityPathViaExistingAncestorSync(params.gatewayConfigPath ?? path.join(gatewayStateDir, "openclaw.json"));
const differences = [cliStateDir !== gatewayStateDir && `state directories (CLI: ${params.cliStateDir}; Gateway: ${gatewayStateDir})`, cliConfigPath !== gatewayConfigPath && `config paths (CLI: ${params.cliConfigPath}; Gateway: ${gatewayConfigPath})`].filter((difference) => Boolean(difference));
if (differences.length === 0) return { kind: "allow" };
const detail = differences.join(" and ");
if (params.mode === "warn") return {
kind: "warn",
message: `CLI and ${params.source} use different ${detail}. Local commands may read or write state the Gateway does not use.`
};
return {
kind: "refuse",
message: [
`No credentials or configuration were written. CLI and ${params.source} use different ${detail}.`,
`Fix: run OPENCLAW_STATE_DIR=${quoteCliArg(gatewayStateDir)} OPENCLAW_CONFIG_PATH=${quoteCliArg(gatewayConfigPath)} ${params.command ?? "openclaw configure"}.`,
params.source === "live Gateway" ? "To write another local store intentionally, stop the running Gateway first." : "To write another local store intentionally, uninstall or reconfigure the divergent Gateway service first."
].join(" ")
};
}
async function checkCliGatewayStateDir(params) {
const cliStateDir = resolveStateDir(process.env);
const cliConfigPath = resolveConfigPath(process.env);
const details = buildGatewayConnectionDetails({ config: params.config });
if (!isLoopbackGatewayUrl(details.url)) return {
kind: "warn",
message: `Gateway target ${projectGatewayUrlForDiagnostics(details.url)} is remote. Local credentials and configuration do not reach that Gateway.`
};
let hello;
let connectionError;
try {
await callGateway({
config: params.config,
method: "status",
params: { includeChannelSummary: false },
scopes: [ADMIN_SCOPE],
sharedStateMode: "read-only",
timeoutMs: STATE_DIR_CHECK_TIMEOUT_MS,
onHelloOk: (value) => {
hello = value;
}
});
} catch (error) {
connectionError = error;
}
if (hello?.snapshot.stateDir) return compareCliGatewayStateDirs({
cliStateDir,
cliConfigPath,
gatewayStateDir: hello.snapshot.stateDir,
gatewayConfigPath: hello.snapshot.configPath,
source: "live Gateway",
mode: "refuse",
command: params.command
});
const servicePaths = await inspectInstalledGatewayStatePaths();
if (servicePaths.kind === "unknown") return {
kind: "warn",
message: GATEWAY_SERVICE_PATHS_UNVERIFIED
};
if (servicePaths.kind === "known") return compareCliGatewayStateDirs({
cliStateDir,
cliConfigPath,
gatewayStateDir: servicePaths.stateDir,
gatewayConfigPath: servicePaths.configPath,
source: "installed Gateway service",
mode: "refuse",
command: params.command
});
if (isGatewayCredentialsRequiredError(connectionError)) {
if ((await probeGateway({
url: details.url,
config: params.config,
timeoutMs: STATE_DIR_CHECK_TIMEOUT_MS,
includeDetails: false,
suppressStoredDeviceAuth: true
})).gatewayReached) return {
kind: "warn",
message: "Gateway is reachable but requires credentials, so its state and config paths could not be verified. Local writes may not reach it."
};
}
return { kind: "allow" };
}
//#endregion
export { inspectInstalledGatewayStatePaths as i, checkCliGatewayStateDir as n, compareCliGatewayStateDirs as r, GATEWAY_SERVICE_PATHS_UNVERIFIED as t };