diff --git a/pkg/agentfs/sdk_version_check.go b/pkg/agentfs/sdk_version_check.go index 894150fd..54bbc01b 100644 --- a/pkg/agentfs/sdk_version_check.go +++ b/pkg/agentfs/sdk_version_check.go @@ -657,7 +657,31 @@ func isVersionSatisfied(version, minVersion string) (bool, error) { return false, fmt.Errorf("invalid minimum version format: %s", minVersion) } - return !v.LessThan(min), nil + // Check if version satisfies minimum using semver comparison + if !v.LessThan(min) { + return true, nil + } + + // Special handling for prerelease versions: if the base version matches, + // consider prerelease versions as satisfying the requirement + // (e.g., 1.3.0-rc1 should satisfy >=1.3.0) + vBase := v.String() + minBase := min.String() + + // Remove prerelease suffix for base version comparison + if strings.Contains(vBase, "-") { + vBase = strings.Split(vBase, "-")[0] + } + if strings.Contains(minBase, "-") { + minBase = strings.Split(minBase, "-")[0] + } + + if vBase == minBase && v.LessThan(min) { + // Same base version, prerelease should satisfy + return true, nil + } + + return false, nil } // normalizeVersion normalizes version strings for semver parsing @@ -674,6 +698,21 @@ func normalizeVersion(version string) string { version = version[1:] } + // Handle prerelease versions: convert various formats to semver + // 1.3.0rc1 -> 1.3.0-rc1, 1.3rc -> 1.3.0-rc, etc. + prereleasePattern := regexp.MustCompile(`^(\d+(?:\.\d+)*)([a-zA-Z][a-zA-Z0-9]*.*)$`) + if matches := prereleasePattern.FindStringSubmatch(version); matches != nil { + baseVersion := matches[1] + prerelease := matches[2] + + // Ensure we have at least MAJOR.MINOR.PATCH + parts := strings.Split(baseVersion, ".") + for len(parts) < 3 { + parts = append(parts, "0") + } + version = strings.Join(parts, ".") + "-" + prerelease + } + return version } diff --git a/pkg/agentfs/sdk_version_check_test.go b/pkg/agentfs/sdk_version_check_test.go index 1acb64a1..ad5e040c 100644 --- a/pkg/agentfs/sdk_version_check_test.go +++ b/pkg/agentfs/sdk_version_check_test.go @@ -142,6 +142,14 @@ version = "1.5.0"`, }, expectError: false, }, + { + name: "Python requirements.txt with prerelease version", + projectType: ProjectTypePythonPip, + setupFiles: map[string]string{ + "requirements.txt": "livekit-agents~=1.3rc", + }, + expectError: false, + }, { name: "No package found", projectType: ProjectTypePythonPip, @@ -209,6 +217,9 @@ func TestIsVersionSatisfied(t *testing.T) { {"~1.5.0", "1.0.0", true, false}, {">=1.5.0", "1.0.0", true, false}, {"==1.5.0", "1.0.0", true, false}, + {"1.3.0rc1", "1.3.0", true, false}, // prerelease should satisfy same base version + {"1.3rc", "1.3.0", true, false}, // short prerelease should satisfy same base version + {"1.3.0rc1", "1.4.0", false, false}, // prerelease should not satisfy higher version {"invalid", "1.0.0", false, true}, {"1.5.0", "invalid", false, true}, } @@ -248,6 +259,12 @@ func TestNormalizeVersion(t *testing.T) { {`'1.5.0'`, "1.5.0"}, {"*", "*"}, {"latest", "latest"}, + {"1.3.0rc1", "1.3.0-rc1"}, + {"1.3.0beta2", "1.3.0-beta2"}, + {"1.3.0alpha1", "1.3.0-alpha1"}, + {"1.3rc", "1.3.0-rc"}, + {"1.3rc1", "1.3.0-rc1"}, + {"~=1.3rc", "1.3.0-rc"}, } for _, tt := range tests {