Skip to content

feat(AIC-3439)!: let wildcard handlers accept only named providers - #111

Merged
jeffdupont merged 13 commits into
mainfrom
aklatzke/AIC-3439/scoped-handlers
Oct 29, 2026
Merged

jeffdupont merged 13 commits into
mainfrom
aklatzke/AIC-3439/scoped-handlers

Conversation

@andrewklatzke

Copy link
Copy Markdown
Contributor

Summary

  • A wildcard handler can take a providers list, so a LangChain adapter used only for Bedrock accepts config.provider.name === "Bedrock" and no other provider.
  • Exact [provider, mode] still wins. Among scoped wildcards that contain the name, the shortest list wins, then the earlier registration. An unscoped * is the fallback.
  • Registry identity is providesFor plus the provider set, so two scoped wildcards of the same mode can be registered together. Judges and graph selection use the same order.

Test plan

  • Vitest on the client, langchain-messages, and langchain-agents suites
  • Biome and tsc on the touched packages
  • Integration success and failure for agent, graph, streaming, graph-streaming, langchain, langchain-messages, langchain-agents, and native-graph-langchain
  • TypeScript judge example still looks for examples/judge-worker.js while only judge-worker.ts is present, so that case does not start

Made with Cursor

A LangChain adapter used for one provider no longer has to match every provider, and two scoped wildcards of the same mode can be registered together.

Co-authored-by: Cursor <cursoragent@cursor.com>
@andrewklatzke

andrewklatzke commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor Author

Human message:

I think this is a "nice to have" not necessarily "must do it". I'm thinking of situations where, for example, a user might want to use the Google ADK and scope it only to gemini (create_google_adk_handler(providers=['Gemini'])). Another example might be folks wanting to use langchain but only for Bedrock so they don't have to deal with boto.

You can technically achieve this now by properly including the right subset of handlers, but this makes it more obvious/colocates it with the code if you want to scope them down.

tldr; if we think this is confusing or don't want it, we can close it

@jeffdupont jeffdupont left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Selection is right in config(), in graph node selection, and in the three judge entry points. The registry keeps scoped wildcards apart the way the PR body says. One judge path skips the allowlist (1 below), and the registry orders handlers differently from Python #136 (2). Those two need fixing before this merges.

At 6cd4ce42, build, tsc, Biome and Sherif are clean, and yarn test gives 1177 passed. I trial-merged it onto today's main (#73, #68 and the rest) and got no conflicts. The merged tree gives 1325 passed, with typecheck and Biome clean. The #73 parameter allowlists in langchain-messages and langchain-agents handler.ts merge without trouble next to the new providers option, and the factory signatures are unchanged.

I probed selectModeHandler, the registry and the judge functions directly:

  • An exact handler beats a scoped wildcard, and a scoped wildcard beats an unscoped one, whatever the registration order.
  • The shortest matching list wins. On equal lengths the earlier handler wins.
  • Names match exactly, so bedrock doesn't match ['Bedrock']. Exact handlers follow the same rule (client.ts:39-44).
  • [], [''] and [' '] throw at createHandler, and the message mentions providers.
  • If a scoped wildcard doesn't list the provider, config() throws Handler for provider OpenAI not found. That's the same message as having no handler at all, and Python gives the same string.
  • Two scoped wildcards of one mode both stay registered. Registering the same set again, in either order, warns and replaces. ['Bedrock', 'Bedrock'] counts as the same identity as ['Bedrock']. compose(a, b) lets b win on a matching set and keeps different sets.
  • runJudges, buildJudgeTasks and runJudge all pick the shortest list. Each falls back to a scoped agent handler with collapseMessages: true, and each skips a judge whose provider isn't in any list.

I tried 24 mutations, and 20 of them fail a test. The 4 that get through are in the inline comments.

  1. The graph-level judge ignores the allowlist. graph.ts:796-807 calls runJudges without handlers, so runJudges takes the judgeHandler = handler branch and never checks the provider (judges.ts:157-158). I ran graph().invoke() with one handler, ['*', 'messages'] scoped to ['Bedrock'], and a graphJudge whose provider is Anthropic. The Bedrock-only handler ran the Anthropic judge. Adding an Anthropic-scoped handler didn't help, because the root handler still ran it. The missing handlers argument predates this PR. Before, though, it only affected which of two acceptable handlers ran. Now it lets a scoped handler run a provider it was set up to refuse. Python passes handlers=resolved_handlers on the same call (graph.py:1016-1024 and :1238-1250). Please pass handlers: judgeHandlers and add a graphJudge test with a provider outside the list.
  2. Re-registering moves a handler to the end, but Python replaces it in place. registry.ts:29 filters out the old entry and pushes the new one. Python's registry.py:74 assigns into the same index. Ties go to the earlier registration, so the two SDKs now pick different handlers. As a repro, register ['Bedrock', 'Gemini'], then ['Bedrock', 'Anthropic'], then ['Bedrock', 'Gemini'] again. JS ends up with [BA, BG], and a Bedrock config runs BA. Python keeps [BG, BA] and runs BG. compose shows the same split: JS gives [aU, bB, bA], Python [bB, aU, bA]. Before this PR it didn't matter, because only one wildcard per mode could be registered. Monorepo #39 doesn't say which is right. I'd go with in place, so a replacement takes the slot of what it replaces. That needs a line in #39 §3.6 and a test in both SDKs.
  3. Repeated names count toward list length. The registry key collapses ['Bedrock', 'Bedrock'] to ['Bedrock'] (registry.ts:6), but bestWildcard compares allow.length (utils.ts:92). So ['Bedrock', 'Bedrock'] ties with ['Bedrock', 'Anthropic'] and loses on registration order, even though the registry treats it as the narrower list. Python does the same (utils.py:97). Deduping in createHandler fixes this, and then #39 can say "fewest distinct names".
  4. createHandler keeps the caller's array. utils.ts:60 stores the array itself, not a copy. If the caller later pushes 'OpenAI' onto it, an OpenAI config routes to that handler, and its registry identity changes too. Python copies into a tuple. Object.freeze([...new Set(providers)]) would fix 3 and 4 together.

Questions and smaller items

  • The createHandler signature freezes at 1.0. providers is the fifth positional argument, so a caller writes createHandler(pf, fn, undefined, undefined, ['Bedrock']), and #39's A.14 has to explain the undefineds. Python made it keyword-only. An options object ({ stream, captureContent, providers }) is harder to get wrong, but we can't switch to one after 1.0 without a major release. I'm fine either way, but let's decide now. The name and type match Python (providers, readonly string[], and Python's Sequence[str] stored as a tuple). The selection helpers aren't exported from index.ts, which is right.
  • API report. main has no API Extractor setup yet, because it's on #71's branch. I trial-merged this PR into #71 (c27005cc). There were no conflicts, but api:check fails on two lines: createHandler(..., providers?: readonly string[]) and ProviderHandler.providers?. Whichever of the two lands second needs yarn api:update.
  • Whitespace. [' Bedrock'] is accepted and never matches anything. Python's docstring says surrounding whitespace is rejected, but its code accepts it too. Either both should reject name !== name.trim(), or the claim should go.
  • Case. Routing is exact, which fits exact handlers and #39. The LangChain handlers lower-case the provider themselves (langchain-messages handler.ts:70 and :198), though. So a config with provider.name = 'bedrock' would take the Bedrock model path, but it won't route to ['Bedrock']. That's fine if LaunchDarkly always serves the canonical spelling, which I haven't checked.
  • Exact handlers that have a list. Routing ignores the list on an exact handler, but the registry key still includes it (registry.ts:5-6). So ['OpenAI', 'messages'] with a list and without one both stay registered, and the first one wins. #39 says two exact handlers collide. Python does the same thing. I'd leave providers out of the key when providesFor[0] !== '*'.
  • Calling createHandler twice on one function. createHandler changes the function in place, so two calls with different lists return the same object, holding the last list. A later unscoped call on the same function keeps the old list, because utils.ts:60 only sets the property when one is passed. captureContent already works this way. The LangChain factories build a new closure each time, so they aren't affected. A JSDoc note is enough.
  • The priority comment at judges.ts:132-138 doesn't mention scoped lists. Nit.

The judge example (from the PR body)

examples/judge.ts:56 resolves ./judge-worker.js, but only examples/judge-worker.ts exists. Both files date from the initial commit (977dba8), and this PR doesn't touch examples/, so the problem already exists on main. I didn't run it.

Parity with python-ai-sdk #136

On my probe cases, the two SDKs agree on selection order, ties, case, a missing provider (undefined / None), empty and blank lists, the error strings and set identity. They differ in five places:

  • re-registration position (2)
  • the graph-level judge (1)
  • copying the caller's list (4)
  • identity of ['a,b'] vs ['a', 'b']: JS joins with commas, so these collide and one replaces the other (registry.ts:6), while Python's frozenset keeps both
  • a bare string or a non-string name: Python raises ValueError mentioning providers, while JS throws a TypeError (providers.some is not a function). That's acceptable, since the TS types already rule it out.

Python also routes judges in its evaluations runner. JS has no runner, and #39's A.14 says so.

Comment thread packages/client/src/graph.ts Resolved
Comment thread packages/client/src/registry.ts Resolved
Comment thread packages/client/src/registry.ts Resolved
Comment thread packages/client/src/utils.ts Resolved
Comment thread packages/client/src/utils.ts Resolved
Comment thread packages/client/src/utils.ts Resolved
Comment thread packages/client/src/client.ts Resolved
Comment thread packages/client/src/judges.ts Resolved
Comment thread packages/client/src/judges.ts Resolved
andrewklatzke and others added 2 commits October 21, 2026 10:12
…ped-handlers

Co-authored-by: Cursor <cursoragent@cursor.com>

# Conflicts:
#	packages/client/src/graph.ts
#	packages/client/src/utils.ts
#	packages/langchain-agents/src/graph.ts
#	packages/langchain-agents/src/handler.ts
#	packages/langchain-messages/src/handler.ts
…vider lists, keep re-registration in place

- createHandler(providesFor, handler, { stream, captureContent, providers })
- providers are deduped, copied and frozen; names with surrounding whitespace are rejected
- the registry replaces a re-registered handler in its slot, keys on a JSON set,
  and leaves providers out of an exact handler's identity
- the graph-level judge gets the graph handlers, so a scoped allowlist applies
- tests for the unscoped fallback, the exact error string, a scoped parent and runJudge

Co-authored-by: Cursor <cursoragent@cursor.com>

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 64d94c8. Configure here.

Comment thread packages/langchain-agents/src/graph.ts Resolved
andrewklatzke and others added 4 commits October 21, 2026 10:21
…ndler

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ped-handlers

# Conflicts:
#	packages/client/src/judges.ts
Route config, registry and judge handler selection through selectModeHandler after main's
selection changes, regenerate the API reports and surfaces, and describe stream as an option.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jeffdupont jeffdupont changed the title feat(AIC-3439): let wildcard handlers accept only named providers feat(AIC-3439)!: let wildcard handlers accept only named providers Oct 23, 2026
@jeffdupont
jeffdupont requested a review from a team as a code owner October 23, 2026 19:16
@jeffdupont

Copy link
Copy Markdown
Contributor

Merged main in and resolved the conflicts (now at the head of aklatzke/AIC-3439/scoped-handlers):

  • config() selection, findHandler and judge selection all go through selectModeHandler (exact provider → shortest scoped wildcard → unscoped *). Judges keep main's agent-mode fallback for a messages judge, and handlerFor is gone.
  • Regenerated ai-server.api.md, the new langchain-agents/messages reports, and api-surface.
  • AGENTS.md now describes streaming as the stream option.
  • Retitled with !: createHandler moves from positional (providesFor, fn, stream?, captureContent?) to (providesFor, fn, options?), which is breaking and freezes at 1.0.

Locally, typecheck and api:check pass, and every package's tests pass (client: 1859 passed). This needs a human re-review; jeffdupont's CHANGES_REQUESTED still stands.

@jeffdupont jeffdupont left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Re-reviewed 3b19aba against my 10-08 review. Your 10-21 fixes resolve my comments. Two things left:

  1. Conflict with main. After #159 merged, the branch conflicts only in packages/client/etc/ai-server.api.md. Please merge main, run yarn workspace @launchdarkly/ai-server api:update, and push.

  2. The evaluations duplicate check ignores the provider scope. packages/client/src/evaluations.ts:314 builds the handler identity from providesFor alone:

    const identity = `${providesFor[0]}\u0000${normalizeMode(providesFor[1])}`;

    So handlers: [createLangChainHandler(llm, { providers: ['Bedrock'] }), createLangChainHandler(llm, { providers: ['Anthropic'] })] throws "Two handlers provide for provider '*' in mode 'messages'", even though the registry treats them as distinct. Python accepts the same pair: python-ai-sdk#136 keys this check on registration_key (evaluations/module.py:669). Please export registrationKey from registry.ts, use it here, and add a test with two wildcards scoped to different providers.

I'll approve once both are in. This one has to land before the 1.0 cut, because the positional createHandler change can't go in after it.

Regenerate ai-server.api.md so the report carries both the options-object
createHandler and main's toolHandlers union.
Two wildcards of one mode with different provider lists are distinct.
The pool check used providesFor alone, so that pair threw. registrationKey
already treats them as distinct and now normalizes mode, so completion
still collides with messages.

@jeffdupont jeffdupont left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Re-reviewed b2adf5f against my 10-27 comment. b2adf5f fixes the evaluations duplicate check: validateHandlerPool now keys on registrationKey (evaluations.ts:314), which also normalizes the mode the way Python's registration_key does. The two new tests cover both cases, two different sets and two matching sets. All the 10-08 items still hold at this head, and CI is green.

The branch conflicts with main again. Eight commits landed after your 10-27 merge, and #173 renamed createLangChainHandler to createLangChainMessagesHandler. A trial three-way merge of head, main and their merge base c6c00fc conflicts in three files: packages/client/etc/ai-server.api.md, packages/langchain-messages/etc/ai-langchain-messages.api.md and packages/langchain-messages/src/handler.ts. In handler.ts the only conflict is the langchainMessages wrapper line: keep main's name and your providers. Three more places merge without a conflict but keep the old name (inline below), so tests fail after the merge until they're renamed. After that, run yarn api:update and push.

I checked every createHandler( call in the repo at head and on main. No caller passes stream or captureContent positionally. The handler packages go through createHandlerInternal, which stays positional, and the API report matches the new options-object signature. Users who pass a stream function or captureContent positionally have to move it into { stream, captureContent }. TypeScript users get a compile error. Plain JavaScript callers don't, and their stream or captureContent is silently ignored (inline at utils.ts:60).

Parity with python-ai-sdk#136 is unchanged and holds: exact provider first, then the scoped wildcard with the shortest list of distinct names, then the earlier registration, then the unscoped *. Identity is the same, a replacement keeps its slot, and the empty/blank/padded-name error string is identical. Monorepo #39 needs two edits after #173: A.19 still says createLangChainHandler, and §3.13 says TypeScript has no evaluations runner, while A.19 (and evaluations.ts) route judges through findHandler.

I'll approve once the merge with main is in and the old LangChain name is renamed. This one has to land before the 1.0 cut.

});

it('scopes the wildcard to the given providers', () => {
const handler = createLangChainHandler(makeMockLLM() as any, { providers: ['Bedrock', 'Anthropic'] });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

#173 renamed this factory to createLangChainMessagesHandler on main. A three-way merge renames the existing calls in this file but leaves your new ones at :128, :132 and :138 on createLangChainHandler, so the file no longer typechecks after the merge, and there's no textual conflict to point at it. The same old name stays in packages/langchain-messages/README.md:7 and packages/langchain-messages/agents.md:15. Please rename all five when you merge main.

Comment thread AGENTS.md Outdated
```

The `providesFor` tuple is how `config()` routes to the correct handler at runtime. The mode element must exactly match the normalized `meta.mode`. The provider element must either exactly match `config.provider.name` **or** be the wildcard `'*'`. A wildcard handler is chosen only when no handler with an exact provider name matches — it acts as a fallback for multi-provider adapters like LangChain. **Always attach `providesFor` using `createHandler` rather than direct property assignment.**
The `providesFor` tuple is how `config()` routes to the correct handler at runtime. The mode element must exactly match the normalized `meta.mode`. The provider element must either exactly match `config.provider.name` **or** be the wildcard `'*'`. A wildcard handler is chosen only when no handler with an exact provider name matches — it acts as a fallback for multi-provider adapters like LangChain. Pass `providers: ['Bedrock']` as the fifth argument to `createHandler` to limit which `config.provider.name` values that wildcard accepts; names must match exactly, and an empty list or a blank name is rejected. Omit `providers` to leave the property unset, which accepts every provider. **Always attach `providesFor` using `createHandler` rather than direct property assignment.**

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This still says to pass providers "as the fifth argument to createHandler". After 64d94c8 it's a field of the third-argument options object: createHandler(providesFor, fn, { providers: ['Bedrock'] }).

handler: HandlerInput,
streamHandler?: StreamHandlerInput,
captureContent?: boolean,
options: { stream?: StreamHandlerInput; captureContent?: boolean; providers?: readonly string[] } = {},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Users who call createHandler(pf, fn, streamFn) or createHandler(pf, fn, undefined, true) from plain JavaScript don't get an error. options.stream reads undefined off the function, so stream() quietly falls back to the blocking handler, and the fourth argument is dropped. TypeScript catches both. waitForSkills handled the same kind of change with a TypeError that names the new form (skills-fdv2.ts:1757-1771). Something like if (typeof options === 'function' || arguments.length > 3) throw new TypeError('createHandler takes { stream, captureContent, providers } as its third argument') would make the 1.0 change fail loudly. Optional, but cheap to add before the signature freezes.

Keep main's flushTracerProvider import next to registrationKey in
evaluations.ts, and pass providers through main's renamed
createLangChainMessagesHandlerInternal in langchainMessages. Rename the
scoped-handler tests to createLangChainMessagesHandler, and regenerate
the ai-server and ai-langchain-messages API reports.
…peError

A plain JavaScript caller still passing createHandler(pf, fn, streamFn)
or createHandler(pf, fn, undefined, true) lost its stream and
captureContent without an error. createHandler now throws a TypeError
naming the options-object form when the third argument is not an object
or a fourth argument is passed, as waitForSkills does for its own
signature change.
…the renamed LangChain factory

AGENTS.md still told callers to pass providers as the fifth argument to
createHandler; it is a field of the third-argument options object. The
langchain-messages README and agents.md still named createLangChainHandler,
which main renamed to createLangChainMessagesHandler.
The createHandler JSDoc grew, which moves the StreamHandlerInput warning
line in the report.
@apucacao
apucacao requested a review from jeffdupont October 29, 2026 16:33

@jeffdupont jeffdupont left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Re-reviewed 04eb5a8 against my 10-28 comment. All three threads are fixed. The merge with main renames the new scoped-handler tests to createLangChainMessagesHandler, and README.md:7 and agents.md:15 now use the new name. The only remaining createLangChainHandler string is the usage-telemetry key, which main has too. AGENTS.md now describes providers as a field of the third-argument options object. createHandler throws a TypeError that names the new form when the third argument isn't an object or a fourth argument is passed (utils.ts:70-76). The four new tests cover a positional stream function, a fourth argument, non-object values and an explicit undefined. The client tests pass locally (458), and CI is green.

One heads-up for sequencing, not a change here: #190 also edits createHandler. It keeps the positional fourth captureContent, which this PR now rejects. It returns a new wrapper instead of the same function. And a re-wrap drops an earlier captureContent override, which this PR's doc comment (utils.ts:57-59) promises to keep. A trial merge of the two heads conflicts in utils.ts, types.ts, utils.test.ts and both LangChain handler.ts files. I'd land this one first and have #190 rebase onto the options object. I'll raise the details on #190.

Approving. This changes the public createHandler signature, so it needs to land before the 1.0 cut.

@jeffdupont
jeffdupont merged commit 9371975 into main Oct 29, 2026
11 checks passed
@jeffdupont
jeffdupont deleted the aklatzke/AIC-3439/scoped-handlers branch October 29, 2026 19:21
@github-actions github-actions Bot mentioned this pull request Oct 29, 2026
apucacao added a commit that referenced this pull request Oct 29, 2026
Brings in the createHandler options object, the positional-form TypeError
and wildcard `providers` from #111. createHandler still returns a new
wrapper; `providers` is validated, deduped and frozen, then set on the
wrapper, and a re-wrap without `providers` keeps the list copied from the
wrapped handler. Tests and docs from this branch now use the options form.
apucacao added a commit that referenced this pull request Oct 29, 2026
#111 replaced createHandler's positional stream and captureContent
arguments with an options object, and the positional form now throws.
The two client tests this branch added still used it.
jeffdupont added a commit 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 pushed a commit that referenced this pull request Oct 30, 2026
🤖 I have created a release *beep* *boop*
---


<details><summary>@launchdarkly/ai-claude-agents: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-claude-agents-0.5.0...@launchdarkly/ai-claude-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
* **SEC-9507:** enable Claude native tools only when the active
variation attaches them
* **claude-agents:** honour the config's max_tokens and disable thinking
unless the config asks
([#183](#183))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#172](#172))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))

### Features

* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
([8dbe2ec](8dbe2ec))
* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))
* **skills:** give Claude Agents runs the skills attached to their
variation ([#136](#136))
([df16ba0](df16ba0))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#172](#172))
([d3e7c5f](d3e7c5f))


### Bug Fixes

* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))
([c6c00fc](c6c00fc))
* **claude-agents:** honour the config's max_tokens and disable thinking
unless the config asks
([#183](#183))
([f58ce21](f58ce21))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))
* **SEC-9507:** dispatch litellm-messages tool calls only to tools
offered for the request
([6926e8a](6926e8a))
* **SEC-9507:** enable Claude native tools only when the active
variation attaches them
([6926e8a](6926e8a))
* **SEC-9507:** pass handlers only the tools attached to the active
variation
([6926e8a](6926e8a))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-claude-messages: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-claude-messages-0.5.0...@launchdarkly/ai-claude-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))

### Features

* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))
([c6c00fc](c6c00fc))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-langchain-agents: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-langchain-agents-0.5.0...@launchdarkly/ai-langchain-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
* **AIC-3439:** let wildcard handlers accept only named providers
([#111](#111))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))

### Features

* **AIC-3439:** let wildcard handlers accept only named providers
([#111](#111))
([9371975](9371975))
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
([8dbe2ec](8dbe2ec))
* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **AIC-3592:** make native LangGraph hand-offs complete
([#192](#192))
([025f2ce](025f2ce))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))
([c6c00fc](c6c00fc))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-langchain-messages: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-langchain-messages-0.5.0...@launchdarkly/ai-langchain-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
* **AIC-3439:** let wildcard handlers accept only named providers
([#111](#111))
* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))

### Features

* **AIC-3439:** let wildcard handlers accept only named providers
([#111](#111))
([9371975](9371975))
* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))
([15a0d37](15a0d37))
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
([8dbe2ec](8dbe2ec))
* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **AIC-3726:** realign three usage IDs with the 1.0 factory names
([#197](#197))
([fc83c7a](fc83c7a))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-litellm-agents: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-litellm-agents-0.2.0...@launchdarkly/ai-litellm-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.

### Features

* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-litellm-messages: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-litellm-messages-0.2.0...@launchdarkly/ai-litellm-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **SEC-9507:** enable Claude native tools only when the active
variation attaches them
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))

### Features

* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))
([c6c00fc](c6c00fc))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))
* **SEC-9507:** dispatch litellm-messages tool calls only to tools
offered for the request
([6926e8a](6926e8a))
* **SEC-9507:** enable Claude native tools only when the active
variation attaches them
([6926e8a](6926e8a))
* **SEC-9507:** pass handlers only the tools attached to the active
variation
([6926e8a](6926e8a))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-node: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-node-0.4.0...@launchdarkly/ai-node-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **evaluations:** promote Evaluations from Code to core
([#181](#181))
* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#172](#172))

### Features

* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))
([15a0d37](15a0d37))
* **evaluations:** promote Evaluations from Code to core
([#181](#181))
([676a2ed](676a2ed))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#172](#172))
([d3e7c5f](d3e7c5f))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-openai-agents: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-openai-agents-0.5.0...@launchdarkly/ai-openai-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
* **AIC-3687:** rename createOpenAIAgentHandler to
createOpenAIAgentsHandler
([#174](#174))

### Features

* **AIC-3687:** rename createOpenAIAgentHandler to
createOpenAIAgentsHandler
([#174](#174))
([cfba4d2](cfba4d2))
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
([8dbe2ec](8dbe2ec))
* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **AIC-3726:** realign three usage IDs with the 1.0 factory names
([#197](#197))
([fc83c7a](fc83c7a))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-openai-messages: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-openai-messages-0.5.0...@launchdarkly/ai-openai-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))

### Features

* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))
([15a0d37](15a0d37))
* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))
([c6c00fc](c6c00fc))
* **AIC-3726:** realign three usage IDs with the 1.0 factory names
([#197](#197))
([fc83c7a](fc83c7a))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-otel: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-otel-0.3.0...@launchdarkly/ai-otel-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** spans carry launchdarkly.project_id instead of
highlight.project_id

### Bug Fixes

* **client:** stamp launchdarkly.project_id on the telemetry resource
([#176](#176))
([93fb412](93fb412))
</details>

<details><summary>@launchdarkly/ai-server: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-server-0.5.0...@launchdarkly/ai-server-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
* **AIC-3439:** let wildcard handlers accept only named providers
([#111](#111))
* **SEC-9507:** enable Claude native tools only when the active
variation attaches them
* **evaluations:** export each offline row as one trace
([#175](#175))
* **evaluations:** promote Evaluations from Code to core
([#181](#181))
* **evaluations:** remove default pass rate threshold
([#184](#184))
* **client:** spans carry launchdarkly.project_id instead of
highlight.project_id
* **AIC-3687:** rename createOpenAIAgentHandler to
createOpenAIAgentsHandler
([#174](#174))
* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#172](#172))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))

### Features

* **AIC-3439:** let wildcard handlers accept only named providers
([#111](#111))
([9371975](9371975))
* **AIC-3686:** rename the LangChain and OpenAI messages factories to
*MessagesHandler
([#173](#173))
([15a0d37](15a0d37))
* **AIC-3687:** rename createOpenAIAgentHandler to
createOpenAIAgentsHandler
([#174](#174))
([cfba4d2](cfba4d2))
* **client:** add result variant and value to the feature_flag span
event ([#186](#186))
([8dbe2ec](8dbe2ec))
* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))
* **client:** point judge spans at the run they graded
([#200](#200))
([ba9c936](ba9c936))
* **evaluations:** export each offline row as one trace
([#175](#175))
([05a7eb1](05a7eb1))
* **evaluations:** promote Evaluations from Code to core
([#181](#181))
([676a2ed](676a2ed))
* **evaluations:** remove default pass rate threshold
([#184](#184))
([f3a3e37](f3a3e37))
* **skills:** give Claude Agents runs the skills attached to their
variation ([#136](#136))
([df16ba0](df16ba0))
* **skills:** rename FDv2SkillStore to LaunchDarklySkillStore
([#172](#172))
([d3e7c5f](d3e7c5f))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **AIC-3598:** type toolHandlers on the handler contract; declare
@langchain/anthropic
([#170](#170))
([c6c00fc](c6c00fc))
* **AIC-3601:** stop multi-edge routing text from asking a router for a
final answer
([#177](#177))
([10cce54](10cce54))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))
* **client:** stamp launchdarkly.project_id on the telemetry resource
([#176](#176))
([93fb412](93fb412))
* **evaluations:** update stale test import
([#189](#189))
([f4d8083](f4d8083))
* **evaluations:** warn once when a scorer returns an invalid score
([#199](#199))
([f43c888](f43c888))
* **graph:** report a node's own judge scores on its node_done stream
event ([#182](#182))
([1230f02](1230f02))
* **SEC-9507:** dispatch litellm-messages tool calls only to tools
offered for the request
([6926e8a](6926e8a))
* **SEC-9507:** enable Claude native tools only when the active
variation attaches them
([6926e8a](6926e8a))
* **SEC-9507:** pass handlers only the tools attached to the active
variation
([6926e8a](6926e8a))
</details>

<details><summary>@launchdarkly/ai-typesafe: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-typesafe-0.2.0...@launchdarkly/ai-typesafe-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.

### Features

* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-vercel-agents: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-vercel-agents-0.3.0...@launchdarkly/ai-vercel-agents-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.

### Features

* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

<details><summary>@launchdarkly/ai-vercel-messages: 1.0.0</summary>

##
[1.0.0](https://github.com/launchdarkly/js-ai-sdk/compare/@launchdarkly/ai-vercel-messages-0.3.0...@launchdarkly/ai-vercel-messages-1.0.0)
(2026-10-30)


### ⚠ BREAKING CHANGES

* **client:** conversation content is now captured on spans by default.
To keep it off, call configure({ options: { captureContent: false } })
once at startup.
* **client:** createHandler returns a new wrapper function rather than
adding providesFor to the function you pass and returning that same
function. Use the handler createHandler returns; the function you passed
in no longer carries providesFor.

### Features

* **client:** capture conversation content on spans by default and add
configure()
([d9c7fc3](d9c7fc3))


### Bug Fixes

* **AIC-3573:** never send a NativeTool to the model as a function tool
([#194](#194))
([ec43b85](ec43b85))
* **client:** return a new handler from createHandler instead of
changing the function passed in
([d9c7fc3](d9c7fc3))


### Dependencies

* The following workspace dependencies were updated
  * dependencies
    * @launchdarkly/ai-server bumped from ^0.5.0 to ^1.0.0
</details>

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Overview**
> This **release-please** PR cuts **1.0.0** for every workspace package
(`@launchdarkly/ai-server`, `@launchdarkly/ai-node`, provider adapters,
`@launchdarkly/ai-otel`, `@launchdarkly/ai-typesafe`) by updating
`.release-please-manifest.json`, each `package.json` / `src/version.ts`,
and adding **1.0.0** changelog sections. Provider packages bump their
`@launchdarkly/ai-server` dependency to **^1.0.0**.
> 
> The release notes bundled here flag **breaking** upgrades integrators
must handle: **`configure()`** with **conversation content on spans by
default** (opt out via `captureContent: false`); **`createHandler`** now
returns a **new wrapper** instead of mutating the passed function;
renamed factories (**`*MessagesHandler`**,
**`createOpenAIAgentsHandler`**); **`LaunchDarklySkillStore`** (was
`FDv2SkillStore`); **Evaluations promoted to core** with offline
export/trace and threshold behavior changes; telemetry
**`launchdarkly.project_id`** (was `highlight.project_id`); richer
**`feature_flag`** span events; and **SEC-9507** tool scoping (native
tools and handlers only see tools on the active variation).
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
f87c9a6. 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: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.

4 participants