@b-apm/integration-api
v0.1.0
Published
Shared contracts and registry for bapm host integrations
Downloads
223
Readme
@b-apm/integration-api
UNSTABLE: Early public release. APIs and on-disk layouts may change without a major bump. Not production-ready.
Shared contracts, registry, and materialize helpers for bapm integrations.
Boundary
| Package | May depend on |
| --------------------------------------------------- | ---------------------------------------------------------------- |
| @b-apm/core | @b-apm/integration-api only (no concrete @b-apm/integration-*) |
| @b-apm/integration-cursor (and other integrations) | @b-apm/integration-api |
| CLI / tests | Register concrete integrations into a registry created here |
Core Install discovers primitives and calls materialize on registered integrations through this package. Integration packages implement detection, deploy roots, and disk writes — core never imports them.
Loadable package export contract (object-map)
When a project manifest uses object-map target / targets, the CLI loads each map value as an npm package from the project cwd and registers a runtime BapmIntegration. A loadable package MUST expose (first match wins):
- Named
createIntegration— zero-arg factory returningBapmIntegration(preferred for third parties); or - Named
createCursorIntegration(or an equivalent documented factory) returningBapmIntegration; or - Default export that is either a
BapmIntegrationobject or a factory returning one.
The loaded instance MUST have non-empty id, deployRoots array, detect, and materialize (configureMcp / compile optional). Optional mcpEnvMode: "bake" | "translate" tells install whether to bake APM ${VAR} placeholders before configureMcp (omitted ⇒ bake-compatible, Cursor default). id MUST equal the map key. Marketplace-output-only packages (no runtime hooks) are rejected. A successful configureMcp report MUST include a non-empty configPath (project-relative, absolute, or home-tilde form for home-scoped hosts).
See @b-apm/integration-cursor for a built-in reference and the VitePress architecture guide for the author how-to.
Helpers
Optional fs/path helpers for host materialize (exported from the package root):
| Symbol | Role |
| --------------------------------- | ------------------------------------------------------------------ |
| primitivesList | Normalize array / { primitives } sets |
| primitivesMaterialize | Dispatch primitives to skill / instruction / … handlers |
| sanitizeName | Path-safe single segment from a primitive name |
| isUnderRoot | Containment check under a deploy root |
| assertUnderDeployRoots | Refuse writes outside registered roots |
| writeDeployedFile | Assert roots + mkdir + write + DeployedFile inventory row |
| readPrimitiveContent | Inline content / source file / stub frontmatter |
| toPosixRel | Absolute → cwd-relative path with / separators |
| findPackageRoot | Nearest apm.yml / bapm.yml / plugin.json ancestor |
| isWithin | Path containment (candidate under root) |
| listFiles | Recursive file listing (absolute paths) |
| copyPortableSkillDirectory | Safe Agent Plugin skill tree copy (no symlink escape) |
| materializeSkill | Shared skill deploy (portable tree / SKILL.md / stub + inventory) |
| renderPrimitivesMarkdown | Deterministic compile markdown (AGENTS.md family) |
| compileMarkdownReport | Preview/write CompileReport for host compile hooks |
| filterFrontmatterKeys | Drop non-allowlisted YAML frontmatter keys |
| SHARED_COMMAND_FRONTMATTER_KEYS | Shared command FM allowlist (description/tools/model/…) |
| HookOwnershipSidecar | Type for .*/bapm-hooks.json owned map (flexible optional fields) |
| readHookOwnershipSidecar | Read ownership sidecar; missing/malformed → { owned: {} } |
| writeHookOwnershipSidecar | Write { owned } as pretty JSON + trailing newline |
| stripOwnedHookCommands | Filter event arrays by owned entry commands (no disk deletes) |
| removeOwnedHookArtifacts | Best-effort rm of owned scripts / hookFile / hookFiles |
| copyHookScript | Simple script copy + command rewrite (needle + caller destRel) |
Prefer primitivesMaterialize({ skill() {…}, … }) over a manual primitivesList loop.
Use materializeSkill({ destDir }) inside the skill handler — hosts only pick the path.
Use writeDeployedFile for single-file markdown/json deploys; use renderPrimitivesMarkdown + compileMarkdownReport inside compile.
Integrations keep host-specific detect + destinations; shared path/content plumbing lives here.
Materialize report
materialize MAY return a MaterializeReport:
type DeployedFile = { path: string; hash?: string };
type MaterializeReport = { deployedFiles: DeployedFile[] };path— project-/cwd-relative harness path (e.g..agents/skills/hello/SKILL.md)hash— optional; when omitted, core computes a stable content hash for lock inventory
Core uses this report only via @b-apm/integration-api to write deployed_file_hashes and drive orphan cleanup / frozen re-verify. There is no adapter catalog or MCP configure surface in this package.
