From 40d902b173041838aa2e6566f64b21da950cdcb4 Mon Sep 17 00:00:00 2001 From: Jeff Dupont Date: Mon, 28 Sep 2026 11:57:01 -0700 Subject: [PATCH 1/2] [AIC-3484] fix: pin LD-API-Version on agent-optimization API calls Defaults the header to 20240415 so those calls survive the pre-v4 block. AI Config calls still send beta, which overrides the default. Co-authored-by: Cursor --- .../optimization/src/ldai_optimizer/ld_api_client.py | 9 ++++++++- packages/optimization/tests/test_ld_api_client.py | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/packages/optimization/src/ldai_optimizer/ld_api_client.py b/packages/optimization/src/ldai_optimizer/ld_api_client.py index 6dbd580a..94216db5 100644 --- a/packages/optimization/src/ldai_optimizer/ld_api_client.py +++ b/packages/optimization/src/ldai_optimizer/ld_api_client.py @@ -13,6 +13,10 @@ logger.addFilter(RedactionFilter()) _BASE_URL = "https://app.launchdarkly.com" +# Pinned so customer tokens that default below API v4 are not rejected after +# the pre-v4 block. Callers that pass LD-API-Version in extra_headers (the +# AI Config endpoints send "beta") still override this. +_LD_API_VERSION = "20240415" _MAX_RETRIES = 3 _INITIAL_BACKOFF = 1.0 # seconds; doubles on each attempt (1s, 2s, 4s) @@ -198,7 +202,10 @@ def __repr__(self) -> str: return f"LDApiClient(base_url={self._base_url!r})" def _auth_headers(self) -> Dict[str, str]: - return {"Authorization": self._api_key} + return { + "Authorization": self._api_key, + "LD-API-Version": _LD_API_VERSION, + } def _request( self, diff --git a/packages/optimization/tests/test_ld_api_client.py b/packages/optimization/tests/test_ld_api_client.py index e2c11cb8..88c6104d 100644 --- a/packages/optimization/tests/test_ld_api_client.py +++ b/packages/optimization/tests/test_ld_api_client.py @@ -168,6 +168,14 @@ def test_authorization_header_always_sent(self): req: urllib.request.Request = mock_open.call_args[0][0] assert req.get_header("Authorization") == "my-api-key" + def test_default_api_version_header_is_v4(self): + client = LDApiClient("test-key") + with patch("urllib.request.urlopen", return_value=_mock_urlopen({})) as mock_open: + client._request("GET", "/path") + req: urllib.request.Request = mock_open.call_args[0][0] + # urllib capitalizes header names; the wire value is still LD-API-Version. + assert req.get_header("Ld-api-version") == "20240415" + def test_raises_ld_api_error_on_http_error(self): client = LDApiClient("test-key") http_error = urllib.error.HTTPError( From fa7b6c3ec33cef9a1b4cea9ecbe149908a9a62a5 Mon Sep 17 00:00:00 2001 From: Jeff Dupont Date: Mon, 28 Sep 2026 12:31:30 -0700 Subject: [PATCH 2/2] fix(optimization): inline the pinned LD-API-Version value Addresses review feedback on #216. Drops the _LD_API_VERSION constant and the comment above it, which explained the pin in terms of an internal "pre-v4 block" that means nothing to an external reader, and moves the value to the single call site that uses it. Co-Authored-By: Claude Opus 5 (1M context) --- packages/optimization/src/ldai_optimizer/ld_api_client.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/optimization/src/ldai_optimizer/ld_api_client.py b/packages/optimization/src/ldai_optimizer/ld_api_client.py index 94216db5..447bb32a 100644 --- a/packages/optimization/src/ldai_optimizer/ld_api_client.py +++ b/packages/optimization/src/ldai_optimizer/ld_api_client.py @@ -13,10 +13,6 @@ logger.addFilter(RedactionFilter()) _BASE_URL = "https://app.launchdarkly.com" -# Pinned so customer tokens that default below API v4 are not rejected after -# the pre-v4 block. Callers that pass LD-API-Version in extra_headers (the -# AI Config endpoints send "beta") still override this. -_LD_API_VERSION = "20240415" _MAX_RETRIES = 3 _INITIAL_BACKOFF = 1.0 # seconds; doubles on each attempt (1s, 2s, 4s) @@ -204,7 +200,7 @@ def __repr__(self) -> str: def _auth_headers(self) -> Dict[str, str]: return { "Authorization": self._api_key, - "LD-API-Version": _LD_API_VERSION, + "LD-API-Version": "20240415", } def _request(