feat(api): add tool filtering and DB-backed cleanup settings

Add feature flag support to skip disabled/experimental tools at startup
by reading disabledTools and enableExperimentalTools from the settings
table. Refactor cleanup.ts to read tempFileMaxAgeHours from DB settings
(with env var fallback) and respect the startupCleanup setting.
This commit is contained in:
Siddharth Kumar Sah
2026-03-26 01:10:51 +08:00
parent 585d66f0c9
commit acfff754b5
4 changed files with 458 additions and 55 deletions
+46 -6
View File
@@ -1,18 +1,56 @@
import { mkdirSync } from "node:fs";
import { readdir, rm, stat } from "node:fs/promises";
import { join } from "node:path";
import { lt } from "drizzle-orm";
import { eq, lt } from "drizzle-orm";
import { env } from "../config.js";
import { db, schema } from "../db/index.js";
/**
* Read the temp file max age from DB settings, falling back to env var.
* Called each cleanup cycle so changes take effect without restart.
*/
export function getMaxAgeMs(): number {
try {
const row = db
.select()
.from(schema.settings)
.where(eq(schema.settings.key, "tempFileMaxAgeHours"))
.get();
if (row) {
const hours = parseFloat(row.value);
if (!isNaN(hours) && hours > 0) return hours * 60 * 60 * 1000;
}
} catch {
/* DB not ready yet, use env */
}
return env.FILE_MAX_AGE_HOURS * 60 * 60 * 1000;
}
/**
* Check whether startup cleanup should run.
* Returns true by default; only returns false when explicitly set to "false".
*/
export function shouldRunStartupCleanup(): boolean {
try {
const row = db
.select()
.from(schema.settings)
.where(eq(schema.settings.key, "startupCleanup"))
.get();
return row ? row.value !== "false" : true;
} catch {
return true;
}
}
export function startCleanupCron() {
// Ensure workspace directory exists
mkdirSync(env.WORKSPACE_PATH, { recursive: true });
const intervalMs = env.CLEANUP_INTERVAL_MINUTES * 60 * 1000;
const maxAgeMs = env.FILE_MAX_AGE_HOURS * 60 * 60 * 1000;
const cleanup = async () => {
const maxAgeMs = getMaxAgeMs();
try {
const entries = await readdir(env.WORKSPACE_PATH, { withFileTypes: true }).catch(() => []);
const now = Date.now();
@@ -52,14 +90,16 @@ export function startCleanupCron() {
}
};
// Run on startup
cleanup();
purgeExpiredSessions();
// Run on startup only if setting allows it
if (shouldRunStartupCleanup()) {
cleanup();
purgeExpiredSessions();
}
// Schedule recurring cleanup
setInterval(cleanup, intervalMs);
setInterval(purgeExpiredSessions, 60 * 60 * 1000); // Hourly
console.log(
`Cleanup scheduled: every ${env.CLEANUP_INTERVAL_MINUTES}m, max age ${env.FILE_MAX_AGE_HOURS}h`,
`Cleanup scheduled: every ${env.CLEANUP_INTERVAL_MINUTES}m, max age configurable (env default: ${env.FILE_MAX_AGE_HOURS}h)`,
);
}