UNPKG

@blundergoat/goat-flow

Version:

AI coding agent harness and local dashboard for Claude Code, OpenAI Codex, Google Antigravity, and GitHub Copilot - setup audits, guardrails, structured skills, deny hooks, and persistent learning loops.

93 lines 3.73 kB
/** * Resolves goat-flow package-root paths that need to work from source and packaged builds. * Template lookup and CLI self-reference should go through this module instead of hardcoding dist-relative paths. */ import { dirname, join } from "node:path"; import { existsSync, readFileSync } from "node:fs"; import { fileURLToPath } from "node:url"; /** Find the goat-flow project root by walking up from this file's directory; throws when no package root is found. */ function findGoatFlowRoot() { let dir = dirname(fileURLToPath(import.meta.url)); for (let i = 0; i < 10; i++) { const candidate = join(dir, "package.json"); if (existsSync(candidate)) { return dir; } const parent = dirname(dir); if (parent === dir) break; dir = parent; } throw new Error("Could not find goat-flow project root"); } /** Absolute path to the goat-flow project root */ const GOAT_FLOW_ROOT = findGoatFlowRoot(); /** * Read the package version from the nearest package.json. * Uses a recover fallback of `0.0.0` when the file is absent or unreadable so help output still renders. * * @returns package version string, or `0.0.0` when unavailable */ export function getPackageVersion() { const pkgPath = join(GOAT_FLOW_ROOT, "package.json"); if (!existsSync(pkgPath)) return "0.0.0"; try { const pkg = JSON.parse(readFileSync(pkgPath, "utf-8")); return typeof pkg.version === "string" ? pkg.version : "0.0.0"; } catch { return "0.0.0"; } } /** * Resolve a relative template path to an absolute path within goat-flow. * * @param relative - package-relative template or workflow path * @returns absolute path inside the resolved goat-flow package root */ export function getTemplatePath(relative) { return join(GOAT_FLOW_ROOT, relative); } /** * Resolve the first existing goat-flow path from a priority-ordered list. * Throws when none exist so callers do not silently use a missing template. * * @param relatives - package-relative candidate paths in preference order * @returns absolute path for the first candidate present on disk */ export function resolveFirstExistingPackagePath(relatives) { for (const relative of relatives) { const absolute = getTemplatePath(relative); if (existsSync(absolute)) return absolute; } throw new Error(`Could not find any of: ${relatives.join(", ")}`); } /** * Build the absolute CLI command used to run goat-flow from any project. * Returns a forward-slash path so it renders cleanly in user-visible setup * prompts and is identically callable from PowerShell, CMD, and Bash on * Windows, where Node accepts forward slashes everywhere argv-style. * * @returns shell-safe `node .../dist/cli/cli.js` command string */ export function getCliCommand() { return `node ${join(GOAT_FLOW_ROOT, "dist", "cli", "cli.js").replace(/\\/g, "/")}`; } /** * Detect whether goat-flow is running from a packaged install rather than a source * checkout. `package.json` `files` ships only `dist/` + `workflow/` plus a small * set of runtime helpers, so consumer environments do not have `src/` or * `.goat-flow/*` present. Code that reads source files at runtime, or validates * evidence_paths that point at framework-repo docs, must gate on this to avoid * spurious failures on consumer installs. * * @returns true - when packaged-mode override is set or source dashboard files are absent */ export function isPackagedInstall() { if (process.env["GOAT_FLOW_PACKAGED_MODE"] === "1") return true; return !existsSync(join(GOAT_FLOW_ROOT, "src", "dashboard")); } //# sourceMappingURL=paths.js.map