openlayer 0.22.2 → 0.23.1

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.
Files changed (65) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/client.d.mts +3 -2
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +3 -2
  5. package/client.d.ts.map +1 -1
  6. package/client.js +15 -2
  7. package/client.js.map +1 -1
  8. package/client.mjs +15 -2
  9. package/client.mjs.map +1 -1
  10. package/internal/detect-platform.js +1 -1
  11. package/internal/detect-platform.js.map +1 -1
  12. package/internal/detect-platform.mjs +1 -1
  13. package/internal/detect-platform.mjs.map +1 -1
  14. package/internal/parse.d.mts.map +1 -1
  15. package/internal/parse.d.ts.map +1 -1
  16. package/internal/parse.js +5 -0
  17. package/internal/parse.js.map +1 -1
  18. package/internal/parse.mjs +5 -0
  19. package/internal/parse.mjs.map +1 -1
  20. package/lib/integrations/openAiTracer.d.mts.map +1 -1
  21. package/lib/integrations/openAiTracer.d.ts.map +1 -1
  22. package/lib/integrations/openAiTracer.js +144 -2
  23. package/lib/integrations/openAiTracer.js.map +1 -1
  24. package/lib/integrations/openAiTracer.mjs +144 -2
  25. package/lib/integrations/openAiTracer.mjs.map +1 -1
  26. package/lib/tracing/tracer.d.mts.map +1 -1
  27. package/lib/tracing/tracer.d.ts.map +1 -1
  28. package/lib/tracing/tracer.js +18 -8
  29. package/lib/tracing/tracer.js.map +1 -1
  30. package/lib/tracing/tracer.mjs +18 -8
  31. package/lib/tracing/tracer.mjs.map +1 -1
  32. package/package.json +1 -1
  33. package/resources/index.d.mts +1 -1
  34. package/resources/index.d.mts.map +1 -1
  35. package/resources/index.d.ts +1 -1
  36. package/resources/index.d.ts.map +1 -1
  37. package/resources/index.js.map +1 -1
  38. package/resources/index.mjs.map +1 -1
  39. package/resources/inference-pipelines/index.d.mts +1 -1
  40. package/resources/inference-pipelines/index.d.mts.map +1 -1
  41. package/resources/inference-pipelines/index.d.ts +1 -1
  42. package/resources/inference-pipelines/index.d.ts.map +1 -1
  43. package/resources/inference-pipelines/index.js.map +1 -1
  44. package/resources/inference-pipelines/index.mjs.map +1 -1
  45. package/resources/inference-pipelines/inference-pipelines.d.mts +65 -1
  46. package/resources/inference-pipelines/inference-pipelines.d.mts.map +1 -1
  47. package/resources/inference-pipelines/inference-pipelines.d.ts +65 -1
  48. package/resources/inference-pipelines/inference-pipelines.d.ts.map +1 -1
  49. package/resources/inference-pipelines/inference-pipelines.js +18 -0
  50. package/resources/inference-pipelines/inference-pipelines.js.map +1 -1
  51. package/resources/inference-pipelines/inference-pipelines.mjs +18 -0
  52. package/resources/inference-pipelines/inference-pipelines.mjs.map +1 -1
  53. package/src/client.ts +22 -3
  54. package/src/internal/detect-platform.ts +1 -1
  55. package/src/internal/parse.ts +6 -0
  56. package/src/lib/integrations/openAiTracer.ts +160 -4
  57. package/src/lib/tracing/tracer.ts +20 -8
  58. package/src/resources/index.ts +2 -0
  59. package/src/resources/inference-pipelines/index.ts +2 -0
  60. package/src/resources/inference-pipelines/inference-pipelines.ts +83 -0
  61. package/src/version.ts +1 -1
  62. package/version.d.mts +1 -1
  63. package/version.d.ts +1 -1
  64. package/version.js +1 -1
  65. package/version.mjs +1 -1
@@ -2,13 +2,15 @@ import OpenAI from 'openai';
2
2
  import { Stream } from 'openai/streaming';
3
3
  import performanceNow from 'performance-now';
4
4
  import { addChatCompletionStepToTrace } from '../tracing/tracer';
5
+ import type { ResponseStreamEvent } from 'openai/resources/responses/responses';
5
6
 
6
7
  export function traceOpenAI(openai: OpenAI): OpenAI {
7
- const createFunction = openai.chat.completions.create;
8
+ // Wrap Chat Completions API
9
+ const chatCreateFunction = openai.chat.completions.create;
8
10
 
9
11
  openai.chat.completions.create = async function (
10
12
  this: typeof openai.chat.completions,
11
- ...args: Parameters<typeof createFunction>
13
+ ...args: Parameters<typeof chatCreateFunction>
12
14
  ): Promise<Stream<OpenAI.Chat.Completions.ChatCompletionChunk> | OpenAI.Chat.Completions.ChatCompletion> {
13
15
  const [params, options] = args;
14
16
  const stream = params?.stream ?? false;
@@ -17,7 +19,7 @@ export function traceOpenAI(openai: OpenAI): OpenAI {
17
19
  const startTime = performanceNow();
18
20
 
19
21
  // Call the original `create` function
20
- let response = await createFunction.apply(this, args);
22
+ let response = await chatCreateFunction.apply(this, args);
21
23
 
22
24
  if (stream) {
23
25
  // Handle streaming responses
@@ -114,7 +116,150 @@ export function traceOpenAI(openai: OpenAI): OpenAI {
114
116
  }
115
117
  // Ensure a return statement is present
116
118
  return undefined as any;
117
- } as typeof createFunction;
119
+ } as typeof chatCreateFunction;
120
+
121
+ // Wrap Responses API (only if available)
122
+ if (!openai.responses) {
123
+ return openai;
124
+ }
125
+ const responsesCreateFunction = openai.responses.create;
126
+
127
+ openai.responses.create = async function (
128
+ this: typeof openai.responses,
129
+ ...args: Parameters<typeof responsesCreateFunction>
130
+ ): Promise<Stream<ResponseStreamEvent> | OpenAI.Responses.Response> {
131
+ const [params, options] = args;
132
+ const stream = params?.stream ?? false;
133
+
134
+ try {
135
+ const startTime = performanceNow();
136
+
137
+ // Call the original `create` function
138
+ let response = await responsesCreateFunction.apply(this, args);
139
+
140
+ if (stream) {
141
+ // Handle streaming responses
142
+ const chunks: ResponseStreamEvent[] = [];
143
+ let collectedOutputData: any[] = [];
144
+ let firstTokenTime: number | undefined;
145
+ let completionTokens: number = 0;
146
+ if (isAsyncIterable(response)) {
147
+ async function* tracedOutputGenerator(): AsyncGenerator<ResponseStreamEvent, void, unknown> {
148
+ for await (const rawChunk of response as AsyncIterable<ResponseStreamEvent>) {
149
+ if (chunks.length === 0) {
150
+ firstTokenTime = performanceNow();
151
+ }
152
+ chunks.push(rawChunk);
153
+
154
+ // Handle different event types
155
+ if (rawChunk.type === 'response.output_text.delta') {
156
+ if ('delta' in rawChunk && rawChunk.delta) {
157
+ collectedOutputData.push(rawChunk.delta);
158
+ }
159
+ } else if (rawChunk.type === 'response.function_call_arguments.delta') {
160
+ if ('delta' in rawChunk && rawChunk.delta) {
161
+ collectedOutputData.push(rawChunk.delta);
162
+ }
163
+ } else if (rawChunk.type === 'response.completed') {
164
+ // Extract final response data
165
+ if ('response' in rawChunk && rawChunk.response) {
166
+ const finalResponse = rawChunk.response;
167
+ completionTokens = finalResponse.usage?.output_tokens ?? 0;
168
+ }
169
+ }
170
+
171
+ yield rawChunk;
172
+ }
173
+ const endTime = performanceNow();
174
+
175
+ // Find the final response from chunks
176
+ const doneChunk = chunks.find((c) => c.type === 'response.completed');
177
+ const finalResponse = doneChunk && 'response' in doneChunk ? (doneChunk as any).response : null;
178
+
179
+ const traceData = {
180
+ name: 'OpenAI Response',
181
+ inputs: { prompt: params.input },
182
+ output: collectedOutputData.join(''),
183
+ latency: endTime - startTime,
184
+ model: finalResponse?.model ?? params.model,
185
+ modelParameters: getResponsesModelParameters(args),
186
+ metadata: { timeToFistToken: firstTokenTime ? firstTokenTime - startTime : null },
187
+ provider: 'OpenAI',
188
+ completionTokens: finalResponse?.usage?.output_tokens ?? completionTokens,
189
+ promptTokens: finalResponse?.usage?.input_tokens ?? 0,
190
+ tokens: finalResponse?.usage?.total_tokens ?? completionTokens,
191
+ startTime: startTime,
192
+ endTime: endTime,
193
+ };
194
+ addChatCompletionStepToTrace(traceData);
195
+ }
196
+ return tracedOutputGenerator() as unknown as Stream<ResponseStreamEvent>;
197
+ }
198
+ } else {
199
+ // Handle non-streaming responses
200
+ response = response as OpenAI.Responses.Response;
201
+ const endTime = performanceNow();
202
+
203
+ // Extract output from the response
204
+ let output: string = response.output_text ?? '';
205
+
206
+ // If output_text is empty, try to extract from output array
207
+ if (!output && response.output && response.output.length > 0) {
208
+ const outputItems: string[] = [];
209
+
210
+ for (const outputItem of response.output) {
211
+ if (outputItem && 'type' in outputItem) {
212
+ if (outputItem.type === 'message' && 'content' in outputItem) {
213
+ // Extract text from message content
214
+ const content = outputItem.content;
215
+ if (Array.isArray(content)) {
216
+ const textContent = content
217
+ .filter((c: any) => c.type === 'output_text')
218
+ .map((c: any) => c.text)
219
+ .join('');
220
+ if (textContent) {
221
+ outputItems.push(textContent);
222
+ }
223
+ }
224
+ } else if (outputItem.type === 'function_call') {
225
+ // Extract function call details - Responses API format
226
+ const functionCall = {
227
+ name: (outputItem as any).name,
228
+ arguments: (outputItem as any).arguments,
229
+ };
230
+ outputItems.push(JSON.stringify(functionCall, null, 2));
231
+ }
232
+ }
233
+ }
234
+
235
+ output = outputItems.join('\n');
236
+ }
237
+
238
+ const traceData = {
239
+ name: 'OpenAI Response',
240
+ inputs: { prompt: params.input },
241
+ output: output,
242
+ latency: endTime - startTime,
243
+ tokens: response.usage?.total_tokens ?? null,
244
+ promptTokens: response.usage?.input_tokens ?? null,
245
+ completionTokens: response.usage?.output_tokens ?? null,
246
+ model: response.model,
247
+ modelParameters: getResponsesModelParameters(args),
248
+ metadata: {},
249
+ provider: 'OpenAI',
250
+ startTime: startTime,
251
+ endTime: endTime,
252
+ };
253
+ addChatCompletionStepToTrace(traceData);
254
+ return response;
255
+ }
256
+ } catch (error) {
257
+ console.error('Failed to trace the create response request with Openlayer', error);
258
+ throw error;
259
+ }
260
+ // Ensure a return statement is present
261
+ return undefined as any;
262
+ } as typeof responsesCreateFunction;
118
263
 
119
264
  return openai;
120
265
  }
@@ -136,5 +281,16 @@ function getModelParameters(args: any): Record<string, any> {
136
281
  };
137
282
  }
138
283
 
284
+ function getResponsesModelParameters(args: any): Record<string, any> {
285
+ const params = args[0];
286
+ return {
287
+ max_output_tokens: params?.max_output_tokens ?? null,
288
+ temperature: params?.temperature ?? null,
289
+ top_p: params?.top_p ?? null,
290
+ parallel_tool_calls: params?.parallel_tool_calls ?? null,
291
+ tool_choice: params?.tool_choice ?? null,
292
+ };
293
+ }
294
+
139
295
  const isAsyncIterable = (x: any) =>
140
296
  x != null && typeof x === 'object' && typeof x[Symbol.asyncIterator] === 'function';
@@ -14,11 +14,22 @@ import Openlayer from '../../index';
14
14
 
15
15
  let currentTrace: Trace | null = null;
16
16
 
17
- const publish = process.env['OPENLAYER_DISABLE_PUBLISH'] != 'true';
17
+ // Lazy-initialized Openlayer client to ensure environment variables are loaded
18
18
  let client: Openlayer | null = null;
19
- if (publish) {
20
- console.debug('Publishing is enabled');
21
- client = new Openlayer();
19
+ let clientInitialized = false;
20
+
21
+ function getOpenlayerClient(): Openlayer | null {
22
+ if (clientInitialized) {
23
+ return client;
24
+ }
25
+ clientInitialized = true;
26
+
27
+ const publish = process.env['OPENLAYER_DISABLE_PUBLISH'] !== 'true';
28
+ if (publish) {
29
+ console.debug('Publishing is enabled');
30
+ client = new Openlayer();
31
+ }
32
+ return client;
22
33
  }
23
34
 
24
35
  export function getCurrentTrace(): Trace | null {
@@ -85,10 +96,11 @@ function createStep(
85
96
  // Post process trace and get the input variable names
86
97
  const { traceData: processedTraceData, inputVariableNames } = postProcessTrace(traceData!);
87
98
 
88
- if (publish && inferencePipelineId) {
99
+ const openlayerClient = getOpenlayerClient();
100
+ if (openlayerClient && inferencePipelineId) {
89
101
  console.debug('Uploading trace to Openlayer...');
90
102
 
91
- client!.inferencePipelines.data
103
+ openlayerClient.inferencePipelines.data
92
104
  .stream(inferencePipelineId, {
93
105
  config: {
94
106
  outputColumnName: 'output',
@@ -121,8 +133,8 @@ function createStep(
121
133
  );
122
134
  });
123
135
  } else {
124
- if (!publish) {
125
- console.debug('Trace upload disabled (OPENLAYER_DISABLE_PUBLISH=true)');
136
+ if (!openlayerClient) {
137
+ console.debug('Trace upload disabled (OPENLAYER_DISABLE_PUBLISH=true or missing API key)');
126
138
  } else if (!inferencePipelineId) {
127
139
  console.warn('Trace upload skipped: OPENLAYER_INFERENCE_PIPELINE_ID environment variable not set');
128
140
  }
@@ -5,8 +5,10 @@ export {
5
5
  InferencePipelines,
6
6
  type InferencePipelineRetrieveResponse,
7
7
  type InferencePipelineUpdateResponse,
8
+ type InferencePipelineRetrieveUsersResponse,
8
9
  type InferencePipelineRetrieveParams,
9
10
  type InferencePipelineUpdateParams,
11
+ type InferencePipelineRetrieveUsersParams,
10
12
  } from './inference-pipelines/inference-pipelines';
11
13
  export {
12
14
  Projects,
@@ -5,8 +5,10 @@ export {
5
5
  InferencePipelines,
6
6
  type InferencePipelineRetrieveResponse,
7
7
  type InferencePipelineUpdateResponse,
8
+ type InferencePipelineRetrieveUsersResponse,
8
9
  type InferencePipelineRetrieveParams,
9
10
  type InferencePipelineUpdateParams,
11
+ type InferencePipelineRetrieveUsersParams,
10
12
  } from './inference-pipelines';
11
13
  export { Rows, type RowUpdateResponse, type RowUpdateParams } from './rows';
12
14
  export { TestResults, type TestResultListResponse, type TestResultListParams } from './test-results';
@@ -71,6 +71,29 @@ export class InferencePipelines extends APIResource {
71
71
  headers: buildHeaders([{ Accept: '*/*' }, options?.headers]),
72
72
  });
73
73
  }
74
+
75
+ /**
76
+ * Get aggregated user data for an inference pipeline with pagination and metadata.
77
+ *
78
+ * Returns a list of users who have interacted with the inference pipeline,
79
+ * including their activity statistics such as session counts, record counts, token
80
+ * usage, and costs.
81
+ *
82
+ * @example
83
+ * ```ts
84
+ * const response =
85
+ * await client.inferencePipelines.retrieveUsers(
86
+ * '182bd5e5-6e1a-4fe4-a799-aa6d9a6ab26e',
87
+ * );
88
+ * ```
89
+ */
90
+ retrieveUsers(
91
+ inferencePipelineID: string,
92
+ query: InferencePipelineRetrieveUsersParams | null | undefined = {},
93
+ options?: RequestOptions,
94
+ ): APIPromise<InferencePipelineRetrieveUsersResponse> {
95
+ return this._client.get(path`/inference-pipelines/${inferencePipelineID}/users`, { query, ...options });
96
+ }
74
97
  }
75
98
 
76
99
  export interface InferencePipelineRetrieveResponse {
@@ -809,6 +832,52 @@ export namespace InferencePipelineUpdateResponse {
809
832
  }
810
833
  }
811
834
 
835
+ export interface InferencePipelineRetrieveUsersResponse {
836
+ /**
837
+ * Array of user aggregation data
838
+ */
839
+ items: Array<InferencePipelineRetrieveUsersResponse.Item>;
840
+ }
841
+
842
+ export namespace InferencePipelineRetrieveUsersResponse {
843
+ export interface Item {
844
+ /**
845
+ * The unique user identifier
846
+ */
847
+ id: string;
848
+
849
+ /**
850
+ * Total cost for this user
851
+ */
852
+ cost: number;
853
+
854
+ /**
855
+ * Timestamp of the user's first event/trace
856
+ */
857
+ dateOfFirstRecord: string;
858
+
859
+ /**
860
+ * Timestamp of the user's last event/trace
861
+ */
862
+ dateOfLastRecord: string;
863
+
864
+ /**
865
+ * Total number of traces/rows for this user
866
+ */
867
+ records: number;
868
+
869
+ /**
870
+ * Count of unique sessions for this user
871
+ */
872
+ sessions: number;
873
+
874
+ /**
875
+ * Total token count for this user
876
+ */
877
+ tokens: number;
878
+ }
879
+ }
880
+
812
881
  export interface InferencePipelineRetrieveParams {
813
882
  /**
814
883
  * Expand specific nested objects.
@@ -834,6 +903,18 @@ export interface InferencePipelineUpdateParams {
834
903
  referenceDatasetUri?: string | null;
835
904
  }
836
905
 
906
+ export interface InferencePipelineRetrieveUsersParams {
907
+ /**
908
+ * The page to return in a paginated query.
909
+ */
910
+ page?: number;
911
+
912
+ /**
913
+ * Maximum number of items to return per page.
914
+ */
915
+ perPage?: number;
916
+ }
917
+
837
918
  InferencePipelines.Data = Data;
838
919
  InferencePipelines.Rows = Rows;
839
920
  InferencePipelines.TestResults = TestResults;
@@ -842,8 +923,10 @@ export declare namespace InferencePipelines {
842
923
  export {
843
924
  type InferencePipelineRetrieveResponse as InferencePipelineRetrieveResponse,
844
925
  type InferencePipelineUpdateResponse as InferencePipelineUpdateResponse,
926
+ type InferencePipelineRetrieveUsersResponse as InferencePipelineRetrieveUsersResponse,
845
927
  type InferencePipelineRetrieveParams as InferencePipelineRetrieveParams,
846
928
  type InferencePipelineUpdateParams as InferencePipelineUpdateParams,
929
+ type InferencePipelineRetrieveUsersParams as InferencePipelineRetrieveUsersParams,
847
930
  };
848
931
 
849
932
  export {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.22.2'; // x-release-please-version
1
+ export const VERSION = '0.23.1'; // x-release-please-version
package/version.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.22.2";
1
+ export declare const VERSION = "0.23.1";
2
2
  //# sourceMappingURL=version.d.mts.map
package/version.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- export declare const VERSION = "0.22.2";
1
+ export declare const VERSION = "0.23.1";
2
2
  //# sourceMappingURL=version.d.ts.map
package/version.js CHANGED
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.VERSION = void 0;
4
- exports.VERSION = '0.22.2'; // x-release-please-version
4
+ exports.VERSION = '0.23.1'; // x-release-please-version
5
5
  //# sourceMappingURL=version.js.map
package/version.mjs CHANGED
@@ -1,2 +1,2 @@
1
- export const VERSION = '0.22.2'; // x-release-please-version
1
+ export const VERSION = '0.23.1'; // x-release-please-version
2
2
  //# sourceMappingURL=version.mjs.map