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

42 lines (41 loc) • 1.73 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/. /** * Small shared helpers for the snapshot fetchers. * * These live in a leaf module (no fetcher or `website-ingest` imports) so the * individual fetchers can share them without cycling through the fetcher * registry — the same reason the SSRF guards were pulled into `host-guard.ts`. */ /** * Neutralize markdown structure in attacker-controlled prose. Without this a * post/tweet body containing a line starting with `##` forges a section * boundary in the snapshot, letting it impersonate content the fetcher * vouched for. */ export function escapeMarkdownStructure(value) { return value .replace(/\r\n?/g, "\n") .split("\n") .map((line) => line.replace(/^(\s*)([#>\-*+=~_`]|\d+[.)])/, "$1\\$2")) .join("\n"); } /** Coerce an unknown JSON value to a string, defaulting to "". */ export function coerceString(value) { return typeof value === "string" ? value : ""; } /** * `index` and `log` are OKF reserved structural basenames at every depth — an * adapter never indexes them, so an asset written there imports but can never * be found by search or show. Remap the trailing segment (`x/index` -> * `x/index-content`). Idempotent: a `-content`-suffixed name is left alone. */ export function avoidReservedBasename(relPath) { const segments = relPath.split("/"); const last = segments[segments.length - 1] ?? ""; if (last === "index" || last === "log") { segments[segments.length - 1] = `${last}-content`; } return segments.join("/"); }