@sentrial/sdk 0.4.4 → 0.4.5

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.d.cts CHANGED
@@ -270,6 +270,9 @@ declare function redactPayload(payload: Record<string, unknown>, config: PiiConf
270
270
  * calls (createSession, completeSession) bypass the batcher entirely
271
271
  * because they need synchronous responses.
272
272
  *
273
+ * Events are delivered in enqueue order so server-assigned sequence numbers
274
+ * match the order an agent actually executed steps.
275
+ *
273
276
  * Flush triggers:
274
277
  * 1. Timer — every `flushIntervalMs` (default 1 000 ms)
275
278
  * 2. Queue size — when queue reaches `flushThreshold` (default 10)
@@ -312,7 +315,7 @@ declare class EventBatcher {
312
315
  /**
313
316
  * Flush all queued events to the API.
314
317
  *
315
- * Drains the queue and fires all requests in parallel. Safe to call
318
+ * Drains the queue and sends requests in enqueue order. Safe to call
316
319
  * concurrently — only one flush runs at a time.
317
320
  */
318
321
  flush(): Promise<void>;
@@ -385,6 +388,8 @@ interface CreateSessionParams {
385
388
  convoId?: string;
386
389
  /** Optional metadata */
387
390
  metadata?: Record<string, unknown>;
391
+ /** Production experiment assignment ids to link to this session */
392
+ experimentAssignmentIds?: string[];
388
393
  }
389
394
  /**
390
395
  * Parameters for completing a session
@@ -582,6 +587,50 @@ interface FinishParams {
582
587
  /** Duration in milliseconds (auto-calculated from begin/finish if not provided) */
583
588
  durationMs?: number;
584
589
  }
590
+ interface ProductionVariantConfig {
591
+ name: string;
592
+ weight?: number;
593
+ prompt?: string;
594
+ systemPrompt?: string;
595
+ model?: string;
596
+ promptVersion?: string;
597
+ toolConfig?: Record<string, unknown>;
598
+ metadata?: Record<string, unknown>;
599
+ }
600
+ interface GetVariantParams {
601
+ /** Production experiment name configured in Sentrial */
602
+ experimentName: string;
603
+ /** Agent name this variant is for */
604
+ agentName?: string;
605
+ /** External user id for sticky bucketing */
606
+ userId?: string;
607
+ /** Conversation id for sticky multi-turn bucketing */
608
+ convoId?: string;
609
+ /** Stable anonymous id if no user/conversation id exists */
610
+ anonymousId?: string;
611
+ /** Optional existing Sentrial session id */
612
+ sessionId?: string;
613
+ /** Variant to use when no active live experiment matches */
614
+ defaultVariant?: string;
615
+ /** Prompt version currently running in the customer app */
616
+ promptVersion?: string;
617
+ /** Model currently running in the customer app */
618
+ model?: string;
619
+ /** Extra assignment metadata */
620
+ metadata?: Record<string, unknown>;
621
+ }
622
+ interface VariantAssignment {
623
+ active: boolean;
624
+ reason: 'assigned' | 'holdout' | 'not_found';
625
+ experimentId?: string;
626
+ assignmentId?: string;
627
+ variant: string;
628
+ variantConfig?: ProductionVariantConfig;
629
+ prompt?: string;
630
+ systemPrompt?: string;
631
+ model?: string;
632
+ promptVersion?: string;
633
+ }
585
634
  /**
586
635
  * Parameters for cost calculation
587
636
  */
@@ -719,6 +768,7 @@ declare class SentrialClient {
719
768
  private piiHydrationPromise?;
720
769
  private readonly _stateVar;
721
770
  private readonly batcher?;
771
+ private pendingExperimentAssignmentIds;
722
772
  /** Per-session cost/token accumulator — populated by trackToolCall/trackDecision */
723
773
  private sessionAccumulators;
724
774
  private get currentState();
@@ -747,6 +797,13 @@ declare class SentrialClient {
747
797
  * @returns Session ID, or null if the request failed and failSilently is true
748
798
  */
749
799
  createSession(params: CreateSessionParams): Promise<string | null>;
800
+ /**
801
+ * Get a sticky production experiment variant for this user/conversation.
802
+ *
803
+ * The returned assignment id is automatically linked to the next session
804
+ * created by this client. You can also pass `sessionId` to link immediately.
805
+ */
806
+ getVariant(params: GetVariantParams): Promise<VariantAssignment>;
750
807
  /**
751
808
  * Track a tool call event
752
809
  *
@@ -986,6 +1043,7 @@ declare function configure(config: SentrialClientConfig): void;
986
1043
  * ```
987
1044
  */
988
1045
  declare function begin(params: BeginParams): Promise<Interaction>;
1046
+ declare function getVariant(params: GetVariantParams): Promise<VariantAssignment>;
989
1047
  /**
990
1048
  * Simple API namespace for module-level usage
991
1049
  */
@@ -994,6 +1052,7 @@ declare function shutdown(): Promise<void>;
994
1052
  declare const sentrial: {
995
1053
  configure: typeof configure;
996
1054
  begin: typeof begin;
1055
+ getVariant: typeof getVariant;
997
1056
  flush: typeof flush;
998
1057
  shutdown: typeof shutdown;
999
1058
  };
@@ -1889,4 +1948,4 @@ declare class Experiment {
1889
1948
  getResults(): Promise<ExperimentResults | null>;
1890
1949
  }
1891
1950
 
1892
- export { ApiError, type ApiResponse, type BatcherConfig, type BeginParams, type CompleteSessionParams, type ContextToken, type ContextVar, type CostParams, type CreateSessionParams, type Event, EventBatcher, EventType, Experiment, type ExperimentContext, type ExperimentResults, type ExperimentRunResult, ExperimentRunTracker, type ExperimentTestCase, type ExperimentVariant, type FinishParams, type GenerateTextParams, type GenerateTextResult, Interaction, NetworkError, type PiiBuiltinPatterns, type PiiConfig, type PiiCustomPattern, type PiiField, type PiiMode, SentrialClient, type SentrialClientConfig, SentrialError, type Session, SessionContext, type SessionStatus, type StreamTextResult, Tool, type TrackDecisionParams, type TrackErrorParams, TrackSession, type TrackToolCallParams, ValidationError, type WrapClaudeAgentOptions, begin, calculateAnthropicCost, calculateGoogleCost, calculateOpenAICost, clearExperimentContext, clearSessionContext, configure, configureVercel, createContextVar, getCurrentInteraction, getCurrentSessionId, getExperimentContext, getExperimentId, getSessionContext, getSystemPrompt, getVariantName, hashValue, isExperimentMode, redactPayload, redactString, redactValue, replaceMatch, sentrial, setClient, setDefaultClient, setExperimentContext, setSessionContext, withSession, withTool, wrapAISDK, wrapAnthropic, wrapClaudeAgent, wrapGoogle, wrapLLM, wrapOpenAI };
1951
+ export { ApiError, type ApiResponse, type BatcherConfig, type BeginParams, type CompleteSessionParams, type ContextToken, type ContextVar, type CostParams, type CreateSessionParams, type Event, EventBatcher, EventType, Experiment, type ExperimentContext, type ExperimentResults, type ExperimentRunResult, ExperimentRunTracker, type ExperimentTestCase, type ExperimentVariant, type FinishParams, type GenerateTextParams, type GenerateTextResult, type GetVariantParams, Interaction, NetworkError, type PiiBuiltinPatterns, type PiiConfig, type PiiCustomPattern, type PiiField, type PiiMode, type ProductionVariantConfig, SentrialClient, type SentrialClientConfig, SentrialError, type Session, SessionContext, type SessionStatus, type StreamTextResult, Tool, type TrackDecisionParams, type TrackErrorParams, TrackSession, type TrackToolCallParams, ValidationError, type VariantAssignment, type WrapClaudeAgentOptions, begin, calculateAnthropicCost, calculateGoogleCost, calculateOpenAICost, clearExperimentContext, clearSessionContext, configure, configureVercel, createContextVar, getCurrentInteraction, getCurrentSessionId, getExperimentContext, getExperimentId, getSessionContext, getSystemPrompt, getVariant, getVariantName, hashValue, isExperimentMode, redactPayload, redactString, redactValue, replaceMatch, sentrial, setClient, setDefaultClient, setExperimentContext, setSessionContext, withSession, withTool, wrapAISDK, wrapAnthropic, wrapClaudeAgent, wrapGoogle, wrapLLM, wrapOpenAI };
package/dist/index.d.ts CHANGED
@@ -270,6 +270,9 @@ declare function redactPayload(payload: Record<string, unknown>, config: PiiConf
270
270
  * calls (createSession, completeSession) bypass the batcher entirely
271
271
  * because they need synchronous responses.
272
272
  *
273
+ * Events are delivered in enqueue order so server-assigned sequence numbers
274
+ * match the order an agent actually executed steps.
275
+ *
273
276
  * Flush triggers:
274
277
  * 1. Timer — every `flushIntervalMs` (default 1 000 ms)
275
278
  * 2. Queue size — when queue reaches `flushThreshold` (default 10)
@@ -312,7 +315,7 @@ declare class EventBatcher {
312
315
  /**
313
316
  * Flush all queued events to the API.
314
317
  *
315
- * Drains the queue and fires all requests in parallel. Safe to call
318
+ * Drains the queue and sends requests in enqueue order. Safe to call
316
319
  * concurrently — only one flush runs at a time.
317
320
  */
318
321
  flush(): Promise<void>;
@@ -385,6 +388,8 @@ interface CreateSessionParams {
385
388
  convoId?: string;
386
389
  /** Optional metadata */
387
390
  metadata?: Record<string, unknown>;
391
+ /** Production experiment assignment ids to link to this session */
392
+ experimentAssignmentIds?: string[];
388
393
  }
389
394
  /**
390
395
  * Parameters for completing a session
@@ -582,6 +587,50 @@ interface FinishParams {
582
587
  /** Duration in milliseconds (auto-calculated from begin/finish if not provided) */
583
588
  durationMs?: number;
584
589
  }
590
+ interface ProductionVariantConfig {
591
+ name: string;
592
+ weight?: number;
593
+ prompt?: string;
594
+ systemPrompt?: string;
595
+ model?: string;
596
+ promptVersion?: string;
597
+ toolConfig?: Record<string, unknown>;
598
+ metadata?: Record<string, unknown>;
599
+ }
600
+ interface GetVariantParams {
601
+ /** Production experiment name configured in Sentrial */
602
+ experimentName: string;
603
+ /** Agent name this variant is for */
604
+ agentName?: string;
605
+ /** External user id for sticky bucketing */
606
+ userId?: string;
607
+ /** Conversation id for sticky multi-turn bucketing */
608
+ convoId?: string;
609
+ /** Stable anonymous id if no user/conversation id exists */
610
+ anonymousId?: string;
611
+ /** Optional existing Sentrial session id */
612
+ sessionId?: string;
613
+ /** Variant to use when no active live experiment matches */
614
+ defaultVariant?: string;
615
+ /** Prompt version currently running in the customer app */
616
+ promptVersion?: string;
617
+ /** Model currently running in the customer app */
618
+ model?: string;
619
+ /** Extra assignment metadata */
620
+ metadata?: Record<string, unknown>;
621
+ }
622
+ interface VariantAssignment {
623
+ active: boolean;
624
+ reason: 'assigned' | 'holdout' | 'not_found';
625
+ experimentId?: string;
626
+ assignmentId?: string;
627
+ variant: string;
628
+ variantConfig?: ProductionVariantConfig;
629
+ prompt?: string;
630
+ systemPrompt?: string;
631
+ model?: string;
632
+ promptVersion?: string;
633
+ }
585
634
  /**
586
635
  * Parameters for cost calculation
587
636
  */
@@ -719,6 +768,7 @@ declare class SentrialClient {
719
768
  private piiHydrationPromise?;
720
769
  private readonly _stateVar;
721
770
  private readonly batcher?;
771
+ private pendingExperimentAssignmentIds;
722
772
  /** Per-session cost/token accumulator — populated by trackToolCall/trackDecision */
723
773
  private sessionAccumulators;
724
774
  private get currentState();
@@ -747,6 +797,13 @@ declare class SentrialClient {
747
797
  * @returns Session ID, or null if the request failed and failSilently is true
748
798
  */
749
799
  createSession(params: CreateSessionParams): Promise<string | null>;
800
+ /**
801
+ * Get a sticky production experiment variant for this user/conversation.
802
+ *
803
+ * The returned assignment id is automatically linked to the next session
804
+ * created by this client. You can also pass `sessionId` to link immediately.
805
+ */
806
+ getVariant(params: GetVariantParams): Promise<VariantAssignment>;
750
807
  /**
751
808
  * Track a tool call event
752
809
  *
@@ -986,6 +1043,7 @@ declare function configure(config: SentrialClientConfig): void;
986
1043
  * ```
987
1044
  */
988
1045
  declare function begin(params: BeginParams): Promise<Interaction>;
1046
+ declare function getVariant(params: GetVariantParams): Promise<VariantAssignment>;
989
1047
  /**
990
1048
  * Simple API namespace for module-level usage
991
1049
  */
@@ -994,6 +1052,7 @@ declare function shutdown(): Promise<void>;
994
1052
  declare const sentrial: {
995
1053
  configure: typeof configure;
996
1054
  begin: typeof begin;
1055
+ getVariant: typeof getVariant;
997
1056
  flush: typeof flush;
998
1057
  shutdown: typeof shutdown;
999
1058
  };
@@ -1889,4 +1948,4 @@ declare class Experiment {
1889
1948
  getResults(): Promise<ExperimentResults | null>;
1890
1949
  }
1891
1950
 
1892
- export { ApiError, type ApiResponse, type BatcherConfig, type BeginParams, type CompleteSessionParams, type ContextToken, type ContextVar, type CostParams, type CreateSessionParams, type Event, EventBatcher, EventType, Experiment, type ExperimentContext, type ExperimentResults, type ExperimentRunResult, ExperimentRunTracker, type ExperimentTestCase, type ExperimentVariant, type FinishParams, type GenerateTextParams, type GenerateTextResult, Interaction, NetworkError, type PiiBuiltinPatterns, type PiiConfig, type PiiCustomPattern, type PiiField, type PiiMode, SentrialClient, type SentrialClientConfig, SentrialError, type Session, SessionContext, type SessionStatus, type StreamTextResult, Tool, type TrackDecisionParams, type TrackErrorParams, TrackSession, type TrackToolCallParams, ValidationError, type WrapClaudeAgentOptions, begin, calculateAnthropicCost, calculateGoogleCost, calculateOpenAICost, clearExperimentContext, clearSessionContext, configure, configureVercel, createContextVar, getCurrentInteraction, getCurrentSessionId, getExperimentContext, getExperimentId, getSessionContext, getSystemPrompt, getVariantName, hashValue, isExperimentMode, redactPayload, redactString, redactValue, replaceMatch, sentrial, setClient, setDefaultClient, setExperimentContext, setSessionContext, withSession, withTool, wrapAISDK, wrapAnthropic, wrapClaudeAgent, wrapGoogle, wrapLLM, wrapOpenAI };
1951
+ export { ApiError, type ApiResponse, type BatcherConfig, type BeginParams, type CompleteSessionParams, type ContextToken, type ContextVar, type CostParams, type CreateSessionParams, type Event, EventBatcher, EventType, Experiment, type ExperimentContext, type ExperimentResults, type ExperimentRunResult, ExperimentRunTracker, type ExperimentTestCase, type ExperimentVariant, type FinishParams, type GenerateTextParams, type GenerateTextResult, type GetVariantParams, Interaction, NetworkError, type PiiBuiltinPatterns, type PiiConfig, type PiiCustomPattern, type PiiField, type PiiMode, type ProductionVariantConfig, SentrialClient, type SentrialClientConfig, SentrialError, type Session, SessionContext, type SessionStatus, type StreamTextResult, Tool, type TrackDecisionParams, type TrackErrorParams, TrackSession, type TrackToolCallParams, ValidationError, type VariantAssignment, type WrapClaudeAgentOptions, begin, calculateAnthropicCost, calculateGoogleCost, calculateOpenAICost, clearExperimentContext, clearSessionContext, configure, configureVercel, createContextVar, getCurrentInteraction, getCurrentSessionId, getExperimentContext, getExperimentId, getSessionContext, getSystemPrompt, getVariant, getVariantName, hashValue, isExperimentMode, redactPayload, redactString, redactValue, replaceMatch, sentrial, setClient, setDefaultClient, setExperimentContext, setSessionContext, withSession, withTool, wrapAISDK, wrapAnthropic, wrapClaudeAgent, wrapGoogle, wrapLLM, wrapOpenAI };
package/dist/index.js CHANGED
@@ -70,7 +70,7 @@ var ValidationError = class extends SentrialError {
70
70
  // src/redact.ts
71
71
  var _createHash;
72
72
  try {
73
- const mod = eval("require")("crypto");
73
+ const mod = new Function('return require("crypto")')();
74
74
  if (mod?.createHash) {
75
75
  _createHash = mod.createHash;
76
76
  }
@@ -175,7 +175,7 @@ function redactPayload(payload, config) {
175
175
  // src/async-context.ts
176
176
  var _AsyncLocalStorage = null;
177
177
  try {
178
- const mod = eval("require")("node:async_hooks");
178
+ const mod = new Function('return require("node:async_hooks")')();
179
179
  if (mod?.AsyncLocalStorage) {
180
180
  _AsyncLocalStorage = mod.AsyncLocalStorage;
181
181
  }
@@ -325,6 +325,9 @@ function getSessionContext() {
325
325
  function setDefaultClient(client) {
326
326
  _defaultClient = client;
327
327
  }
328
+ function getDefaultClient() {
329
+ return _defaultClient;
330
+ }
328
331
  function _setSessionContextWithTokens(sessionId, client) {
329
332
  const _sessionToken = _currentSessionId.set(sessionId);
330
333
  const _clientToken = client ? _currentClient.set(client) : _currentClient.set(_currentClient.get());
@@ -882,7 +885,7 @@ var EventBatcher = class {
882
885
  /**
883
886
  * Flush all queued events to the API.
884
887
  *
885
- * Drains the queue and fires all requests in parallel. Safe to call
888
+ * Drains the queue and sends requests in enqueue order. Safe to call
886
889
  * concurrently — only one flush runs at a time.
887
890
  */
888
891
  async flush() {
@@ -890,15 +893,15 @@ var EventBatcher = class {
890
893
  this.flushing = true;
891
894
  const batch = this.queue.splice(0, this.queue.length);
892
895
  try {
893
- await Promise.all(
894
- batch.map(
895
- (event) => this.sendFn(event.method, event.url, event.body).catch((err) => {
896
- if (typeof console !== "undefined") {
897
- console.warn("Sentrial: Batched event failed:", err);
898
- }
899
- })
900
- )
901
- );
896
+ for (const event of batch) {
897
+ try {
898
+ await this.sendFn(event.method, event.url, event.body);
899
+ } catch (err) {
900
+ if (typeof console !== "undefined") {
901
+ console.warn("Sentrial: Batched event failed:", err);
902
+ }
903
+ }
904
+ }
902
905
  } finally {
903
906
  this.flushing = false;
904
907
  }
@@ -951,6 +954,7 @@ var SentrialClient = class {
951
954
  piiHydrationPromise;
952
955
  _stateVar = createContextVar({});
953
956
  batcher;
957
+ pendingExperimentAssignmentIds = [];
954
958
  /** Per-session cost/token accumulator — populated by trackToolCall/trackDecision */
955
959
  sessionAccumulators = /* @__PURE__ */ new Map();
956
960
  get currentState() {
@@ -1101,12 +1105,12 @@ var SentrialClient = class {
1101
1105
  }
1102
1106
  }
1103
1107
  }
1104
- const networkError = new NetworkError(
1105
- lastError?.message ?? "Unknown network error",
1106
- lastError
1107
- );
1108
+ const networkError = new NetworkError(lastError?.message ?? "Unknown network error", lastError);
1108
1109
  if (this.failSilently) {
1109
- console.warn(`Sentrial: Request failed after ${MAX_RETRIES + 1} attempts (${method} ${url}):`, networkError.message);
1110
+ console.warn(
1111
+ `Sentrial: Request failed after ${MAX_RETRIES + 1} attempts (${method} ${url}):`,
1112
+ networkError.message
1113
+ );
1110
1114
  return null;
1111
1115
  }
1112
1116
  throw networkError;
@@ -1149,13 +1153,53 @@ var SentrialClient = class {
1149
1153
  if (params.convoId) {
1150
1154
  payload.convoId = params.convoId;
1151
1155
  }
1156
+ const experimentAssignmentIds = [
1157
+ ...params.experimentAssignmentIds || [],
1158
+ ...this.pendingExperimentAssignmentIds
1159
+ ];
1160
+ if (experimentAssignmentIds.length > 0) {
1161
+ payload.experimentAssignmentIds = Array.from(new Set(experimentAssignmentIds));
1162
+ payload.metadata = {
1163
+ ...params.metadata || {},
1164
+ sentrial_experiment_assignment_ids: payload.experimentAssignmentIds
1165
+ };
1166
+ }
1152
1167
  const response = await this.safeRequest(
1153
1168
  "POST",
1154
1169
  `${this.apiUrl}/api/sdk/sessions`,
1155
1170
  payload
1156
1171
  );
1172
+ if (response?.id && experimentAssignmentIds.length > 0) {
1173
+ this.pendingExperimentAssignmentIds = [];
1174
+ }
1157
1175
  return response?.id ?? null;
1158
1176
  }
1177
+ /**
1178
+ * Get a sticky production experiment variant for this user/conversation.
1179
+ *
1180
+ * The returned assignment id is automatically linked to the next session
1181
+ * created by this client. You can also pass `sessionId` to link immediately.
1182
+ */
1183
+ async getVariant(params) {
1184
+ const fallback = {
1185
+ active: false,
1186
+ reason: "not_found",
1187
+ variant: params.defaultVariant || "control"
1188
+ };
1189
+ const response = await this.safeRequest(
1190
+ "POST",
1191
+ `${this.apiUrl}/api/sdk/experiments/variant`,
1192
+ {
1193
+ ...params,
1194
+ sdkName: "@sentrial/sdk"
1195
+ }
1196
+ );
1197
+ if (!response) return fallback;
1198
+ if (response.active && response.assignmentId && !params.sessionId) {
1199
+ this.pendingExperimentAssignmentIds.push(response.assignmentId);
1200
+ }
1201
+ return response;
1202
+ }
1159
1203
  /**
1160
1204
  * Track a tool call event
1161
1205
  *
@@ -1264,11 +1308,9 @@ var SentrialClient = class {
1264
1308
  * @returns Updated session or null on error
1265
1309
  */
1266
1310
  async setInput(sessionId, input) {
1267
- return this.safeRequest(
1268
- "PATCH",
1269
- `${this.apiUrl}/api/sdk/sessions/${sessionId}`,
1270
- { userInput: input }
1271
- );
1311
+ return this.safeRequest("PATCH", `${this.apiUrl}/api/sdk/sessions/${sessionId}`, {
1312
+ userInput: input
1313
+ });
1272
1314
  }
1273
1315
  /**
1274
1316
  * Track a generic event
@@ -1328,10 +1370,14 @@ var SentrialClient = class {
1328
1370
  }
1329
1371
  const acc = this.sessionAccumulators.get(params.sessionId);
1330
1372
  if (acc) {
1331
- if (params.estimatedCost === void 0 && acc.cost > 0) params = { ...params, estimatedCost: acc.cost };
1332
- if (params.promptTokens === void 0 && acc.promptTokens > 0) params = { ...params, promptTokens: acc.promptTokens };
1333
- if (params.completionTokens === void 0 && acc.completionTokens > 0) params = { ...params, completionTokens: acc.completionTokens };
1334
- if (params.totalTokens === void 0 && acc.totalTokens > 0) params = { ...params, totalTokens: acc.totalTokens };
1373
+ if (params.estimatedCost === void 0 && acc.cost > 0)
1374
+ params = { ...params, estimatedCost: acc.cost };
1375
+ if (params.promptTokens === void 0 && acc.promptTokens > 0)
1376
+ params = { ...params, promptTokens: acc.promptTokens };
1377
+ if (params.completionTokens === void 0 && acc.completionTokens > 0)
1378
+ params = { ...params, completionTokens: acc.completionTokens };
1379
+ if (params.totalTokens === void 0 && acc.totalTokens > 0)
1380
+ params = { ...params, totalTokens: acc.totalTokens };
1335
1381
  this.sessionAccumulators.delete(params.sessionId);
1336
1382
  }
1337
1383
  const payload = {
@@ -1570,6 +1616,9 @@ function configure(config) {
1570
1616
  function begin(params) {
1571
1617
  return getClient().begin(params);
1572
1618
  }
1619
+ function getVariant(params) {
1620
+ return getClient().getVariant(params);
1621
+ }
1573
1622
  async function flush() {
1574
1623
  if (defaultClient) await defaultClient.flush();
1575
1624
  }
@@ -1579,6 +1628,7 @@ async function shutdown() {
1579
1628
  var sentrial = {
1580
1629
  configure,
1581
1630
  begin,
1631
+ getVariant,
1582
1632
  flush,
1583
1633
  shutdown
1584
1634
  };
@@ -2396,6 +2446,11 @@ function wrapClaudeAgent(queryFn, wrapOptions) {
2396
2446
  var _defaultClient3 = null;
2397
2447
  var _currentInteraction = createContextVar(null);
2398
2448
  function getClient3() {
2449
+ const configuredClient = getDefaultClient();
2450
+ if (configuredClient) {
2451
+ _defaultClient3 = configuredClient;
2452
+ return configuredClient;
2453
+ }
2399
2454
  if (!_defaultClient3) {
2400
2455
  try {
2401
2456
  _defaultClient3 = new SentrialClient();
@@ -3163,6 +3218,7 @@ export {
3163
3218
  getExperimentId,
3164
3219
  getSessionContext,
3165
3220
  getSystemPrompt,
3221
+ getVariant,
3166
3222
  getVariantName,
3167
3223
  hashValue,
3168
3224
  isExperimentMode,