Skip to content

Commit 2341d80

Browse files
committed
perf: update codex version
1 parent 2c6d218 commit 2341d80

6 files changed

Lines changed: 77 additions & 10 deletions

File tree

‎Dockerfile‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ ARG VERSION=dev
77
RUN CGO_ENABLED=0 go build -trimpath -ldflags "-s -w -X main.Version=${VERSION}" -o /opt/kael/kael ./cmd/kael
88

99
FROM node:22-trixie-slim AS stage-codex
10-
RUN npm install --global @openai/codex@0.153.2 \
10+
RUN npm install --global '@openai/codex@>=0.153.2' \
1111
&& codex --version
1212

1313
FROM node:22-trixie-slim

‎config_example.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
# Codex harness is the sole Agent runtime; install the exact pinned CLI version.
2-
# npm install -g @openai/codex@0.153.2
1+
# Codex harness is the sole Agent runtime; install CLI version 0.153.2 or newer.
2+
# npm install -g '@openai/codex@>=0.153.2'
33
CODEX_BINARY: codex
44
# CHAT_AI_BASE_URL in Core must support Responses API. Chat Completions is not supported.
55
# 与 Koko 一致,Kael 只使用平铺配置。

‎docs/adr/0007-codex-harness.md‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313

1414
## 协议与执行
1515

16-
固定 `codex-cli 0.153.2`;启动时检查精确版本,Docker 同样固定 npm 包版本。依赖该版本的 experimental dynamicTools 和 environments 字段,升级需要重新生成/验证协议并执行集成测试。
16+
要求 `codex-cli 0.153.2` 或更高版本;启动时按语义版本比较,Docker 安装满足该下限的最新版本。Codex 尚未达到 1.0,跨 minor 版本仍可能调整 experimental dynamicTools 和 environments 字段,因此升级后需要执行集成测试。
1717

1818
Luna bootstrap 必须收到 `agent_engine=codex`、`agent_protocol_version=1`。现有 `/kael/api/v1` HTTP、PanelDelivery SSE、工具回执和审批端点保持。`model.requested/completed` 的 `scope=agent_turn` 表示一次完整 harness turn,包含工具和审批等待;不再声称是内部单次模型请求。现有 ModelCall/ModelRequestCount 存储字段在本分支记录 harness turn,值通常为 1;Luna 不将该总耗时分摊到某次工具调用。usage 从 Codex 累积计数扣除本 turn 起点,覆盖该 turn 内所有模型调用。
1919

@@ -35,7 +35,7 @@ Core TerminalConfig 仍是模型凭据唯一来源;启动及每次 Run 执行
3535

3636
## 试用
3737

38-
1. 安装 `npm install -g @openai/codex@0.153.2`,用 `codex --version` 核对。
38+
1. 安装 `npm install -g '@openai/codex@>=0.153.2'`,用 `codex --version` 核对不低于 `0.153.2`。
3939
2. Core 开启 Chat AI,配置支持 Responses 的模型、base URL 和 API key。保留原组件注册和 Platform Gateway delegation 配置。
4040
3. 使用 `CODEX_BINARY` 指定可执行路径,或使用默认 PATH 中的 `codex`。运行 `make run`;同时使用 Luna 的 `harness` 分支。
4141
4. 验证终端只读排查、SQL/脚本 proposal 审批、拒绝审批、停止、多轮追问及断连。真实模型效果和真实 Core/Koko/Chen 联调需要试用环境验收。

‎internal/runtime/harness.go‎

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"os"
1111
"os/exec"
1212
"path/filepath"
13+
"strconv"
1314
"strings"
1415
"sync"
1516
"time"
@@ -97,8 +98,8 @@ func NewHarness(ctx context.Context, binary, root string, loader model.ConfigLoa
9798
versionCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
9899
defer cancel()
99100
version, err := exec.CommandContext(versionCtx, resolved, "--version").Output()
100-
if err != nil || strings.TrimSpace(string(version)) != "codex-cli "+CodexVersion {
101-
return nil, fmt.Errorf("Kael requires codex-cli %s", CodexVersion)
101+
if err != nil || !compatibleCodexVersion(string(version)) {
102+
return nil, fmt.Errorf("Kael requires codex-cli %s or newer", CodexMinimumVersion)
102103
}
103104
config, err := loader(ctx)
104105
if err != nil {
@@ -119,6 +120,51 @@ func NewHarness(ctx context.Context, binary, root string, loader model.ConfigLoa
119120
return h, nil
120121
}
121122

123+
func compatibleCodexVersion(output string) bool {
124+
version, ok := strings.CutPrefix(strings.TrimSpace(output), "codex-cli ")
125+
if !ok {
126+
return false
127+
}
128+
actual, ok := parseCodexVersion(version)
129+
if !ok {
130+
return false
131+
}
132+
minimum, ok := parseCodexVersion(CodexMinimumVersion)
133+
if !ok {
134+
return false
135+
}
136+
for i := range actual {
137+
if actual[i] != minimum[i] {
138+
return actual[i] > minimum[i]
139+
}
140+
}
141+
return true
142+
}
143+
144+
func parseCodexVersion(version string) ([3]uint64, bool) {
145+
var parsed [3]uint64
146+
parts := strings.Split(version, ".")
147+
if len(parts) != len(parsed) {
148+
return parsed, false
149+
}
150+
for i, part := range parts {
151+
if part == "" {
152+
return parsed, false
153+
}
154+
for _, digit := range part {
155+
if digit < '0' || digit > '9' {
156+
return parsed, false
157+
}
158+
}
159+
value, err := strconv.ParseUint(part, 10, 64)
160+
if err != nil {
161+
return parsed, false
162+
}
163+
parsed[i] = value
164+
}
165+
return parsed, true
166+
}
167+
122168
func validateConfig(config model.Config) error {
123169
parsed, err := url.Parse(config.BaseURL)
124170
if err != nil || parsed.Host == "" || (parsed.Scheme != "http" && parsed.Scheme != "https") || parsed.User != nil || parsed.RawQuery != "" || parsed.Fragment != "" || strings.TrimSpace(config.Model) == "" || strings.TrimSpace(config.APIKey) == "" {

‎internal/runtime/harness_test.go‎

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,33 @@ import (
1717
"github.com/jumpserver/kael/internal/model"
1818
)
1919

20-
// Runs the actual pinned Codex executable against a local Responses fixture.
20+
func TestCompatibleCodexVersion(t *testing.T) {
21+
tests := map[string]bool{
22+
"codex-cli 0.144.4": false,
23+
"codex-cli 0.153.1": false,
24+
"codex-cli 0.153.2": true,
25+
"codex-cli 0.153.999": true,
26+
"codex-cli 0.154.0": true,
27+
"codex-cli 1.0.0": true,
28+
"codex-cli 0.153": false,
29+
"codex-cli 0.153.dev": false,
30+
"codex 0.153.2": false,
31+
}
32+
for output, want := range tests {
33+
t.Run(output, func(t *testing.T) {
34+
if got := compatibleCodexVersion(output); got != want {
35+
t.Fatalf("compatibleCodexVersion(%q) = %t, want %t", output, got, want)
36+
}
37+
})
38+
}
39+
}
40+
41+
// Runs an actual compatible Codex executable against a local Responses fixture.
2142
// No real model request or external API credential is used.
2243
func TestCodexAppServerIntegration(t *testing.T) {
2344
binary := os.Getenv("KAEL_TEST_CODEX")
2445
if binary == "" {
25-
t.Skip("set KAEL_TEST_CODEX to the pinned Codex binary for the protocol integration test")
46+
t.Skip("set KAEL_TEST_CODEX to a compatible Codex binary for the protocol integration test")
2647
}
2748
var mu sync.Mutex
2849
requests := 0

‎internal/runtime/protocol.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
"sync"
1212
)
1313

14-
const CodexVersion = "0.153.2"
14+
const CodexMinimumVersion = "0.153.2"
1515
const maxProtocolBytes = 8 * 1024 * 1024
1616

1717
type rpcMessage struct {

0 commit comments

Comments
 (0)