@sentrial/sdk 0.1.0 → 0.2.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.d.ts CHANGED
@@ -38,6 +38,8 @@ interface CreateSessionParams {
38
38
  agentName: string;
39
39
  /** External user ID (for grouping sessions by end-user) */
40
40
  userId: string;
41
+ /** Optional parent session ID for multi-agent hierarchies */
42
+ parentSessionId?: string;
41
43
  /** Optional metadata */
42
44
  metadata?: Record<string, unknown>;
43
45
  }
@@ -67,6 +69,8 @@ interface CompleteSessionParams {
67
69
  userInput?: string;
68
70
  /** The final assistant response for this session */
69
71
  assistantOutput?: string;
72
+ /** Alias for assistantOutput - the final output text */
73
+ output?: string;
70
74
  }
71
75
  /**
72
76
  * Session data returned from the API
@@ -74,6 +78,7 @@ interface CompleteSessionParams {
74
78
  interface Session {
75
79
  id: string;
76
80
  agentId?: string;
81
+ parentSessionId?: string;
77
82
  name: string;
78
83
  agentName: string;
79
84
  userId: string;
@@ -366,9 +371,13 @@ declare class SentrialClient {
366
371
  private currentState;
367
372
  constructor(config?: SentrialClientConfig);
368
373
  /**
369
- * Make an HTTP request with graceful error handling
374
+ * Make an HTTP request with retry logic and exponential backoff.
375
+ *
376
+ * Retries on transient failures (network errors, timeouts, 429/5xx).
377
+ * Up to MAX_RETRIES attempts with exponential backoff.
370
378
  */
371
379
  private safeRequest;
380
+ private sleep;
372
381
  /**
373
382
  * Create a new session
374
383
  *
@@ -404,6 +413,26 @@ declare class SentrialClient {
404
413
  * @param value - State value
405
414
  */
406
415
  updateState(key: string, value: unknown): void;
416
+ /**
417
+ * Set the user input for a session
418
+ *
419
+ * @param sessionId - Session ID
420
+ * @param input - User input text
421
+ * @returns Updated session or null on error
422
+ */
423
+ setInput(sessionId: string, input: string): Promise<Session | null>;
424
+ /**
425
+ * Track a generic event
426
+ *
427
+ * @param params - Event parameters
428
+ * @returns Event data or null on error
429
+ */
430
+ trackEvent(params: {
431
+ sessionId: string;
432
+ eventType: string;
433
+ eventData?: Record<string, unknown>;
434
+ metadata?: Record<string, unknown>;
435
+ }): Promise<Event | null>;
407
436
  /**
408
437
  * Complete a session with performance metrics
409
438
  *
@@ -462,6 +491,7 @@ interface InteractionConfig {
462
491
  eventId: string;
463
492
  userId: string;
464
493
  event: string;
494
+ userInput?: string;
465
495
  }
466
496
  /**
467
497
  * Represents an in-progress interaction that can be finished.
@@ -485,6 +515,7 @@ declare class Interaction {
485
515
  private success;
486
516
  private failureReason?;
487
517
  private output?;
518
+ private readonly userInput?;
488
519
  private readonly degraded;
489
520
  constructor(config: InteractionConfig);
490
521
  /**
@@ -639,4 +670,911 @@ declare class ValidationError extends SentrialError {
639
670
  constructor(message: string, details?: Record<string, unknown>);
640
671
  }
641
672
 
642
- export { ApiError, type ApiResponse, type BeginParams, type CompleteSessionParams, type CostParams, type CreateSessionParams, type Event, EventType, type FinishParams, Interaction, NetworkError, SentrialClient, type SentrialClientConfig, SentrialError, type Session, type SessionStatus, type TrackDecisionParams, type TrackErrorParams, type TrackToolCallParams, ValidationError, begin, calculateAnthropicCost, calculateGoogleCost, calculateOpenAICost, configure, sentrial };
673
+ /**
674
+ * Vercel AI SDK Integration for Sentrial
675
+ *
676
+ * Automatically traces AI SDK calls with full input/output logging, metrics, and tool execution.
677
+ * Supports Vercel AI SDK v3, v4, v5, and v6.
678
+ *
679
+ * @example Simple Usage
680
+ * ```ts
681
+ * import { configure, wrapAISDK } from '@sentrial/sdk';
682
+ * import * as ai from 'ai';
683
+ * import { openai } from '@ai-sdk/openai';
684
+ *
685
+ * configure({
686
+ * apiKey: process.env.SENTRIAL_API_KEY,
687
+ * defaultAgent: 'my-ai-agent',
688
+ * });
689
+ *
690
+ * const { generateText } = wrapAISDK(ai);
691
+ *
692
+ * // This automatically logs to Sentrial
693
+ * const { text } = await generateText({
694
+ * model: openai('gpt-4'),
695
+ * prompt: 'What is the capital of France?',
696
+ * });
697
+ * ```
698
+ *
699
+ * @example With Tools
700
+ * ```ts
701
+ * import { configure, wrapAISDK } from '@sentrial/sdk';
702
+ * import * as ai from 'ai';
703
+ * import { openai } from '@ai-sdk/openai';
704
+ * import { z } from 'zod';
705
+ *
706
+ * configure({ apiKey: process.env.SENTRIAL_API_KEY, defaultAgent: 'tool-agent' });
707
+ *
708
+ * const { generateText } = wrapAISDK(ai);
709
+ *
710
+ * const { text } = await generateText({
711
+ * model: openai('gpt-4'),
712
+ * prompt: "What's the weather in San Francisco?",
713
+ * tools: {
714
+ * getWeather: {
715
+ * description: 'Get weather for a location',
716
+ * parameters: z.object({ location: z.string() }),
717
+ * execute: async ({ location }) => ({ temperature: 72, conditions: 'sunny' }),
718
+ * },
719
+ * },
720
+ * });
721
+ * // Tool calls are automatically traced as child spans!
722
+ * ```
723
+ *
724
+ * @packageDocumentation
725
+ */
726
+
727
+ type AIModule = {
728
+ generateText?: Function;
729
+ streamText?: Function;
730
+ generateObject?: Function;
731
+ streamObject?: Function;
732
+ experimental_generateText?: Function;
733
+ experimental_streamText?: Function;
734
+ };
735
+ type GenerateTextParams = {
736
+ model: {
737
+ modelId?: string;
738
+ provider?: string;
739
+ } & Record<string, unknown>;
740
+ prompt?: string;
741
+ messages?: Array<{
742
+ role: string;
743
+ content: string;
744
+ }>;
745
+ system?: string;
746
+ tools?: Record<string, {
747
+ execute?: Function;
748
+ } & Record<string, unknown>>;
749
+ maxTokens?: number;
750
+ temperature?: number;
751
+ [key: string]: unknown;
752
+ };
753
+ type GenerateTextResult = {
754
+ text: string;
755
+ usage?: {
756
+ promptTokens?: number;
757
+ completionTokens?: number;
758
+ totalTokens?: number;
759
+ };
760
+ finishReason?: string;
761
+ toolCalls?: Array<{
762
+ toolName: string;
763
+ args: unknown;
764
+ }>;
765
+ toolResults?: Array<{
766
+ toolName: string;
767
+ result: unknown;
768
+ }>;
769
+ response?: {
770
+ modelId?: string;
771
+ };
772
+ [key: string]: unknown;
773
+ };
774
+ type StreamTextResult = {
775
+ textStream: AsyncIterable<string>;
776
+ usage?: Promise<{
777
+ promptTokens?: number;
778
+ completionTokens?: number;
779
+ totalTokens?: number;
780
+ }>;
781
+ finishReason?: Promise<string>;
782
+ toolCalls?: Promise<Array<{
783
+ toolName: string;
784
+ args: unknown;
785
+ }>>;
786
+ toolResults?: Promise<Array<{
787
+ toolName: string;
788
+ result: unknown;
789
+ }>>;
790
+ [key: string]: unknown;
791
+ };
792
+ /**
793
+ * Configure the Sentrial SDK for Vercel AI SDK integration.
794
+ *
795
+ * @example
796
+ * ```ts
797
+ * import { configure } from '@sentrial/sdk';
798
+ *
799
+ * configure({
800
+ * apiKey: process.env.SENTRIAL_API_KEY,
801
+ * defaultAgent: 'my-chatbot',
802
+ * userId: 'user_123', // Optional default user ID
803
+ * });
804
+ * ```
805
+ */
806
+ declare function configureVercel(config: {
807
+ apiKey?: string;
808
+ apiUrl?: string;
809
+ defaultAgent?: string;
810
+ userId?: string;
811
+ failSilently?: boolean;
812
+ }): void;
813
+ /**
814
+ * Wrap generateText function
815
+ */
816
+ declare function wrapGenerateText(originalFn: Function, client: SentrialClient): (params: GenerateTextParams) => Promise<GenerateTextResult>;
817
+ /**
818
+ * Wrap streamText function
819
+ */
820
+ declare function wrapStreamText(originalFn: Function, client: SentrialClient): (params: GenerateTextParams) => StreamTextResult;
821
+ /**
822
+ * Wrap generateObject function (similar to generateText)
823
+ */
824
+ declare function wrapGenerateObject(originalFn: Function, client: SentrialClient): (params: GenerateTextParams) => Promise<unknown>;
825
+ /**
826
+ * Wrap streamObject function
827
+ */
828
+ declare function wrapStreamObject(originalFn: Function, client: SentrialClient): (params: GenerateTextParams) => unknown;
829
+ /**
830
+ * Wrap the Vercel AI SDK to automatically trace all AI calls.
831
+ *
832
+ * @param ai - The imported `ai` module from the Vercel AI SDK
833
+ * @returns Wrapped versions of the AI SDK functions
834
+ *
835
+ * @example
836
+ * ```ts
837
+ * import { configure, wrapAISDK } from '@sentrial/sdk';
838
+ * import * as ai from 'ai';
839
+ * import { openai } from '@ai-sdk/openai';
840
+ *
841
+ * configure({ apiKey: process.env.SENTRIAL_API_KEY, defaultAgent: 'my-agent' });
842
+ *
843
+ * const { generateText, streamText, generateObject, streamObject } = wrapAISDK(ai);
844
+ *
845
+ * // All calls are now automatically traced!
846
+ * const { text } = await generateText({
847
+ * model: openai('gpt-4'),
848
+ * prompt: 'Hello!',
849
+ * });
850
+ * ```
851
+ */
852
+ declare function wrapAISDK(ai: AIModule): {
853
+ generateText: ReturnType<typeof wrapGenerateText>;
854
+ streamText: ReturnType<typeof wrapStreamText>;
855
+ generateObject: ReturnType<typeof wrapGenerateObject>;
856
+ streamObject: ReturnType<typeof wrapStreamObject>;
857
+ };
858
+
859
+ /**
860
+ * Sentrial LLM Wrappers - Auto-instrument LLM provider SDKs
861
+ *
862
+ * These wrappers automatically track all LLM calls with:
863
+ * - Input messages
864
+ * - Output responses
865
+ * - Token counts
866
+ * - Cost estimation
867
+ * - Latency
868
+ *
869
+ * @example OpenAI
870
+ * ```ts
871
+ * import OpenAI from 'openai';
872
+ * import { wrapOpenAI, configure } from '@sentrial/sdk';
873
+ *
874
+ * configure({ apiKey: 'sentrial_live_xxx' });
875
+ *
876
+ * const openai = wrapOpenAI(new OpenAI());
877
+ *
878
+ * // All calls are now automatically tracked!
879
+ * const response = await openai.chat.completions.create({
880
+ * model: 'gpt-4o',
881
+ * messages: [{ role: 'user', content: 'Hello!' }],
882
+ * });
883
+ * ```
884
+ *
885
+ * @example Anthropic
886
+ * ```ts
887
+ * import Anthropic from '@anthropic-ai/sdk';
888
+ * import { wrapAnthropic, configure } from '@sentrial/sdk';
889
+ *
890
+ * configure({ apiKey: 'sentrial_live_xxx' });
891
+ *
892
+ * const anthropic = wrapAnthropic(new Anthropic());
893
+ *
894
+ * const response = await anthropic.messages.create({
895
+ * model: 'claude-3-5-sonnet-20241022',
896
+ * max_tokens: 1024,
897
+ * messages: [{ role: 'user', content: 'Hello!' }],
898
+ * });
899
+ * ```
900
+ */
901
+
902
+ /**
903
+ * Set the current session context for auto-tracking.
904
+ *
905
+ * Call this before making LLM calls to associate them with a session.
906
+ * This is automatically called when using withSession() or decorators.
907
+ *
908
+ * @param sessionId - The session ID to track LLM calls under
909
+ * @param client - Optional Sentrial client (uses default if not provided)
910
+ */
911
+ declare function setSessionContext(sessionId: string, client?: SentrialClient): void;
912
+ /**
913
+ * Clear the current session context.
914
+ */
915
+ declare function clearSessionContext(): void;
916
+ /**
917
+ * Get the current session ID.
918
+ */
919
+ declare function getSessionContext(): string | null;
920
+ /**
921
+ * Set the default client for wrappers.
922
+ */
923
+ declare function setDefaultClient(client: SentrialClient): void;
924
+ /**
925
+ * Wrap an OpenAI client to automatically track all LLM calls.
926
+ *
927
+ * @param client - OpenAI client instance
928
+ * @param options - Wrapper options
929
+ * @returns The same client, now with auto-tracking enabled
930
+ *
931
+ * @example
932
+ * ```ts
933
+ * import OpenAI from 'openai';
934
+ * import { wrapOpenAI, configure } from '@sentrial/sdk';
935
+ *
936
+ * configure({ apiKey: 'sentrial_live_xxx' });
937
+ * const openai = wrapOpenAI(new OpenAI());
938
+ *
939
+ * // Now use client normally - all calls are tracked!
940
+ * const response = await openai.chat.completions.create({
941
+ * model: 'gpt-4o',
942
+ * messages: [{ role: 'user', content: 'Hello' }],
943
+ * });
944
+ * ```
945
+ */
946
+ declare function wrapOpenAI<T extends object>(client: T, options?: {
947
+ trackWithoutSession?: boolean;
948
+ }): T;
949
+ /**
950
+ * Wrap an Anthropic client to automatically track all LLM calls.
951
+ *
952
+ * @param client - Anthropic client instance
953
+ * @param options - Wrapper options
954
+ * @returns The same client, now with auto-tracking enabled
955
+ *
956
+ * @example
957
+ * ```ts
958
+ * import Anthropic from '@anthropic-ai/sdk';
959
+ * import { wrapAnthropic, configure } from '@sentrial/sdk';
960
+ *
961
+ * configure({ apiKey: 'sentrial_live_xxx' });
962
+ * const anthropic = wrapAnthropic(new Anthropic());
963
+ *
964
+ * const response = await anthropic.messages.create({
965
+ * model: 'claude-3-5-sonnet-20241022',
966
+ * max_tokens: 1024,
967
+ * messages: [{ role: 'user', content: 'Hello!' }],
968
+ * });
969
+ * ```
970
+ */
971
+ declare function wrapAnthropic<T extends object>(client: T, options?: {
972
+ trackWithoutSession?: boolean;
973
+ }): T;
974
+ /**
975
+ * Wrap a Google GenerativeModel to automatically track all LLM calls.
976
+ *
977
+ * @param model - Google GenerativeModel instance
978
+ * @param options - Wrapper options
979
+ * @returns The same model, now with auto-tracking enabled
980
+ *
981
+ * @example
982
+ * ```ts
983
+ * import { GoogleGenerativeAI } from '@google/generative-ai';
984
+ * import { wrapGoogle, configure } from '@sentrial/sdk';
985
+ *
986
+ * configure({ apiKey: 'sentrial_live_xxx' });
987
+ *
988
+ * const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY!);
989
+ * const model = wrapGoogle(genAI.getGenerativeModel({ model: 'gemini-2.0-flash' }));
990
+ *
991
+ * const response = await model.generateContent('Hello!');
992
+ * ```
993
+ */
994
+ declare function wrapGoogle<T extends object>(model: T, options?: {
995
+ trackWithoutSession?: boolean;
996
+ }): T;
997
+ /**
998
+ * Auto-detect and wrap any supported LLM client.
999
+ *
1000
+ * @param client - Any supported LLM client (OpenAI, Anthropic, Google)
1001
+ * @param provider - Optional provider hint
1002
+ * @returns The wrapped client
1003
+ *
1004
+ * @example
1005
+ * ```ts
1006
+ * import OpenAI from 'openai';
1007
+ * import { wrapLLM } from '@sentrial/sdk';
1008
+ *
1009
+ * const client = wrapLLM(new OpenAI()); // Auto-detected as OpenAI
1010
+ * ```
1011
+ */
1012
+ declare function wrapLLM<T extends object>(client: T, provider?: 'openai' | 'anthropic' | 'google'): T;
1013
+
1014
+ /**
1015
+ * Sentrial Decorators - Easy instrumentation for AI agents
1016
+ *
1017
+ * Provides decorators and higher-order functions for automatic tracking:
1018
+ * - withTool: Track tool/function calls
1019
+ * - withSession: Create session boundaries around agent runs
1020
+ *
1021
+ * @example Using higher-order functions (works everywhere)
1022
+ * ```ts
1023
+ * import { withTool, withSession, configure } from '@sentrial/sdk';
1024
+ *
1025
+ * configure({ apiKey: 'sentrial_live_xxx' });
1026
+ *
1027
+ * // Wrap a tool function
1028
+ * const searchWeb = withTool('search', async (query: string) => {
1029
+ * return await fetch(`/search?q=${query}`).then(r => r.json());
1030
+ * });
1031
+ *
1032
+ * // Wrap an agent session
1033
+ * const handleRequest = withSession('support-agent', async (userId: string, message: string) => {
1034
+ * const results = await searchWeb(message);
1035
+ * return processResults(results);
1036
+ * });
1037
+ * ```
1038
+ *
1039
+ * @example Using TypeScript decorators (requires experimentalDecorators)
1040
+ * ```ts
1041
+ * import { Tool, Session } from '@sentrial/sdk';
1042
+ *
1043
+ * class MyAgent {
1044
+ * @Tool('search')
1045
+ * async searchWeb(query: string) {
1046
+ * return await fetch(`/search?q=${query}`).then(r => r.json());
1047
+ * }
1048
+ *
1049
+ * @Session('support-agent')
1050
+ * async handleRequest(userId: string, message: string) {
1051
+ * const results = await this.searchWeb(message);
1052
+ * return processResults(results);
1053
+ * }
1054
+ * }
1055
+ * ```
1056
+ */
1057
+
1058
+ /**
1059
+ * Set the default client for decorators
1060
+ */
1061
+ declare function setClient(client: SentrialClient): void;
1062
+ /**
1063
+ * Get the current session ID (if inside a session context)
1064
+ */
1065
+ declare function getCurrentSessionId(): string | null;
1066
+ /**
1067
+ * Get the current interaction (if inside a session context)
1068
+ */
1069
+ declare function getCurrentInteraction(): Interaction | null;
1070
+ type AsyncFunction<TArgs extends unknown[], TReturn> = (...args: TArgs) => Promise<TReturn>;
1071
+ type SyncFunction<TArgs extends unknown[], TReturn> = (...args: TArgs) => TReturn;
1072
+ /**
1073
+ * Wrap a function to automatically track it as a tool call.
1074
+ *
1075
+ * When called within a session context, automatically tracks:
1076
+ * - tool_input: Function arguments
1077
+ * - tool_output: Return value
1078
+ * - duration: Execution time
1079
+ * - errors: Any exceptions raised
1080
+ *
1081
+ * @param name - Name of the tool
1082
+ * @param fn - The function to wrap
1083
+ * @returns Wrapped function with automatic tracking
1084
+ *
1085
+ * @example
1086
+ * ```ts
1087
+ * const searchWeb = withTool('search', async (query: string) => {
1088
+ * return await fetch(`/search?q=${query}`).then(r => r.json());
1089
+ * });
1090
+ *
1091
+ * // Use within a session - automatically tracked
1092
+ * const results = await searchWeb('AI agents');
1093
+ * ```
1094
+ */
1095
+ declare function withTool<TArgs extends unknown[], TReturn>(name: string, fn: AsyncFunction<TArgs, TReturn>): AsyncFunction<TArgs, TReturn>;
1096
+ declare function withTool<TArgs extends unknown[], TReturn>(name: string, fn: SyncFunction<TArgs, TReturn>): SyncFunction<TArgs, TReturn>;
1097
+ interface SessionOptions {
1098
+ /** Parameter index or name for user ID (default: looks for 'userId' or first param) */
1099
+ userIdParam?: string | number;
1100
+ /** Parameter index or name for input (default: looks for 'input', 'message', 'query') */
1101
+ inputParam?: string | number;
1102
+ }
1103
+ /**
1104
+ * Wrap a function to automatically manage a session around it.
1105
+ *
1106
+ * Automatically:
1107
+ * - Creates a session when the function is called
1108
+ * - Sets up context for withTool and wrapped LLM calls
1109
+ * - Captures output from return value
1110
+ * - Completes the session when the function returns
1111
+ * - Marks as failed if an exception is raised
1112
+ *
1113
+ * @param agentName - Name of the agent
1114
+ * @param fn - The function to wrap
1115
+ * @param options - Session options
1116
+ * @returns Wrapped function with automatic session management
1117
+ *
1118
+ * @example
1119
+ * ```ts
1120
+ * const handleRequest = withSession('support-agent', async (userId: string, message: string) => {
1121
+ * // Session automatically created
1122
+ * // All withTool calls and wrapped LLM calls are tracked
1123
+ * const response = await processRequest(message);
1124
+ * return response; // Captured as output
1125
+ * });
1126
+ *
1127
+ * await handleRequest('user_123', 'Hello!');
1128
+ * ```
1129
+ */
1130
+ declare function withSession<TArgs extends unknown[], TReturn>(agentName: string, fn: AsyncFunction<TArgs, TReturn>, options?: SessionOptions): AsyncFunction<TArgs, TReturn>;
1131
+ declare function withSession<TArgs extends unknown[], TReturn>(agentName: string, fn: SyncFunction<TArgs, TReturn>, options?: SessionOptions): AsyncFunction<TArgs, TReturn>;
1132
+ /**
1133
+ * Method decorator to track a method as a tool call.
1134
+ *
1135
+ * @param name - Name of the tool (optional, defaults to method name)
1136
+ *
1137
+ * @example
1138
+ * ```ts
1139
+ * class MyAgent {
1140
+ * @Tool('search')
1141
+ * async searchWeb(query: string) {
1142
+ * return await fetch(`/search?q=${query}`).then(r => r.json());
1143
+ * }
1144
+ * }
1145
+ * ```
1146
+ */
1147
+ declare function Tool(name?: string): MethodDecorator;
1148
+ /**
1149
+ * Method decorator to wrap a method in a session.
1150
+ *
1151
+ * @param agentName - Name of the agent (optional, defaults to class name)
1152
+ * @param options - Session options
1153
+ *
1154
+ * @example
1155
+ * ```ts
1156
+ * class MyAgent {
1157
+ * @TrackSession('support-agent')
1158
+ * async handleRequest(userId: string, message: string) {
1159
+ * // Session automatically created
1160
+ * const results = await this.searchWeb(message);
1161
+ * return processResults(results);
1162
+ * }
1163
+ * }
1164
+ * ```
1165
+ */
1166
+ declare function TrackSession(agentName?: string, options?: SessionOptions): MethodDecorator;
1167
+ /**
1168
+ * Manual session context for when you need more control.
1169
+ *
1170
+ * @example
1171
+ * ```ts
1172
+ * const ctx = new SessionContext({
1173
+ * userId: 'user_123',
1174
+ * agent: 'my-agent',
1175
+ * input: 'Hello!',
1176
+ * });
1177
+ *
1178
+ * await ctx.start();
1179
+ * try {
1180
+ * // All tool calls are tracked
1181
+ * const result = await myTool(...);
1182
+ * ctx.setOutput(result);
1183
+ * await ctx.finish();
1184
+ * } catch (error) {
1185
+ * await ctx.finish({ success: false, error: error.message });
1186
+ * }
1187
+ * ```
1188
+ */
1189
+ declare class SessionContext {
1190
+ private readonly userId;
1191
+ private readonly agent;
1192
+ private readonly input?;
1193
+ private readonly client;
1194
+ private interaction;
1195
+ private output?;
1196
+ constructor(options: {
1197
+ userId: string;
1198
+ agent: string;
1199
+ input?: string;
1200
+ client?: SentrialClient;
1201
+ });
1202
+ /**
1203
+ * Start the session
1204
+ */
1205
+ start(): Promise<this>;
1206
+ /**
1207
+ * Set the output for this session
1208
+ */
1209
+ setOutput(output: string): void;
1210
+ /**
1211
+ * Finish the session
1212
+ */
1213
+ finish(options?: {
1214
+ success?: boolean;
1215
+ error?: string;
1216
+ }): Promise<void>;
1217
+ /**
1218
+ * Get the session ID
1219
+ */
1220
+ get sessionId(): string | null;
1221
+ }
1222
+
1223
+ /**
1224
+ * Sentrial Experiment Context
1225
+ *
1226
+ * Provides context-aware configuration for experiments. When running experiments
1227
+ * via the CLI, the system prompt and other experiment config is automatically
1228
+ * available to your agent code via simple function calls.
1229
+ *
1230
+ * @example
1231
+ * ```ts
1232
+ * import { getSystemPrompt } from '@sentrial/sdk';
1233
+ *
1234
+ * async function myAgent(query: string): Promise<string> {
1235
+ * // When running normally: returns your default
1236
+ * // When running experiment: returns the variant's system prompt
1237
+ * const systemPrompt = getSystemPrompt('You are a helpful assistant.');
1238
+ *
1239
+ * const response = await openai.chat.completions.create({
1240
+ * model: 'gpt-4o',
1241
+ * messages: [
1242
+ * { role: 'system', content: systemPrompt },
1243
+ * { role: 'user', content: query },
1244
+ * ],
1245
+ * });
1246
+ *
1247
+ * return response.choices[0].message.content!;
1248
+ * }
1249
+ * ```
1250
+ *
1251
+ * That's it! No other changes needed. The experiment runner handles setting the context.
1252
+ */
1253
+ /**
1254
+ * Context for the current experiment run.
1255
+ */
1256
+ interface ExperimentContext {
1257
+ /** The system prompt for this variant */
1258
+ systemPrompt: string;
1259
+ /** Name of the variant being tested */
1260
+ variantName: string;
1261
+ /** The experiment ID */
1262
+ experimentId: string;
1263
+ /** The test case session ID (if applicable) */
1264
+ testCaseId?: string;
1265
+ /** Additional metadata */
1266
+ metadata?: Record<string, unknown>;
1267
+ }
1268
+ /**
1269
+ * Get the current system prompt.
1270
+ *
1271
+ * When running an experiment, this returns the variant's system prompt.
1272
+ * Otherwise, returns your default.
1273
+ *
1274
+ * @param defaultPrompt - The default system prompt to use when not in experiment mode.
1275
+ * This should be your normal production prompt.
1276
+ * @returns The system prompt to use.
1277
+ *
1278
+ * @example
1279
+ * ```ts
1280
+ * import { getSystemPrompt } from '@sentrial/sdk';
1281
+ *
1282
+ * async function myAgent(query: string) {
1283
+ * // Just wrap your existing prompt with getSystemPrompt()
1284
+ * const prompt = getSystemPrompt('You are a helpful weather assistant.');
1285
+ *
1286
+ * const response = await openai.chat.completions.create({
1287
+ * model: 'gpt-4o',
1288
+ * messages: [
1289
+ * { role: 'system', content: prompt },
1290
+ * { role: 'user', content: query },
1291
+ * ],
1292
+ * });
1293
+ *
1294
+ * return response.choices[0].message.content;
1295
+ * }
1296
+ * ```
1297
+ */
1298
+ declare function getSystemPrompt(defaultPrompt?: string): string;
1299
+ /**
1300
+ * Get the full experiment context if running in experiment mode.
1301
+ *
1302
+ * Returns null if not running an experiment.
1303
+ *
1304
+ * @returns ExperimentContext with variant info, or null.
1305
+ *
1306
+ * @example
1307
+ * ```ts
1308
+ * import { getExperimentContext } from '@sentrial/sdk';
1309
+ *
1310
+ * const ctx = getExperimentContext();
1311
+ * if (ctx) {
1312
+ * console.log(`Running variant: ${ctx.variantName}`);
1313
+ * }
1314
+ * ```
1315
+ */
1316
+ declare function getExperimentContext(): ExperimentContext | null;
1317
+ /**
1318
+ * Check if currently running in experiment mode.
1319
+ *
1320
+ * @returns True if running via experiment runner, false otherwise.
1321
+ */
1322
+ declare function isExperimentMode(): boolean;
1323
+ /**
1324
+ * Get the current variant name if in experiment mode.
1325
+ *
1326
+ * @returns The variant name (e.g., "Control", "Variant A"), or null.
1327
+ */
1328
+ declare function getVariantName(): string | null;
1329
+ /**
1330
+ * Get the current experiment ID if in experiment mode.
1331
+ *
1332
+ * @returns The experiment ID, or null.
1333
+ */
1334
+ declare function getExperimentId(): string | null;
1335
+ /**
1336
+ * Set the experiment context. Called by the experiment runner before running agent.
1337
+ *
1338
+ * @internal This is an internal function - users don't need to call this directly.
1339
+ */
1340
+ declare function setExperimentContext(context: ExperimentContext): void;
1341
+ /**
1342
+ * Clear the experiment context. Called by the experiment runner after agent completes.
1343
+ *
1344
+ * @internal This is an internal function - users don't need to call this directly.
1345
+ */
1346
+ declare function clearExperimentContext(): void;
1347
+
1348
+ /**
1349
+ * Sentrial Experiments - Run prompt A/B tests with results synced to Sentrial
1350
+ *
1351
+ * @example
1352
+ * ```ts
1353
+ * import { Experiment } from '@sentrial/sdk';
1354
+ *
1355
+ * const experiment = new Experiment('exp_abc123');
1356
+ *
1357
+ * // Get config
1358
+ * await experiment.load();
1359
+ * console.log(`Testing ${experiment.variants.length} variants on ${experiment.testCases.length} inputs`);
1360
+ *
1361
+ * // Run with your agent function
1362
+ * await experiment.run(async (testCase, variant, tracker) => {
1363
+ * // Create a session for this run
1364
+ * const interaction = await client.begin({
1365
+ * userId: 'experiment',
1366
+ * event: 'my-agent',
1367
+ * input: testCase.userInput,
1368
+ * });
1369
+ * tracker.setResultSessionId(interaction.getSessionId()!);
1370
+ *
1371
+ * // Run your agent with the variant's system prompt
1372
+ * const response = await runAgent(testCase.userInput, variant.systemPrompt);
1373
+ *
1374
+ * await interaction.finish({ output: response, success: true });
1375
+ * });
1376
+ * ```
1377
+ *
1378
+ * @example Manual run tracking
1379
+ * ```ts
1380
+ * const experiment = new Experiment('exp_abc123');
1381
+ * await experiment.load();
1382
+ *
1383
+ * for (const variant of experiment.variants) {
1384
+ * for (const testCase of experiment.testCases) {
1385
+ * const tracker = await experiment.trackRun(variant.name, testCase.sessionId);
1386
+ * try {
1387
+ * const sessionId = await runAgent(testCase.userInput, variant.systemPrompt);
1388
+ * tracker.setResultSessionId(sessionId);
1389
+ * await tracker.complete();
1390
+ * } catch (error) {
1391
+ * await tracker.fail(error.message);
1392
+ * }
1393
+ * }
1394
+ * }
1395
+ * ```
1396
+ */
1397
+
1398
+ /**
1399
+ * A prompt variant to test.
1400
+ */
1401
+ interface ExperimentVariant {
1402
+ /** Name of the variant */
1403
+ name: string;
1404
+ /** The system prompt for this variant */
1405
+ systemPrompt: string;
1406
+ /** Optional description */
1407
+ description?: string;
1408
+ }
1409
+ /**
1410
+ * A test case (input) to run against each variant.
1411
+ */
1412
+ interface ExperimentTestCase {
1413
+ /** Session ID of the original session */
1414
+ sessionId: string;
1415
+ /** The user input to test */
1416
+ userInput: string;
1417
+ }
1418
+ /**
1419
+ * Result of a single experiment run.
1420
+ */
1421
+ interface ExperimentRunResult {
1422
+ /** Name of the variant */
1423
+ variantName: string;
1424
+ /** Session ID of the original test case */
1425
+ testCaseSessionId: string;
1426
+ /** Session ID of the result session (if created) */
1427
+ resultSessionId?: string;
1428
+ /** Whether the run succeeded */
1429
+ success: boolean;
1430
+ /** Error message if failed */
1431
+ errorMessage?: string;
1432
+ }
1433
+ /**
1434
+ * Aggregated experiment results.
1435
+ */
1436
+ interface ExperimentResults {
1437
+ experimentId: string;
1438
+ status: string;
1439
+ variants: Array<{
1440
+ name: string;
1441
+ successRate: number;
1442
+ avgScore?: number;
1443
+ avgCost?: number;
1444
+ avgDuration?: number;
1445
+ runCount: number;
1446
+ }>;
1447
+ winner?: string;
1448
+ }
1449
+ /**
1450
+ * Tracks a single experiment run.
1451
+ *
1452
+ * Created by Experiment.trackRun() - use this to manually track runs.
1453
+ */
1454
+ declare class ExperimentRunTracker {
1455
+ private readonly experiment;
1456
+ private readonly variantName;
1457
+ private readonly baseSessionId;
1458
+ private runId?;
1459
+ private resultSessionId?;
1460
+ private _success;
1461
+ private _errorMessage?;
1462
+ /** @internal */
1463
+ constructor(experiment: Experiment, variantName: string, baseSessionId: string);
1464
+ /**
1465
+ * Start the run - creates a run record via API.
1466
+ */
1467
+ start(): Promise<this>;
1468
+ /**
1469
+ * Set the session ID of the result session.
1470
+ */
1471
+ setResultSessionId(sessionId: string): void;
1472
+ /**
1473
+ * Mark the run as complete.
1474
+ */
1475
+ complete(): Promise<void>;
1476
+ /**
1477
+ * Mark the run as failed.
1478
+ */
1479
+ fail(errorMessage: string): Promise<void>;
1480
+ /**
1481
+ * Get the result of this run.
1482
+ */
1483
+ getResult(): ExperimentRunResult;
1484
+ }
1485
+ type AgentFunction = (testCase: ExperimentTestCase, variant: ExperimentVariant, tracker: ExperimentRunTracker) => Promise<void>;
1486
+ /**
1487
+ * Run experiments with results synced to Sentrial.
1488
+ *
1489
+ * @example
1490
+ * ```ts
1491
+ * const experiment = new Experiment('exp_abc123');
1492
+ *
1493
+ * await experiment.load();
1494
+ * console.log(`Testing ${experiment.variants.length} variants`);
1495
+ *
1496
+ * await experiment.run(async (testCase, variant, tracker) => {
1497
+ * const sessionId = await runMyAgent(testCase.userInput, variant.systemPrompt);
1498
+ * tracker.setResultSessionId(sessionId);
1499
+ * });
1500
+ * ```
1501
+ */
1502
+ declare class Experiment {
1503
+ /** The experiment ID */
1504
+ readonly experimentId: string;
1505
+ /** @internal */
1506
+ readonly client: SentrialClient;
1507
+ /** @internal */
1508
+ readonly apiUrl: string;
1509
+ /** @internal */
1510
+ readonly apiKey?: string;
1511
+ private config?;
1512
+ private _variants?;
1513
+ private _testCases?;
1514
+ /**
1515
+ * Create an experiment instance.
1516
+ *
1517
+ * @param experimentId - The experiment ID from Sentrial dashboard
1518
+ * @param options - Configuration options
1519
+ */
1520
+ constructor(experimentId: string, options?: {
1521
+ apiKey?: string;
1522
+ apiUrl?: string;
1523
+ });
1524
+ /**
1525
+ * Make an HTTP request to the API
1526
+ * @internal
1527
+ */
1528
+ request<T>(method: string, path: string, body?: unknown): Promise<T | null>;
1529
+ /**
1530
+ * Load the experiment configuration from the API.
1531
+ */
1532
+ load(): Promise<this>;
1533
+ /**
1534
+ * Get experiment name.
1535
+ */
1536
+ get name(): string;
1537
+ /**
1538
+ * Get experiment status.
1539
+ */
1540
+ get status(): string;
1541
+ /**
1542
+ * Get list of variants to test.
1543
+ */
1544
+ get variants(): ExperimentVariant[];
1545
+ /**
1546
+ * Get list of test cases.
1547
+ */
1548
+ get testCases(): ExperimentTestCase[];
1549
+ /**
1550
+ * Get a specific variant by name.
1551
+ */
1552
+ getVariant(name: string): ExperimentVariant | undefined;
1553
+ /**
1554
+ * Create a run tracker for manual experiment runs.
1555
+ */
1556
+ trackRun(variantName: string, baseSessionId: string): Promise<ExperimentRunTracker>;
1557
+ /**
1558
+ * Run the experiment with all variants and test cases.
1559
+ *
1560
+ * @param agentFn - Function that runs your agent with a test case and variant
1561
+ * @param options - Run options
1562
+ * @returns List of run results
1563
+ */
1564
+ run(agentFn: AgentFunction, options?: {
1565
+ /** Run test cases in parallel */
1566
+ parallel?: boolean;
1567
+ /** Max parallel workers */
1568
+ maxWorkers?: number;
1569
+ }): Promise<ExperimentRunResult[]>;
1570
+ /**
1571
+ * Reset all runs for this experiment (for re-running).
1572
+ */
1573
+ reset(): Promise<boolean>;
1574
+ /**
1575
+ * Fetch aggregated results from the API.
1576
+ */
1577
+ getResults(): Promise<ExperimentResults | null>;
1578
+ }
1579
+
1580
+ export { ApiError, type ApiResponse, type BeginParams, type CompleteSessionParams, type CostParams, type CreateSessionParams, type Event, EventType, Experiment, type ExperimentContext, type ExperimentResults, type ExperimentRunResult, ExperimentRunTracker, type ExperimentTestCase, type ExperimentVariant, type FinishParams, type GenerateTextParams, type GenerateTextResult, Interaction, NetworkError, SentrialClient, type SentrialClientConfig, SentrialError, type Session, SessionContext, type SessionStatus, type StreamTextResult, Tool, type TrackDecisionParams, type TrackErrorParams, TrackSession, type TrackToolCallParams, ValidationError, begin, calculateAnthropicCost, calculateGoogleCost, calculateOpenAICost, clearExperimentContext, clearSessionContext, configure, configureVercel, getCurrentInteraction, getCurrentSessionId, getExperimentContext, getExperimentId, getSessionContext, getSystemPrompt, getVariantName, isExperimentMode, sentrial, setClient, setDefaultClient, setExperimentContext, setSessionContext, withSession, withTool, wrapAISDK, wrapAnthropic, wrapGoogle, wrapLLM, wrapOpenAI };