UNPKG

@phren/cli

Version:

Knowledge layer for AI agents - CLI, MCP server, and data layer

38 lines (37 loc) • 1.85 kB
/** * One computer rewrites a store's generated files (topic `## Now` blocks, * summary.md's "What phren knows", archived tasks, pruned findings) at a * time. When every computer's background maintenance rewrote them, each * sync merged two rewrites of the same lines. The holder renews its lease * daily as it runs; a holder that has stopped running loses it after three * days to the next computer that does. */ import * as fs from "fs"; import * as path from "path"; import { getMachineName } from "../machine-identity.js"; import { atomicWriteText } from "../phren-paths.js"; export const MAINTENANCE_WRITER_FILE = ".config/maintenance-writer.json"; export const MAINTENANCE_LEASE_MS = 3 * 86_400_000; const RENEW_AFTER_MS = 86_400_000; function readLease(file) { try { const lease = JSON.parse(fs.readFileSync(file, "utf8")); return typeof lease?.computer === "string" && lease.computer && typeof lease.renewedAt === "string" && !Number.isNaN(Date.parse(lease.renewedAt)) ? lease : undefined; } catch { return undefined; } } /** Whether this computer may rewrite generated files now; claims or renews the lease when it may. */ export function claimMaintenanceWriter(phrenPath, computer = getMachineName(), now = Date.now()) { const file = path.join(phrenPath, MAINTENANCE_WRITER_FILE); const lease = readLease(file); const age = lease ? now - Date.parse(lease.renewedAt) : Number.POSITIVE_INFINITY; if (lease && lease.computer !== computer && age < MAINTENANCE_LEASE_MS) return { writer: false, holder: lease.computer }; if (!lease || lease.computer !== computer || age > RENEW_AFTER_MS) { atomicWriteText(file, `${JSON.stringify({ computer, renewedAt: new Date(now).toISOString() }, null, 2)}\n`); } return { writer: true, holder: computer }; }