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
95 lines (94 loc) • 3.77 kB
JavaScript
// 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/.
/**
* Embedded task templates.
*
* Curated sets of read-only YAML task templates ship inside the akm binary
* under `src/assets/tasks/<category>/` — `core/` (general-purpose maintenance)
* and `improve/` (the maintainer-oriented multi-cadence improve schedule,
* folded in from the retired `registerDefaultTasks`/`akm tasks init` path in
* 0.9, S6). Every category subdirectory is enumerated the same way; adding a
* new one needs no code change here. Templates are resolved at runtime via
* `import.meta.dir` (mirroring `SKELETON_DIR` in
* src/commands/stash-skeleton.ts) and are NOT written to any stash at
* install time — the `akm setup` wizard copies a template into the primary
* stash only when the user opts in (copy-on-enable).
*
* Each entry exposes the parsed `command`, `schedule`, and `description`
* alongside the raw `yaml`, so the wizard can both render a choice and write
* the file verbatim (with an optional schedule edit applied).
*/
import fs from "node:fs";
import path from "node:path";
import { getDirname } from "../runtime.js";
import { parseTaskSource } from "./source/parse-task-source.js";
/** Directory holding the bundled task template categories. */
const TASKS_ASSETS_DIR = path.join(getDirname(import.meta.url), "../assets/tasks");
const DEFAULT_DISABLED_TASKS = new Set(["improve/akm-improve-catchup"]);
/**
* Enumerate the embedded task templates from every category subdirectory of
* the bundled assets directory. Sorted by category then id for deterministic
* ordering. Returns an empty array if the directory is missing (defensive —
* a build without assets should not crash the wizard).
*/
export function listEmbeddedTasks() {
let categories;
try {
categories = fs
.readdirSync(TASKS_ASSETS_DIR, { withFileTypes: true })
.filter((entry) => entry.isDirectory())
.map((entry) => entry.name)
.sort();
}
catch {
return [];
}
const tasks = [];
for (const category of categories) {
const categoryDir = path.join(TASKS_ASSETS_DIR, category);
let entries;
try {
entries = fs.readdirSync(categoryDir);
}
catch {
continue;
}
for (const entry of entries.sort()) {
if (!entry.endsWith(".yml"))
continue;
const id = entry.slice(0, -4);
const filePath = path.join(categoryDir, entry);
let yaml;
try {
yaml = fs.readFileSync(filePath, "utf8");
}
catch {
continue;
}
let parsed;
try {
parsed = parseTaskSource({ yaml, filePath, workspaceRoot: TASKS_ASSETS_DIR });
}
catch {
continue;
}
// Setup defaults are trusted application metadata, not bundle-authored
// task data. Task source can describe a schedule but cannot activate it.
const task = parsed.v4;
const [firstSchedule] = task.schedule;
if (task.target.kind !== "run" || !firstSchedule)
continue;
tasks.push({
id,
label: `${category}/${id}`,
command: task.target.run,
schedule: firstSchedule.cron,
description: task.description ?? "",
enabled: !DEFAULT_DISABLED_TASKS.has(`${category}/${id}`),
yaml,
});
}
}
return tasks;
}