diff --git a/codeagent-wrapper/main.go b/codeagent-wrapper/main.go index 39ce81e..5ad2107 100644 --- a/codeagent-wrapper/main.go +++ b/codeagent-wrapper/main.go @@ -241,6 +241,13 @@ func run() (exitCode int) { if strings.TrimSpace(cfg.Tasks[i].Backend) == "" { cfg.Tasks[i].Backend = backendName } + // Inject ROLE_FILE content if present + injectedTask, err := injectRoleFile(cfg.Tasks[i].Task) + if err != nil { + logWarn(fmt.Sprintf("Failed to inject ROLE_FILE for task %s: %v", cfg.Tasks[i].ID, err)) + } else { + cfg.Tasks[i].Task = injectedTask + } } timeoutSec := resolveTimeout() @@ -338,6 +345,11 @@ func run() (exitCode int) { logError("Explicit stdin mode requires task input from stdin") return 1 } + // Inject ROLE_FILE content if present + taskText, err = injectRoleFile(taskText) + if err != nil { + logWarn(fmt.Sprintf("Failed to inject ROLE_FILE: %v", err)) + } piped = !isTerminal() } else { pipedTask, err := readPipedTask() @@ -347,7 +359,11 @@ func run() (exitCode int) { } piped = pipedTask != "" if piped { - taskText = pipedTask + // Inject ROLE_FILE content if present + taskText, err = injectRoleFile(pipedTask) + if err != nil { + logWarn(fmt.Sprintf("Failed to inject ROLE_FILE: %v", err)) + } } else { taskText = cfg.Task } diff --git a/codeagent-wrapper/utils.go b/codeagent-wrapper/utils.go index 79dcec1..5ac847a 100644 --- a/codeagent-wrapper/utils.go +++ b/codeagent-wrapper/utils.go @@ -5,6 +5,8 @@ import ( "fmt" "io" "os" + "path/filepath" + "regexp" "strconv" "strings" ) @@ -67,6 +69,47 @@ func isTerminal() bool { return isTerminalFn() } +// injectRoleFile processes ROLE_FILE: directives in task text +// Format: "ROLE_FILE: " on a single line +// Replaces the line with the content of the specified file +func injectRoleFile(taskText string) (string, error) { + // Match "ROLE_FILE: " at the beginning of a line + roleFilePattern := regexp.MustCompile(`(?m)^ROLE_FILE:\s*(.+)$`) + + result := roleFilePattern.ReplaceAllStringFunc(taskText, func(match string) string { + // Extract file path + submatches := roleFilePattern.FindStringSubmatch(match) + if len(submatches) < 2 { + logWarn(fmt.Sprintf("Invalid ROLE_FILE format: %s", match)) + return match + } + + filePath := strings.TrimSpace(submatches[1]) + + // Expand ~ to home directory + if strings.HasPrefix(filePath, "~/") { + home, err := os.UserHomeDir() + if err != nil { + logWarn(fmt.Sprintf("Failed to get home directory: %v", err)) + return match + } + filePath = filepath.Join(home, filePath[2:]) + } + + // Read file content + content, err := os.ReadFile(filePath) + if err != nil { + logWarn(fmt.Sprintf("Failed to read ROLE_FILE '%s': %v", filePath, err)) + return match // Keep original line if file read fails + } + + logInfo(fmt.Sprintf("Injected ROLE_FILE: %s (%d bytes)", filePath, len(content))) + return string(content) + }) + + return result, nil +} + func getEnv(key, defaultValue string) string { if val := os.Getenv(key); val != "" { return val diff --git a/package.json b/package.json index 39aaa1d..39e3297 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ccg-workflow", - "version": "1.1.3", + "version": "1.2.0", "description": "Claude-Codex-Gemini 多模型协作系统 - 智能路由多模型开发工作流", "type": "module", "packageManager": "pnpm@10.17.1",