Skip to content

Commit 2667a1e

Browse files
jsonbaileyclaude
andcommitted
feat!: remove deprecated AIProvider methods and create*/init* aliases (AIC-2388)
Now that all provider packages (#1337 OpenAI, #1338 LangChain, #1339 Vercel) have migrated to the Runner protocol, the deprecated compatibility surface on the umbrella `feat/next-ai-release` branch can be removed. BREAKING CHANGE: Removes the following deprecated APIs: AIProvider abstract base class: - `invokeModel()` and `invokeStructuredModel()` instance methods - `static create()` factory method - `protected logger` field on the constructor (provider subclasses now declare their own private `_logger` field) LDAIClient deprecated method aliases: - `config()` (use `completionConfig`) - `agent()` (use `agentConfig`) - `agents()` (use `agentConfigs`) - `createChat()` and `initChat()` (use `createModel`) Public types: - `StructuredResponse` (only consumed by the removed `invokeStructuredModel` method) Type narrowing on `AIProvider` and `RunnerFactory`: - `createModel(config: LDAICompletionConfig | LDAIJudgeConfig)` - `createAgent(config: LDAIAgentConfig)` - `createAgentGraph(graphDef: AgentGraphDefinition)` Previously these accepted the wider `LDAIConfigKind` union; the new signatures mirror what the provider subclasses already declared and surface mode mismatches at the type level. Also updates README examples to use `createModel`/`run()` and removes the stale `_LegacyProviderAdapter` references in `RunnerFactory` doc comments. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 70e4eb9 commit 2667a1e

16 files changed

Lines changed: 121 additions & 333 deletions

File tree

packages/ai-providers/server-ai-langchain/README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
## Quick Setup
2222

23-
This package provides LangChain integration for the LaunchDarkly AI SDK. The simplest way to use it is with the LaunchDarkly AI SDK's `initChat` method:
23+
This package provides LangChain integration for the LaunchDarkly AI SDK. The simplest way to use it is with the LaunchDarkly AI SDK's `createModel` method:
2424

2525
1. Install the required packages:
2626

@@ -30,7 +30,7 @@ npm install @launchdarkly/server-sdk-ai @launchdarkly/server-sdk-ai-langchain --
3030
yarn add @launchdarkly/server-sdk-ai @launchdarkly/server-sdk-ai-langchain
3131
```
3232

33-
2. Create a chat session and use it:
33+
2. Create a managed model and run it:
3434

3535
```typescript
3636
import { init } from '@launchdarkly/node-server-sdk';
@@ -40,17 +40,17 @@ import { initAi } from '@launchdarkly/server-sdk-ai';
4040
const ldClient = init(sdkKey);
4141
const aiClient = initAi(ldClient);
4242

43-
// Create a chat session
44-
const defaultConfig = {
45-
enabled: true,
43+
// Create a managed model
44+
const defaultConfig = {
45+
enabled: true,
4646
model: { name: 'gpt-4' },
4747
provider: { name: 'openai' }
4848
};
49-
const chat = await aiClient.initChat('my-chat-config', context, defaultConfig);
49+
const model = await aiClient.createModel('my-chat-config', context, defaultConfig);
5050

51-
if (chat) {
52-
const response = await chat.invoke('What is the capital of France?');
53-
console.log(response.message.content);
51+
if (model) {
52+
const result = await model.run('What is the capital of France?');
53+
console.log(result.content);
5454
}
5555
```
5656

packages/ai-providers/server-ai-langchain/src/LangChainRunnerFactory.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ let instrumentPromise: Promise<void> | undefined;
1818
* Factory for creating LangChain runners (chat completion and agent).
1919
*/
2020
export class LangChainRunnerFactory extends AIProvider {
21+
private _logger?: LDLogger;
22+
2123
constructor(logger?: LDLogger) {
22-
super(logger);
24+
super();
25+
this._logger = logger;
2326
// eslint-disable-next-line no-underscore-dangle
2427
LangChainRunnerFactory._ensureInstrumented(logger).catch(() => {});
2528
}
@@ -29,7 +32,7 @@ export class LangChainRunnerFactory extends AIProvider {
2932
*/
3033
async createModel(config: LDAICompletionConfig): Promise<LangChainModelRunner> {
3134
const llm = await createLangChainModel(config);
32-
return new LangChainModelRunner(llm, config, this.logger);
35+
return new LangChainModelRunner(llm, config, this._logger);
3336
}
3437

3538
/**
@@ -51,7 +54,7 @@ export class LangChainRunnerFactory extends AIProvider {
5154
};
5255
const llm = await createLangChainModel(configForModel);
5356

54-
const lcTools = buildStructuredTools(toolDefinitions, tools ?? {}, this.logger);
57+
const lcTools = buildStructuredTools(toolDefinitions, tools ?? {}, this._logger);
5558
const instructions = config.instructions ?? '';
5659

5760
const agent = createAgent({
@@ -60,7 +63,7 @@ export class LangChainRunnerFactory extends AIProvider {
6063
systemPrompt: instructions || undefined,
6164
});
6265

63-
return new LangChainAgentRunner(agent as any, this.logger);
66+
return new LangChainAgentRunner(agent as any, this._logger);
6467
}
6568

6669
/**

packages/ai-providers/server-ai-openai/README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@
2323

2424
## Quick Setup
2525

26-
This package provides OpenAI integration for the LaunchDarkly AI SDK. The simplest way to use it is with the LaunchDarkly AI SDK's `initChat` method:
26+
This package provides OpenAI integration for the LaunchDarkly AI SDK. The simplest way to use it is with the LaunchDarkly AI SDK's `createModel` method:
2727

2828
1. Install the required packages:
2929

3030
```shell
3131
npm install @launchdarkly/server-sdk-ai @launchdarkly/server-sdk-ai-openai --save
3232
```
3333

34-
2. Create a chat session and use it:
34+
2. Create a managed model and run it:
3535

3636
```typescript
3737
import { init } from '@launchdarkly/node-server-sdk';
@@ -41,17 +41,17 @@ import { initAi } from '@launchdarkly/server-sdk-ai';
4141
const ldClient = init(sdkKey);
4242
const aiClient = initAi(ldClient);
4343

44-
// Create a chat session
45-
const defaultConfig = {
46-
enabled: true,
44+
// Create a managed model
45+
const defaultConfig = {
46+
enabled: true,
4747
model: { name: 'gpt-4' },
4848
provider: { name: 'openai' }
4949
};
50-
const chat = await aiClient.initChat('my-chat-config', context, defaultConfig);
50+
const model = await aiClient.createModel('my-chat-config', context, defaultConfig);
5151

52-
if (chat) {
53-
const response = await chat.invoke("What is the capital of France?");
54-
console.log(response.message.content);
52+
if (model) {
53+
const result = await model.run('What is the capital of France?');
54+
console.log(result.content);
5555
}
5656
```
5757

packages/ai-providers/server-ai-openai/src/OpenAIRunnerFactory.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ let instrumentPromise: Promise<void> | undefined;
1717
*/
1818
export class OpenAIRunnerFactory extends AIProvider {
1919
private _client: OpenAI;
20+
private _logger?: LDLogger;
2021

2122
constructor(logger?: LDLogger) {
22-
super(logger);
23+
super();
24+
this._logger = logger;
2325
this._client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });
2426
// Fire-and-forget: OTel instrumentation is optional and must not block construction.
2527
// eslint-disable-next-line no-underscore-dangle
@@ -30,7 +32,7 @@ export class OpenAIRunnerFactory extends AIProvider {
3032
* Create a model runner from a completion AI configuration.
3133
*/
3234
async createModel(config: LDAICompletionConfig): Promise<OpenAIModelRunner> {
33-
return new OpenAIModelRunner(this._client, config, this.logger);
35+
return new OpenAIModelRunner(this._client, config, this._logger);
3436
}
3537

3638
/**
@@ -67,7 +69,12 @@ export class OpenAIRunnerFactory extends AIProvider {
6769
const parameters = mapParameterKeys({ ...(config.model?.parameters ?? {}) });
6870
delete parameters.tools;
6971

70-
const { agentTools, toolNameMap } = buildAgentTools(toolHelper, configTools, registry, this.logger);
72+
const { agentTools, toolNameMap } = buildAgentTools(
73+
toolHelper,
74+
configTools,
75+
registry,
76+
this._logger,
77+
);
7178
const agent = new Agent({
7279
name: 'ldai-agent',
7380
instructions: config.instructions || undefined,
@@ -76,7 +83,7 @@ export class OpenAIRunnerFactory extends AIProvider {
7683
modelSettings: parameters,
7784
});
7885

79-
return new OpenAIAgentRunner(agent, agentRun, toolNameMap, this.logger);
86+
return new OpenAIAgentRunner(agent, agentRun, toolNameMap, this._logger);
8087
}
8188

8289
/**

packages/ai-providers/server-ai-vercel/README.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020

2121
## Quick Setup
2222

23-
This package provides Vercel AI SDK integration for the LaunchDarkly AI SDK. The simplest way to use it is with the LaunchDarkly AI SDK's `initChat` method:
23+
This package provides Vercel AI SDK integration for the LaunchDarkly AI SDK. The simplest way to use it is with the LaunchDarkly AI SDK's `createModel` method:
2424

2525
1. Install the required packages:
2626

@@ -30,7 +30,7 @@ npm install @launchdarkly/server-sdk-ai @launchdarkly/server-sdk-ai-vercel --sav
3030
yarn add @launchdarkly/server-sdk-ai @launchdarkly/server-sdk-ai-vercel
3131
```
3232

33-
2. Create a chat session and use it:
33+
2. Create a managed model and run it:
3434

3535
```typescript
3636
import { init } from '@launchdarkly/node-server-sdk';
@@ -40,17 +40,17 @@ import { initAi } from '@launchdarkly/server-sdk-ai';
4040
const ldClient = init(sdkKey);
4141
const aiClient = initAi(ldClient);
4242

43-
// Create a chat session
44-
const defaultConfig = {
45-
enabled: true,
43+
// Create a managed model
44+
const defaultConfig = {
45+
enabled: true,
4646
model: { name: 'gpt-4' },
4747
provider: { name: 'openai' }
4848
};
49-
const chat = await aiClient.initChat('my-chat-config', context, defaultConfig);
49+
const model = await aiClient.createModel('my-chat-config', context, defaultConfig);
5050

51-
if (chat) {
52-
const response = await chat.invoke('What is the capital of France?');
53-
console.log(response.message.content);
51+
if (model) {
52+
const result = await model.run('What is the capital of France?');
53+
console.log(result.content);
5454
}
5555
```
5656

packages/ai-providers/server-ai-vercel/src/VercelRunnerFactory.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,11 @@ import { VercelModelRunner } from './VercelModelRunner';
1515
* framework.
1616
*/
1717
export class VercelRunnerFactory extends AIProvider {
18+
private _logger?: LDLogger;
19+
1820
constructor(logger?: LDLogger) {
19-
super(logger);
21+
super();
22+
this._logger = logger;
2023
}
2124

2225
/**
@@ -25,7 +28,7 @@ export class VercelRunnerFactory extends AIProvider {
2528
async createModel(config: LDAICompletionConfig): Promise<VercelModelRunner> {
2629
const model = await VercelRunnerFactory.createVercelModel(config);
2730
const parameters = VercelRunnerFactory.mapParameters(config.model?.parameters);
28-
return new VercelModelRunner(model, config, parameters, this.logger);
31+
return new VercelModelRunner(model, config, parameters, this._logger);
2932
}
3033

3134
/**

packages/sdk/server-ai/README.md

Lines changed: 13 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -79,37 +79,34 @@ if (aiConfig.enabled) {
7979
}
8080
```
8181

82-
## TrackedChat for Conversational AI
82+
## ManagedModel for Tracked Model Invocations
8383

84-
`TrackedChat` provides a high-level interface for conversational AI with automatic conversation management and metrics tracking:
84+
`ManagedModel` provides a high-level interface for invoking AI models with automatic metrics tracking and judge evaluation:
8585

8686
- Automatically configures models based on AI configuration
87-
- Maintains conversation history across multiple interactions
8887
- Automatically tracks token usage, latency, and success rates
88+
- Runs configured judges asynchronously and reports their results
8989
- Works with any supported AI provider (see [AI Providers](https://github.com/launchdarkly/js-core#ai-providers) for available packages)
9090

91-
### Using TrackedChat
91+
### Using ManagedModel
9292

9393
```typescript
9494
// Use the same defaultConfig from the retrieval section above
95-
const chat = await aiClient.createChat(
95+
const model = await aiClient.createModel(
9696
'customer-support-chat',
9797
context,
9898
defaultConfig,
9999
{ customerName: 'John' }
100100
);
101101

102-
if (chat) {
103-
// Simple conversation flow - metrics are automatically tracked by invoke()
104-
const response1 = await chat.invoke('I need help with my order');
105-
console.log(response1.message.content);
106-
107-
const response2 = await chat.invoke("What's the status?");
108-
console.log(response2.message.content);
109-
110-
// Access conversation history
111-
const messages = chat.getMessages();
112-
console.log(`Conversation has ${messages.length} messages`);
102+
if (model) {
103+
// Metrics are automatically tracked by run()
104+
const result = await model.run('I need help with my order');
105+
console.log(result.content);
106+
107+
// Judge evaluations run asynchronously; await if you need their results
108+
const evals = await result.evaluations;
109+
console.log('Judge results:', evals);
113110
}
114111
```
115112

packages/sdk/server-ai/__tests__/LDAIClientImpl.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ describe('createJudge method', () => {
634634

635635
beforeEach(() => {
636636
mockProvider = {
637-
invokeStructuredModel: jest.fn(),
637+
run: jest.fn(),
638638
};
639639

640640
mockJudge = {

packages/sdk/server-ai/__tests__/RunnerFactory.test.ts

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
import { LDAIConfigKind } from '../src/api/config/types';
1+
import {
2+
LDAIAgentConfig,
3+
LDAICompletionConfig,
4+
} from '../src/api/config/types';
25
import { AIProvider, ToolRegistry } from '../src/api/providers/AIProvider';
36
import { AgentGraphRunner, Runner } from '../src/api/providers/Runner';
47
import { RunnerFactory, SupportedAIProvider } from '../src/api/providers/RunnerFactory';
@@ -7,14 +10,23 @@ import { RunnerFactory, SupportedAIProvider } from '../src/api/providers/RunnerF
710
// Helpers
811
// ---------------------------------------------------------------------------
912

10-
const makeConfig = (providerName: string): LDAIConfigKind =>
13+
const makeConfig = (providerName: string): LDAICompletionConfig =>
1114
({
1215
key: 'test-config',
1316
enabled: true,
1417
provider: { name: providerName },
1518
createTracker: () => ({}) as any,
1619
evaluator: {} as any,
17-
}) as unknown as LDAIConfigKind;
20+
}) as unknown as LDAICompletionConfig;
21+
22+
const makeAgentConfig = (providerName: string): LDAIAgentConfig =>
23+
({
24+
key: 'test-agent-config',
25+
enabled: true,
26+
provider: { name: providerName },
27+
createTracker: () => ({}) as any,
28+
evaluator: {} as any,
29+
}) as unknown as LDAIAgentConfig;
1830

1931
const makeRunner = (): Runner => ({ run: jest.fn() });
2032
const makeGraphRunner = (): AgentGraphRunner => ({ run: jest.fn() });
@@ -162,7 +174,7 @@ describe('RunnerFactory.createAgent', () => {
162174

163175
jest.spyOn(RunnerFactory as any, '_getProviderFactory').mockResolvedValue(mockFactory);
164176

165-
const result = await RunnerFactory.createAgent(makeConfig('openai'), tools);
177+
const result = await RunnerFactory.createAgent(makeAgentConfig('openai'), tools);
166178

167179
expect(result).toBe(runner);
168180
expect(mockFactory.createAgent).toHaveBeenCalledWith(
@@ -177,7 +189,11 @@ describe('RunnerFactory.createAgent', () => {
177189

178190
jest.spyOn(RunnerFactory as any, '_getProviderFactory').mockResolvedValue(undefined);
179191

180-
const result = await RunnerFactory.createAgent(makeConfig('openai'), undefined, logger as any);
192+
const result = await RunnerFactory.createAgent(
193+
makeAgentConfig('openai'),
194+
undefined,
195+
logger as any,
196+
);
181197

182198
expect(result).toBeUndefined();
183199
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('not supported'));
@@ -243,7 +259,7 @@ describe('AIProvider default factory methods', () => {
243259

244260
it('createAgent returns undefined by default', async () => {
245261
const provider = new ConcreteProvider();
246-
const result = await provider.createAgent(makeConfig('openai'));
262+
const result = await provider.createAgent(makeAgentConfig('openai'));
247263
expect(result).toBeUndefined();
248264
});
249265

@@ -252,25 +268,4 @@ describe('AIProvider default factory methods', () => {
252268
const result = await provider.createAgentGraph({} as any);
253269
expect(result).toBeUndefined();
254270
});
255-
256-
it('createModel warns when not overridden', async () => {
257-
const warnSpy = jest.fn();
258-
const provider = new ConcreteProvider({ warn: warnSpy } as any);
259-
await provider.createModel(makeConfig('openai'));
260-
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('createModel not implemented'));
261-
});
262-
263-
it('createAgent warns when not overridden', async () => {
264-
const warnSpy = jest.fn();
265-
const provider = new ConcreteProvider({ warn: warnSpy } as any);
266-
await provider.createAgent(makeConfig('openai'));
267-
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('createAgent not implemented'));
268-
});
269-
270-
it('createAgentGraph warns when not overridden', async () => {
271-
const warnSpy = jest.fn();
272-
const provider = new ConcreteProvider({ warn: warnSpy } as any);
273-
await provider.createAgentGraph({} as any);
274-
expect(warnSpy).toHaveBeenCalledWith(expect.stringContaining('createAgentGraph not implemented'));
275-
});
276271
});

packages/sdk/server-ai/examples/openai-observability/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Provider-Specific Observability Example (OpenAI)
22

3-
This example shows how to use the LaunchDarkly observability plugin when calling an AI provider directly — without the higher-level `createChat` abstraction. It uses OpenAI as the provider, but the same pattern applies to any provider (Bedrock, Anthropic, Vercel AI SDK, etc.).
3+
This example shows how to use the LaunchDarkly observability plugin when calling an AI provider directly — without the higher-level `createModel` abstraction. It uses OpenAI as the provider, but the same pattern applies to any provider (Bedrock, Anthropic, Vercel AI SDK, etc.).
44

55
## How it works
66

0 commit comments

Comments
 (0)