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
70 lines (69 loc) • 2.87 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/.
import fs from "node:fs";
import path from "node:path";
import { pathToFileURL } from "node:url";
import { warn } from "../../core/warn.js";
import blueskyFetcher from "./bluesky.js";
import githubFetcher from "./github.js";
import rssFetcher from "./rss.js";
import xFetcher from "./x.js";
import youtubeFetcher from "./youtube.js";
const FETCHER_DIR = path.join("scripts", "wiki-fetchers");
const FETCHER_FILE_PATTERN = /\.(?:ts|js|mjs)$/i;
/**
* Order matters: the first fetcher whose `matches` returns true and whose
* `fetch` returns non-null wins. Host-specific fetchers therefore precede the
* generic RSS fetcher, whose `matches` is path-shaped and deliberately loose.
* Any fetcher returning null falls through to the generic website crawler.
*/
const BUILTIN_FETCHERS = [
githubFetcher,
youtubeFetcher,
blueskyFetcher,
xFetcher,
rssFetcher,
];
function isWikiSnapshotFetcher(value) {
if (!value || typeof value !== "object")
return false;
const candidate = value;
return (typeof candidate.name === "string" &&
typeof candidate.matches === "function" &&
typeof candidate.fetch === "function");
}
export async function loadWikiSnapshotFetchers(stashDir) {
const fetchers = [];
if (stashDir) {
const fetcherDir = path.join(stashDir, FETCHER_DIR);
try {
const entries = fs.readdirSync(fetcherDir).sort();
for (const entry of entries) {
if (!FETCHER_FILE_PATTERN.test(entry))
continue;
try {
const fileUrl = pathToFileURL(path.join(fetcherDir, entry)).toString();
const mod = await import(fileUrl);
if (isWikiSnapshotFetcher(mod.default)) {
fetchers.push(mod.default);
}
else {
warn("[akm] wiki-fetcher %s skipped: missing { name, matches, fetch }", entry);
}
}
catch (error) {
warn("[akm] wiki-fetcher %s failed to load: %s", entry, error instanceof Error ? error.message : String(error));
}
}
}
catch (error) {
const code = typeof error === "object" && error && "code" in error ? error.code : undefined;
if (code !== "ENOENT") {
warn("[akm] wiki-fetcher directory %s could not be read: %s", fetcherDir, error instanceof Error ? error.message : String(error));
}
// Missing directory means no custom fetchers.
}
}
return [...fetchers, ...BUILTIN_FETCHERS];
}