{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,eAAO,MAAM,WAAW,SACqF,CAAC;AAE9G,gEAAgE;AAChE,eAAO,MAAM,YAAY,SAAyB,CAAC;AAMnD,MAAM,MAAM,aAAa,GAAG,YAAY,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAEvF,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,mBAAmB,IAAI,aAAa,CAqBnD;AA6GD,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CAOvF;AAED,wBAAgB,mCAAmC,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAS/E;AAED,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAOhE;AAMD;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAqBtC;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,IAAI,MAAM,CAQrC;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAO7C;AAED,+BAA+B;AAC/B,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,4BAA4B;AAC5B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,iCAAiC;AACjC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,qCAAqC;AACrC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAOhD;AAED,8CAA8C;AAC9C,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnE;AAkBD,eAAO,MAAM,YAAY,EAAE,MAAoD,CAAC;AAChF,eAAO,MAAM,0BAA0B,kCAAkC,CAAC;AAC1E,eAAO,MAAM,mBAAmB,QAA4E,CAAC;AAC7G,eAAO,MAAM,QAAQ,EAAE,MAAoC,CAAC;AAC5D,eAAO,MAAM,SAAS,iBAAO,CAAC;AAC9B,eAAO,MAAM,eAAe,EAAE,MAAyC,CAAC;AACxE,eAAO,MAAM,2BAA2B,YAAY,CAAC;AACrD,eAAO,MAAM,OAAO,EAAE,MAA+B,CAAC;AAEtD,eAAO,MAAM,aAAa,4BAA4B,CAAC;AAIvD,6CAA6C;AAC7C,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAGxD;AAuCD,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAK1D;AAED,4DAA0D;AAC1D,wBAAgB,WAAW,IAAI,MAAM,CAWpC;AAED,iDAAiD;AACjD,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,8BAA8B;AAC9B,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,4BAA4B;AAC5B,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,gCAAgC;AAChC,wBAAgB,eAAe,IAAI,MAAM,CAExC;AAED,kCAAkC;AAClC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,6CAA6C;AAC7C,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,qCAAqC;AACrC,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,iCAAiC;AACjC,wBAAgB,eAAe,IAAI,MAAM,CAExC","sourcesContent":["import { spawnSync } from \"child_process\";\nimport { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, symlinkSync, unlinkSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { dirname, join, relative, resolve, sep } from \"path\";\nimport { fileURLToPath } from \"url\";\n\n// =============================================================================\n// Package Detection\n// =============================================================================\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = dirname(__filename);\n\n/**\n * Detect if we're running as a Bun compiled binary.\n * Bun binaries have import.meta.url containing \"$bunfs\", \"~BUN\", or \"%7EBUN\" (Bun's virtual filesystem path)\n */\nexport const isBunBinary =\n\timport.meta.url.includes(\"$bunfs\") || import.meta.url.includes(\"~BUN\") || import.meta.url.includes(\"%7EBUN\");\n\n/** Detect if Bun is the runtime (compiled binary or bun run) */\nexport const isBunRuntime = !!process.versions.bun;\n\n// =============================================================================\n// Install Method Detection\n// =============================================================================\n\nexport type InstallMethod = \"bun-binary\" | \"npm\" | \"pnpm\" | \"yarn\" | \"bun\" | \"unknown\";\n\nexport interface SelfUpdateCommand {\n\tcommand: string;\n\targs: string[];\n\tdisplay: string;\n}\n\nexport function detectInstallMethod(): InstallMethod {\n\tif (isBunBinary) {\n\t\treturn \"bun-binary\";\n\t}\n\n\tconst resolvedPath = `${__dirname}\\0${process.execPath || \"\"}`.toLowerCase().replace(/\\\\/g, \"/\");\n\n\tif (resolvedPath.includes(\"/pnpm/\") || resolvedPath.includes(\"/.pnpm/\")) {\n\t\treturn \"pnpm\";\n\t}\n\tif (resolvedPath.includes(\"/yarn/\") || resolvedPath.includes(\"/.yarn/\")) {\n\t\treturn \"yarn\";\n\t}\n\tif (isBunRuntime) {\n\t\treturn \"bun\";\n\t}\n\tif (resolvedPath.includes(\"/npm/\") || resolvedPath.includes(\"/node_modules/\")) {\n\t\treturn \"npm\";\n\t}\n\n\treturn \"unknown\";\n}\n\nfunction getSelfUpdateCommandForMethod(method: InstallMethod, packageName: string): SelfUpdateCommand | undefined {\n\tswitch (method) {\n\t\tcase \"bun-binary\":\n\t\t\treturn undefined;\n\t\tcase \"pnpm\":\n\t\t\treturn {\n\t\t\t\tcommand: \"pnpm\",\n\t\t\t\targs: [\"install\", \"-g\", packageName],\n\t\t\t\tdisplay: `pnpm install -g ${packageName}`,\n\t\t\t};\n\t\tcase \"yarn\":\n\t\t\treturn {\n\t\t\t\tcommand: \"yarn\",\n\t\t\t\targs: [\"global\", \"add\", packageName],\n\t\t\t\tdisplay: `yarn global add ${packageName}`,\n\t\t\t};\n\t\tcase \"bun\":\n\t\t\treturn {\n\t\t\t\tcommand: \"bun\",\n\t\t\t\targs: [\"install\", \"-g\", packageName],\n\t\t\t\tdisplay: `bun install -g ${packageName}`,\n\t\t\t};\n\t\tcase \"npm\":\n\t\t\treturn {\n\t\t\t\tcommand: \"npm\",\n\t\t\t\targs: [\"install\", \"-g\", packageName],\n\t\t\t\tdisplay: `npm install -g ${packageName}`,\n\t\t\t};\n\t\tcase \"unknown\":\n\t\t\treturn undefined;\n\t}\n}\n\nfunction readCommandOutput(command: string, args: string[]): string | undefined {\n\tconst result = spawnSync(command, args, {\n\t\tencoding: \"utf-8\",\n\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\ttimeout: 2000,\n\t\t// Windows package managers are commonly .cmd shims. Use the shell so Node can execute them;\n\t\t// command and args are fixed literals from getGlobalPackageRoots(), not user input.\n\t\tshell: process.platform === \"win32\",\n\t});\n\tif (result.status !== 0) return undefined;\n\tconst stdout = result.stdout.trim();\n\treturn stdout || undefined;\n}\n\nfunction getGlobalPackageRoots(method: InstallMethod): string[] {\n\tswitch (method) {\n\t\tcase \"npm\": {\n\t\t\tconst root = readCommandOutput(\"npm\", [\"root\", \"-g\"]);\n\t\t\treturn root ? [root] : [];\n\t\t}\n\t\tcase \"pnpm\": {\n\t\t\tconst root = readCommandOutput(\"pnpm\", [\"root\", \"-g\"]);\n\t\t\treturn root ? [root, dirname(root)] : [];\n\t\t}\n\t\tcase \"yarn\": {\n\t\t\tconst dir = readCommandOutput(\"yarn\", [\"global\", \"dir\"]);\n\t\t\treturn dir ? [dir, join(dir, \"node_modules\")] : [];\n\t\t}\n\t\tcase \"bun\": {\n\t\t\tconst bunBin = readCommandOutput(\"bun\", [\"pm\", \"bin\", \"-g\"]);\n\t\t\tconst roots = [join(homedir(), \".bun\", \"install\", \"global\", \"node_modules\")];\n\t\t\tif (bunBin) {\n\t\t\t\troots.push(join(dirname(dirname(bunBin)), \"install\", \"global\", \"node_modules\"));\n\t\t\t}\n\t\t\treturn roots;\n\t\t}\n\t\tcase \"bun-binary\":\n\t\tcase \"unknown\":\n\t\t\treturn [];\n\t}\n}\n\nfunction normalizeExistingPathForComparison(path: string): string | undefined {\n\tconst resolvedPath = resolve(path);\n\tif (!existsSync(resolvedPath)) {\n\t\treturn undefined;\n\t}\n\tlet normalizedPath: string;\n\ttry {\n\t\tnormalizedPath = realpathSync(resolvedPath);\n\t} catch {\n\t\treturn undefined;\n\t}\n\tif (process.platform === \"win32\") {\n\t\tnormalizedPath = normalizedPath.toLowerCase();\n\t}\n\treturn normalizedPath;\n}\n\nfunction isManagedByGlobalPackageManager(method: InstallMethod): boolean {\n\tconst packageDir = normalizeExistingPathForComparison(getPackageDir());\n\tif (!packageDir) {\n\t\treturn false;\n\t}\n\treturn getGlobalPackageRoots(method).some((root) => {\n\t\tconst normalizedRoot = normalizeExistingPathForComparison(root);\n\t\treturn (\n\t\t\tnormalizedRoot !== undefined &&\n\t\t\t(packageDir === normalizedRoot ||\n\t\t\t\tpackageDir.startsWith(normalizedRoot.endsWith(sep) ? normalizedRoot : `${normalizedRoot}${sep}`))\n\t\t);\n\t});\n}\n\nexport function getSelfUpdateCommand(packageName: string): SelfUpdateCommand | undefined {\n\tconst method = detectInstallMethod();\n\tconst command = getSelfUpdateCommandForMethod(method, packageName);\n\tif (!command || !isManagedByGlobalPackageManager(method)) {\n\t\treturn undefined;\n\t}\n\treturn command;\n}\n\nexport function getSelfUpdateUnavailableInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tif (method === \"bun-binary\") {\n\t\treturn `Download from: https://github.com/open-hax/eta-mu/releases/latest`;\n\t}\n\tif (getSelfUpdateCommandForMethod(method, packageName)) {\n\t\treturn `This installation is not managed by a global ${method} install. Update it with the package manager, wrapper, or source checkout that provides it.`;\n\t}\n\treturn `Update ${packageName} using the package manager, wrapper, or source checkout that provides this installation.`;\n}\n\nexport function getUpdateInstruction(packageName: string): string {\n\tconst method = detectInstallMethod();\n\tconst command = getSelfUpdateCommandForMethod(method, packageName);\n\tif (command) {\n\t\treturn `Run: ${command.display}`;\n\t}\n\treturn getSelfUpdateUnavailableInstruction(packageName);\n}\n\n// =============================================================================\n// Package Asset Paths (shipped with executable)\n// =============================================================================\n\n/**\n * Get the base directory for resolving package assets (themes, package.json, README.md, CHANGELOG.md).\n * - For Bun binary: returns the directory containing the executable\n * - For Node.js (dist/): returns __dirname (the dist/ directory)\n * - For tsx (src/): returns parent directory (the package root)\n */\nexport function getPackageDir(): string {\n\t// Allow override via environment variable (useful for Nix/Guix where store paths tokenize poorly)\n\tconst envDir = process.env.ETA_MU_PACKAGE_DIR;\n\tif (envDir) {\n\t\treturn expandHomePath(envDir);\n\t}\n\n\tif (isBunBinary) {\n\t\t// Bun binary: process.execPath points to the compiled executable\n\t\treturn dirname(process.execPath);\n\t}\n\t// Node.js: walk up from __dirname until we find package.json\n\tlet dir = __dirname;\n\twhile (dir !== dirname(dir)) {\n\t\tif (existsSync(join(dir, \"package.json\"))) {\n\t\t\treturn dir;\n\t\t}\n\t\tdir = dirname(dir);\n\t}\n\t// Fallback (shouldn't happen)\n\treturn __dirname;\n}\n\n/**\n * Get path to built-in themes directory (shipped with package)\n * - For Bun binary: theme/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/theme/\n * - For tsx (src/): src/modes/interactive/theme/\n */\nexport function getThemesDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"theme\");\n\t}\n\t// Theme is in modes/interactive/theme/ relative to src/ or dist/\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"theme\");\n}\n\n/**\n * Get path to HTML export template directory (shipped with package)\n * - For Bun binary: export-html/ next to executable\n * - For Node.js (dist/): dist/core/export-html/\n * - For tsx (src/): src/core/export-html/\n */\nexport function getExportTemplateDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"export-html\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"core\", \"export-html\");\n}\n\n/** Get path to package.json */\nexport function getPackageJsonPath(): string {\n\treturn join(getPackageDir(), \"package.json\");\n}\n\n/** Get path to README.md */\nexport function getReadmePath(): string {\n\treturn resolve(join(getPackageDir(), \"README.md\"));\n}\n\n/** Get path to docs directory */\nexport function getDocsPath(): string {\n\treturn resolve(join(getPackageDir(), \"docs\"));\n}\n\n/** Get path to examples directory */\nexport function getExamplesPath(): string {\n\treturn resolve(join(getPackageDir(), \"examples\"));\n}\n\n/** Get path to CHANGELOG.md */\nexport function getChangelogPath(): string {\n\treturn resolve(join(getPackageDir(), \"CHANGELOG.md\"));\n}\n\n/**\n * Get path to built-in interactive assets directory.\n * - For Bun binary: assets/ next to executable\n * - For Node.js (dist/): dist/modes/interactive/assets/\n * - For tsx (src/): src/modes/interactive/assets/\n */\nexport function getInteractiveAssetsDir(): string {\n\tif (isBunBinary) {\n\t\treturn join(getPackageDir(), \"assets\");\n\t}\n\tconst packageDir = getPackageDir();\n\tconst srcOrDist = existsSync(join(packageDir, \"src\")) ? \"src\" : \"dist\";\n\treturn join(packageDir, srcOrDist, \"modes\", \"interactive\", \"assets\");\n}\n\n/** Get path to a bundled interactive asset */\nexport function getBundledInteractiveAssetPath(name: string): string {\n\treturn join(getInteractiveAssetsDir(), name);\n}\n\n// =============================================================================\n// App Config (from package.json piConfig)\n// =============================================================================\n\ninterface PackageJson {\n\tname?: string;\n\tversion?: string;\n\tpiConfig?: {\n\t\tname?: string;\n\t\tconfigDir?: string;\n\t};\n}\n\nconst pkg = JSON.parse(readFileSync(getPackageJsonPath(), \"utf-8\")) as PackageJson;\n\nconst etaMuConfigName: string | undefined = pkg.piConfig?.name;\nexport const PACKAGE_NAME: string = pkg.name || \"@open-hax/eta-mu-coding-agent\";\nexport const VERSION_CHECK_PACKAGE_NAME = \"@open-hax/eta-mu-coding-agent\";\nexport const UPDATE_PACKAGE_NAME = process.env.ETA_MU_CLI === \"true\" ? \"@open-hax/eta-mu-cli\" : PACKAGE_NAME;\nexport const APP_NAME: string = etaMuConfigName || \"eta-mu\";\nexport const APP_TITLE = \"ημ\";\nexport const CONFIG_DIR_NAME: string = pkg.piConfig?.configDir || \".ημ\";\nexport const CONVENIENCE_CONFIG_DIR_NAME = \".eta-mu\";\nexport const VERSION: string = pkg.version || \"0.0.0\";\n\nexport const ENV_AGENT_DIR = \"ETA_MU_CODING_AGENT_DIR\";\n\nconst DEFAULT_SHARE_VIEWER_URL = \"https://eta-mu.openhax.ai/session/\";\n\n/** Get the share viewer URL for a gist ID */\nexport function getShareViewerUrl(gistId: string): string {\n\tconst baseUrl = process.env.ETA_MU_SHARE_VIEWER_URL || DEFAULT_SHARE_VIEWER_URL;\n\treturn `${baseUrl}#${gistId}`;\n}\n\n// =============================================================================\n// User Config Paths (~/.ημ/agent/*)\n// =============================================================================\n\nfunction expandHomePath(value: string): string {\n\tif (value === \"~\") return homedir();\n\tif (value.startsWith(\"~/\")) return homedir() + value.slice(1);\n\treturn value;\n}\n\nfunction ensureRealDirectory(dirPath: string): void {\n\ttry {\n\t\tif (existsSync(dirPath) && lstatSync(dirPath).isSymbolicLink()) {\n\t\t\tunlinkSync(dirPath);\n\t\t}\n\t\tmkdirSync(dirPath, { recursive: true });\n\t} catch {\n\t\tmkdirSync(dirPath, { recursive: true });\n\t}\n}\n\nfunction ensureDirectorySymlink(linkPath: string, targetPath: string): void {\n\ttry {\n\t\tif (existsSync(linkPath)) {\n\t\t\tconst stat = lstatSync(linkPath);\n\t\t\tif (stat.isSymbolicLink()) return;\n\t\t\treturn;\n\t\t}\n\t\tconst targetParent = dirname(linkPath);\n\t\tmkdirSync(targetParent, { recursive: true });\n\t\tconst linkTarget = relative(targetParent, targetPath) || targetPath;\n\t\tsymlinkSync(linkTarget, linkPath, \"junction\");\n\t} catch {\n\t\t// Symlink creation is best-effort convenience only.\n\t}\n}\n\nexport function ensureProjectConfigDir(cwd: string): string {\n\tconst projectConfigDir = join(cwd, CONFIG_DIR_NAME);\n\tensureRealDirectory(projectConfigDir);\n\tensureDirectorySymlink(join(cwd, CONVENIENCE_CONFIG_DIR_NAME), projectConfigDir);\n\treturn projectConfigDir;\n}\n\n/** Get the agent config directory (e.g., ~/.ημ/agent/) */\nexport function getAgentDir(): string {\n\tconst envDir = process.env[ENV_AGENT_DIR];\n\tif (envDir) {\n\t\treturn expandHomePath(envDir);\n\t}\n\tconst etaMuRootDir = join(homedir(), CONFIG_DIR_NAME);\n\tensureRealDirectory(etaMuRootDir);\n\tensureDirectorySymlink(join(homedir(), CONVENIENCE_CONFIG_DIR_NAME), etaMuRootDir);\n\tconst etaMuAgentDir = join(etaMuRootDir, \"agent\");\n\tensureRealDirectory(etaMuAgentDir);\n\treturn etaMuAgentDir;\n}\n\n/** Get path to user's custom themes directory */\nexport function getCustomThemesDir(): string {\n\treturn join(getAgentDir(), \"themes\");\n}\n\n/** Get path to models.json */\nexport function getModelsPath(): string {\n\treturn join(getAgentDir(), \"models.json\");\n}\n\n/** Get path to auth.json */\nexport function getAuthPath(): string {\n\treturn join(getAgentDir(), \"auth.json\");\n}\n\n/** Get path to settings.json */\nexport function getSettingsPath(): string {\n\treturn join(getAgentDir(), \"settings.json\");\n}\n\n/** Get path to tools directory */\nexport function getToolsDir(): string {\n\treturn join(getAgentDir(), \"tools\");\n}\n\n/** Get path to managed binaries directory (fd, rg) */\nexport function getBinDir(): string {\n\treturn join(getAgentDir(), \"bin\");\n}\n\n/** Get path to prompt templates directory */\nexport function getPromptsDir(): string {\n\treturn join(getAgentDir(), \"prompts\");\n}\n\n/** Get path to sessions directory */\nexport function getSessionsDir(): string {\n\treturn join(getAgentDir(), \"sessions\");\n}\n\n/** Get path to debug log file */\nexport function getDebugLogPath(): string {\n\treturn join(getAgentDir(), `${APP_NAME}-debug.log`);\n}\n"]}