mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
feat(agent/agentcontextconfig): discover skills from ~/.coder/skills (#25271)
The default skills lookup only scanned the project-relative .agents/skills directory, so personal skills had to be repeated per project or wired in via CODER_AGENT_EXP_SKILLS_DIRS. Now the default is the comma-separated list ~/.coder/skills,.agents/skills, which lets discoverSkills's existing first-occurrence-wins policy prefer home-scoped skills over project ones with the same name. The change is additive when ~/.coder/skills is absent (missing directories are silently skipped in discoverSkills) and unaffects users who set the env var explicitly. Closes CODAGT-403
This commit is contained in:
committed by
GitHub
parent
fb3aef1883
commit
5b87d7b74f
@@ -60,10 +60,14 @@ var skillNamePattern = regexp.MustCompile(
|
|||||||
|
|
||||||
// Default values for agent-internal configuration. These are
|
// Default values for agent-internal configuration. These are
|
||||||
// used when the corresponding env vars are unset.
|
// used when the corresponding env vars are unset.
|
||||||
|
//
|
||||||
|
// DefaultSkillsDir is a comma-separated list so home-scoped
|
||||||
|
// skills override project-scoped ones with the same name
|
||||||
|
// (discoverSkills picks the first occurrence per skill name).
|
||||||
const (
|
const (
|
||||||
DefaultInstructionsDir = "~/.coder"
|
DefaultInstructionsDir = "~/.coder"
|
||||||
DefaultInstructionsFile = "AGENTS.md"
|
DefaultInstructionsFile = "AGENTS.md"
|
||||||
DefaultSkillsDir = ".agents/skills"
|
DefaultSkillsDir = "~/.coder/skills,.agents/skills"
|
||||||
DefaultSkillMetaFile = "SKILL.md"
|
DefaultSkillMetaFile = "SKILL.md"
|
||||||
DefaultMCPConfigFile = ".mcp.json"
|
DefaultMCPConfigFile = ".mcp.json"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -461,6 +461,37 @@ func TestResolve(t *testing.T) {
|
|||||||
require.Len(t, skillParts, 1)
|
require.Len(t, skillParts, 1)
|
||||||
require.Equal(t, "from skills1", skillParts[0].SkillDescription)
|
require.Equal(t, "from skills1", skillParts[0].SkillDescription)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
//nolint:paralleltest // Uses t.Setenv to mutate HOME.
|
||||||
|
t.Run("DefaultDiscoversHomeAndProjectSkillsHomeWins", func(t *testing.T) {
|
||||||
|
fakeHome := t.TempDir()
|
||||||
|
t.Setenv("HOME", fakeHome)
|
||||||
|
t.Setenv("USERPROFILE", fakeHome)
|
||||||
|
workDir := t.TempDir()
|
||||||
|
|
||||||
|
homeSkills := filepath.Join(fakeHome, ".coder", "skills")
|
||||||
|
writeSkillMetaFileInRoot(t, homeSkills, "home-only", "home only")
|
||||||
|
writeSkillMetaFileInRoot(t, homeSkills, "shared", "from home")
|
||||||
|
writeSkillMetaFile(t, workDir, "project-only", "project only")
|
||||||
|
writeSkillMetaFile(t, workDir, "shared", "from project")
|
||||||
|
|
||||||
|
// Construct the Config directly with the package defaults
|
||||||
|
// to verify the default skills list (and only the defaults).
|
||||||
|
cfg, _ := agentcontextconfig.Resolve(workDir, agentcontextconfig.Config{
|
||||||
|
SkillsDirs: agentcontextconfig.DefaultSkillsDir,
|
||||||
|
SkillMetaFile: agentcontextconfig.DefaultSkillMetaFile,
|
||||||
|
})
|
||||||
|
|
||||||
|
got := map[string]string{}
|
||||||
|
for _, p := range filterParts(cfg.Parts, codersdk.ChatMessagePartTypeSkill) {
|
||||||
|
got[p.SkillName] = p.SkillDescription
|
||||||
|
}
|
||||||
|
require.Equal(t, map[string]string{
|
||||||
|
"home-only": "home only",
|
||||||
|
"project-only": "project only",
|
||||||
|
"shared": "from home",
|
||||||
|
}, got)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewAPI_LazyDirectory(t *testing.T) {
|
func TestNewAPI_LazyDirectory(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user