Skip to content

chore(AIC-3672): release every Python package as 1.0.0 - #242

Merged
jeffdupont merged 3 commits into
mainfrom
jdupont/aic-3672-release-1-0
Oct 30, 2026
Merged

jeffdupont merged 3 commits into
mainfrom
jdupont/aic-3672-release-1-0

Conversation

@jeffdupont

@jeffdupont jeffdupont commented Oct 28, 2026 •

Copy link
Copy Markdown
Contributor

Steps 1 and 2 of AIC-3672. The JS half is AIC-3673.

What this does

  • release-as: 1.0.0 on all 14 packages in release-please-config.json. Without it, release-please keeps bumping 0.x minors, so the next release PR would ship launchdarkly-ai-server 0.6.0 instead of 1.0.0.
  • Internal pins. Every package that depends on launchdarkly-ai-server now requires >=1.0.0,<2. release-please doesn't update these for Python. fix(AIC-3598)!: make Python packaging and public types GA-ready #218 (merged) set them to >=0.6,<2 so either release order resolves; this tightens them to the 1.0 line.
  • uv.lock needs no change: uv records workspace dependencies without a version specifier. uv lock --check passes.

changelog-sections is left alone. #235 removes the evaluations Experimental rows when it promotes Evaluations from Code to core.

Merge this last

Merge this after the PRs below. Anything merged before the release PR (#231) merges ships in 1.0.0, and a ! change merged after 1.0 forces 2.0.

#241 (Shadow Requests) is closed; 1.0 ships with nothing experimental.

After merging

  1. Confirm the regenerated chore: release main #231 lists 1.0.0 for all 14 packages, then merge it.
  2. Install each package from PyPI into an empty venv and import its public entry points (AIC-3672 step 5).
  3. Open a PR removing release-as straight away, or every later release PR proposes 1.0.0 again.

Checks

🤖 Generated with Claude Code


Note

Overview
Prepares the 1.0.0 GA cut for all 14 Python packages by teaching release-please to release 1.0.0 instead of another 0.x bump.

Adds release-as: "1.0.0" on every entry in release-please-config.json (core launchdarkly-ai-server, barrel, and all handler packages).

Tightens internal PyPI pins from launchdarkly-ai-server>=0.6,<2 to >=1.0.0,<2 in each handler pyproject.toml and in packages/ai (including otel / ld extras). Published wheels will require the 1.0 server line once those versions ship.

Reviewed by Cursor Bugbot for commit ae9f2cc. Bugbot is set up for automated code reviews on this repo. Configure here.

- release-please-config.json: "release-as": "1.0.0" on all 14 packages, so the
  next release PR proposes 1.0.0 for every package instead of a 0.x minor.
- Internal pins: every package that depends on launchdarkly-ai-server now requires
  >=1.0.0,<2 (11 handlers had >=0.4.1; ai and typesafe had no bound).
- uv.lock refreshed for the new specifiers.

release-as must be removed straight after the release, or every later release PR
proposes 1.0.0 again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jeffdupont added a commit that referenced this pull request Oct 28, 2026
…resolves

>=1.0.0,<2 could not resolve if a release went out before release-as 1.0.0
lands (Bugbot). >=0.6 still excludes server 0.5.0, which lacks
NativeGraphRunner; this PR's breaking change makes core's next 0.x release
0.6.0, and 1.0.0 satisfies it too. #242 tightens it to >=1.0.0,<2 at the cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
jeffdupont added a commit that referenced this pull request Oct 29, 2026
Python half of
[AIC-3598](https://launchdarkly.atlassian.net/browse/AIC-3598). The spec
change is launchdarkly/ai-sdks-monorepo#91.

## Packaging

- **Classifiers.** All 14 packages say `Development Status :: 5 -
Production/Stable`. The two `vercel-*` packages had no classifiers at
all.
- **Third-party floors** move to the version CI tests wherever the old
floor crossed a breaking line (a major for 1.x+ libraries, a minor for
0.x):
- `langchain-core>=1.6`, `langgraph>=1.2`, `openai>=2.44`,
`openai-agents>=0.17`
  - `anthropic>=0.113`, `httpx>=0.28`, `typesafe-sdk>=0.7`

The rule, as the shared spec states it: a floor sits on the line CI
tests, the same major as the tested version for a 1.x+ library and the
same minor for a 0.x one. The README says so.

Floors already on the tested major stay put (`opentelemetry-api>=1.25`,
`litellm>=1.83`).
- **`[ld]` extra** on `launchdarkly-ai-server` and
`launchdarkly-ai-python` installs `launchdarkly-server-sdk>=9.18.3,<10`.
It's an extra rather than a dependency so bring-your-own-client installs
stay lean, as `client/AGENTS.md` requires. The READMEs and the
`init_client` error message point to it.
- **Undeclared LangChain provider packages, found by the new check.**
Both langchain packages imported `langchain_openai` and
`langchain_anthropic` without declaring them, the Python side of the JS
`@langchain/anthropic` gap:
- `langchain-agents` now depends on `langchain-openai`, its default
model, and offers `[anthropic]` and `[aws]` extras.
- `langchain-messages` now depends on `langchain-openai`, its default
model, as langchain-agents does, and offers `[anthropic]` and `[aws]`.
- The Anthropic and OpenAI imports are now guarded with an install hint,
as Bedrock's already was.
- **Internal ranges:** every package pins
`launchdarkly-ai-server>=0.6,<2`. The native graph adapters import
`NativeGraphRunner`, which published server 0.5.0 lacks, so `>=0.4.1`
would let a handler resolve to a core it can't import from. `>=0.6`
resolves whichever lands first, this PR's 0.6.0 or the 1.0.0 cut; #242
(AIC-3672) tightens it to `>=1.0.0,<2`.

## Public types

- **`LDClientInterface` becomes a `Protocol`.** It was a plain class
with `async` methods, which matched neither the synchronous
`ldclient.LDClient` nor the "maybe awaitable" way core calls it.
`ldclient.LDClient` now satisfies it structurally; checked with mypy in
both directions (a client missing `track` is rejected). `init_client`
and `get_client` return it. `variation`, `flush` and `close` may be
async; `track` must be synchronous (`-> None`), because no call site
awaits it.
- **`tool_handlers` on the handler protocol** and in every handler is
typed `Mapping[str, Callable[..., Any] | NativeTool]` instead of
`dict[str, Any]`, so a caller's precisely typed `dict` is accepted.
Offline evaluations pass a `NativeTool` to the handler unwrapped, so
`langchain-agents` now checks `callable()` before calling. It used to
raise `TypeError: 'NativeTool' object is not callable`; there's a test,
and it fails without the fix.
- **Native graph adapters** (`to_lang_graph`, `to_openai_agents`,
`to_claude_agents`, `to_litellm_agents`, `to_vercel_agents`):
  - take `Awaitable[GraphDefinition]`
  - take a per-package options `TypedDict` exported from the root
- return the new core `NativeGraphRunner` protocol. They return a small
class rather than a `SimpleNamespace`, because mypy accepts any
`SimpleNamespace` as any protocol.

## Packaging check (`make check-packaging`, new CI job `packaging`)

`scripts/check_packaging.py` installs each wheel alone, with no extras,
into an empty venv, which proves core loads without
`launchdarkly-server-sdk`. It imports every public module and `__all__`
name. Then it checks that every module the source imports
unconditionally, lazy `importlib.import_module` calls included, comes
from a distribution the package declares; installed through some other
dependency is not enough. That found undeclared `pydantic` in four
packages and `openai` in litellm-agents, now declared. Each declared
extra gets its own venv and must import what `EXTRA_IMPORTS` lists for
it; an extra with no entry fails. Internal dependencies resolve to this
commit's wheels and third-party ones from PyPI. Each import is resolved
by its full dotted name to the distribution that owns it, so a namespace
package such as `opentelemetry.sdk` needs `opentelemetry-sdk` declared;
that found `langgraph.prebuilt` undeclared in langchain-agents. The 22
runs go through a thread pool.

## Checks

- `make lint`, `make format-check`, `make typecheck` (no issues in 104
files), `make api-report-check` (15 reports current)
- `make test`: 3,651 passed, 18 skipped
- `make check-packaging`: all 14 packages and 8 extras pass; removing
`pydantic` from vercel-agents makes it fail with `pydantic (from
pydantic, not declared)`

## Versioning

The README documents the 1.0 rule: from 1.0.0, every package is released
at the same version.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[AIC-3598]:
https://launchdarkly.atlassian.net/browse/AIC-3598?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Prepares the Python AI SDK monorepo for GA by tightening
**packaging**, **install docs**, and **public types**, plus a CI gate
that catches undeclared dependencies workspace tests miss.
> 
> **Packaging and installs.** All packages move to **Production/Stable**
classifiers; third-party floors are raised to versions CI exercises
(LangChain 1.x, OpenAI 2.x, etc.). **`launchdarkly-ai-server[ld]`** and
**`launchdarkly-ai-python[ld]`** now install bounded
**`launchdarkly-server-sdk`**; READMEs drop separate
`launchdarkly-server-sdk` lines. Handlers pin
**`launchdarkly-ai-server>=0.6,<2`**. LangChain packages **declare**
`langchain-openai` and add **`[anthropic]` / `[aws]`** extras with
guarded import errors; missing deps like **`pydantic`** and
**`langgraph-prebuilt`** are added where the new checker found gaps.
> 
> **`make check-packaging` + CI `packaging` job.** New
**`scripts/check_packaging.py`** builds wheels, installs each package
(and each extra) in an isolated venv, validates public **`__all__`**
imports, and asserts every unconditional/lazy import is owned by a
**declared** distribution—not a transitive install.
> 
> **Public API typing.** **`LDClientInterface`** is a **`Protocol`**
aligned with real **`ldclient`** usage; **`get_client` / `init_client`**
return it. **`tool_handlers`** is **`Mapping[str, Callable[..., Any] |
NativeTool]`** across core and handlers (LangChain agents reject
unwrapped **`NativeTool`**). Native graph **`to_*`** adapters take
**`Awaitable[GraphDefinition]`**, export per-package options
**`TypedDict`s**, and return **`NativeGraphRunner`** instead of untyped
namespaces.
> 
> README adds **1.0 synchronized versioning** policy for the SDK.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
bdd635b. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Takes main's pyproject.toml files (with #218's new dependencies) and keeps this
branch's internal pin, launchdarkly-ai-server>=1.0.0,<2, in all 13.

Also fixes release-please-config.json: 12727f3 wrote the release-as lines with
literal backslashes (\"release-as\": \"1.0.0\"), which is invalid JSON. The
file now parses, with release-as 1.0.0 on all 14 packages.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jeffdupont
jeffdupont marked this pull request as ready for review October 29, 2026 21:06
@andrewklatzke
andrewklatzke self-requested a review October 30, 2026 18:21
jeffdupont added a commit to launchdarkly/js-ai-sdk that referenced this pull request Oct 30, 2026
Steps 1 and 3 of
[AIC-3673](https://launchdarkly.atlassian.net/browse/AIC-3673). The
Python half is launchdarkly/python-ai-sdk#242.

## What this does

- **`release-as: 1.0.0`** on all 14 packages in
`release-please-config.json`. The `node-workspace` plugin updates the
internal dependency ranges.
- **Publish jobs for `litellm-agents` and `litellm-messages`.** They had
none, so `@launchdarkly/ai-litellm-*-0.2.0` was tagged but never
published. Both are also added to the manual-publish choices.

`changelog-sections` is left alone: #181 (merged) removed the
evaluations Experimental rows when it promoted Evaluations from Code to
core.

## ⚠️ npm setup: trusted publishers still to confirm for 5 of 14
packages

The 26 Oct release run
([40393827352](https://github.com/launchdarkly/js-ai-sdk/actions/runs/40393827352))
failed 3 publish jobs, and the litellm packages have never had a job:

| Package | On npm | Failure |
|---|---|---|
| `@launchdarkly/ai-typesafe` | 0.0.0 placeholder | `E404 … PUT
@launchdarkly/ai-typesafe`: the package doesn't exist, and OIDC can't
create it |
| `@launchdarkly/ai-vercel-agents` | 0.0.0 placeholder | `E403 OIDC
permission denied` |
| `@launchdarkly/ai-vercel-messages` | 0.0.0 placeholder | `E403 OIDC
permission denied` |
| `@launchdarkly/ai-litellm-agents` | 0.0.0 placeholder | no publish job
(added here) |
| `@launchdarkly/ai-litellm-messages` | 0.0.0 placeholder | no publish
job (added here) |

Before the release PR merges, an npm org admin needs to:
1. ~~Publish a 0.0.0 placeholder for `ai-typesafe`, `ai-litellm-agents`
and `ai-litellm-messages`.~~ Done: all three are on npm at 0.0.0
(checked 29 Oct).
2. Add a trusted publisher (`launchdarkly/js-ai-sdk`, workflow
`release-please.yml`) to all five.

Otherwise 1.0.0 ships 9 of 14 packages.

## Merge this last

Merge this only after the items below are done. Anything merged before
the release PR (#171) merges ships in 1.0.0, and a `!` change merged
after 1.0 forces 2.0.

- [x] #181 feat(evaluations)!: promote Evaluations from Code to core.
After it, `@launchdarkly/ai-server/experimental` exports nothing.
- [x] #180 fix(SEC-9507)!: dispatch tools only from the active
variation's config.tools
- [x] #183 fix(claude-agents)!: honour max_tokens and disable thinking
by default
- [x] #111 feat(AIC-3439)!: wildcard handlers accept only named
providers (merged 29 Oct)
- [x] npm placeholders (above)
- [ ] Trusted publishers on all five packages (above; needs an npm org
admin to confirm)
- [ ] #192 fix(AIC-3592): make native LangGraph hand-offs complete
(ready for review; spec launchdarkly/ai-sdks-monorepo#118)
- [ ] #194 fix(AIC-3573): never send a NativeTool to the model as a
function tool (ready for review; spec launchdarkly/ai-sdks-monorepo#116)
- [ ] #190 feat(client)!: capture conversation content by default and
add configure() (approved; breaking, so it must land before #171)
- [ ] #196 test(AIC-3716): run the OpenAI native graph with a tool on
the real SDK (test only; optional for the release)

Not in 1.0: #187 (Shadow Requests, closed). 1.0 ships with nothing
experimental.

## After merging

1. Confirm the regenerated #171 lists 1.0.0 for all 14 packages and its
CI is green, then merge it.
2. Install each package from npm into an empty project and import its
entry points, in both ESM and CJS (AIC-3673 step 5).
3. Open a PR removing `release-as` straight away.

## Checks

- The workflow YAML parses: 14 per-package publish jobs plus
release-please and the canary. The new jobs are copies of
`release-typesafe`.
- No local build was run: this is config only, made through the GitHub
API.

🤖 Generated with [Claude Code](https://claude.com/claude-code)


[AIC-3673]:
https://launchdarkly.atlassian.net/browse/AIC-3673?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> Prepares the monorepo for a coordinated **1.0.0** npm release by
setting **`release-as: "1.0.0"`** on all 14 workspaces in
`release-please-config.json` (the `node-workspace` plugin will align
internal dependency ranges when the release PR lands).
> 
> The **`release-please`** workflow now fully covers
**`litellm-agents`** and **`litellm-messages`**: they appear in manual
`workflow_dispatch` package choices, expose release-please job outputs,
and get dedicated **`release-litellm-*`** publish jobs (build, attest,
npm publish) matching the other packages—closing the gap where LiteLLM
tags could be created without a publish step.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
af882d4. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: andrewklatzke <aklatzke@launchdarkly.com>
@jeffdupont
jeffdupont merged commit c49a41e into main Oct 30, 2026
10 checks passed
@jeffdupont
jeffdupont deleted the jdupont/aic-3672-release-1-0 branch October 30, 2026 20:32
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.

2 participants