@sentrial/sdk 0.4.3 → 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/README.md +72 -21
- package/dist/cli.cjs +1139 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.cts +77 -0
- package/dist/cli.d.ts +77 -0
- package/dist/cli.js +1100 -0
- package/dist/cli.js.map +1 -0
- package/dist/index.cjs +117 -39
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +69 -8
- package/dist/index.d.ts +69 -8
- package/dist/index.js +115 -38
- package/dist/index.js.map +1 -1
- package/package.json +4 -1
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
|
|
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
|
};
|
|
@@ -1187,11 +1246,13 @@ type StreamTextResult = {
|
|
|
1187
1246
|
}>;
|
|
1188
1247
|
[key: string]: unknown;
|
|
1189
1248
|
};
|
|
1249
|
+
/** String or function that returns a string (for dynamic per-request values) */
|
|
1250
|
+
type StringOrFn = string | (() => string | undefined);
|
|
1190
1251
|
/** Per-instance config passed through closures (not global) */
|
|
1191
1252
|
type WrapperConfig = {
|
|
1192
1253
|
defaultAgent?: string;
|
|
1193
|
-
userId?:
|
|
1194
|
-
convoId?:
|
|
1254
|
+
userId?: StringOrFn;
|
|
1255
|
+
convoId?: StringOrFn;
|
|
1195
1256
|
};
|
|
1196
1257
|
/**
|
|
1197
1258
|
* Configure the Sentrial SDK for Vercel AI SDK integration.
|
|
@@ -1211,8 +1272,8 @@ declare function configureVercel(config: {
|
|
|
1211
1272
|
apiKey?: string;
|
|
1212
1273
|
apiUrl?: string;
|
|
1213
1274
|
defaultAgent?: string;
|
|
1214
|
-
userId?:
|
|
1215
|
-
convoId?:
|
|
1275
|
+
userId?: StringOrFn;
|
|
1276
|
+
convoId?: StringOrFn;
|
|
1216
1277
|
failSilently?: boolean;
|
|
1217
1278
|
}): void;
|
|
1218
1279
|
declare function wrapGenerateText(originalFn: Function, client: SentrialClient, config: WrapperConfig): (params: GenerateTextParams) => Promise<GenerateTextResult>;
|
|
@@ -1246,8 +1307,8 @@ declare function wrapStreamObject(originalFn: Function, client: SentrialClient,
|
|
|
1246
1307
|
declare function wrapAISDK(ai: AIModule, options?: {
|
|
1247
1308
|
client?: SentrialClient;
|
|
1248
1309
|
defaultAgent?: string;
|
|
1249
|
-
userId?:
|
|
1250
|
-
convoId?:
|
|
1310
|
+
userId?: StringOrFn;
|
|
1311
|
+
convoId?: StringOrFn;
|
|
1251
1312
|
}): {
|
|
1252
1313
|
generateText: ReturnType<typeof wrapGenerateText>;
|
|
1253
1314
|
streamText: ReturnType<typeof wrapStreamText>;
|
|
@@ -1887,4 +1948,4 @@ declare class Experiment {
|
|
|
1887
1948
|
getResults(): Promise<ExperimentResults | null>;
|
|
1888
1949
|
}
|
|
1889
1950
|
|
|
1890
|
-
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
|
|
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
|
};
|
|
@@ -1187,11 +1246,13 @@ type StreamTextResult = {
|
|
|
1187
1246
|
}>;
|
|
1188
1247
|
[key: string]: unknown;
|
|
1189
1248
|
};
|
|
1249
|
+
/** String or function that returns a string (for dynamic per-request values) */
|
|
1250
|
+
type StringOrFn = string | (() => string | undefined);
|
|
1190
1251
|
/** Per-instance config passed through closures (not global) */
|
|
1191
1252
|
type WrapperConfig = {
|
|
1192
1253
|
defaultAgent?: string;
|
|
1193
|
-
userId?:
|
|
1194
|
-
convoId?:
|
|
1254
|
+
userId?: StringOrFn;
|
|
1255
|
+
convoId?: StringOrFn;
|
|
1195
1256
|
};
|
|
1196
1257
|
/**
|
|
1197
1258
|
* Configure the Sentrial SDK for Vercel AI SDK integration.
|
|
@@ -1211,8 +1272,8 @@ declare function configureVercel(config: {
|
|
|
1211
1272
|
apiKey?: string;
|
|
1212
1273
|
apiUrl?: string;
|
|
1213
1274
|
defaultAgent?: string;
|
|
1214
|
-
userId?:
|
|
1215
|
-
convoId?:
|
|
1275
|
+
userId?: StringOrFn;
|
|
1276
|
+
convoId?: StringOrFn;
|
|
1216
1277
|
failSilently?: boolean;
|
|
1217
1278
|
}): void;
|
|
1218
1279
|
declare function wrapGenerateText(originalFn: Function, client: SentrialClient, config: WrapperConfig): (params: GenerateTextParams) => Promise<GenerateTextResult>;
|
|
@@ -1246,8 +1307,8 @@ declare function wrapStreamObject(originalFn: Function, client: SentrialClient,
|
|
|
1246
1307
|
declare function wrapAISDK(ai: AIModule, options?: {
|
|
1247
1308
|
client?: SentrialClient;
|
|
1248
1309
|
defaultAgent?: string;
|
|
1249
|
-
userId?:
|
|
1250
|
-
convoId?:
|
|
1310
|
+
userId?: StringOrFn;
|
|
1311
|
+
convoId?: StringOrFn;
|
|
1251
1312
|
}): {
|
|
1252
1313
|
generateText: ReturnType<typeof wrapGenerateText>;
|
|
1253
1314
|
streamText: ReturnType<typeof wrapStreamText>;
|
|
@@ -1887,4 +1948,4 @@ declare class Experiment {
|
|
|
1887
1948
|
getResults(): Promise<ExperimentResults | null>;
|
|
1888
1949
|
}
|
|
1889
1950
|
|
|
1890
|
-
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 =
|
|
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 =
|
|
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
|
|
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
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
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(
|
|
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
|
-
|
|
1269
|
-
|
|
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)
|
|
1332
|
-
|
|
1333
|
-
if (params.
|
|
1334
|
-
|
|
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 = {
|
|
@@ -1565,10 +1611,14 @@ function getClient() {
|
|
|
1565
1611
|
}
|
|
1566
1612
|
function configure(config) {
|
|
1567
1613
|
defaultClient = new SentrialClient(config);
|
|
1614
|
+
setDefaultClient(defaultClient);
|
|
1568
1615
|
}
|
|
1569
1616
|
function begin(params) {
|
|
1570
1617
|
return getClient().begin(params);
|
|
1571
1618
|
}
|
|
1619
|
+
function getVariant(params) {
|
|
1620
|
+
return getClient().getVariant(params);
|
|
1621
|
+
}
|
|
1572
1622
|
async function flush() {
|
|
1573
1623
|
if (defaultClient) await defaultClient.flush();
|
|
1574
1624
|
}
|
|
@@ -1578,11 +1628,16 @@ async function shutdown() {
|
|
|
1578
1628
|
var sentrial = {
|
|
1579
1629
|
configure,
|
|
1580
1630
|
begin,
|
|
1631
|
+
getVariant,
|
|
1581
1632
|
flush,
|
|
1582
1633
|
shutdown
|
|
1583
1634
|
};
|
|
1584
1635
|
|
|
1585
1636
|
// src/vercel.ts
|
|
1637
|
+
function resolveStringOrFn(value, fallback) {
|
|
1638
|
+
if (typeof value === "function") return value() ?? fallback;
|
|
1639
|
+
return value ?? fallback;
|
|
1640
|
+
}
|
|
1586
1641
|
var _defaultClient2 = null;
|
|
1587
1642
|
var _globalConfig = {};
|
|
1588
1643
|
function configureVercel(config) {
|
|
@@ -1591,6 +1646,7 @@ function configureVercel(config) {
|
|
|
1591
1646
|
apiUrl: config.apiUrl,
|
|
1592
1647
|
failSilently: config.failSilently ?? true
|
|
1593
1648
|
});
|
|
1649
|
+
setDefaultClient(_defaultClient2);
|
|
1594
1650
|
_globalConfig = {
|
|
1595
1651
|
defaultAgent: config.defaultAgent,
|
|
1596
1652
|
userId: config.userId,
|
|
@@ -1640,14 +1696,26 @@ function calculateCostForCall(provider, modelId, promptTokens, completionTokens)
|
|
|
1640
1696
|
return 0;
|
|
1641
1697
|
}
|
|
1642
1698
|
}
|
|
1699
|
+
function extractContentText(content) {
|
|
1700
|
+
if (typeof content === "string") return content;
|
|
1701
|
+
if (Array.isArray(content)) {
|
|
1702
|
+
const textParts = content.filter((part) => part && part.type === "text" && typeof part.text === "string").map((part) => part.text);
|
|
1703
|
+
if (textParts.length > 0) return textParts.join("\n");
|
|
1704
|
+
}
|
|
1705
|
+
return JSON.stringify(content);
|
|
1706
|
+
}
|
|
1643
1707
|
function extractInput(params) {
|
|
1644
1708
|
if (params.prompt) return params.prompt;
|
|
1645
1709
|
if (params.messages && params.messages.length > 0) {
|
|
1646
1710
|
const lastUserMessage = [...params.messages].reverse().find((m) => m.role === "user");
|
|
1647
1711
|
if (lastUserMessage) {
|
|
1648
|
-
return
|
|
1712
|
+
return extractContentText(lastUserMessage.content);
|
|
1649
1713
|
}
|
|
1650
|
-
|
|
1714
|
+
const lastNonSystem = [...params.messages].reverse().find((m) => m.role !== "system");
|
|
1715
|
+
if (lastNonSystem) {
|
|
1716
|
+
return extractContentText(lastNonSystem.content);
|
|
1717
|
+
}
|
|
1718
|
+
return "";
|
|
1651
1719
|
}
|
|
1652
1720
|
return "";
|
|
1653
1721
|
}
|
|
@@ -1761,8 +1829,8 @@ function wrapGenerateText(originalFn, client, config) {
|
|
|
1761
1829
|
const sessionId = await client.createSession({
|
|
1762
1830
|
name: `generateText: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
1763
1831
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
1764
|
-
userId: config.userId
|
|
1765
|
-
convoId: config.convoId,
|
|
1832
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
1833
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
1766
1834
|
metadata: {
|
|
1767
1835
|
model: modelId,
|
|
1768
1836
|
provider,
|
|
@@ -1862,6 +1930,7 @@ function wrapStreamText(originalFn, client, config) {
|
|
|
1862
1930
|
const { modelId, provider } = extractModelInfo(params.model);
|
|
1863
1931
|
const input = extractInput(params);
|
|
1864
1932
|
let sessionId = null;
|
|
1933
|
+
let sessionCompleted = false;
|
|
1865
1934
|
let resolveSessionReady;
|
|
1866
1935
|
const sessionReady = new Promise((resolve) => {
|
|
1867
1936
|
resolveSessionReady = resolve;
|
|
@@ -1871,8 +1940,8 @@ function wrapStreamText(originalFn, client, config) {
|
|
|
1871
1940
|
const id = await client.createSession({
|
|
1872
1941
|
name: `streamText: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
1873
1942
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
1874
|
-
userId: config.userId
|
|
1875
|
-
convoId: config.convoId,
|
|
1943
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
1944
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
1876
1945
|
metadata: {
|
|
1877
1946
|
model: modelId,
|
|
1878
1947
|
provider,
|
|
@@ -1928,7 +1997,8 @@ function wrapStreamText(originalFn, client, config) {
|
|
|
1928
1997
|
},
|
|
1929
1998
|
onFinish: async (event) => {
|
|
1930
1999
|
await sessionReady;
|
|
1931
|
-
if (sessionId) {
|
|
2000
|
+
if (sessionId && !sessionCompleted) {
|
|
2001
|
+
sessionCompleted = true;
|
|
1932
2002
|
const durationMs = Date.now() - startTime;
|
|
1933
2003
|
const usage = normalizeUsage(event.totalUsage ?? event.usage);
|
|
1934
2004
|
const resolvedModelId = event.response?.modelId ?? modelId;
|
|
@@ -1958,7 +2028,8 @@ function wrapStreamText(originalFn, client, config) {
|
|
|
1958
2028
|
},
|
|
1959
2029
|
onError: async (event) => {
|
|
1960
2030
|
await sessionReady;
|
|
1961
|
-
if (sessionId) {
|
|
2031
|
+
if (sessionId && !sessionCompleted) {
|
|
2032
|
+
sessionCompleted = true;
|
|
1962
2033
|
const durationMs = Date.now() - startTime;
|
|
1963
2034
|
const msg = event.error?.message ?? "Unknown error";
|
|
1964
2035
|
await client.trackError({
|
|
@@ -2008,8 +2079,8 @@ function wrapGenerateObject(originalFn, client, config) {
|
|
|
2008
2079
|
const sessionId = await client.createSession({
|
|
2009
2080
|
name: `generateObject: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
2010
2081
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
2011
|
-
userId: config.userId
|
|
2012
|
-
convoId: config.convoId,
|
|
2082
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
2083
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
2013
2084
|
metadata: {
|
|
2014
2085
|
model: modelId,
|
|
2015
2086
|
provider,
|
|
@@ -2084,8 +2155,8 @@ function wrapStreamObject(originalFn, client, config) {
|
|
|
2084
2155
|
const id = await client.createSession({
|
|
2085
2156
|
name: `streamObject: ${input.slice(0, 50)}${input.length > 50 ? "..." : ""}`,
|
|
2086
2157
|
agentName: config.defaultAgent ?? "vercel-ai-sdk",
|
|
2087
|
-
userId: config.userId
|
|
2088
|
-
convoId: config.convoId,
|
|
2158
|
+
userId: resolveStringOrFn(config.userId, "anonymous"),
|
|
2159
|
+
convoId: resolveStringOrFn(config.convoId),
|
|
2089
2160
|
metadata: {
|
|
2090
2161
|
model: modelId,
|
|
2091
2162
|
provider,
|
|
@@ -2375,6 +2446,11 @@ function wrapClaudeAgent(queryFn, wrapOptions) {
|
|
|
2375
2446
|
var _defaultClient3 = null;
|
|
2376
2447
|
var _currentInteraction = createContextVar(null);
|
|
2377
2448
|
function getClient3() {
|
|
2449
|
+
const configuredClient = getDefaultClient();
|
|
2450
|
+
if (configuredClient) {
|
|
2451
|
+
_defaultClient3 = configuredClient;
|
|
2452
|
+
return configuredClient;
|
|
2453
|
+
}
|
|
2378
2454
|
if (!_defaultClient3) {
|
|
2379
2455
|
try {
|
|
2380
2456
|
_defaultClient3 = new SentrialClient();
|
|
@@ -3142,6 +3218,7 @@ export {
|
|
|
3142
3218
|
getExperimentId,
|
|
3143
3219
|
getSessionContext,
|
|
3144
3220
|
getSystemPrompt,
|
|
3221
|
+
getVariant,
|
|
3145
3222
|
getVariantName,
|
|
3146
3223
|
hashValue,
|
|
3147
3224
|
isExperimentMode,
|