@@ -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+
122168func 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 ) == "" {
0 commit comments