refactor(core): extract shared dedup helpers

This commit is contained in:
Peter Steinberger
2026-03-07 10:40:49 +00:00
parent 14c61bb33f
commit 3c71e2bd48
114 changed files with 3400 additions and 2040 deletions

View File

@@ -405,20 +405,15 @@ async function saveSessionStoreUnlocked(
.map((entry) => entry?.sessionId)
.filter((id): id is string => Boolean(id)),
);
for (const [sessionId, sessionFile] of removedSessionFiles) {
if (referencedSessionIds.has(sessionId)) {
continue;
}
const archived = archiveSessionTranscripts({
sessionId,
storePath,
sessionFile,
reason: "deleted",
restrictToStoreDir: true,
});
for (const archivedPath of archived) {
archivedDirs.add(path.dirname(archivedPath));
}
const archivedForDeletedSessions = archiveRemovedSessionTranscripts({
removedSessionFiles,
referencedSessionIds,
storePath,
reason: "deleted",
restrictToStoreDir: true,
});
for (const archivedDir of archivedForDeletedSessions) {
archivedDirs.add(archivedDir);
}
if (archivedDirs.size > 0 || maintenance.resetArchiveRetentionMs != null) {
const targetDirs =
@@ -574,6 +569,32 @@ function rememberRemovedSessionFile(
}
}
export function archiveRemovedSessionTranscripts(params: {
removedSessionFiles: Iterable<[string, string | undefined]>;
referencedSessionIds: ReadonlySet<string>;
storePath: string;
reason: "deleted" | "reset";
restrictToStoreDir?: boolean;
}): Set<string> {
const archivedDirs = new Set<string>();
for (const [sessionId, sessionFile] of params.removedSessionFiles) {
if (params.referencedSessionIds.has(sessionId)) {
continue;
}
const archived = archiveSessionTranscripts({
sessionId,
storePath: params.storePath,
sessionFile,
reason: params.reason,
restrictToStoreDir: params.restrictToStoreDir,
});
for (const archivedPath of archived) {
archivedDirs.add(path.dirname(archivedPath));
}
}
return archivedDirs;
}
async function writeSessionStoreAtomic(params: {
storePath: string;
store: Record<string, SessionEntry>;

View File

@@ -285,7 +285,7 @@ export function validateConfigObject(
};
}
export function validateConfigObjectWithPlugins(raw: unknown):
type ValidateConfigWithPluginsResult =
| {
ok: true;
config: OpenClawConfig;
@@ -295,38 +295,20 @@ export function validateConfigObjectWithPlugins(raw: unknown):
ok: false;
issues: ConfigValidationIssue[];
warnings: ConfigValidationIssue[];
} {
};
export function validateConfigObjectWithPlugins(raw: unknown): ValidateConfigWithPluginsResult {
return validateConfigObjectWithPluginsBase(raw, { applyDefaults: true });
}
export function validateConfigObjectRawWithPlugins(raw: unknown):
| {
ok: true;
config: OpenClawConfig;
warnings: ConfigValidationIssue[];
}
| {
ok: false;
issues: ConfigValidationIssue[];
warnings: ConfigValidationIssue[];
} {
export function validateConfigObjectRawWithPlugins(raw: unknown): ValidateConfigWithPluginsResult {
return validateConfigObjectWithPluginsBase(raw, { applyDefaults: false });
}
function validateConfigObjectWithPluginsBase(
raw: unknown,
opts: { applyDefaults: boolean },
):
| {
ok: true;
config: OpenClawConfig;
warnings: ConfigValidationIssue[];
}
| {
ok: false;
issues: ConfigValidationIssue[];
warnings: ConfigValidationIssue[];
} {
): ValidateConfigWithPluginsResult {
const base = opts.applyDefaults ? validateConfigObject(raw) : validateConfigObjectRaw(raw);
if (!base.ok) {
return { ok: false, issues: base.issues, warnings: [] };

View File

@@ -25,6 +25,21 @@ type SlackConfigLike = {
accounts?: Record<string, SlackAccountLike | undefined>;
};
function forEachEnabledAccount<T extends { enabled?: unknown }>(
accounts: Record<string, T | undefined> | undefined,
run: (accountId: string, account: T) => void,
): void {
if (!accounts) {
return;
}
for (const [accountId, account] of Object.entries(accounts)) {
if (!account || account.enabled === false) {
continue;
}
run(accountId, account);
}
}
export function validateTelegramWebhookSecretRequirements(
value: TelegramConfigLike,
ctx: z.RefinementCtx,
@@ -38,20 +53,11 @@ export function validateTelegramWebhookSecretRequirements(
path: ["webhookSecret"],
});
}
if (!value.accounts) {
return;
}
for (const [accountId, account] of Object.entries(value.accounts)) {
if (!account) {
continue;
}
if (account.enabled === false) {
continue;
}
forEachEnabledAccount(value.accounts, (accountId, account) => {
const accountWebhookUrl =
typeof account.webhookUrl === "string" ? account.webhookUrl.trim() : "";
if (!accountWebhookUrl) {
continue;
return;
}
const hasAccountSecret = hasConfiguredSecretInput(account.webhookSecret);
if (!hasAccountSecret && !hasBaseWebhookSecret) {
@@ -62,7 +68,7 @@ export function validateTelegramWebhookSecretRequirements(
path: ["accounts", accountId, "webhookSecret"],
});
}
}
});
}
export function validateSlackSigningSecretRequirements(
@@ -77,20 +83,11 @@ export function validateSlackSigningSecretRequirements(
path: ["signingSecret"],
});
}
if (!value.accounts) {
return;
}
for (const [accountId, account] of Object.entries(value.accounts)) {
if (!account) {
continue;
}
if (account.enabled === false) {
continue;
}
forEachEnabledAccount(value.accounts, (accountId, account) => {
const accountMode =
account.mode === "http" || account.mode === "socket" ? account.mode : baseMode;
if (accountMode !== "http") {
continue;
return;
}
const accountSecret = account.signingSecret ?? value.signingSecret;
if (!hasConfiguredSecretInput(accountSecret)) {
@@ -101,5 +98,5 @@ export function validateSlackSigningSecretRequirements(
path: ["accounts", accountId, "signingSecret"],
});
}
}
});
}