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

64 lines (63 loc) • 2.85 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 target-ref classifier (P1a Lane B, docs/plans/specs/p1a-with-rejection-classifier.md §4.1). * * `classifyTargetRef` is the canonical classifier for a canonical asset ref * used as an execution target: `commands/<name>`, `scripts/<name>`, * `tasks/<name>`, or `workflows/<name>`, each optionally bundle-qualified * (`<bundle>//commands/<name>`). It reuses the repo's one ref parser * (`parseBundleRef` / `bundleRefToString`, src/core/asset/asset-ref.ts) and * accepts a value only when all of the following hold: * * 1. `parseBundleRef(value)` does not throw; * 2. the parsed ref carries no `#fragment`; * 3. `bundleRefToString(parsed) === value` — the value round-trips, which * rejects non-canonical spellings (`akm:commands/review`, * `bad.bundle//commands/review`) even when they happen to parse; * 4. the concept id contains a `/`, and the family segment before the * first `/` is one of `commands`, `scripts`, `tasks`, `workflows`; * 5. the name segment after the first `/` is non-empty. * * Explicit non-goals (binding, spec §4.1): no GitHub locator grammar, no * `akm/command` builtin special case, no resolution, no filesystem access, no * guessing. Callers layer builtin detection on top (see * `classifyWorkflowStepUses` in src/workflows/source-semantics.ts). */ import { bundleRefToString, parseBundleRef } from "../core/asset/asset-ref.js"; import { UsageError } from "../core/errors.js"; const FAMILY_KIND = { commands: "command", scripts: "script", tasks: "task", workflows: "workflow", }; function targetRefInvalid(value) { return new UsageError(`Target ref ${JSON.stringify(value)} must be a canonical commands/, scripts/, tasks/, or workflows/ asset ref.`, "TARGET_REF_INVALID"); } /** Classify one exact canonical asset ref as an execution target. Never resolves or guesses. */ export function classifyTargetRef(value) { let parsed; try { parsed = parseBundleRef(value); } catch { throw targetRefInvalid(value); } if (parsed.fragment !== undefined) throw targetRefInvalid(value); if (bundleRefToString(parsed) !== value) throw targetRefInvalid(value); const slash = parsed.conceptId.indexOf("/"); if (slash < 0) throw targetRefInvalid(value); const family = parsed.conceptId.slice(0, slash); const name = parsed.conceptId.slice(slash + 1); if (name.length === 0) throw targetRefInvalid(value); const kind = FAMILY_KIND[family]; if (kind === undefined) throw targetRefInvalid(value); return Object.freeze({ kind, ref: value }); }