mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-11 03:23:50 +08:00
feat(skills): add per-task skill spec auto-detection and injection
Replace external inject-spec.py hook with built-in zero-config skill detection in codeagent-wrapper. The system auto-detects project type from fingerprint files (go.mod, package.json, etc.), maps to installed skills, and injects SKILL.md content directly into sub-agent prompts. Key changes: - Add DetectProjectSkills/ResolveSkillContent in executor/prompt.go - Add Skills field to TaskSpec with parallel config parsing - Add --skills CLI flag for explicit override - Update /do SKILL.md Phase 4 with per-task skill examples - Remove on-stop.py global hook (not needed) - Replace inject-spec.py with no-op (detection now internal) - Add 20 unit tests covering detection, resolution, budget, security Security: path traversal protection via validSkillName regex, 16K char budget with tag overhead accounting, CRLF normalization. Generated with SWE-Agent.ai Co-Authored-By: SWE-Agent.ai <noreply@swe-agent.ai>
This commit is contained in:
@@ -29,6 +29,7 @@ type cliOptions struct {
|
||||
ReasoningEffort string
|
||||
Agent string
|
||||
PromptFile string
|
||||
Skills string
|
||||
SkipPermissions bool
|
||||
Worktree bool
|
||||
|
||||
@@ -134,6 +135,7 @@ func addRootFlags(fs *pflag.FlagSet, opts *cliOptions) {
|
||||
fs.StringVar(&opts.ReasoningEffort, "reasoning-effort", "", "Reasoning effort (backend-specific)")
|
||||
fs.StringVar(&opts.Agent, "agent", "", "Agent preset name (from ~/.codeagent/models.json)")
|
||||
fs.StringVar(&opts.PromptFile, "prompt-file", "", "Prompt file path")
|
||||
fs.StringVar(&opts.Skills, "skills", "", "Comma-separated skill names for spec injection")
|
||||
|
||||
fs.BoolVar(&opts.SkipPermissions, "skip-permissions", false, "Skip permissions prompts (also via CODEAGENT_SKIP_PERMISSIONS)")
|
||||
fs.BoolVar(&opts.SkipPermissions, "dangerously-skip-permissions", false, "Alias for --skip-permissions")
|
||||
@@ -339,6 +341,16 @@ func buildSingleConfig(cmd *cobra.Command, args []string, rawArgv []string, opts
|
||||
return nil, fmt.Errorf("task required")
|
||||
}
|
||||
|
||||
var skills []string
|
||||
if cmd.Flags().Changed("skills") {
|
||||
for _, s := range strings.Split(opts.Skills, ",") {
|
||||
s = strings.TrimSpace(s)
|
||||
if s != "" {
|
||||
skills = append(skills, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg := &Config{
|
||||
WorkDir: defaultWorkdir,
|
||||
Backend: backendName,
|
||||
@@ -352,6 +364,7 @@ func buildSingleConfig(cmd *cobra.Command, args []string, rawArgv []string, opts
|
||||
MaxParallelWorkers: config.ResolveMaxParallelWorkers(),
|
||||
AllowedTools: resolvedAllowedTools,
|
||||
DisallowedTools: resolvedDisallowedTools,
|
||||
Skills: skills,
|
||||
Worktree: opts.Worktree,
|
||||
}
|
||||
|
||||
@@ -418,7 +431,7 @@ func runParallelMode(cmd *cobra.Command, args []string, opts *cliOptions, v *vip
|
||||
return 1
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("agent") || cmd.Flags().Changed("prompt-file") || cmd.Flags().Changed("reasoning-effort") {
|
||||
if cmd.Flags().Changed("agent") || cmd.Flags().Changed("prompt-file") || cmd.Flags().Changed("reasoning-effort") || cmd.Flags().Changed("skills") {
|
||||
fmt.Fprintln(os.Stderr, "ERROR: --parallel reads its task configuration from stdin; only --backend, --model, --full-output and --skip-permissions are allowed.")
|
||||
return 1
|
||||
}
|
||||
@@ -585,6 +598,17 @@ func runSingleMode(cfg *Config, name string) int {
|
||||
taskText = wrapTaskWithAgentPrompt(prompt, taskText)
|
||||
}
|
||||
|
||||
// Resolve skills: explicit > auto-detect from workdir
|
||||
skills := cfg.Skills
|
||||
if len(skills) == 0 {
|
||||
skills = detectProjectSkills(cfg.WorkDir)
|
||||
}
|
||||
if len(skills) > 0 {
|
||||
if content := resolveSkillContent(skills, 0); content != "" {
|
||||
taskText = taskText + "\n\n# Domain Best Practices\n\n" + content
|
||||
}
|
||||
}
|
||||
|
||||
useStdin := cfg.ExplicitStdin || shouldUseStdin(taskText, piped)
|
||||
|
||||
targetArg := taskText
|
||||
|
||||
@@ -52,3 +52,11 @@ func runCodexProcess(parentCtx context.Context, codexArgs []string, taskText str
|
||||
func runCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backend Backend, customArgs []string, useCustomArgs bool, silent bool, timeoutSec int) TaskResult {
|
||||
return executor.RunCodexTaskWithContext(parentCtx, taskSpec, backend, codexCommand, buildCodexArgsFn, customArgs, useCustomArgs, silent, timeoutSec)
|
||||
}
|
||||
|
||||
func detectProjectSkills(workDir string) []string {
|
||||
return executor.DetectProjectSkills(workDir)
|
||||
}
|
||||
|
||||
func resolveSkillContent(skills []string, maxBudget int) string {
|
||||
return executor.ResolveSkillContent(skills, maxBudget)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user