UNPKG

akm-cli

Version:

akm (Agent Knowledge Manager) — a portable, local-first capability library for AI agents. Discover, load, share, and improve reusable skills, scripts, workflows, and knowledge across any shell-capable coding agent, including Claude Code, OpenCode, and Cur

54 lines (53 loc) • 1.97 kB
// This Source Code Form is subject to the terms of the Mozilla Public // License, v. 2.0. If a copy of the MPL was not distributed with this // file, You can obtain one at https://mozilla.org/MPL/2.0/. /** * The one process lock around native scheduler writes. * * `task sync|add|enable|disable|prune --yes` read the installed rows, plan, * and apply under it, so two akm processes never interleave their writes to * the same crontab or LaunchAgents directory. It is an `O_EXCL` lock file * under `$STATE/locks`, reclaimed only from a verifiably dead holder, and * re-entrant within one process (`add` runs `sync` inside it). */ import fs from "node:fs"; import path from "node:path"; import { TransientError } from "../core/errors.js"; import { createLockPayload, probeLock, reclaimStaleLock, releaseLock, tryAcquireLockSync } from "../core/file-lock.js"; import { getStateDir } from "../core/paths.js"; export function schedulerLockPath() { return path.join(getStateDir(), "locks", "scheduler.lock"); } let depth = 0; export async function withSchedulerLock(fn) { if (depth > 0) { depth += 1; try { return await fn(); } finally { depth -= 1; } } const lockPath = schedulerLockPath(); fs.mkdirSync(path.dirname(lockPath), { recursive: true }); const acquire = () => tryAcquireLockSync(lockPath, createLockPayload({ purpose: "scheduler" })); let ownership = acquire(); if (!ownership) { const probe = probeLock(lockPath); if (probe.state === "absent" || (probe.state === "stale" && reclaimStaleLock(lockPath, probe))) { ownership = acquire(); } } if (!ownership) { throw new TransientError("Another akm process is syncing the scheduler right now.", "SCHEDULER_LOCK_HELD"); } depth = 1; try { return await fn(); } finally { depth = 0; releaseLock(ownership); } }