-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
fix: resolve skills-core.js path using home directory for Windows compatibility #326
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -8,12 +8,19 @@ | |||||||||||||||||||||||||||||||||||||||||||||
| import path from 'path'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import fs from 'fs'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import os from 'os'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { fileURLToPath } from 'url'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { fileURLToPath, pathToFileURL } from 'url'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import { tool } from '@opencode-ai/plugin/tool'; | ||||||||||||||||||||||||||||||||||||||||||||||
| import * as skillsCore from '../../lib/skills-core.js'; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| const __dirname = path.dirname(fileURLToPath(import.meta.url)); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Resolve skills-core.js path dynamically to work with both symlinks and copies | ||||||||||||||||||||||||||||||||||||||||||||||
| // On Mac/Linux with symlink: __dirname points to actual location | ||||||||||||||||||||||||||||||||||||||||||||||
| // On Windows with copy: we need to find the superpowers installation | ||||||||||||||||||||||||||||||||||||||||||||||
| const homeDir = os.homedir(); | ||||||||||||||||||||||||||||||||||||||||||||||
| const superpowersRoot = path.join(homeDir, '.config/opencode/superpowers'); | ||||||||||||||||||||||||||||||||||||||||||||||
| const skillsCorePathResolved = path.join(superpowersRoot, 'lib/skills-core.js'); | ||||||||||||||||||||||||||||||||||||||||||||||
| const skillsCore = await import(pathToFileURL(skillsCorePathResolved).href); | ||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+19
to
+22
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Inconsistency: hardcoded path ignores The Consider using the same resolution logic: 🛠️ Suggested fix: respect OPENCODE_CONFIG_DIR+// Helper to normalize path (needed before plugin init)
+const normalizePathEarly = (p, home) => {
+ if (!p || typeof p !== 'string') return null;
+ let normalized = p.trim();
+ if (!normalized) return null;
+ if (normalized.startsWith('~/')) {
+ normalized = path.join(home, normalized.slice(2));
+ } else if (normalized === '~') {
+ normalized = home;
+ }
+ return path.resolve(normalized);
+};
+
const homeDir = os.homedir();
-const superpowersRoot = path.join(homeDir, '.config/opencode/superpowers');
+const envConfigDir = normalizePathEarly(process.env.OPENCODE_CONFIG_DIR, homeDir);
+const superpowersRoot = path.join(envConfigDir || path.join(homeDir, '.config/opencode'), 'superpowers');
const skillsCorePathResolved = path.join(superpowersRoot, 'lib/skills-core.js');📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
| // Normalize a path: trim whitespace, expand ~, resolve to absolute | ||||||||||||||||||||||||||||||||||||||||||||||
| const normalizePath = (p, homeDir) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| if (!p || typeof p !== 'string') return null; | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -32,8 +39,8 @@ const normalizePath = (p, homeDir) => { | |||||||||||||||||||||||||||||||||||||||||||||
| export const SuperpowersPlugin = async ({ client, directory }) => { | ||||||||||||||||||||||||||||||||||||||||||||||
| const homeDir = os.homedir(); | ||||||||||||||||||||||||||||||||||||||||||||||
| const projectSkillsDir = path.join(directory, '.opencode/skills'); | ||||||||||||||||||||||||||||||||||||||||||||||
| // Derive superpowers skills dir from plugin location (works for both symlinked and local installs) | ||||||||||||||||||||||||||||||||||||||||||||||
| const superpowersSkillsDir = path.resolve(__dirname, '../../skills'); | ||||||||||||||||||||||||||||||||||||||||||||||
| // Derive superpowers skills dir - use absolute path for Windows compatibility | ||||||||||||||||||||||||||||||||||||||||||||||
| const superpowersSkillsDir = path.join(superpowersRoot, 'skills'); | ||||||||||||||||||||||||||||||||||||||||||||||
| // Respect OPENCODE_CONFIG_DIR if set, otherwise fall back to default | ||||||||||||||||||||||||||||||||||||||||||||||
| const envConfigDir = normalizePath(process.env.OPENCODE_CONFIG_DIR, homeDir); | ||||||||||||||||||||||||||||||||||||||||||||||
| const configDir = envConfigDir || path.join(homeDir, '.config/opencode'); | ||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing error handling for dynamic import.
The top-level
await import()will throw an unhandled error ifskills-core.jsdoesn't exist at the resolved path (e.g., fresh install, non-standard installation). This causes the entire plugin to fail to load with an unhelpful error message.🛠️ Suggested fix: wrap in try-catch with helpful error
📝 Committable suggestion
🤖 Prompt for AI Agents