@launchdarkly/server-sdk-ai 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,129 +1,110 @@
1
1
  // src/LDAIClientImpl.ts
2
- import Mustache2 from "mustache";
2
+ import Mustache from "mustache";
3
3
  import { randomUUID } from "crypto";
4
4
 
5
- // src/api/chat/TrackedChat.ts
6
- var TrackedChat = class {
7
- constructor(aiConfig, provider, judges = {}, _logger) {
8
- this.aiConfig = aiConfig;
9
- this.provider = provider;
10
- this.judges = judges;
5
+ // src/api/ManagedAgent.ts
6
+ var ManagedAgent = class {
7
+ constructor(aiAgentConfig, runner, _logger) {
8
+ this.aiAgentConfig = aiAgentConfig;
9
+ this.runner = runner;
11
10
  this._logger = _logger;
12
- this.messages = [];
13
11
  }
14
12
  /**
15
- * Invoke the chat model with a prompt string.
16
- * This method handles conversation management and tracking, delegating to the provider's invokeModel method.
13
+ * Invoke the agent with a prompt string and return a ManagedResult.
14
+ *
15
+ * `run()` resolves before `ManagedResult.evaluations` resolves. Awaiting
16
+ * `evaluations` guarantees both judge evaluation and tracker.trackJudgeResult()
17
+ * are complete.
18
+ *
19
+ * @param prompt The user input to send to the agent.
20
+ * @returns Promise resolving to ManagedResult (before evaluations settle).
17
21
  */
18
- async invoke(prompt) {
19
- const tracker = this.aiConfig.createTracker();
20
- const userMessage = {
21
- role: "user",
22
- content: prompt
23
- };
24
- this.messages.push(userMessage);
25
- const configMessages = this.aiConfig.messages || [];
26
- const allMessages = [...configMessages, ...this.messages];
27
- const response = await tracker.trackMetricsOf(
28
- (result) => result.metrics,
29
- () => this.provider.invokeModel(allMessages)
22
+ async run(prompt) {
23
+ const tracker = this.aiAgentConfig.createTracker();
24
+ const result = await tracker.trackMetricsOf(
25
+ (r) => r.metrics,
26
+ () => this.runner.run(prompt)
30
27
  );
31
- if (this.aiConfig.judgeConfiguration?.judges && this.aiConfig.judgeConfiguration.judges.length > 0) {
32
- response.evaluations = this._evaluateWithJudges(this.messages, response).then(
33
- (evaluations) => {
34
- evaluations.forEach((judgeResult) => {
35
- tracker.trackJudgeResult(judgeResult);
36
- });
37
- return evaluations;
28
+ const metrics = tracker.getSummary();
29
+ const output = result.content;
30
+ const evaluations = this.aiAgentConfig.evaluator.evaluate(prompt, output).then((results) => {
31
+ results.forEach((judgeResult) => {
32
+ if (!judgeResult.sampled) {
33
+ return;
38
34
  }
39
- );
40
- }
41
- this.messages.push(response.message);
42
- return response;
43
- }
44
- /**
45
- * Evaluates the response with all configured judges.
46
- * Returns a promise that resolves to an array of evaluation results.
47
- *
48
- * @param messages Array of messages representing the conversation history
49
- * @param response The AI response to be evaluated
50
- * @returns Promise resolving to array of judge evaluation results
51
- */
52
- async _evaluateWithJudges(messages, response) {
53
- const judgeConfigs = this.aiConfig.judgeConfiguration.judges;
54
- const evaluationPromises = judgeConfigs.map(async (judgeConfig) => {
55
- const judge = this.judges[judgeConfig.key];
56
- if (!judge) {
57
- this._logger?.warn(
58
- `Judge configuration is not enabled for ${judgeConfig.key} in ${this.aiConfig.key}`
59
- );
60
- const result = {
61
- success: false,
62
- sampled: true,
63
- errorMessage: `Judge configuration is not enabled for ${judgeConfig.key}`
64
- };
65
- return result;
66
- }
67
- return judge.evaluateMessages(messages, response, judgeConfig.samplingRate);
68
- });
69
- const results = await Promise.allSettled(evaluationPromises);
70
- return results.map((settled) => {
71
- if (settled.status === "fulfilled") {
72
- return settled.value;
73
- }
74
- const result = {
75
- success: false,
76
- sampled: true,
77
- errorMessage: "Judge evaluation failed"
78
- };
79
- return result;
35
+ tracker.trackJudgeResult(judgeResult);
36
+ });
37
+ return results;
38
+ }).catch((err) => {
39
+ this._logger?.warn("Judge evaluation failed unexpectedly:", err);
40
+ return [];
80
41
  });
42
+ return {
43
+ content: output,
44
+ metrics,
45
+ raw: result.raw,
46
+ parsed: result.parsed,
47
+ evaluations
48
+ };
81
49
  }
82
50
  /**
83
- * Get the underlying AI configuration used to initialize this TrackedChat.
51
+ * Get the underlying AI agent configuration used to initialize this ManagedAgent.
84
52
  */
85
53
  getConfig() {
86
- return this.aiConfig;
54
+ return this.aiAgentConfig;
87
55
  }
88
- /**
89
- * Get the underlying AI provider instance.
90
- * This provides direct access to the provider for advanced use cases.
91
- */
92
- getProvider() {
93
- return this.provider;
94
- }
95
- /**
96
- * Get the judges associated with this TrackedChat.
97
- * Returns a record of judge instances keyed by their configuration keys.
98
- */
99
- getJudges() {
100
- return this.judges;
56
+ };
57
+
58
+ // src/api/ManagedModel.ts
59
+ var ManagedModel = class {
60
+ constructor(aiConfig, runner, _logger) {
61
+ this.aiConfig = aiConfig;
62
+ this.runner = runner;
63
+ this._logger = _logger;
101
64
  }
102
65
  /**
103
- * Append messages to the conversation history.
104
- * Adds messages to the conversation history without invoking the model,
105
- * which is useful for managing multi-turn conversations or injecting context.
66
+ * Invoke the model with a prompt string and return a ManagedResult.
106
67
  *
107
- * @param messages Array of messages to append to the conversation history
68
+ * `run()` resolves before `ManagedResult.evaluations` resolves. Awaiting
69
+ * `evaluations` guarantees both judge evaluation and tracker.trackJudgeResult()
70
+ * are complete.
71
+ *
72
+ * @param prompt The user input to send to the model.
73
+ * @returns Promise resolving to ManagedResult (before evaluations settle).
108
74
  */
109
- appendMessages(messages) {
110
- this.messages.push(...messages);
75
+ async run(prompt) {
76
+ const tracker = this.aiConfig.createTracker();
77
+ const result = await tracker.trackMetricsOf(
78
+ (r) => r.metrics,
79
+ () => this.runner.run(prompt)
80
+ );
81
+ const metrics = tracker.getSummary();
82
+ const output = result.content;
83
+ const evaluations = this.aiConfig.evaluator.evaluate(prompt, output).then((results) => {
84
+ results.forEach((judgeResult) => {
85
+ if (!judgeResult.sampled) {
86
+ return;
87
+ }
88
+ tracker.trackJudgeResult(judgeResult);
89
+ });
90
+ return results;
91
+ }).catch((err) => {
92
+ this._logger?.warn("Judge evaluation failed unexpectedly:", err);
93
+ return [];
94
+ });
95
+ return {
96
+ content: output,
97
+ metrics,
98
+ raw: result.raw,
99
+ parsed: result.parsed,
100
+ evaluations
101
+ };
111
102
  }
112
103
  /**
113
- * Get all messages in the conversation history.
114
- *
115
- * @param includeConfigMessages Whether to include the config messages from the AIConfig.
116
- * Defaults to false.
117
- * @returns Array of messages. When includeConfigMessages is true, returns both config
118
- * messages and conversation history with config messages prepended. When false,
119
- * returns only the conversation history messages.
104
+ * Get the underlying AI configuration used to initialize this ManagedModel.
120
105
  */
121
- getMessages(includeConfigMessages = false) {
122
- if (includeConfigMessages) {
123
- const configMessages = this.aiConfig.messages || [];
124
- return [...configMessages, ...this.messages];
125
- }
126
- return [...this.messages];
106
+ getConfig() {
107
+ return this.aiConfig;
127
108
  }
128
109
  };
129
110
 
@@ -175,46 +156,52 @@ var LDAIConfigUtils = class {
175
156
  * @param key The configuration key
176
157
  * @param flagValue The flag value from LaunchDarkly
177
158
  * @param trackerFactory A factory function that creates a new tracker for each execution
159
+ * @param evaluator The evaluator to attach to completion and agent configs
178
160
  * @returns The appropriate AI configuration type
179
161
  */
180
- static fromFlagValue(key, flagValue, trackerFactory) {
162
+ static fromFlagValue(key, flagValue, trackerFactory, evaluator) {
181
163
  const flagValueMode = flagValue._ldMeta?.mode;
182
164
  switch (flagValueMode) {
183
165
  case "agent":
184
- return this.toAgentConfig(key, flagValue, trackerFactory);
166
+ return this.toAgentConfig(key, flagValue, trackerFactory, evaluator);
185
167
  case "judge":
186
168
  return this.toJudgeConfig(key, flagValue, trackerFactory);
187
169
  case "completion":
188
170
  default:
189
- return this.toCompletionConfig(key, flagValue, trackerFactory);
171
+ return this.toCompletionConfig(key, flagValue, trackerFactory, evaluator);
190
172
  }
191
173
  }
192
174
  /**
193
175
  * Creates a disabled configuration of the specified mode.
194
176
  *
177
+ * @param key The configuration key
195
178
  * @param mode The mode for the disabled config
179
+ * @param createTracker A factory function that creates a new tracker for each execution
180
+ * @param evaluator The evaluator to attach to completion and agent configs
196
181
  * @returns A disabled config of the appropriate type
197
182
  */
198
- static createDisabledConfig(key, mode) {
183
+ static createDisabledConfig(key, mode, createTracker, evaluator) {
199
184
  switch (mode) {
200
185
  case "agent":
201
186
  return {
202
187
  key,
203
188
  enabled: false,
204
- createTracker: void 0
189
+ createTracker,
190
+ evaluator
205
191
  };
206
192
  case "judge":
207
193
  return {
208
194
  key,
209
195
  enabled: false,
210
- createTracker: void 0
196
+ createTracker
211
197
  };
212
198
  case "completion":
213
199
  default:
214
200
  return {
215
201
  key,
216
202
  enabled: false,
217
- createTracker: void 0
203
+ createTracker,
204
+ evaluator
218
205
  };
219
206
  }
220
207
  }
@@ -256,12 +243,14 @@ var LDAIConfigUtils = class {
256
243
  * @param key The configuration key
257
244
  * @param flagValue The flag value from LaunchDarkly
258
245
  * @param trackerFactory A factory function that creates a new tracker for each execution
246
+ * @param evaluator The evaluator for this completion config
259
247
  * @returns A completion configuration
260
248
  */
261
- static toCompletionConfig(key, flagValue, trackerFactory) {
249
+ static toCompletionConfig(key, flagValue, trackerFactory, evaluator) {
262
250
  return {
263
251
  ...this._toBaseConfig(key, flagValue),
264
252
  createTracker: trackerFactory,
253
+ evaluator,
265
254
  messages: flagValue.messages,
266
255
  judgeConfiguration: flagValue.judgeConfiguration,
267
256
  tools: this._resolveTools(flagValue)
@@ -273,12 +262,14 @@ var LDAIConfigUtils = class {
273
262
  * @param key The configuration key
274
263
  * @param flagValue The flag value from LaunchDarkly
275
264
  * @param trackerFactory A factory function that creates a new tracker for each execution
265
+ * @param evaluator The evaluator for this agent config
276
266
  * @returns An agent configuration
277
267
  */
278
- static toAgentConfig(key, flagValue, trackerFactory) {
268
+ static toAgentConfig(key, flagValue, trackerFactory, evaluator) {
279
269
  return {
280
270
  ...this._toBaseConfig(key, flagValue),
281
271
  createTracker: trackerFactory,
272
+ evaluator,
282
273
  instructions: flagValue.instructions,
283
274
  judgeConfiguration: flagValue.judgeConfiguration,
284
275
  tools: this._resolveTools(flagValue)
@@ -543,8 +534,98 @@ var AgentGraphDefinition = class _AgentGraphDefinition {
543
534
  }
544
535
  };
545
536
 
537
+ // src/api/graph/ManagedAgentGraph.ts
538
+ var ManagedAgentGraph = class {
539
+ constructor(_graphDefinition, _logger) {
540
+ this._graphDefinition = _graphDefinition;
541
+ this._logger = _logger;
542
+ }
543
+ /**
544
+ * Runs the agent graph using the provided runner function and returns a ManagedGraphResult.
545
+ *
546
+ * The runner function receives the graph tracker and AgentGraphDefinition,
547
+ * executes the graph, and returns an AgentGraphRunnerResult.
548
+ *
549
+ * run() returns before ManagedGraphResult.evaluations resolves.
550
+ *
551
+ * @param runner Async function that executes the graph and returns AgentGraphRunnerResult.
552
+ * @returns ManagedGraphResult with LDAIGraphMetricSummary and evaluations promise.
553
+ */
554
+ async run(runner) {
555
+ const graphTracker = this._graphDefinition.createTracker();
556
+ const runnerResult = await runner(this._graphDefinition, graphTracker);
557
+ const metrics = {
558
+ success: runnerResult.metrics.success,
559
+ path: runnerResult.metrics.path,
560
+ durationMs: runnerResult.metrics.durationMs,
561
+ tokens: runnerResult.metrics.tokens,
562
+ nodeMetrics: this._trackNodeMetrics(runnerResult.metrics.nodeMetrics),
563
+ resumptionToken: graphTracker.resumptionToken
564
+ };
565
+ const evaluations = Promise.resolve([]);
566
+ return {
567
+ content: runnerResult.content,
568
+ metrics,
569
+ raw: runnerResult.raw,
570
+ evaluations
571
+ };
572
+ }
573
+ /**
574
+ * Converts per-node LDAIMetrics from the runner into LDAIMetricSummary by
575
+ * creating a per-node tracker, firing tracking events, and calling getSummary().
576
+ */
577
+ _trackNodeMetrics(nodeMetrics) {
578
+ const summaries = {};
579
+ for (const [nodeKey, metrics] of Object.entries(nodeMetrics)) {
580
+ const node = this._graphDefinition.getNode(nodeKey);
581
+ if (!node) {
582
+ this._logger?.warn(`ManagedAgentGraph: no node found for key "${nodeKey}", skipping metrics`);
583
+ continue;
584
+ }
585
+ const tracker = node.getConfig().createTracker();
586
+ if (metrics.tokens) {
587
+ tracker.trackTokens(metrics.tokens);
588
+ }
589
+ if (metrics.durationMs !== void 0) {
590
+ tracker.trackDuration(metrics.durationMs);
591
+ }
592
+ if (metrics.toolCalls?.length) {
593
+ tracker.trackToolCalls(metrics.toolCalls);
594
+ }
595
+ if (metrics.success) {
596
+ tracker.trackSuccess();
597
+ } else {
598
+ tracker.trackError();
599
+ }
600
+ summaries[nodeKey] = tracker.getSummary();
601
+ }
602
+ return summaries;
603
+ }
604
+ /**
605
+ * Returns the underlying AgentGraphDefinition.
606
+ */
607
+ getGraphDefinition() {
608
+ return this._graphDefinition;
609
+ }
610
+ };
611
+
612
+ // src/api/judge/Evaluator.ts
613
+ var Evaluator = class _Evaluator {
614
+ constructor(_judges) {
615
+ this._judges = _judges;
616
+ }
617
+ static noop() {
618
+ return new _Evaluator([]);
619
+ }
620
+ async evaluate(input, output) {
621
+ if (this._judges.length === 0) {
622
+ return [];
623
+ }
624
+ return Promise.all(this._judges.map((judge) => judge.evaluate(input, output)));
625
+ }
626
+ };
627
+
546
628
  // src/api/judge/Judge.ts
547
- import Mustache from "mustache";
548
629
  var EVALUATION_SCHEMA = {
549
630
  type: "object",
550
631
  properties: {
@@ -562,12 +643,25 @@ var EVALUATION_SCHEMA = {
562
643
  required: ["score", "reasoning"],
563
644
  additionalProperties: false
564
645
  };
646
+ function stripLegacyJudgeMessages(messages) {
647
+ return messages.filter(
648
+ (msg) => msg.role === "system" || !msg.content.includes("{{message_history}}") && !msg.content.includes("{{response_to_evaluate}}")
649
+ );
650
+ }
565
651
  var Judge = class {
566
- constructor(_aiConfig, _aiProvider, logger) {
652
+ constructor(_aiConfig, _runner, _sampleRate = 1, logger) {
567
653
  this._aiConfig = _aiConfig;
568
- this._aiProvider = _aiProvider;
654
+ this._runner = _runner;
655
+ this._sampleRate = _sampleRate;
569
656
  this._logger = logger;
570
657
  }
658
+ /**
659
+ * The default sampling rate baked in at construction. Used by `evaluate` /
660
+ * `evaluateMessages` when no per-call rate is supplied.
661
+ */
662
+ get sampleRate() {
663
+ return this._sampleRate;
664
+ }
571
665
  /**
572
666
  * Gets the evaluation metric key, prioritizing evaluationMetricKey over evaluationMetricKeys.
573
667
  * Falls back to the first valid (non-empty, non-whitespace) value in evaluationMetricKeys if evaluationMetricKey is not provided.
@@ -591,10 +685,13 @@ var Judge = class {
591
685
  *
592
686
  * @param input The input prompt or question that was provided to the AI
593
687
  * @param output The AI-generated response to be evaluated
594
- * @param samplingRate Sampling rate (0-1) to determine if evaluation should be processed (defaults to 1)
688
+ * @param samplingRate Sampling rate (0-1) to determine if evaluation should be processed.
689
+ * When omitted, the Judge's constructor-default rate is used. An explicit `0` overrides
690
+ * the default — only `undefined` falls through.
595
691
  * @returns Promise that resolves to evaluation results
596
692
  */
597
- async evaluate(input, output, samplingRate = 1) {
693
+ async evaluate(input, output, samplingRate) {
694
+ const effectiveRate = samplingRate ?? this._sampleRate;
598
695
  const result = {
599
696
  success: false,
600
697
  sampled: false,
@@ -612,26 +709,20 @@ var Judge = class {
612
709
  result.errorMessage = "Judge configuration is missing required evaluation metric key";
613
710
  return result;
614
711
  }
615
- if (!this._aiConfig.messages) {
616
- this._logger?.warn("Judge configuration must include messages", tracker.getTrackData());
617
- result.sampled = true;
618
- result.errorMessage = "Judge configuration must include messages";
619
- return result;
620
- }
621
- if (Math.random() > samplingRate) {
622
- this._logger?.debug(`Judge evaluation skipped due to sampling rate: ${samplingRate}`);
712
+ if (Math.random() > effectiveRate) {
713
+ this._logger?.debug(`Judge evaluation skipped due to sampling rate: ${effectiveRate}`);
623
714
  return result;
624
715
  }
625
716
  result.sampled = true;
626
- const messages = this._constructEvaluationMessages(input, output);
717
+ const evaluationInput = this._buildEvaluationInput(input, output);
627
718
  const response = await tracker.trackMetricsOf(
628
719
  (r) => r.metrics,
629
- () => this._aiProvider.invokeStructuredModel(messages, EVALUATION_SCHEMA)
720
+ () => this._runner.run(evaluationInput, EVALUATION_SCHEMA)
630
721
  );
631
- const evalResult = this._parseEvaluationResponse(response.data);
722
+ const evalResult = this._parseEvaluationResponse(response.parsed);
632
723
  if (!evalResult) {
633
724
  this._logger?.warn(
634
- `Could not parse evaluation response: ${JSON.stringify(response.data)}`,
725
+ `Could not parse evaluation response: ${JSON.stringify(response.parsed)}`,
635
726
  tracker.getTrackData()
636
727
  );
637
728
  return result;
@@ -655,10 +746,11 @@ var Judge = class {
655
746
  *
656
747
  * @param messages Array of messages representing the conversation history
657
748
  * @param response The AI response to be evaluated
658
- * @param samplingRatio Sampling ratio (0-1) to determine if evaluation should be processed (defaults to 1)
749
+ * @param samplingRatio Sampling ratio (0-1). When omitted, the Judge's
750
+ * constructor-default rate is used.
659
751
  * @returns Promise that resolves to evaluation results
660
752
  */
661
- async evaluateMessages(messages, response, samplingRatio = 1) {
753
+ async evaluateMessages(messages, response, samplingRatio) {
662
754
  const input = messages.length === 0 ? "" : messages.map((msg) => msg.content).join("\r\n");
663
755
  const output = response.message.content;
664
756
  return this.evaluate(input, output, samplingRatio);
@@ -670,29 +762,23 @@ var Judge = class {
670
762
  return this._aiConfig;
671
763
  }
672
764
  /**
673
- * Returns the AI provider used by this judge.
765
+ * Returns the runner used by this judge.
674
766
  */
675
- getProvider() {
676
- return this._aiProvider;
677
- }
678
- /**
679
- * Constructs evaluation messages by combining judge's config messages with input/output.
680
- */
681
- _constructEvaluationMessages(input, output) {
682
- const messages = this._aiConfig.messages.map((msg) => ({
683
- ...msg,
684
- content: this._interpolateMessage(msg.content, {
685
- message_history: input,
686
- response_to_evaluate: output
687
- })
688
- }));
689
- return messages;
767
+ getRunner() {
768
+ return this._runner;
690
769
  }
691
770
  /**
692
- * Interpolates message content with variables using Mustache templating.
771
+ * Builds the evaluation input string passed to the runner.
772
+ *
773
+ * Combines the original prompt and the response into a single, well-known
774
+ * format the judge model is expected to evaluate.
693
775
  */
694
- _interpolateMessage(content, variables) {
695
- return Mustache.render(content, variables, void 0, { escape: (item) => item });
776
+ _buildEvaluationInput(input, output) {
777
+ return `MESSAGE HISTORY:
778
+ ${input}
779
+
780
+ RESPONSE TO EVALUATE:
781
+ ${output}`;
696
782
  }
697
783
  /**
698
784
  * Parses the structured evaluation response. Expects top-level {score, reasoning}.
@@ -718,115 +804,101 @@ var Judge = class {
718
804
  // src/api/providers/AIProvider.ts
719
805
  var AIProvider = class {
720
806
  constructor(logger) {
721
- this.logger = logger;
807
+ this._logger = logger;
722
808
  }
723
809
  /**
724
- * Invoke the chat model with an array of messages.
725
- * This method should convert messages to provider format, invoke the model,
726
- * and return a ChatResponse with the result and metrics.
810
+ * Create a Runner for a completion or judge AI Config.
727
811
  *
728
- * Default implementation takes no action and returns a placeholder response.
729
- * Provider implementations should override this method.
812
+ * Override in provider subclasses to return a configured {@link Runner}.
813
+ * Default implementation returns `undefined`.
730
814
  *
731
- * @param messages Array of LDMessage objects representing the conversation
732
- * @returns Promise that resolves to a ChatResponse containing the model's response
815
+ * @param config The completion or judge AI configuration.
816
+ * @returns Promise resolving to a {@link Runner}, or `undefined` if this
817
+ * provider does not support model creation.
733
818
  */
734
- async invokeModel(_messages) {
735
- this.logger?.warn("invokeModel not implemented by this provider");
736
- return {
737
- message: {
738
- role: "assistant",
739
- content: ""
740
- },
741
- metrics: {
742
- success: false,
743
- usage: {
744
- total: 0,
745
- input: 0,
746
- output: 0
747
- }
748
- }
749
- };
819
+ async createModel(_config) {
820
+ return void 0;
750
821
  }
751
822
  /**
752
- * Invoke the chat model with structured output support.
753
- * This method should convert messages to provider format, invoke the model with
754
- * structured output configuration, and return a structured response.
823
+ * Create a Runner for an agent AI Config.
755
824
  *
756
- * Default implementation takes no action and returns a placeholder response.
757
- * Provider implementations should override this method.
825
+ * Override in provider subclasses to return a configured {@link Runner}.
826
+ * Default implementation returns `undefined`.
758
827
  *
759
- * @param messages Array of LDMessage objects representing the conversation
760
- * @param responseStructure Dictionary of output configurations keyed by output name
761
- * @returns Promise that resolves to a structured response
828
+ * @param config The agent AI configuration.
829
+ * @param tools Optional registry of callable tools.
830
+ * @returns Promise resolving to a {@link Runner}, or `undefined` if this
831
+ * provider does not support agent creation.
762
832
  */
763
- async invokeStructuredModel(_messages, _responseStructure) {
764
- this.logger?.warn("invokeStructuredModel not implemented by this provider");
765
- return {
766
- data: {},
767
- rawResponse: "",
768
- metrics: {
769
- success: false,
770
- usage: {
771
- total: 0,
772
- input: 0,
773
- output: 0
774
- }
775
- }
776
- };
833
+ async createAgent(_config, _tools) {
834
+ return void 0;
777
835
  }
778
836
  /**
779
- * Static method that constructs an instance of the provider.
780
- * Each provider implementation must provide their own static create method
781
- * that accepts an AIConfig and returns a configured instance.
837
+ * Create an AgentGraphRunner for an agent graph definition.
782
838
  *
783
- * @param aiConfig The LaunchDarkly AI configuration
784
- * @param logger Optional logger for the provider
785
- * @returns Promise that resolves to a configured provider instance
839
+ * Override in provider subclasses to return a configured {@link AgentGraphRunner}.
840
+ * Default implementation returns `undefined`.
841
+ *
842
+ * @param graphDef The agent graph definition.
843
+ * @param tools Optional registry of callable tools.
844
+ * @returns Promise resolving to an {@link AgentGraphRunner}, or `undefined` if
845
+ * this provider does not support graph execution.
786
846
  */
787
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
788
- static async create(aiConfig, logger) {
789
- throw new Error("Provider implementations must override the static create method");
847
+ async createAgentGraph(_graphDef, _tools) {
848
+ return void 0;
790
849
  }
791
850
  };
792
851
 
793
- // src/api/providers/AIProviderFactory.ts
852
+ // src/api/providers/RunnerFactory.ts
794
853
  var SUPPORTED_AI_PROVIDERS = [
795
854
  "openai",
796
855
  // Multi-provider packages should be last in the list
797
856
  "langchain",
798
857
  "vercel"
799
858
  ];
800
- var AIProviderFactory = class {
859
+ var RunnerFactory = class _RunnerFactory {
801
860
  /**
802
- * Create an AIProvider instance based on the AI configuration.
803
- * This method attempts to load provider-specific implementations dynamically.
804
- * Returns undefined if the provider is not supported.
861
+ * Load and return the AIProvider factory for the given provider type.
862
+ *
863
+ * This is the single place in the codebase that knows provider package names.
864
+ * Each supported provider package exports a `*RunnerFactory` class that
865
+ * extends {@link AIProvider}; this method instantiates it directly.
805
866
  *
806
- * @param aiConfig The AI configuration
807
- * @param logger Optional logger for logging provider initialization
808
- * @param defaultAiProvider Optional default AI provider to use
867
+ * @param providerType One of the {@link SUPPORTED_AI_PROVIDERS} values.
868
+ * @param logger Optional logger forwarded to the provider factory.
869
+ * @returns A configured {@link AIProvider} instance, or `undefined` if the
870
+ * package cannot be loaded.
809
871
  */
810
- static async create(aiConfig, logger, defaultAiProvider) {
811
- const providerName = aiConfig.provider?.name?.toLowerCase();
812
- const providersToTry = this._getProvidersToTry(defaultAiProvider, providerName);
813
- for (const providerType of providersToTry) {
814
- logger?.debug(
815
- `Attempting to create AIProvider for: ${aiConfig.provider?.name} with provider type: ${providerType}`
816
- );
817
- const provider = await this._tryCreateProvider(providerType, aiConfig, logger);
818
- if (provider) {
819
- logger?.debug(`Successfully created AIProvider for: ${aiConfig.provider?.name}`);
820
- return provider;
872
+ static async _getProviderFactory(providerType, logger) {
873
+ try {
874
+ let module;
875
+ switch (providerType) {
876
+ case "openai": {
877
+ module = await import("@launchdarkly/server-sdk-ai-openai");
878
+ return new module.OpenAIRunnerFactory(logger);
879
+ }
880
+ case "langchain": {
881
+ module = await import("@launchdarkly/server-sdk-ai-langchain");
882
+ return new module.LangChainRunnerFactory(logger);
883
+ }
884
+ case "vercel": {
885
+ module = await import("@launchdarkly/server-sdk-ai-vercel");
886
+ return new module.VercelRunnerFactory(logger);
887
+ }
888
+ default:
889
+ return void 0;
821
890
  }
891
+ } catch (error) {
892
+ logger?.warn(
893
+ `Unable to load provider package. Check that you have installed the correct package. ${error.message}`
894
+ );
895
+ return void 0;
822
896
  }
823
- logger?.warn(
824
- `Provider is not supported or failed to initialize: ${aiConfig.provider?.name ?? "unknown"}`
825
- );
826
- return void 0;
827
897
  }
828
898
  /**
829
899
  * Determine which providers to try based on defaultAiProvider and providerName.
900
+ *
901
+ * Mirrors Python's `_get_providers_to_try` helper.
830
902
  */
831
903
  static _getProvidersToTry(defaultAiProvider, providerName) {
832
904
  if (defaultAiProvider) {
@@ -843,36 +915,111 @@ var AIProviderFactory = class {
843
915
  return Array.from(providerSet);
844
916
  }
845
917
  /**
846
- * Try to create a provider of the specified type.
918
+ * Try each provider in order and return the first non-undefined result.
919
+ *
920
+ * Mirrors Python's `_with_fallback` helper. Loads each provider factory via
921
+ * {@link _getProviderFactory} and calls `fn` with it. Returns the first
922
+ * truthy result, or `undefined` if no provider succeeds.
923
+ *
924
+ * @param providers Ordered list of provider types to try.
925
+ * @param fn Callback that calls the appropriate factory method on the provider.
926
+ * @param logger Optional logger forwarded to each provider factory.
847
927
  */
848
- static async _tryCreateProvider(providerType, aiConfig, logger) {
849
- try {
850
- let module;
851
- switch (providerType) {
852
- case "openai": {
853
- module = await import("@launchdarkly/server-sdk-ai-openai");
854
- const provider = await module.OpenAIProvider.create(aiConfig, logger);
855
- return provider;
856
- }
857
- case "langchain": {
858
- module = await import("@launchdarkly/server-sdk-ai-langchain");
859
- const provider = await module.LangChainProvider.create(aiConfig, logger);
860
- return provider;
861
- }
862
- case "vercel": {
863
- module = await import("@launchdarkly/server-sdk-ai-vercel");
864
- const provider = await module.VercelProvider.create(aiConfig, logger);
865
- return provider;
928
+ static async _withFallback(providers, fn, logger) {
929
+ for (const providerType of providers) {
930
+ logger?.debug(`Attempting to create runner with provider: ${providerType}`);
931
+ const factory = await _RunnerFactory._getProviderFactory(providerType, logger);
932
+ if (factory) {
933
+ const result = await fn(factory);
934
+ if (result) {
935
+ logger?.debug(`Successfully created runner with provider: ${providerType}`);
936
+ return result;
866
937
  }
867
- default:
868
- return void 0;
869
938
  }
870
- } catch (error) {
939
+ }
940
+ return void 0;
941
+ }
942
+ /**
943
+ * Create a Runner for the given AI configuration.
944
+ *
945
+ * Suitable for completion, judge, and agent config modes. Dynamically
946
+ * loads the matching provider package via {@link _getProviderFactory} and
947
+ * delegates to its {@link AIProvider.createModel} method.
948
+ *
949
+ * @param config The AI configuration (completion, agent, or judge).
950
+ * @param logger Optional logger forwarded to the underlying provider.
951
+ * @param defaultAiProvider Optional provider override
952
+ * ('openai', 'langchain', 'vercel', …). When set, only that provider is
953
+ * tried. When omitted, providers are tried in priority order based on the
954
+ * provider name in the config.
955
+ * @returns A configured {@link Runner} ready to invoke the model, or
956
+ * `undefined` if no suitable provider could be loaded.
957
+ */
958
+ static async createModel(config, logger, defaultAiProvider) {
959
+ const providerName = config.provider?.name?.toLowerCase();
960
+ const providers = _RunnerFactory._getProvidersToTry(defaultAiProvider, providerName);
961
+ const runner = await _RunnerFactory._withFallback(
962
+ providers,
963
+ (factory) => factory.createModel(config),
964
+ logger
965
+ );
966
+ if (!runner) {
871
967
  logger?.warn(
872
- `Unable to create AIProvider. Check that you have installed the correct package. ${error.message}`
968
+ `Provider is not supported or failed to initialize: ${config.provider?.name ?? "unknown"}`
873
969
  );
874
- return void 0;
875
970
  }
971
+ return runner;
972
+ }
973
+ /**
974
+ * Create a Runner for an agent AI Config.
975
+ *
976
+ * Delegates to the provider factory's {@link AIProvider.createAgent} method.
977
+ *
978
+ * @param config The agent AI configuration.
979
+ * @param tools Optional registry of callable tools.
980
+ * @param logger Optional logger forwarded to the underlying provider.
981
+ * @param defaultAiProvider Optional provider override.
982
+ * @returns A configured {@link Runner}, or `undefined` if no suitable
983
+ * provider could be loaded.
984
+ */
985
+ static async createAgent(config, tools, logger, defaultAiProvider) {
986
+ const providerName = config.provider?.name?.toLowerCase();
987
+ const providers = _RunnerFactory._getProvidersToTry(defaultAiProvider, providerName);
988
+ const runner = await _RunnerFactory._withFallback(
989
+ providers,
990
+ (factory) => factory.createAgent(config, tools),
991
+ logger
992
+ );
993
+ if (!runner) {
994
+ logger?.warn(
995
+ `Provider is not supported or failed to initialize: ${config.provider?.name ?? "unknown"}`
996
+ );
997
+ }
998
+ return runner;
999
+ }
1000
+ /**
1001
+ * Create an AgentGraphRunner for the given agent graph definition.
1002
+ *
1003
+ * Delegates to the provider factory's {@link AIProvider.createAgentGraph} method.
1004
+ *
1005
+ * @param graphDef The agent graph definition.
1006
+ * @param tools Optional registry of callable tools.
1007
+ * @param logger Optional logger forwarded to the underlying provider.
1008
+ * @param defaultAiProvider Optional provider override.
1009
+ * @returns A configured {@link AgentGraphRunner}, or `undefined` if no
1010
+ * suitable provider could be loaded.
1011
+ */
1012
+ static async createAgentGraph(graphDef, tools, logger, defaultAiProvider) {
1013
+ const providers = _RunnerFactory._getProvidersToTry(defaultAiProvider);
1014
+ const runner = await _RunnerFactory._withFallback(
1015
+ providers,
1016
+ (factory) => factory.createAgentGraph(graphDef, tools),
1017
+ logger
1018
+ );
1019
+ if (!runner) {
1020
+ logger?.warn(`No provider could create an AgentGraphRunner for the given graph definition.`);
1021
+ }
1022
+ return runner;
876
1023
  }
877
1024
  };
878
1025
 
@@ -923,6 +1070,7 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
923
1070
  this._context = _context;
924
1071
  this._graphKey = _graphKey;
925
1072
  this._trackedMetrics = {};
1073
+ this._trackedMetrics.resumptionToken = this.resumptionToken;
926
1074
  }
927
1075
  getTrackData() {
928
1076
  return {
@@ -1006,6 +1154,10 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
1006
1154
  }
1007
1155
  }
1008
1156
  trackToolCall(toolKey) {
1157
+ if (!this._trackedMetrics.toolCalls) {
1158
+ this._trackedMetrics.toolCalls = [];
1159
+ }
1160
+ this._trackedMetrics.toolCalls.push(toolKey);
1009
1161
  this._ldClient.track("$ld:ai:tool_call", this._context, { ...this.getTrackData(), toolKey }, 1);
1010
1162
  }
1011
1163
  trackToolCalls(toolKeys) {
@@ -1061,8 +1213,11 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
1061
1213
  } else {
1062
1214
  this.trackError();
1063
1215
  }
1064
- if (metrics.usage) {
1065
- this.trackTokens(metrics.usage);
1216
+ if (metrics.tokens) {
1217
+ this.trackTokens(metrics.tokens);
1218
+ }
1219
+ if (metrics.toolCalls?.length) {
1220
+ this.trackToolCalls(metrics.toolCalls);
1066
1221
  }
1067
1222
  return result;
1068
1223
  }
@@ -1086,8 +1241,11 @@ var LDAIConfigTrackerImpl = class _LDAIConfigTrackerImpl {
1086
1241
  } else {
1087
1242
  this.trackError();
1088
1243
  }
1089
- if (metrics.usage) {
1090
- this.trackTokens(metrics.usage);
1244
+ if (metrics.tokens) {
1245
+ this.trackTokens(metrics.tokens);
1246
+ }
1247
+ if (metrics.toolCalls?.length) {
1248
+ this.trackToolCalls(metrics.toolCalls);
1091
1249
  }
1092
1250
  } catch (error) {
1093
1251
  this.trackError();
@@ -1172,6 +1330,7 @@ var LDGraphTrackerImpl = class _LDGraphTrackerImpl {
1172
1330
  this._version = _version;
1173
1331
  this._context = _context;
1174
1332
  this._summary = {};
1333
+ this._summary.resumptionToken = this.resumptionToken;
1175
1334
  }
1176
1335
  /**
1177
1336
  * Reconstructs an {@link LDGraphTrackerImpl} from a resumption token, preserving
@@ -1197,15 +1356,12 @@ var LDGraphTrackerImpl = class _LDGraphTrackerImpl {
1197
1356
  );
1198
1357
  }
1199
1358
  getTrackData() {
1200
- const data = {
1359
+ return {
1201
1360
  runId: this._runId,
1202
1361
  graphKey: this._graphKey,
1203
- version: this._version
1362
+ version: this._version,
1363
+ ...this._variationKey !== void 0 ? { variationKey: this._variationKey } : {}
1204
1364
  };
1205
- if (this._variationKey !== void 0) {
1206
- data.variationKey = this._variationKey;
1207
- }
1208
- return data;
1209
1365
  }
1210
1366
  getSummary() {
1211
1367
  return { ...this._summary };
@@ -1310,13 +1466,14 @@ var LDGraphTrackerImpl = class _LDGraphTrackerImpl {
1310
1466
 
1311
1467
  // src/sdkInfo.ts
1312
1468
  var aiSdkName = "@launchdarkly/server-sdk-ai";
1313
- var aiSdkVersion = "0.19.0";
1469
+ var aiSdkVersion = "0.20.0";
1314
1470
  var aiSdkLanguage = "javascript";
1315
1471
 
1316
1472
  // src/LDAIClientImpl.ts
1317
1473
  var TRACK_SDK_INFO = "$ld:ai:sdk:info";
1318
1474
  var TRACK_USAGE_COMPLETION_CONFIG = "$ld:ai:usage:completion-config";
1319
1475
  var TRACK_USAGE_CREATE_CHAT = "$ld:ai:usage:create-chat";
1476
+ var TRACK_USAGE_CREATE_AGENT = "$ld:ai:usage:create-agent";
1320
1477
  var TRACK_USAGE_JUDGE_CONFIG = "$ld:ai:usage:judge-config";
1321
1478
  var TRACK_USAGE_CREATE_JUDGE = "$ld:ai:usage:create-judge";
1322
1479
  var TRACK_USAGE_AGENT_CONFIG = "$ld:ai:usage:agent-config";
@@ -1344,18 +1501,11 @@ var LDAIClientImpl = class {
1344
1501
  );
1345
1502
  }
1346
1503
  _interpolateTemplate(template, variables) {
1347
- return Mustache2.render(template, variables, void 0, { escape: (item) => item });
1504
+ return Mustache.render(template, variables, void 0, { escape: (item) => item });
1348
1505
  }
1349
- async _evaluate(key, context, defaultValue, mode, variables, graphKey) {
1506
+ async _evaluate(key, context, defaultValue, mode, variables, graphKey, defaultAiProvider) {
1350
1507
  const ldFlagValue = LDAIConfigUtils.toFlagValue(defaultValue, mode);
1351
1508
  const value = await this._ldClient.variation(key, context, ldFlagValue);
1352
- const flagMode = value._ldMeta?.mode ?? "completion";
1353
- if (flagMode !== mode) {
1354
- this._logger?.warn(
1355
- `AI Config mode mismatch for ${key}: expected ${mode}, got ${flagMode}. Returning disabled config.`
1356
- );
1357
- return LDAIConfigUtils.createDisabledConfig(key, mode);
1358
- }
1359
1509
  const trackerFactory = () => new LDAIConfigTrackerImpl(
1360
1510
  this._ldClient,
1361
1511
  randomUUID(),
@@ -1369,7 +1519,23 @@ var LDAIClientImpl = class {
1369
1519
  context,
1370
1520
  graphKey
1371
1521
  );
1372
- const config = LDAIConfigUtils.fromFlagValue(key, value, trackerFactory);
1522
+ const flagMode = value._ldMeta?.mode ?? "completion";
1523
+ let evaluator = Evaluator.noop();
1524
+ if (flagMode !== mode) {
1525
+ this._logger?.warn(
1526
+ `AI Config mode mismatch for ${key}: expected ${mode}, got ${flagMode}. Returning disabled config.`
1527
+ );
1528
+ return LDAIConfigUtils.createDisabledConfig(key, mode, trackerFactory, evaluator);
1529
+ }
1530
+ if (flagMode !== "judge") {
1531
+ evaluator = await this._buildEvaluator(
1532
+ value.judgeConfiguration?.judges ?? [],
1533
+ context,
1534
+ variables,
1535
+ defaultAiProvider
1536
+ );
1537
+ }
1538
+ const config = LDAIConfigUtils.fromFlagValue(key, value, trackerFactory, evaluator);
1373
1539
  return this._applyInterpolation(config, context, variables);
1374
1540
  }
1375
1541
  _applyInterpolation(config, context, variables) {
@@ -1391,33 +1557,44 @@ var LDAIClientImpl = class {
1391
1557
  }
1392
1558
  return config;
1393
1559
  }
1394
- async _initializeJudges(judgeConfigs, context, variables, defaultAiProvider) {
1395
- const judges = {};
1396
- const judgePromises = judgeConfigs.map(async (judgeConfig) => {
1397
- const judge = await this.createJudge(
1398
- judgeConfig.key,
1399
- context,
1400
- void 0,
1401
- variables,
1402
- defaultAiProvider
1403
- );
1404
- return judge ? { key: judgeConfig.key, judge } : null;
1405
- });
1406
- const results = await Promise.all(judgePromises);
1407
- results.forEach((result) => {
1408
- if (result) {
1409
- judges[result.key] = result.judge;
1410
- }
1411
- });
1412
- return judges;
1413
- }
1414
- async _completionConfig(key, context, defaultValue, variables) {
1415
- const config = await this._evaluate(key, context, defaultValue, "completion", variables);
1416
- return config;
1560
+ async _buildEvaluator(judgeConfigs, context, variables, defaultAiProvider) {
1561
+ if (judgeConfigs.length === 0) {
1562
+ return Evaluator.noop();
1563
+ }
1564
+ const judgeInstances = (await Promise.all(
1565
+ judgeConfigs.map(
1566
+ (jc) => this._createJudgeInstance(
1567
+ jc.key,
1568
+ context,
1569
+ void 0,
1570
+ variables,
1571
+ defaultAiProvider,
1572
+ jc.samplingRate
1573
+ )
1574
+ )
1575
+ )).filter((j) => j !== void 0);
1576
+ return new Evaluator(judgeInstances);
1577
+ }
1578
+ async _completionConfig(key, context, defaultValue, variables, defaultAiProvider) {
1579
+ return await this._evaluate(
1580
+ key,
1581
+ context,
1582
+ defaultValue,
1583
+ "completion",
1584
+ variables,
1585
+ void 0,
1586
+ defaultAiProvider
1587
+ );
1417
1588
  }
1418
- async completionConfig(key, context, defaultValue, variables) {
1589
+ async completionConfig(key, context, defaultValue, variables, defaultAiProvider) {
1419
1590
  this._ldClient.track(TRACK_USAGE_COMPLETION_CONFIG, context, key, 1);
1420
- return this._completionConfig(key, context, defaultValue ?? disabledAIConfig, variables);
1591
+ return this._completionConfig(
1592
+ key,
1593
+ context,
1594
+ defaultValue ?? disabledAIConfig,
1595
+ variables,
1596
+ defaultAiProvider
1597
+ );
1421
1598
  }
1422
1599
  /**
1423
1600
  * @deprecated Use `completionConfig` instead. This method will be removed in a future version.
@@ -1426,20 +1603,58 @@ var LDAIClientImpl = class {
1426
1603
  return this.completionConfig(key, context, defaultValue, variables);
1427
1604
  }
1428
1605
  async _judgeConfig(key, context, defaultValue, variables) {
1429
- const config = await this._evaluate(key, context, defaultValue, "judge", variables);
1606
+ if (variables?.message_history !== void 0) {
1607
+ this._logger?.warn(
1608
+ "The variable 'message_history' is reserved by the judge and will be ignored."
1609
+ );
1610
+ }
1611
+ if (variables?.response_to_evaluate !== void 0) {
1612
+ this._logger?.warn(
1613
+ "The variable 'response_to_evaluate' is reserved by the judge and will be ignored."
1614
+ );
1615
+ }
1616
+ const extendedVariables = {
1617
+ ...variables,
1618
+ message_history: "{{message_history}}",
1619
+ response_to_evaluate: "{{response_to_evaluate}}"
1620
+ };
1621
+ const config = await this._evaluate(
1622
+ key,
1623
+ context,
1624
+ defaultValue,
1625
+ "judge",
1626
+ extendedVariables
1627
+ );
1628
+ if (config.messages) {
1629
+ return { ...config, messages: stripLegacyJudgeMessages(config.messages) };
1630
+ }
1430
1631
  return config;
1431
1632
  }
1432
1633
  async judgeConfig(key, context, defaultValue, variables) {
1433
1634
  this._ldClient.track(TRACK_USAGE_JUDGE_CONFIG, context, key, 1);
1434
1635
  return this._judgeConfig(key, context, defaultValue ?? disabledAIConfig, variables);
1435
1636
  }
1436
- async _agentConfig(key, context, defaultValue, variables, graphKey) {
1437
- const config = await this._evaluate(key, context, defaultValue, "agent", variables, graphKey);
1438
- return config;
1637
+ async _agentConfig(key, context, defaultValue, variables, graphKey, defaultAiProvider) {
1638
+ return await this._evaluate(
1639
+ key,
1640
+ context,
1641
+ defaultValue,
1642
+ "agent",
1643
+ variables,
1644
+ graphKey,
1645
+ defaultAiProvider
1646
+ );
1439
1647
  }
1440
- async agentConfig(key, context, defaultValue, variables) {
1648
+ async agentConfig(key, context, defaultValue, variables, defaultAiProvider) {
1441
1649
  this._ldClient.track(TRACK_USAGE_AGENT_CONFIG, context, key, 1);
1442
- return this._agentConfig(key, context, defaultValue ?? disabledAIConfig, variables);
1650
+ return this._agentConfig(
1651
+ key,
1652
+ context,
1653
+ defaultValue ?? disabledAIConfig,
1654
+ variables,
1655
+ void 0,
1656
+ defaultAiProvider
1657
+ );
1443
1658
  }
1444
1659
  /**
1445
1660
  * @deprecated Use `agentConfig` instead. This method will be removed in a future version.
@@ -1474,73 +1689,89 @@ var LDAIClientImpl = class {
1474
1689
  async agents(agentConfigs, context) {
1475
1690
  return this.agentConfigs(agentConfigs, context);
1476
1691
  }
1477
- async createChat(key, context, defaultValue, variables, defaultAiProvider) {
1478
- this._ldClient.track(TRACK_USAGE_CREATE_CHAT, context, key, 1);
1479
- const config = await this._completionConfig(
1692
+ async createJudge(key, context, defaultValue, variables, defaultAiProvider, sampleRate = 1) {
1693
+ this._ldClient.track(TRACK_USAGE_CREATE_JUDGE, context, key, 1);
1694
+ return this._createJudgeInstance(
1480
1695
  key,
1481
1696
  context,
1482
- defaultValue ?? disabledAIConfig,
1483
- variables
1484
- );
1485
- if (!config.enabled) {
1486
- this._logger?.info(`Chat configuration is disabled: ${key}`);
1487
- return void 0;
1488
- }
1489
- const provider = await AIProviderFactory.create(config, this._logger, defaultAiProvider);
1490
- if (!provider) {
1491
- return void 0;
1492
- }
1493
- const judges = await this._initializeJudges(
1494
- config.judgeConfiguration?.judges ?? [],
1495
- context,
1697
+ defaultValue,
1496
1698
  variables,
1497
- defaultAiProvider
1699
+ defaultAiProvider,
1700
+ sampleRate
1498
1701
  );
1499
- return new TrackedChat(config, provider, judges, this._logger);
1500
1702
  }
1501
- async createJudge(key, context, defaultValue, variables, defaultAiProvider) {
1502
- this._ldClient.track(TRACK_USAGE_CREATE_JUDGE, context, key, 1);
1703
+ async _createJudgeInstance(key, context, defaultValue, variables, defaultAiProvider, sampleRate = 1) {
1503
1704
  try {
1504
- if (variables?.message_history !== void 0) {
1505
- this._logger?.warn(
1506
- "The variable 'message_history' is reserved by the judge and will be ignored."
1507
- );
1508
- }
1509
- if (variables?.response_to_evaluate !== void 0) {
1510
- this._logger?.warn(
1511
- "The variable 'response_to_evaluate' is reserved by the judge and will be ignored."
1512
- );
1513
- }
1514
- const extendedVariables = {
1515
- ...variables,
1516
- message_history: "{{message_history}}",
1517
- response_to_evaluate: "{{response_to_evaluate}}"
1518
- };
1519
1705
  const judgeConfig = await this._judgeConfig(
1520
1706
  key,
1521
1707
  context,
1522
1708
  defaultValue ?? disabledAIConfig,
1523
- extendedVariables
1709
+ variables
1524
1710
  );
1525
1711
  if (!judgeConfig.enabled) {
1526
1712
  this._logger?.info(`Judge configuration is disabled: ${key}`);
1527
1713
  return void 0;
1528
1714
  }
1529
- const provider = await AIProviderFactory.create(judgeConfig, this._logger, defaultAiProvider);
1530
- if (!provider) {
1715
+ const runner = await RunnerFactory.createModel(judgeConfig, this._logger, defaultAiProvider);
1716
+ if (!runner) {
1531
1717
  return void 0;
1532
1718
  }
1533
- return new Judge(judgeConfig, provider, this._logger);
1719
+ return new Judge(judgeConfig, runner, sampleRate, this._logger);
1534
1720
  } catch (error) {
1535
1721
  this._logger?.error(`Failed to initialize judge ${key}:`, error);
1536
1722
  return void 0;
1537
1723
  }
1538
1724
  }
1725
+ async createModel(key, context, defaultValue, variables, defaultAiProvider) {
1726
+ this._ldClient.track(TRACK_USAGE_CREATE_CHAT, context, key, 1);
1727
+ const config = await this._completionConfig(
1728
+ key,
1729
+ context,
1730
+ defaultValue ?? disabledAIConfig,
1731
+ variables,
1732
+ defaultAiProvider
1733
+ );
1734
+ if (!config.enabled) {
1735
+ this._logger?.info(`Completion configuration is disabled: ${key}`);
1736
+ return void 0;
1737
+ }
1738
+ const runner = await RunnerFactory.createModel(config, this._logger, defaultAiProvider);
1739
+ if (!runner) {
1740
+ return void 0;
1741
+ }
1742
+ return new ManagedModel(config, runner, this._logger);
1743
+ }
1744
+ async createAgent(key, context, defaultValue, variables, defaultAiProvider) {
1745
+ this._ldClient.track(TRACK_USAGE_CREATE_AGENT, context, key, 1);
1746
+ const config = await this._agentConfig(
1747
+ key,
1748
+ context,
1749
+ defaultValue ?? disabledAIConfig,
1750
+ variables,
1751
+ void 0,
1752
+ defaultAiProvider
1753
+ );
1754
+ if (!config.enabled) {
1755
+ this._logger?.info(`Agent configuration is disabled: ${key}`);
1756
+ return void 0;
1757
+ }
1758
+ const runner = await RunnerFactory.createAgent(config, void 0, this._logger, defaultAiProvider);
1759
+ if (!runner) {
1760
+ return void 0;
1761
+ }
1762
+ return new ManagedAgent(config, runner, this._logger);
1763
+ }
1764
+ /**
1765
+ * @deprecated Use `createModel` instead. This method will be removed in a future version.
1766
+ */
1767
+ async createChat(key, context, defaultValue, variables, defaultAiProvider) {
1768
+ return this.createModel(key, context, defaultValue, variables, defaultAiProvider);
1769
+ }
1539
1770
  /**
1540
- * @deprecated Use `createChat` instead. This method will be removed in a future version.
1771
+ * @deprecated Use `createModel` instead. This method will be removed in a future version.
1541
1772
  */
1542
1773
  async initChat(key, context, defaultValue, variables, defaultAiProvider) {
1543
- return this.createChat(key, context, defaultValue, variables, defaultAiProvider);
1774
+ return this.createModel(key, context, defaultValue, variables, defaultAiProvider);
1544
1775
  }
1545
1776
  createTracker(token, context) {
1546
1777
  return LDAIConfigTrackerImpl.fromResumptionToken(token, this._ldClient, context);
@@ -1625,14 +1856,16 @@ function initAi(ldClient) {
1625
1856
  }
1626
1857
  export {
1627
1858
  AIProvider,
1628
- AIProviderFactory,
1629
1859
  AgentGraphDefinition,
1630
1860
  AgentGraphNode,
1631
1861
  Judge,
1632
1862
  LDFeedbackKind,
1633
1863
  LDGraphTrackerImpl,
1864
+ ManagedAgent,
1865
+ ManagedAgentGraph,
1866
+ ManagedModel,
1867
+ RunnerFactory,
1634
1868
  SUPPORTED_AI_PROVIDERS,
1635
- TrackedChat,
1636
1869
  createBedrockTokenUsage,
1637
1870
  createOpenAiUsage,
1638
1871
  createVercelAISDKTokenUsage,