fix: adopt plural config dirs for agents, commands, and skills (#198)
This commit is contained in:
committed by
GitHub
parent
7c36418e23
commit
95e41940f8
@@ -5,9 +5,9 @@ import yaml from 'yaml';
|
||||
import { parse as parseJsonc } from 'jsonc-parser';
|
||||
|
||||
const OPENCODE_CONFIG_DIR = path.join(os.homedir(), '.config', 'opencode');
|
||||
const AGENT_DIR = path.join(OPENCODE_CONFIG_DIR, 'agent');
|
||||
const COMMAND_DIR = path.join(OPENCODE_CONFIG_DIR, 'command');
|
||||
const SKILL_DIR = path.join(OPENCODE_CONFIG_DIR, 'skill');
|
||||
const AGENT_DIR = path.join(OPENCODE_CONFIG_DIR, 'agents');
|
||||
const COMMAND_DIR = path.join(OPENCODE_CONFIG_DIR, 'commands');
|
||||
const SKILL_DIR = path.join(OPENCODE_CONFIG_DIR, 'skills');
|
||||
const CONFIG_FILE = path.join(OPENCODE_CONFIG_DIR, 'opencode.json');
|
||||
const CUSTOM_CONFIG_FILE = process.env.OPENCODE_CONFIG
|
||||
? path.resolve(process.env.OPENCODE_CONFIG)
|
||||
@@ -51,10 +51,14 @@ function ensureDirs() {
|
||||
* Ensure project-level agent directory exists
|
||||
*/
|
||||
function ensureProjectAgentDir(workingDirectory) {
|
||||
const projectAgentDir = path.join(workingDirectory, '.opencode', 'agent');
|
||||
const projectAgentDir = path.join(workingDirectory, '.opencode', 'agents');
|
||||
if (!fs.existsSync(projectAgentDir)) {
|
||||
fs.mkdirSync(projectAgentDir, { recursive: true });
|
||||
}
|
||||
const legacyProjectAgentDir = path.join(workingDirectory, '.opencode', 'agent');
|
||||
if (!fs.existsSync(legacyProjectAgentDir)) {
|
||||
fs.mkdirSync(legacyProjectAgentDir, { recursive: true });
|
||||
}
|
||||
return projectAgentDir;
|
||||
}
|
||||
|
||||
@@ -62,14 +66,20 @@ function ensureProjectAgentDir(workingDirectory) {
|
||||
* Get project-level agent path
|
||||
*/
|
||||
function getProjectAgentPath(workingDirectory, agentName) {
|
||||
return path.join(workingDirectory, '.opencode', 'agent', `${agentName}.md`);
|
||||
const pluralPath = path.join(workingDirectory, '.opencode', 'agents', `${agentName}.md`);
|
||||
const legacyPath = path.join(workingDirectory, '.opencode', 'agent', `${agentName}.md`);
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-level agent path
|
||||
*/
|
||||
function getUserAgentPath(agentName) {
|
||||
return path.join(AGENT_DIR, `${agentName}.md`);
|
||||
const pluralPath = path.join(AGENT_DIR, `${agentName}.md`);
|
||||
const legacyPath = path.join(OPENCODE_CONFIG_DIR, 'agent', `${agentName}.md`);
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -173,10 +183,14 @@ function getAgentPermissionSource(agentName, workingDirectory) {
|
||||
* Ensure project-level command directory exists
|
||||
*/
|
||||
function ensureProjectCommandDir(workingDirectory) {
|
||||
const projectCommandDir = path.join(workingDirectory, '.opencode', 'command');
|
||||
const projectCommandDir = path.join(workingDirectory, '.opencode', 'commands');
|
||||
if (!fs.existsSync(projectCommandDir)) {
|
||||
fs.mkdirSync(projectCommandDir, { recursive: true });
|
||||
}
|
||||
const legacyProjectCommandDir = path.join(workingDirectory, '.opencode', 'command');
|
||||
if (!fs.existsSync(legacyProjectCommandDir)) {
|
||||
fs.mkdirSync(legacyProjectCommandDir, { recursive: true });
|
||||
}
|
||||
return projectCommandDir;
|
||||
}
|
||||
|
||||
@@ -184,14 +198,20 @@ function ensureProjectCommandDir(workingDirectory) {
|
||||
* Get project-level command path
|
||||
*/
|
||||
function getProjectCommandPath(workingDirectory, commandName) {
|
||||
return path.join(workingDirectory, '.opencode', 'command', `${commandName}.md`);
|
||||
const pluralPath = path.join(workingDirectory, '.opencode', 'commands', `${commandName}.md`);
|
||||
const legacyPath = path.join(workingDirectory, '.opencode', 'command', `${commandName}.md`);
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-level command path
|
||||
*/
|
||||
function getUserCommandPath(commandName) {
|
||||
return path.join(COMMAND_DIR, `${commandName}.md`);
|
||||
const pluralPath = path.join(COMMAND_DIR, `${commandName}.md`);
|
||||
const legacyPath = path.join(OPENCODE_CONFIG_DIR, 'command', `${commandName}.md`);
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -245,10 +265,14 @@ function getCommandWritePath(commandName, workingDirectory, requestedScope) {
|
||||
* Ensure project-level skill directory exists
|
||||
*/
|
||||
function ensureProjectSkillDir(workingDirectory) {
|
||||
const projectSkillDir = path.join(workingDirectory, '.opencode', 'skill');
|
||||
const projectSkillDir = path.join(workingDirectory, '.opencode', 'skills');
|
||||
if (!fs.existsSync(projectSkillDir)) {
|
||||
fs.mkdirSync(projectSkillDir, { recursive: true });
|
||||
}
|
||||
const legacyProjectSkillDir = path.join(workingDirectory, '.opencode', 'skill');
|
||||
if (!fs.existsSync(legacyProjectSkillDir)) {
|
||||
fs.mkdirSync(legacyProjectSkillDir, { recursive: true });
|
||||
}
|
||||
return projectSkillDir;
|
||||
}
|
||||
|
||||
@@ -256,28 +280,40 @@ function ensureProjectSkillDir(workingDirectory) {
|
||||
* Get project-level skill directory path (.opencode/skill/{name}/)
|
||||
*/
|
||||
function getProjectSkillDir(workingDirectory, skillName) {
|
||||
return path.join(workingDirectory, '.opencode', 'skill', skillName);
|
||||
const pluralPath = path.join(workingDirectory, '.opencode', 'skills', skillName);
|
||||
const legacyPath = path.join(workingDirectory, '.opencode', 'skill', skillName);
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get project-level skill SKILL.md path
|
||||
*/
|
||||
function getProjectSkillPath(workingDirectory, skillName) {
|
||||
return path.join(getProjectSkillDir(workingDirectory, skillName), 'SKILL.md');
|
||||
const pluralPath = path.join(workingDirectory, '.opencode', 'skills', skillName, 'SKILL.md');
|
||||
const legacyPath = path.join(workingDirectory, '.opencode', 'skill', skillName, 'SKILL.md');
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-level skill directory path
|
||||
*/
|
||||
function getUserSkillDir(skillName) {
|
||||
return path.join(SKILL_DIR, skillName);
|
||||
const pluralPath = path.join(SKILL_DIR, skillName);
|
||||
const legacyPath = path.join(OPENCODE_CONFIG_DIR, 'skill', skillName);
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user-level skill SKILL.md path
|
||||
*/
|
||||
function getUserSkillPath(skillName) {
|
||||
return path.join(getUserSkillDir(skillName), 'SKILL.md');
|
||||
const pluralPath = path.join(SKILL_DIR, skillName, 'SKILL.md');
|
||||
const legacyPath = path.join(OPENCODE_CONFIG_DIR, 'skill', skillName, 'SKILL.md');
|
||||
if (fs.existsSync(legacyPath) && !fs.existsSync(pluralPath)) return legacyPath;
|
||||
return pluralPath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1463,9 +1499,9 @@ function discoverSkills(workingDirectory) {
|
||||
}
|
||||
};
|
||||
|
||||
// 1. Project level .opencode/skill/ (highest priority)
|
||||
// 1. Project level .opencode/skills/ (highest priority)
|
||||
if (workingDirectory) {
|
||||
const projectSkillDir = path.join(workingDirectory, '.opencode', 'skill');
|
||||
const projectSkillDir = path.join(workingDirectory, '.opencode', 'skills');
|
||||
if (fs.existsSync(projectSkillDir)) {
|
||||
const entries = fs.readdirSync(projectSkillDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
@@ -1477,6 +1513,19 @@ function discoverSkills(workingDirectory) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const legacyProjectSkillDir = path.join(workingDirectory, '.opencode', 'skill');
|
||||
if (fs.existsSync(legacyProjectSkillDir)) {
|
||||
const entries = fs.readdirSync(legacyProjectSkillDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const skillMdPath = path.join(legacyProjectSkillDir, entry.name, 'SKILL.md');
|
||||
if (fs.existsSync(skillMdPath)) {
|
||||
addSkill(entry.name, skillMdPath, SKILL_SCOPE.PROJECT, 'opencode');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Claude-compatible .claude/skills/
|
||||
const claudeSkillDir = path.join(workingDirectory, '.claude', 'skills');
|
||||
@@ -1493,7 +1542,7 @@ function discoverSkills(workingDirectory) {
|
||||
}
|
||||
}
|
||||
|
||||
// 3. User level ~/.config/opencode/skill/
|
||||
// 3. User level ~/.config/opencode/skills/
|
||||
if (fs.existsSync(SKILL_DIR)) {
|
||||
const entries = fs.readdirSync(SKILL_DIR, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
@@ -1505,6 +1554,19 @@ function discoverSkills(workingDirectory) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const legacyUserSkillDir = path.join(OPENCODE_CONFIG_DIR, 'skill');
|
||||
if (fs.existsSync(legacyUserSkillDir)) {
|
||||
const entries = fs.readdirSync(legacyUserSkillDir, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
const skillMdPath = path.join(legacyUserSkillDir, entry.name, 'SKILL.md');
|
||||
if (fs.existsSync(skillMdPath)) {
|
||||
addSkill(entry.name, skillMdPath, SKILL_SCOPE.USER, 'opencode');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Array.from(skills.values());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user