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
91 lines (90 loc) • 3.65 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 { stashDirFor } from "../../core/asset/asset-placement.js";
import { isBundleSlug, parseBundleRef } from "../../core/asset/asset-ref.js";
/** Channel order is the order links are stored and shown in. */
const CHANNELS = [
["xref", (doc) => doc.xrefs],
["superseded_by", (doc) => doc.supersededBy],
["contradicted_by", (doc) => doc.contradictedBy],
["belief_peer", (doc) => doc.currentBeliefRefs],
["derived_from", (doc) => doc.derivedFrom],
["cites", (doc) => doc.sources],
["links_to", (doc) => doc.links],
["uses", (doc) => doc.uses],
];
/** The links an indexed document declares, in channel then authored order; one per (kind, target). */
export function declaredLinks(doc, owner) {
const links = [];
const seen = new Set();
for (const [kind, read] of CHANNELS) {
for (const raw of stringValues(read(doc))) {
const target = linkTarget(raw, owner.conceptId);
if (!target)
continue;
const bundle = target.bundle ?? owner.bundleId;
if (bundle === owner.bundleId && target.conceptId === owner.conceptId)
continue;
const key = `${kind}\0${bundle}\0${target.conceptId}`;
if (seen.has(key))
continue;
seen.add(key);
links.push({ kind, raw, ...target });
}
}
return links;
}
function stringValues(value) {
if (typeof value === "string")
return [value];
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
}
/**
* The target a token names, or `undefined` when the token is not an asset ref
* (a session id, a URL, prose, a template placeholder). Retired spellings
* convert in memory: `<type>:<name>` (`memory:x`), `wiki:<wiki>/<path>` (0.8
* wikis, now knowledge under `wikis/`), a `.md` suffix, and a `#fragment`.
* Inside a wiki page, `raw/…` and `pages/…` are relative to the wiki root.
*/
function linkTarget(raw, ownerConceptId) {
const token = raw.trim();
if (!token || /[\s<*]/.test(token) || token.includes("$(") || token.includes("${"))
return;
let bundle;
let body = token;
const boundary = token.indexOf("//");
if (boundary >= 0) {
bundle = token.slice(0, boundary);
body = token.slice(boundary + 2);
if (!isBundleSlug(bundle))
return;
}
const conceptId = legacyConceptId(body.split("#", 1)[0] ?? "", ownerConceptId);
if (conceptId === undefined || conceptId.length <= 1 || conceptId.includes("//"))
return;
try {
return { ...(bundle ? { bundle } : {}), conceptId: parseBundleRef(conceptId).conceptId };
}
catch {
return;
}
}
function legacyConceptId(body, ownerConceptId) {
const stripped = body.replace(/\.md$/i, "");
const colon = stripped.indexOf(":");
if (colon >= 0) {
const type = stripped.slice(0, colon);
const name = stripped.slice(colon + 1);
if (!name || name.includes(":"))
return;
if (type === "wiki")
return `knowledge/wikis/${name}`;
const stashDir = stashDirFor(type);
return stashDir === undefined ? undefined : `${stashDir}/${name}`;
}
const wikiRoot = /^((?:[^/]+\/)*?wikis\/[^/]+\/)/.exec(ownerConceptId)?.[1];
if (wikiRoot && /^(raw|pages)\//.test(stripped))
return `${wikiRoot}${stripped}`;
return stripped;
}