Files
myclaude/codeagent-wrapper/internal/app/executor_alias.go
cexll 97dfa907d9 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>
2026-02-09 11:06:36 +08:00

63 lines
2.4 KiB
Go

package wrapper
import (
"context"
backend "codeagent-wrapper/internal/backend"
config "codeagent-wrapper/internal/config"
executor "codeagent-wrapper/internal/executor"
)
// defaultRunCodexTaskFn is the default implementation of runCodexTaskFn (exposed for test reset).
func defaultRunCodexTaskFn(task TaskSpec, timeout int) TaskResult {
return executor.DefaultRunCodexTaskFn(task, timeout)
}
var runCodexTaskFn = defaultRunCodexTaskFn
func topologicalSort(tasks []TaskSpec) ([][]TaskSpec, error) {
return executor.TopologicalSort(tasks)
}
func executeConcurrent(layers [][]TaskSpec, timeout int) []TaskResult {
maxWorkers := config.ResolveMaxParallelWorkers()
return executeConcurrentWithContext(context.Background(), layers, timeout, maxWorkers)
}
func executeConcurrentWithContext(parentCtx context.Context, layers [][]TaskSpec, timeout int, maxWorkers int) []TaskResult {
return executor.ExecuteConcurrentWithContext(parentCtx, layers, timeout, maxWorkers, runCodexTaskFn)
}
func generateFinalOutput(results []TaskResult) string {
return executor.GenerateFinalOutput(results)
}
func generateFinalOutputWithMode(results []TaskResult, summaryOnly bool) string {
return executor.GenerateFinalOutputWithMode(results, summaryOnly)
}
func buildCodexArgs(cfg *Config, targetArg string) []string {
return backend.BuildCodexArgs(cfg, targetArg)
}
func runCodexTask(taskSpec TaskSpec, silent bool, timeoutSec int) TaskResult {
return runCodexTaskWithContext(context.Background(), taskSpec, nil, nil, false, silent, timeoutSec)
}
func runCodexProcess(parentCtx context.Context, codexArgs []string, taskText string, useStdin bool, timeoutSec int) (message, threadID string, exitCode int) {
res := runCodexTaskWithContext(parentCtx, TaskSpec{Task: taskText, WorkDir: defaultWorkdir, Mode: "new", UseStdin: useStdin}, nil, codexArgs, true, false, timeoutSec)
return res.Message, res.SessionID, res.ExitCode
}
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)
}