Skip to content

feat: add evaluations module scaffold, credentials, LD API client, result types - #39

Draft
donei003 wants to merge 1 commit into
mainfrom
devin/1786604824-evaluations-scaffold
Draft

feat: add evaluations module scaffold, credentials, LD API client, result types#39
donei003 wants to merge 1 commit into
mainfrom
devin/1786604824-evaluations-scaffold

Conversation

@donei003

@donei003 donei003 commented Aug 13, 2026

Copy link
Copy Markdown

Summary

AIC-3077 — the scaffold for the Phase 2 SDK-run evaluations harness, in Tier 0 launchdarkly_ai_server since the harness is provider-independent (it only speaks LD HTTP; provider work stays behind the ProviderHandler contract).

Three pieces, no harness logic yet (run() lands with a later milestone):

  • Credential resolutioninit_evaluations(api_token=..., sdk_key=..., base_uri=...), explicit args first, then LD_API_TOKEN / LD_SDK_KEY / LD_BASE_URI. A missing API token raises EvaluationsError at init, before any socket is opened, rather than surfacing as an opaque 401 mid-run; a missing SDK key just logs and disables traces.
  • LDApiClient — every request carries Authorization: <token>, base URI is overridable for non-default instances, non-2xx raises LDApiError carrying status/method/path/body. HTTP goes through a Transport protocol defaulting to urllib (no new dependency on the core package), which is also the seam tests swap out.
  • Result typesEvalRunResult { passed, url, run_id, summary }, RunSummary { total_rows, passed_rows, failed_rows, error_rows }, and Usage. Usage deliberately duplicates rather than reuses UsageDict: the eval ingest wire shape is input_tokens / output_tokens, so handler results can be forwarded verbatim.

Tests are fully mocked (RecordingTransport), and the missing-token case uses a transport that raises on any call to prove no network I/O happens.

Link to Devin session: https://app.devin.ai/sessions/02393d0331464004ba78a6d1fcfcc43f
Requested by: @donei003

@donei003 donei003 self-assigned this Aug 13, 2026
@devin-ai-integration

Copy link
Copy Markdown

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 1 potential issue.

View 2 additional findings in Devin Review.

Open in Devin Review

Comment on lines +72 to +76
api_client = LDApiClient(
api_token=token,
base_uri=base_uri or _env("LD_BASE_URI") or DEFAULT_BASE_URI,
transport=transport,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Custom LaunchDarkly host setting for flag delivery is reused for management API calls, sending requests to the wrong server

The evaluations client picks up the same host setting already used for flag delivery (_env("LD_BASE_URI") at packages/client/src/launchdarkly_ai_server/evaluations/module.py:74) even though the two point at different LaunchDarkly services, so anyone who configured a streaming/relay host will have their evaluation requests sent to a server that cannot answer them.
Impact: Users with a relay proxy or staging streaming endpoint configured get failing or misdirected evaluation API calls instead of reaching the LaunchDarkly management API.

Env var collision between SDK polling base URI and /api/v2 base URI

packages/client/src/launchdarkly_ai_server/lifecycle.py:175 already consumes LD_BASE_URI as the SDK polling/streaming base URI (documented in packages/client/README.md:36 as "Override the LaunchDarkly polling base URI"). The evaluations module reuses the same variable but appends /api/v2/... (packages/client/src/launchdarkly_ai_server/evaluations/api.py:93), which targets the public management API (default https://app.launchdarkly.com). A user pointing LD_BASE_URI at e.g. a relay proxy or https://sdk.launchdarkly.com would silently redirect all evaluations API traffic there. A distinct variable (e.g. LD_API_BASE_URI) avoids the conflict.

Suggested change
api_client = LDApiClient(
api_token=token,
base_uri=base_uri or _env("LD_BASE_URI") or DEFAULT_BASE_URI,
transport=transport,
)
api_client = LDApiClient(
api_token=token,
base_uri=base_uri or _env("LD_API_BASE_URI") or DEFAULT_BASE_URI,
transport=transport,
)
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant