mirror of
https://github.com/moltbot/moltbot.git
synced 2026-05-16 10:28:45 +00:00
refactor: remove state file escape hatches
This commit is contained in:
@@ -38,6 +38,8 @@ describe("device identity crypto helpers", () => {
|
||||
const created = loadOrCreateDeviceIdentity(identityPath);
|
||||
|
||||
expect(loadDeviceIdentityIfPresent(identityPath)).toEqual(created);
|
||||
expect(fs.existsSync(identityPath)).toBe(false);
|
||||
expect(fs.existsSync(`${identityPath}.sqlite`)).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { resolveStateDir } from "../config/paths.js";
|
||||
import type { OpenClawStateDatabaseOptions } from "../state/openclaw-state-db.js";
|
||||
import {
|
||||
readOpenClawStateKvJson,
|
||||
writeOpenClawStateKvJson,
|
||||
@@ -32,6 +31,7 @@ type StoredSwiftIdentity = {
|
||||
|
||||
const DEVICE_IDENTITY_SCOPE = "identity.device";
|
||||
const DEVICE_IDENTITY_KEY = "default";
|
||||
const DEVICE_IDENTITY_PATH_KEY_PREFIX = "path:";
|
||||
|
||||
function resolveDefaultIdentityPath(): string {
|
||||
return path.join(resolveStateDir(), "identity", "device.json");
|
||||
@@ -41,8 +41,9 @@ function resolveIdentityPathForEnv(env: NodeJS.ProcessEnv = process.env): string
|
||||
return path.join(resolveStateDir(env), "identity", "device.json");
|
||||
}
|
||||
|
||||
function sqliteOptionsForIdentityPath(filePath: string): OpenClawStateDatabaseOptions {
|
||||
function stateDbOptionsForIdentityPath(filePath: string): { env: NodeJS.ProcessEnv } {
|
||||
const resolved = path.resolve(filePath);
|
||||
const envStateDir = resolveStateDir(process.env);
|
||||
if (resolved.endsWith(path.join("identity", "device.json"))) {
|
||||
return {
|
||||
env: {
|
||||
@@ -51,7 +52,28 @@ function sqliteOptionsForIdentityPath(filePath: string): OpenClawStateDatabaseOp
|
||||
},
|
||||
};
|
||||
}
|
||||
return { path: `${resolved}.sqlite` };
|
||||
if (resolved.startsWith(`${path.resolve(envStateDir)}${path.sep}`)) {
|
||||
return {
|
||||
env: {
|
||||
...process.env,
|
||||
OPENCLAW_STATE_DIR: envStateDir,
|
||||
},
|
||||
};
|
||||
}
|
||||
return {
|
||||
env: {
|
||||
...process.env,
|
||||
OPENCLAW_STATE_DIR: path.dirname(resolved),
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function identityKeyForPath(filePath: string): string {
|
||||
const resolved = path.resolve(filePath);
|
||||
if (resolved.endsWith(path.join("identity", "device.json"))) {
|
||||
return DEVICE_IDENTITY_KEY;
|
||||
}
|
||||
return `${DEVICE_IDENTITY_PATH_KEY_PREFIX}${crypto.createHash("sha256").update(resolved).digest("hex")}`;
|
||||
}
|
||||
|
||||
const ED25519_SPKI_PREFIX = Buffer.from("302a300506032b6570032100", "hex");
|
||||
@@ -171,8 +193,8 @@ function readStoredIdentity(filePath: string): StoredIdentity | null {
|
||||
return parseStoredIdentity(
|
||||
readOpenClawStateKvJson(
|
||||
DEVICE_IDENTITY_SCOPE,
|
||||
DEVICE_IDENTITY_KEY,
|
||||
sqliteOptionsForIdentityPath(filePath),
|
||||
identityKeyForPath(filePath),
|
||||
stateDbOptionsForIdentityPath(filePath),
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -186,9 +208,9 @@ function readStoredIdentityForEnv(env: NodeJS.ProcessEnv): StoredIdentity | null
|
||||
function writeStoredIdentity(filePath: string, stored: StoredIdentity): void {
|
||||
writeOpenClawStateKvJson<OpenClawStateJsonValue>(
|
||||
DEVICE_IDENTITY_SCOPE,
|
||||
DEVICE_IDENTITY_KEY,
|
||||
identityKeyForPath(filePath),
|
||||
stored as unknown as OpenClawStateJsonValue,
|
||||
sqliteOptionsForIdentityPath(filePath),
|
||||
stateDbOptionsForIdentityPath(filePath),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
import { z } from "zod";
|
||||
import { tryReadJson, tryReadJsonSync } from "../infra/json-files.js";
|
||||
import { tryReadJsonSync } from "../infra/json-files.js";
|
||||
import { isBlockedObjectKey } from "../infra/prototype-keys.js";
|
||||
import { readOpenClawStateKvJson } from "../state/openclaw-state-kv.js";
|
||||
import { safeParseWithSchema } from "../utils/zod-parse.js";
|
||||
import { extractPluginInstallRecordsFromInstalledPluginIndex } from "./installed-plugin-index-install-records.js";
|
||||
import {
|
||||
resolveInstalledPluginIndexStorePath,
|
||||
type InstalledPluginIndexStoreOptions,
|
||||
} from "./installed-plugin-index-store-path.js";
|
||||
import { type InstalledPluginIndexStoreOptions } from "./installed-plugin-index-store-path.js";
|
||||
import {
|
||||
INSTALLED_PLUGIN_INDEX_MIGRATION_VERSION,
|
||||
INSTALLED_PLUGIN_INDEX_VERSION,
|
||||
@@ -153,9 +150,6 @@ export function resolveInstalledPluginIndexStateDbOptions(
|
||||
function readPersistedInstalledPluginIndexJsonSync(
|
||||
options: InstalledPluginIndexStoreOptions,
|
||||
): unknown {
|
||||
if (options.filePath) {
|
||||
return tryReadJsonSync(resolveInstalledPluginIndexStorePath(options));
|
||||
}
|
||||
try {
|
||||
return readOpenClawStateKvJson(
|
||||
INSTALLED_PLUGIN_INDEX_KV_SCOPE,
|
||||
@@ -170,9 +164,7 @@ function readPersistedInstalledPluginIndexJsonSync(
|
||||
export async function readPersistedInstalledPluginIndex(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): Promise<InstalledPluginIndex | null> {
|
||||
const parsed = options.filePath
|
||||
? await tryReadJson<unknown>(resolveInstalledPluginIndexStorePath(options))
|
||||
: readPersistedInstalledPluginIndexJsonSync(options);
|
||||
const parsed = readPersistedInstalledPluginIndexJsonSync(options);
|
||||
return parseInstalledPluginIndex(parsed);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@ export const PLUGIN_INSTALLS_CONFIG_PATH = ["plugins", "installs"] as const;
|
||||
export type InstalledPluginIndexRecordStoreOptions = {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
stateDir?: string;
|
||||
filePath?: string;
|
||||
};
|
||||
|
||||
type InstalledPluginIndexRecordRefreshOptions = InstalledPluginIndexRecordStoreOptions &
|
||||
|
||||
@@ -6,15 +6,11 @@ const INSTALLED_PLUGIN_INDEX_STORE_PATH = path.join("plugins", "installs.json");
|
||||
export type InstalledPluginIndexStoreOptions = {
|
||||
env?: NodeJS.ProcessEnv;
|
||||
stateDir?: string;
|
||||
filePath?: string;
|
||||
};
|
||||
|
||||
export function resolveInstalledPluginIndexStorePath(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): string {
|
||||
if (options.filePath) {
|
||||
return options.filePath;
|
||||
}
|
||||
const env = options.env ?? process.env;
|
||||
const stateDir = options.stateDir ?? resolveStateDir(env);
|
||||
return path.join(stateDir, INSTALLED_PLUGIN_INDEX_STORE_PATH);
|
||||
|
||||
@@ -95,18 +95,6 @@ export function writePersistedInstalledPluginIndexSync(
|
||||
export function deletePersistedInstalledPluginIndexSync(
|
||||
options: InstalledPluginIndexStoreOptions = {},
|
||||
): boolean {
|
||||
if (options.filePath) {
|
||||
try {
|
||||
fs.unlinkSync(resolveInstalledPluginIndexStorePath(options));
|
||||
clearCurrentPluginMetadataSnapshotState();
|
||||
return true;
|
||||
} catch (err) {
|
||||
if ((err as NodeJS.ErrnoException)?.code !== "ENOENT") {
|
||||
throw err;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
const removed = deleteOpenClawStateKvJson(
|
||||
INSTALLED_PLUGIN_INDEX_KV_SCOPE,
|
||||
INSTALLED_PLUGIN_INDEX_KV_KEY,
|
||||
|
||||
Reference in New Issue
Block a user