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

55 lines (54 loc) • 2.41 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/. /** * Shared `--path` / `--name` semantics for asset-creating commands * (`remember`, `import`, `propose`, `workflow create`, ...). * * The contract, applied consistently across the command surface: * - `--name` (or the name positional) is a FLAT asset name — no `/`. * - `--path` is a relative directory, applied rooted at the asset's type * directory. The final asset name is `<path>/<name>`. * * Subdirectory placement is `--path`'s job, not `--name`'s. System-derived * names (e.g. a URL-path-derived knowledge name) are exempt — only the user's * explicit name should be flat-checked, at the command layer. */ import { UsageError } from "../errors.js"; /** * Normalise an optional `--path` value: a relative directory, applied rooted * at the asset's type directory (e.g. `personal/projects` under `memories/`). * Rejects absolute paths and `.`/`..` segments. Returns `""` when unset. */ export function normalizeCreateSubPath(subPath) { if (subPath === undefined) return ""; const trimmed = subPath .trim() .replace(/\\/g, "/") .replace(/^\/+|\/+$/g, ""); if (!trimmed) return ""; if (trimmed.split("/").some((segment) => !segment || segment === "." || segment === "..")) { throw new UsageError("--path must be a relative directory without '.' or '..' segments."); } return trimmed; } /** * Enforce that an explicit, user-supplied name is a flat (single-segment) * name. A `/` in the name is rejected with guidance to use `--path`. Applied * at the command layer to the user's name only — system-derived names may nest. */ export function assertFlatAssetName(name) { if (name?.replace(/\\/g, "/").replace(/\.md$/i, "").includes("/")) { throw new UsageError("Asset --name must be a flat name without '/'. Use --path to choose a subdirectory " + "(e.g. --path personal --name grocery-list)."); } } /** * Combine a normalised `--path` subdirectory with a flat base name into the * nested asset name the path resolver expects. `subPath` may be `""`. */ export function combineCreatePath(subPath, baseName) { return subPath ? `${subPath}/${baseName}` : baseName; }