Repository navigation
Expand file tree
/
Copy pathcodex_engine.go
More file actions
140 lines (120 loc) · 4.48 KB
/
Copy pathcodex_engine.go
File metadata and controls
140 lines (120 loc) · 4.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package workflow
import (
"fmt"
"strings"
)
// CodexEngine represents the Codex agentic engine (experimental)
type CodexEngine struct {
BaseEngine
}
func NewCodexEngine() *CodexEngine {
return &CodexEngine{
BaseEngine: BaseEngine{
id: "codex",
displayName: "Codex",
description: "Uses OpenAI Codex CLI with MCP server support",
experimental: true,
supportsToolsWhitelist: true,
supportsHTTPTransport: false, // Codex only supports stdio transport
},
}
}
func (e *CodexEngine) GetInstallationSteps(engineConfig *EngineConfig) []GitHubActionStep {
// Build the npm install command, optionally with version
installCmd := "npm install -g @openai/codex"
if engineConfig != nil && engineConfig.Version != "" {
installCmd = fmt.Sprintf("npm install -g @openai/codex@%s", engineConfig.Version)
}
return []GitHubActionStep{
{
" - name: Setup Node.js",
" uses: actions/setup-node@v4",
" with:",
" node-version: '24'",
},
{
" - name: Install Codex",
fmt.Sprintf(" run: %s", installCmd),
},
}
}
func (e *CodexEngine) GetExecutionConfig(workflowName string, logFile string, engineConfig *EngineConfig) ExecutionConfig {
// Use model from engineConfig if available, otherwise default to o4-mini
model := "o4-mini"
if engineConfig != nil && engineConfig.Model != "" {
model = engineConfig.Model
}
command := fmt.Sprintf(`INSTRUCTION=$(cat /tmp/aw-prompts/prompt.txt)
export CODEX_HOME=/tmp/mcp-config
# Create log directory outside git repo
mkdir -p /tmp/aw-logs
# Run codex with log capture
codex exec \
-c model=%s \
--full-auto "$INSTRUCTION" 2>&1 | tee %s`, model, logFile)
return ExecutionConfig{
StepName: "Run Codex",
Command: command,
Environment: map[string]string{
"OPENAI_API_KEY": "${{ secrets.OPENAI_API_KEY }}",
"GITHUB_STEP_SUMMARY": "${{ env.GITHUB_STEP_SUMMARY }}",
},
}
}
func (e *CodexEngine) RenderMCPConfig(yaml *strings.Builder, tools map[string]any, mcpTools []string) {
yaml.WriteString(" cat > /tmp/mcp-config/config.toml << EOF\n")
// Add history configuration to disable persistence
yaml.WriteString(" [history]\n")
yaml.WriteString(" persistence = \"none\"\n")
// Generate [mcp_servers] section
for _, toolName := range mcpTools {
switch toolName {
case "github":
githubTool := tools["github"]
e.renderGitHubCodexMCPConfig(yaml, githubTool)
default:
// Handle custom MCP tools (those with MCP-compatible type)
if toolConfig, ok := tools[toolName].(map[string]any); ok {
if hasMcp, _ := hasMCPConfig(toolConfig); hasMcp {
if err := e.renderCodexMCPConfig(yaml, toolName, toolConfig); err != nil {
fmt.Printf("Error generating custom MCP configuration for %s: %v\n", toolName, err)
}
}
}
}
}
yaml.WriteString(" EOF\n")
}
// renderGitHubCodexMCPConfig generates GitHub MCP server configuration for codex config.toml
// Always uses Docker MCP as the default
func (e *CodexEngine) renderGitHubCodexMCPConfig(yaml *strings.Builder, githubTool any) {
githubDockerImageVersion := getGitHubDockerImageVersion(githubTool)
yaml.WriteString(" \n")
yaml.WriteString(" [mcp_servers.github]\n")
// Always use Docker-based GitHub MCP server (services mode has been removed)
yaml.WriteString(" command = \"docker\"\n")
yaml.WriteString(" args = [\n")
yaml.WriteString(" \"run\",\n")
yaml.WriteString(" \"-i\",\n")
yaml.WriteString(" \"--rm\",\n")
yaml.WriteString(" \"-e\",\n")
yaml.WriteString(" \"GITHUB_PERSONAL_ACCESS_TOKEN\",\n")
yaml.WriteString(" \"ghcr.io/github/github-mcp-server:" + githubDockerImageVersion + "\"\n")
yaml.WriteString(" ]\n")
yaml.WriteString(" env = { \"GITHUB_PERSONAL_ACCESS_TOKEN\" = \"${{ secrets.GITHUB_TOKEN }}\" }\n")
}
// renderCodexMCPConfig generates custom MCP server configuration for a single tool in codex workflow config.toml
func (e *CodexEngine) renderCodexMCPConfig(yaml *strings.Builder, toolName string, toolConfig map[string]any) error {
yaml.WriteString(" \n")
yaml.WriteString(fmt.Sprintf(" [mcp_servers.%s]\n", toolName))
// Use the shared MCP config renderer with TOML format
renderer := MCPConfigRenderer{
IndentLevel: " ",
Format: "toml",
}
err := renderSharedMCPConfig(yaml, toolName, toolConfig, false, renderer)
if err != nil {
return err
}
return nil
}