diff --git a/core/src/standards/atlas.ts b/core/src/standards/atlas.ts index 1fc2a95..e3627bf 100644 --- a/core/src/standards/atlas.ts +++ b/core/src/standards/atlas.ts @@ -25,20 +25,34 @@ interface AtlasYamlDoc { } /** - * Resolve the ATLAS YAML. Two layouts are supported: - * - Published package: `/atlas-data/ATLAS.yaml` (vendored into the tarball at pack time). - * - Monorepo dev: `/third_party/atlas-data/dist/ATLAS.yaml` (the git submodule). - * - * This module is at `core/{src,dist}/standards/atlas.{ts,js}`, so the package root is 2 levels - * up and the repo root is 3 levels up — true whether run from `src` (tsx) or `dist` (compiled). + * Resolve the ATLAS YAML. Three layouts are supported, tried in order: + * - Bundled runner (cli/mcp/sdk): the runner's esbuild/tsup bundle flattens this module to + * `/dist/*.js`, so `atlas-data/` (vendored at pack time) is 1 level up: `/atlas-data/ATLAS.yaml`. + * - Published core package: this module is at `core/dist/standards/atlas.js`, so `atlas-data/` + * (vendored at pack time) is 2 levels up: `/atlas-data/ATLAS.yaml`. + * - Monorepo dev: `/third_party/atlas-data/dist/ATLAS.yaml` (the git submodule), 3 levels up + * from `core/{src,dist}/standards/`. */ -function atlasYamlPath(): string { +function atlasYamlPath(): string | undefined { const here = path.dirname(fileURLToPath(import.meta.url)); - const packageLocal = path.resolve(here, "..", "..", "atlas-data", "ATLAS.yaml"); - if (existsSync(packageLocal)) { - return packageLocal; - } - return path.resolve(here, "..", "..", "..", "third_party", "atlas-data", "dist", "ATLAS.yaml"); + const candidates = [ + path.resolve(here, "..", "atlas-data", "ATLAS.yaml"), + path.resolve(here, "..", "..", "atlas-data", "ATLAS.yaml"), + path.resolve(here, "..", "..", "..", "third_party", "atlas-data", "dist", "ATLAS.yaml"), + ]; + return candidates.find((p) => existsSync(p)); +} + +function missingAtlasHelp(): string { + return [ + "MITRE ATLAS data not found.", + "", + "Published package (cli / mcp / sdk): atlas-data/ is bundled at install time.", + " Try reinstalling: npm install @keyvaluesystems/agent-opfor-cli (or -mcp / -sdk)", + "", + "Monorepo checkout: initialize the atlas-data submodule with:", + " git submodule update --init --recursive", + ].join("\n"); } function missingSubmoduleHelp(atlasPath: string): string { @@ -57,6 +71,9 @@ function missingSubmoduleHelp(atlasPath: string): string { */ export async function loadAtlasTechniqueIndex(): Promise> { const atlasPath = atlasYamlPath(); + if (atlasPath === undefined) { + throw new Error(missingAtlasHelp()); + } let raw: string; try { raw = await readFile(atlasPath, "utf8"); diff --git a/package-lock.json b/package-lock.json index 907d02d..5858c17 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7248,6 +7248,9 @@ "name": "@keyvaluesystems/agent-opfor-sdk", "version": "0.9.0", "license": "Apache-2.0", + "dependencies": { + "@modelcontextprotocol/sdk": "^1.29.0" + }, "devDependencies": { "@keyvaluesystems/agent-opfor-core": "^0.9.0", "@types/node": "^24.0.0", diff --git a/runners/sdk/package.json b/runners/sdk/package.json index de3c3b6..7c2b8e2 100644 --- a/runners/sdk/package.json +++ b/runners/sdk/package.json @@ -30,6 +30,9 @@ "publishConfig": { "access": "public" }, + "dependencies": { + "@modelcontextprotocol/sdk": "^1.29.0" + }, "devDependencies": { "@keyvaluesystems/agent-opfor-core": "^0.9.0", "@types/node": "^24.0.0", diff --git a/runners/sdk/tsup.config.ts b/runners/sdk/tsup.config.ts index d1bbbb0..b853cc8 100644 --- a/runners/sdk/tsup.config.ts +++ b/runners/sdk/tsup.config.ts @@ -13,4 +13,13 @@ export default defineConfig({ target: "node20", external: ["node:*"], sourcemap: true, + // ESM output bundling CJS deps (yaml, etc.) that call require() at runtime needs a + // real require — without this shim esbuild's stub throws "Dynamic require ... not supported". + // Mirrors the createRequire banner in the cli/mcp esbuild bundles. + banner: { + js: [ + "import { createRequire } from 'module';", + "const require = createRequire(import.meta.url);", + ].join("\n"), + }, });