diff --git a/src/commands/install-skill.ts b/src/commands/install-skill.ts index 58611424..02f4ac39 100644 --- a/src/commands/install-skill.ts +++ b/src/commands/install-skill.ts @@ -1,9 +1,9 @@ import { homedir } from 'os'; -import { join, dirname } from 'path'; +import { join } from 'path'; import { existsSync } from 'fs'; import { mkdir, copyFile, readdir } from 'fs/promises'; -import { fileURLToPath } from 'url'; import chalk from 'chalk'; +import { getPackageRoot } from '../utils/paths.js'; export interface AgentConfig { name: string; @@ -48,9 +48,7 @@ export interface InstallSkillOptions { } export function getSkillsDir(): string { - const currentFile = fileURLToPath(import.meta.url); - // From dist/src/commands/install-skill.js -> skills/ - return join(dirname(currentFile), '..', '..', '..', 'skills'); + return join(getPackageRoot(import.meta.url), 'skills'); } export async function discoverSkills(skillsDir: string): Promise { diff --git a/src/lib/agent-interface.ts b/src/lib/agent-interface.ts index 649f53da..33a73bfb 100644 --- a/src/lib/agent-interface.ts +++ b/src/lib/agent-interface.ts @@ -4,7 +4,7 @@ */ import path from 'path'; -import { fileURLToPath } from 'url'; +import { getPackageRoot } from '../utils/paths.js'; import { debug, logInfo, logWarn, logError, initLogFile, getLogFilePath } from '../utils/debug.js'; import type { InstallerOptions } from '../utils/types.js'; import { analytics } from '../utils/analytics.js'; @@ -577,10 +577,7 @@ export async function runAgent( }; // Load plugin with bundled skills - // Path from dist/lib/ back to package root - const __filename = fileURLToPath(import.meta.url); - const __dirname = path.dirname(__filename); - const pluginPath = path.join(__dirname, '../..'); + const pluginPath = getPackageRoot(import.meta.url); logInfo('Loading plugin from:', pluginPath); const response = query({ diff --git a/src/utils/paths.ts b/src/utils/paths.ts new file mode 100644 index 00000000..b81d9e05 --- /dev/null +++ b/src/utils/paths.ts @@ -0,0 +1,18 @@ +import { dirname, join } from 'path'; +import { existsSync } from 'fs'; +import { fileURLToPath } from 'url'; + +/** + * Resolve the package root by walking up from a compiled file until we find package.json. + * Immune to changes in tsconfig outDir/rootDir structure. + */ +export function getPackageRoot(metaUrl: string): string { + let dir = dirname(fileURLToPath(metaUrl)); + while (dir !== dirname(dir)) { + if (existsSync(join(dir, 'package.json'))) { + return dir; + } + dir = dirname(dir); + } + throw new Error('Could not find package root (no package.json found in parent directories)'); +}