@posthog/ai 6.5.1 → 6.6.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/anthropic/index.cjs +13 -3
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +13 -3
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +74 -5
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.mjs +74 -5
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +301 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +301 -28
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +42 -1
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +42 -1
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +151 -15
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.mjs +151 -15
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +156 -8
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +156 -8
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +3 -3
package/dist/openai/index.cjs
CHANGED
|
@@ -6,7 +6,7 @@ var openai = require('openai');
|
|
|
6
6
|
var buffer = require('buffer');
|
|
7
7
|
var uuid = require('uuid');
|
|
8
8
|
|
|
9
|
-
var version = "6.
|
|
9
|
+
var version = "6.6.0";
|
|
10
10
|
|
|
11
11
|
// Type guards for safer type checking
|
|
12
12
|
|
|
@@ -151,6 +151,109 @@ const withPrivacyMode = (client, privacyMode, input) => {
|
|
|
151
151
|
return client.privacy_mode || privacyMode ? null : input;
|
|
152
152
|
};
|
|
153
153
|
|
|
154
|
+
/**
|
|
155
|
+
* Calculate web search count from raw API response.
|
|
156
|
+
*
|
|
157
|
+
* Uses a two-tier detection strategy:
|
|
158
|
+
* Priority 1 (Exact Count): Count actual web search calls when available
|
|
159
|
+
* Priority 2 (Binary Detection): Return 1 if web search indicators are present, 0 otherwise
|
|
160
|
+
*
|
|
161
|
+
* @param result - Raw API response from any provider (OpenAI, Perplexity, OpenRouter, Gemini, etc.)
|
|
162
|
+
* @returns Number of web searches performed (exact count or binary 1/0)
|
|
163
|
+
*/
|
|
164
|
+
function calculateWebSearchCount(result) {
|
|
165
|
+
if (!result || typeof result !== 'object') {
|
|
166
|
+
return 0;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Priority 1: Exact Count
|
|
170
|
+
// Check for OpenAI Responses API web_search_call items
|
|
171
|
+
if ('output' in result && Array.isArray(result.output)) {
|
|
172
|
+
let count = 0;
|
|
173
|
+
for (const item of result.output) {
|
|
174
|
+
if (typeof item === 'object' && item !== null && 'type' in item && item.type === 'web_search_call') {
|
|
175
|
+
count++;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (count > 0) {
|
|
179
|
+
return count;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Priority 2: Binary Detection (1 or 0)
|
|
184
|
+
|
|
185
|
+
// Check for citations at root level (Perplexity)
|
|
186
|
+
if ('citations' in result && Array.isArray(result.citations) && result.citations.length > 0) {
|
|
187
|
+
return 1;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Check for search_results at root level (Perplexity via OpenRouter)
|
|
191
|
+
if ('search_results' in result && Array.isArray(result.search_results) && result.search_results.length > 0) {
|
|
192
|
+
return 1;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Check for usage.search_context_size (Perplexity via OpenRouter)
|
|
196
|
+
if ('usage' in result && typeof result.usage === 'object' && result.usage !== null) {
|
|
197
|
+
if ('search_context_size' in result.usage && result.usage.search_context_size) {
|
|
198
|
+
return 1;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Check for annotations with url_citation in choices[].message (OpenAI/Perplexity)
|
|
203
|
+
if ('choices' in result && Array.isArray(result.choices)) {
|
|
204
|
+
for (const choice of result.choices) {
|
|
205
|
+
if (typeof choice === 'object' && choice !== null && 'message' in choice) {
|
|
206
|
+
const message = choice.message;
|
|
207
|
+
if (typeof message === 'object' && message !== null && 'annotations' in message) {
|
|
208
|
+
const annotations = message.annotations;
|
|
209
|
+
if (Array.isArray(annotations)) {
|
|
210
|
+
const hasUrlCitation = annotations.some(ann => {
|
|
211
|
+
return typeof ann === 'object' && ann !== null && 'type' in ann && ann.type === 'url_citation';
|
|
212
|
+
});
|
|
213
|
+
if (hasUrlCitation) {
|
|
214
|
+
return 1;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Check for annotations in output[].content[] (OpenAI Responses API)
|
|
223
|
+
if ('output' in result && Array.isArray(result.output)) {
|
|
224
|
+
for (const item of result.output) {
|
|
225
|
+
if (typeof item === 'object' && item !== null && 'content' in item) {
|
|
226
|
+
const content = item.content;
|
|
227
|
+
if (Array.isArray(content)) {
|
|
228
|
+
for (const contentItem of content) {
|
|
229
|
+
if (typeof contentItem === 'object' && contentItem !== null && 'annotations' in contentItem) {
|
|
230
|
+
const annotations = contentItem.annotations;
|
|
231
|
+
if (Array.isArray(annotations)) {
|
|
232
|
+
const hasUrlCitation = annotations.some(ann => {
|
|
233
|
+
return typeof ann === 'object' && ann !== null && 'type' in ann && ann.type === 'url_citation';
|
|
234
|
+
});
|
|
235
|
+
if (hasUrlCitation) {
|
|
236
|
+
return 1;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Check for grounding_metadata (Gemini)
|
|
247
|
+
if ('candidates' in result && Array.isArray(result.candidates)) {
|
|
248
|
+
for (const candidate of result.candidates) {
|
|
249
|
+
if (typeof candidate === 'object' && candidate !== null && 'grounding_metadata' in candidate && candidate.grounding_metadata) {
|
|
250
|
+
return 1;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return 0;
|
|
255
|
+
}
|
|
256
|
+
|
|
154
257
|
/**
|
|
155
258
|
* Extract available tool calls from the request parameters.
|
|
156
259
|
* These are the tools provided to the LLM, not the tool calls in the response.
|
|
@@ -269,6 +372,9 @@ const sendEventToPosthog = async ({
|
|
|
269
372
|
} : {}),
|
|
270
373
|
...(usage.cacheCreationInputTokens ? {
|
|
271
374
|
$ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
|
|
375
|
+
} : {}),
|
|
376
|
+
...(usage.webSearchCount ? {
|
|
377
|
+
$ai_web_search_count: usage.webSearchCount
|
|
272
378
|
} : {})
|
|
273
379
|
};
|
|
274
380
|
const properties = {
|
|
@@ -510,13 +616,18 @@ class WrappedCompletions extends Completions {
|
|
|
510
616
|
let accumulatedContent = '';
|
|
511
617
|
let usage = {
|
|
512
618
|
inputTokens: 0,
|
|
513
|
-
outputTokens: 0
|
|
619
|
+
outputTokens: 0,
|
|
620
|
+
webSearchCount: 0
|
|
514
621
|
};
|
|
515
622
|
|
|
516
623
|
// Map to track in-progress tool calls
|
|
517
624
|
const toolCallsInProgress = new Map();
|
|
518
625
|
for await (const chunk of stream1) {
|
|
519
626
|
const choice = chunk?.choices?.[0];
|
|
627
|
+
const chunkWebSearchCount = calculateWebSearchCount(chunk);
|
|
628
|
+
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
629
|
+
usage.webSearchCount = chunkWebSearchCount;
|
|
630
|
+
}
|
|
520
631
|
|
|
521
632
|
// Handle text content
|
|
522
633
|
const deltaContent = choice?.delta?.content;
|
|
@@ -558,6 +669,7 @@ class WrappedCompletions extends Completions {
|
|
|
558
669
|
// Handle usage information
|
|
559
670
|
if (chunk.usage) {
|
|
560
671
|
usage = {
|
|
672
|
+
...usage,
|
|
561
673
|
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
562
674
|
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
563
675
|
reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
@@ -612,7 +724,13 @@ class WrappedCompletions extends Completions {
|
|
|
612
724
|
baseURL: this.baseURL,
|
|
613
725
|
params: body,
|
|
614
726
|
httpStatus: 200,
|
|
615
|
-
usage
|
|
727
|
+
usage: {
|
|
728
|
+
inputTokens: usage.inputTokens,
|
|
729
|
+
outputTokens: usage.outputTokens,
|
|
730
|
+
reasoningTokens: usage.reasoningTokens,
|
|
731
|
+
cacheReadInputTokens: usage.cacheReadInputTokens,
|
|
732
|
+
webSearchCount: usage.webSearchCount
|
|
733
|
+
},
|
|
616
734
|
tools: availableTools
|
|
617
735
|
});
|
|
618
736
|
} catch (error) {
|
|
@@ -648,13 +766,14 @@ class WrappedCompletions extends Completions {
|
|
|
648
766
|
if ('choices' in result) {
|
|
649
767
|
const latency = (Date.now() - startTime) / 1000;
|
|
650
768
|
const availableTools = extractAvailableToolCalls('openai', openAIParams);
|
|
769
|
+
const formattedOutput = formatResponseOpenAI(result);
|
|
651
770
|
await sendEventToPosthog({
|
|
652
771
|
client: this.phClient,
|
|
653
772
|
...posthogParams,
|
|
654
773
|
model: openAIParams.model,
|
|
655
774
|
provider: 'openai',
|
|
656
775
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
657
|
-
output:
|
|
776
|
+
output: formattedOutput,
|
|
658
777
|
latency,
|
|
659
778
|
baseURL: this.baseURL,
|
|
660
779
|
params: body,
|
|
@@ -663,7 +782,8 @@ class WrappedCompletions extends Completions {
|
|
|
663
782
|
inputTokens: result.usage?.prompt_tokens ?? 0,
|
|
664
783
|
outputTokens: result.usage?.completion_tokens ?? 0,
|
|
665
784
|
reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
666
|
-
cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
|
|
785
|
+
cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0,
|
|
786
|
+
webSearchCount: calculateWebSearchCount(result)
|
|
667
787
|
},
|
|
668
788
|
tools: availableTools
|
|
669
789
|
});
|
|
@@ -725,14 +845,22 @@ class WrappedResponses extends Responses {
|
|
|
725
845
|
let finalContent = [];
|
|
726
846
|
let usage = {
|
|
727
847
|
inputTokens: 0,
|
|
728
|
-
outputTokens: 0
|
|
848
|
+
outputTokens: 0,
|
|
849
|
+
webSearchCount: 0
|
|
729
850
|
};
|
|
730
851
|
for await (const chunk of stream1) {
|
|
852
|
+
if ('response' in chunk && chunk.response) {
|
|
853
|
+
const chunkWebSearchCount = calculateWebSearchCount(chunk.response);
|
|
854
|
+
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
855
|
+
usage.webSearchCount = chunkWebSearchCount;
|
|
856
|
+
}
|
|
857
|
+
}
|
|
731
858
|
if (chunk.type === 'response.completed' && 'response' in chunk && chunk.response?.output && chunk.response.output.length > 0) {
|
|
732
859
|
finalContent = chunk.response.output;
|
|
733
860
|
}
|
|
734
861
|
if ('response' in chunk && chunk.response?.usage) {
|
|
735
862
|
usage = {
|
|
863
|
+
...usage,
|
|
736
864
|
inputTokens: chunk.response.usage.input_tokens ?? 0,
|
|
737
865
|
outputTokens: chunk.response.usage.output_tokens ?? 0,
|
|
738
866
|
reasoningTokens: chunk.response.usage.output_tokens_details?.reasoning_tokens ?? 0,
|
|
@@ -754,7 +882,13 @@ class WrappedResponses extends Responses {
|
|
|
754
882
|
baseURL: this.baseURL,
|
|
755
883
|
params: body,
|
|
756
884
|
httpStatus: 200,
|
|
757
|
-
usage
|
|
885
|
+
usage: {
|
|
886
|
+
inputTokens: usage.inputTokens,
|
|
887
|
+
outputTokens: usage.outputTokens,
|
|
888
|
+
reasoningTokens: usage.reasoningTokens,
|
|
889
|
+
cacheReadInputTokens: usage.cacheReadInputTokens,
|
|
890
|
+
webSearchCount: usage.webSearchCount
|
|
891
|
+
},
|
|
758
892
|
tools: availableTools
|
|
759
893
|
});
|
|
760
894
|
} catch (error) {
|
|
@@ -789,6 +923,9 @@ class WrappedResponses extends Responses {
|
|
|
789
923
|
if ('output' in result) {
|
|
790
924
|
const latency = (Date.now() - startTime) / 1000;
|
|
791
925
|
const availableTools = extractAvailableToolCalls('openai', openAIParams);
|
|
926
|
+
const formattedOutput = formatResponseOpenAI({
|
|
927
|
+
output: result.output
|
|
928
|
+
});
|
|
792
929
|
await sendEventToPosthog({
|
|
793
930
|
client: this.phClient,
|
|
794
931
|
...posthogParams,
|
|
@@ -796,9 +933,7 @@ class WrappedResponses extends Responses {
|
|
|
796
933
|
model: openAIParams.model,
|
|
797
934
|
provider: 'openai',
|
|
798
935
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
799
|
-
output:
|
|
800
|
-
output: result.output
|
|
801
|
-
}),
|
|
936
|
+
output: formattedOutput,
|
|
802
937
|
latency,
|
|
803
938
|
baseURL: this.baseURL,
|
|
804
939
|
params: body,
|
|
@@ -807,7 +942,8 @@ class WrappedResponses extends Responses {
|
|
|
807
942
|
inputTokens: result.usage?.input_tokens ?? 0,
|
|
808
943
|
outputTokens: result.usage?.output_tokens ?? 0,
|
|
809
944
|
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
810
|
-
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0
|
|
945
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
946
|
+
webSearchCount: calculateWebSearchCount(result)
|
|
811
947
|
},
|
|
812
948
|
tools: availableTools
|
|
813
949
|
});
|
|
@@ -845,9 +981,9 @@ class WrappedResponses extends Responses {
|
|
|
845
981
|
} = extractPosthogParams(body);
|
|
846
982
|
const startTime = Date.now();
|
|
847
983
|
const originalCreate = super.create.bind(this);
|
|
848
|
-
const
|
|
849
|
-
const tempCreate =
|
|
850
|
-
|
|
984
|
+
const originalSelfRecord = this;
|
|
985
|
+
const tempCreate = originalSelfRecord['create'];
|
|
986
|
+
originalSelfRecord['create'] = originalCreate;
|
|
851
987
|
try {
|
|
852
988
|
const parentPromise = super.parse(openAIParams, options);
|
|
853
989
|
const wrappedPromise = parentPromise.then(async result => {
|
|
@@ -896,7 +1032,7 @@ class WrappedResponses extends Responses {
|
|
|
896
1032
|
return wrappedPromise;
|
|
897
1033
|
} finally {
|
|
898
1034
|
// Restore our wrapped create method
|
|
899
|
-
|
|
1035
|
+
originalSelfRecord['create'] = tempCreate;
|
|
900
1036
|
}
|
|
901
1037
|
}
|
|
902
1038
|
}
|