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

156 lines (155 loc) • 6.48 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 `website-snapshot` adapter — akm 0.9.0 format-family work item (#46). * * A READ-ONLY (Mode A) view over a materialized crawl snapshot written by * `src/sources/snapshot-fetchers/website-ingest.ts` (spec §6/§7). The on-disk * pages are KNOWLEDGE-shaped markdown under `stash/knowledge/**` with no `type:` * field; this adapter RE-TYPES them to the open `type: website`. Per * open-question-3 (RESOLVED, maintainer 2026-07) the re-type is GATED — it * applies only to a page carrying the `website` tag / a `sourceUrl` (a page * lacking both is not re-typed); the document KEEPS its `sourceUrl` (surfaced as * `sourceRef` on `documentJson`); and the conceptId STRIPS the * `stash/knowledge/` prefix. `manifest.json` is snapshot PROVENANCE * (`{url, fetchedAt}`), read by the probe but never indexed as a concept. * * Read-only ⇒ NO `placeNew` (Mode B export routes content through the * DESTINATION adapter, which owns placement). `validate` runs base checks only * (a mirror the adapter does not author has no native validators); `updated` * never appears on a snapshot page, so `missing-updated` is filtered out. * * Conformance oracle (authored, DO NOT modify): fixture * `tests/fixtures/bundles/website-snapshot/` + goldens * `tests/fixtures/format-family-goldens/website-snapshot/{recognition,placement,lint,renderer}.json`. */ import fs from "node:fs"; import path from "node:path"; import { parse as parseYaml } from "yaml"; import { parseFrontmatter, parseFrontmatterBlock } from "../../asset/frontmatter.js"; import { toPosix } from "../../common.js"; import { hashContent, nonEmptyString, runBaseValidateChecks } from "./shared.js"; /** A snapshot bundle is single-component; its one component is `main`. */ const COMPONENT_ID = "main"; /** The crawl page root the snapshot writer materializes pages under. */ const PAGES_PREFIX = "stash/knowledge/"; /** The provenance manifest basename (probe marker only, never indexed). */ const MANIFEST_FILE = "manifest.json"; /** The tag the snapshot writer stamps on every crawled page. */ const WEBSITE_TAG = "website"; function parseSnapshotFrontmatter(raw) { const out = { tags: [] }; const block = parseFrontmatterBlock(raw); if (!block) return out; let data = {}; try { const value = parseYaml(block.frontmatter); if (value && typeof value === "object" && !Array.isArray(value)) data = value; } catch { return out; } out.title = nonEmptyString(data.title); out.description = nonEmptyString(data.description); out.sourceUrl = nonEmptyString(data.sourceUrl); if (Array.isArray(data.tags)) { out.tags = data.tags.filter((t) => typeof t === "string" && t.trim().length > 0).map((t) => t.trim()); } return out; } /** True when a page is a crawl snapshot page under `stash/knowledge/**`. */ function isSnapshotPage(relPath) { const posix = toPosix(relPath); return posix.startsWith(PAGES_PREFIX) && posix.toLowerCase().endsWith(".md"); } /** The GATED re-type predicate (open-question-3): the page carries the `website` tag OR a `sourceUrl`. */ function isReTypeGated(fm) { return fm.sourceUrl !== undefined || fm.tags.includes(WEBSITE_TAG); } /** conceptId = page path − `stash/knowledge/` prefix − `.md`. */ function conceptIdOf(relPath) { return toPosix(relPath).slice(PAGES_PREFIX.length).replace(/\.md$/i, ""); } function recognize(c, file) { if (file.ext !== ".md" || !isSnapshotPage(file.relPath)) return null; const raw = file.content(); const fm = parseSnapshotFrontmatter(raw); if (!isReTypeGated(fm)) return null; // not a re-typed website page const conceptId = conceptIdOf(file.relPath); const name = fm.title ?? conceptId.split("/").pop() ?? conceptId; const body = parseFrontmatter(raw).content; const doc = { ref: `${c.id}//${conceptId}`, bundle: c.id, component: COMPONENT_ID, conceptId, path: file.absPath, hash: hashContent(raw), adapterId: "website-snapshot", ownsPresentation: true, type: "website", name, content: body, }; if (fm.description !== undefined) doc.description = fm.description; if (fm.sourceUrl !== undefined) doc.documentJson = { sourceRef: fm.sourceUrl }; return doc; } async function validate(c, changes, ctx) { const diagnostics = []; for (const change of changes) { if (change.op === "delete") continue; const raw = change.after ?? (await ctx.readFile(change.path)); if (typeof raw !== "string") continue; if (!isSnapshotPage(change.path)) continue; const base = await runBaseValidateChecks(toPosix(change.path), parseFrontmatter(raw), c.root, ctx); // A read-only crawl mirror carries `fetchedAt` provenance, never an `updated` // field — so `missing-updated` is not a defect on a snapshot page. diagnostics.push(...base.filter((d) => d.issue !== "missing-updated")); } return diagnostics; } export const websiteSnapshotAdapter = { id: "website-snapshot", version: "0.9.0", extensions: [".md"], recognize, validate, readCandidates(c, conceptId) { const canonical = toPosix(conceptId).replace(/\.md$/i, ""); return [{ path: path.join(c.root, PAGES_PREFIX, `${canonical}.md`), conceptId: canonical }]; }, // No placeNew: the snapshot is READ-ONLY (Mode A). Export (Mode B) routes // content through the DESTINATION adapter, which owns placement. /** * Install-time probe (§1.2): a root carrying the snapshot provenance * `manifest.json` (`{url, fetchedAt}`). No other bundle root carries this * exact marker, so the probe is unambiguous. */ looksLikeRoot(root) { let raw; try { raw = fs.readFileSync(path.join(root, MANIFEST_FILE), "utf8"); } catch { return false; } try { const manifest = JSON.parse(raw); return typeof manifest.url === "string" && typeof manifest.fetchedAt === "string"; } catch { return false; } }, };