@posthog/ai 6.5.1 → 7.0.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 +590 -373
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +590 -373
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +330 -346
- package/dist/langchain/index.cjs.map +1 -1
- package/dist/langchain/index.mjs +330 -346
- package/dist/langchain/index.mjs.map +1 -1
- package/dist/openai/index.cjs +152 -15
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.d.ts +1 -1
- package/dist/openai/index.mjs +152 -15
- package/dist/openai/index.mjs.map +1 -1
- package/dist/vercel/index.cjs +157 -8
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +157 -8
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +10 -10
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 = "
|
|
9
|
+
var version = "7.0.0";
|
|
10
10
|
|
|
11
11
|
// Type guards for safer type checking
|
|
12
12
|
|
|
@@ -151,6 +151,110 @@ 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 or choices[].delta (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) {
|
|
206
|
+
// Check both message (non-streaming) and delta (streaming) for annotations
|
|
207
|
+
const content = ('message' in choice ? choice.message : null) || ('delta' in choice ? choice.delta : null);
|
|
208
|
+
if (typeof content === 'object' && content !== null && 'annotations' in content) {
|
|
209
|
+
const annotations = content.annotations;
|
|
210
|
+
if (Array.isArray(annotations)) {
|
|
211
|
+
const hasUrlCitation = annotations.some(ann => {
|
|
212
|
+
return typeof ann === 'object' && ann !== null && 'type' in ann && ann.type === 'url_citation';
|
|
213
|
+
});
|
|
214
|
+
if (hasUrlCitation) {
|
|
215
|
+
return 1;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Check for annotations in output[].content[] (OpenAI Responses API)
|
|
224
|
+
if ('output' in result && Array.isArray(result.output)) {
|
|
225
|
+
for (const item of result.output) {
|
|
226
|
+
if (typeof item === 'object' && item !== null && 'content' in item) {
|
|
227
|
+
const content = item.content;
|
|
228
|
+
if (Array.isArray(content)) {
|
|
229
|
+
for (const contentItem of content) {
|
|
230
|
+
if (typeof contentItem === 'object' && contentItem !== null && 'annotations' in contentItem) {
|
|
231
|
+
const annotations = contentItem.annotations;
|
|
232
|
+
if (Array.isArray(annotations)) {
|
|
233
|
+
const hasUrlCitation = annotations.some(ann => {
|
|
234
|
+
return typeof ann === 'object' && ann !== null && 'type' in ann && ann.type === 'url_citation';
|
|
235
|
+
});
|
|
236
|
+
if (hasUrlCitation) {
|
|
237
|
+
return 1;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// Check for grounding_metadata (Gemini)
|
|
248
|
+
if ('candidates' in result && Array.isArray(result.candidates)) {
|
|
249
|
+
for (const candidate of result.candidates) {
|
|
250
|
+
if (typeof candidate === 'object' && candidate !== null && 'grounding_metadata' in candidate && candidate.grounding_metadata) {
|
|
251
|
+
return 1;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return 0;
|
|
256
|
+
}
|
|
257
|
+
|
|
154
258
|
/**
|
|
155
259
|
* Extract available tool calls from the request parameters.
|
|
156
260
|
* These are the tools provided to the LLM, not the tool calls in the response.
|
|
@@ -269,6 +373,9 @@ const sendEventToPosthog = async ({
|
|
|
269
373
|
} : {}),
|
|
270
374
|
...(usage.cacheCreationInputTokens ? {
|
|
271
375
|
$ai_cache_creation_input_tokens: usage.cacheCreationInputTokens
|
|
376
|
+
} : {}),
|
|
377
|
+
...(usage.webSearchCount ? {
|
|
378
|
+
$ai_web_search_count: usage.webSearchCount
|
|
272
379
|
} : {})
|
|
273
380
|
};
|
|
274
381
|
const properties = {
|
|
@@ -510,13 +617,18 @@ class WrappedCompletions extends Completions {
|
|
|
510
617
|
let accumulatedContent = '';
|
|
511
618
|
let usage = {
|
|
512
619
|
inputTokens: 0,
|
|
513
|
-
outputTokens: 0
|
|
620
|
+
outputTokens: 0,
|
|
621
|
+
webSearchCount: 0
|
|
514
622
|
};
|
|
515
623
|
|
|
516
624
|
// Map to track in-progress tool calls
|
|
517
625
|
const toolCallsInProgress = new Map();
|
|
518
626
|
for await (const chunk of stream1) {
|
|
519
627
|
const choice = chunk?.choices?.[0];
|
|
628
|
+
const chunkWebSearchCount = calculateWebSearchCount(chunk);
|
|
629
|
+
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
630
|
+
usage.webSearchCount = chunkWebSearchCount;
|
|
631
|
+
}
|
|
520
632
|
|
|
521
633
|
// Handle text content
|
|
522
634
|
const deltaContent = choice?.delta?.content;
|
|
@@ -558,6 +670,7 @@ class WrappedCompletions extends Completions {
|
|
|
558
670
|
// Handle usage information
|
|
559
671
|
if (chunk.usage) {
|
|
560
672
|
usage = {
|
|
673
|
+
...usage,
|
|
561
674
|
inputTokens: chunk.usage.prompt_tokens ?? 0,
|
|
562
675
|
outputTokens: chunk.usage.completion_tokens ?? 0,
|
|
563
676
|
reasoningTokens: chunk.usage.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
@@ -612,7 +725,13 @@ class WrappedCompletions extends Completions {
|
|
|
612
725
|
baseURL: this.baseURL,
|
|
613
726
|
params: body,
|
|
614
727
|
httpStatus: 200,
|
|
615
|
-
usage
|
|
728
|
+
usage: {
|
|
729
|
+
inputTokens: usage.inputTokens,
|
|
730
|
+
outputTokens: usage.outputTokens,
|
|
731
|
+
reasoningTokens: usage.reasoningTokens,
|
|
732
|
+
cacheReadInputTokens: usage.cacheReadInputTokens,
|
|
733
|
+
webSearchCount: usage.webSearchCount
|
|
734
|
+
},
|
|
616
735
|
tools: availableTools
|
|
617
736
|
});
|
|
618
737
|
} catch (error) {
|
|
@@ -648,13 +767,14 @@ class WrappedCompletions extends Completions {
|
|
|
648
767
|
if ('choices' in result) {
|
|
649
768
|
const latency = (Date.now() - startTime) / 1000;
|
|
650
769
|
const availableTools = extractAvailableToolCalls('openai', openAIParams);
|
|
770
|
+
const formattedOutput = formatResponseOpenAI(result);
|
|
651
771
|
await sendEventToPosthog({
|
|
652
772
|
client: this.phClient,
|
|
653
773
|
...posthogParams,
|
|
654
774
|
model: openAIParams.model,
|
|
655
775
|
provider: 'openai',
|
|
656
776
|
input: sanitizeOpenAI(openAIParams.messages),
|
|
657
|
-
output:
|
|
777
|
+
output: formattedOutput,
|
|
658
778
|
latency,
|
|
659
779
|
baseURL: this.baseURL,
|
|
660
780
|
params: body,
|
|
@@ -663,7 +783,8 @@ class WrappedCompletions extends Completions {
|
|
|
663
783
|
inputTokens: result.usage?.prompt_tokens ?? 0,
|
|
664
784
|
outputTokens: result.usage?.completion_tokens ?? 0,
|
|
665
785
|
reasoningTokens: result.usage?.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
666
|
-
cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0
|
|
786
|
+
cacheReadInputTokens: result.usage?.prompt_tokens_details?.cached_tokens ?? 0,
|
|
787
|
+
webSearchCount: calculateWebSearchCount(result)
|
|
667
788
|
},
|
|
668
789
|
tools: availableTools
|
|
669
790
|
});
|
|
@@ -725,14 +846,22 @@ class WrappedResponses extends Responses {
|
|
|
725
846
|
let finalContent = [];
|
|
726
847
|
let usage = {
|
|
727
848
|
inputTokens: 0,
|
|
728
|
-
outputTokens: 0
|
|
849
|
+
outputTokens: 0,
|
|
850
|
+
webSearchCount: 0
|
|
729
851
|
};
|
|
730
852
|
for await (const chunk of stream1) {
|
|
853
|
+
if ('response' in chunk && chunk.response) {
|
|
854
|
+
const chunkWebSearchCount = calculateWebSearchCount(chunk.response);
|
|
855
|
+
if (chunkWebSearchCount > 0 && chunkWebSearchCount > (usage.webSearchCount ?? 0)) {
|
|
856
|
+
usage.webSearchCount = chunkWebSearchCount;
|
|
857
|
+
}
|
|
858
|
+
}
|
|
731
859
|
if (chunk.type === 'response.completed' && 'response' in chunk && chunk.response?.output && chunk.response.output.length > 0) {
|
|
732
860
|
finalContent = chunk.response.output;
|
|
733
861
|
}
|
|
734
862
|
if ('response' in chunk && chunk.response?.usage) {
|
|
735
863
|
usage = {
|
|
864
|
+
...usage,
|
|
736
865
|
inputTokens: chunk.response.usage.input_tokens ?? 0,
|
|
737
866
|
outputTokens: chunk.response.usage.output_tokens ?? 0,
|
|
738
867
|
reasoningTokens: chunk.response.usage.output_tokens_details?.reasoning_tokens ?? 0,
|
|
@@ -754,7 +883,13 @@ class WrappedResponses extends Responses {
|
|
|
754
883
|
baseURL: this.baseURL,
|
|
755
884
|
params: body,
|
|
756
885
|
httpStatus: 200,
|
|
757
|
-
usage
|
|
886
|
+
usage: {
|
|
887
|
+
inputTokens: usage.inputTokens,
|
|
888
|
+
outputTokens: usage.outputTokens,
|
|
889
|
+
reasoningTokens: usage.reasoningTokens,
|
|
890
|
+
cacheReadInputTokens: usage.cacheReadInputTokens,
|
|
891
|
+
webSearchCount: usage.webSearchCount
|
|
892
|
+
},
|
|
758
893
|
tools: availableTools
|
|
759
894
|
});
|
|
760
895
|
} catch (error) {
|
|
@@ -789,6 +924,9 @@ class WrappedResponses extends Responses {
|
|
|
789
924
|
if ('output' in result) {
|
|
790
925
|
const latency = (Date.now() - startTime) / 1000;
|
|
791
926
|
const availableTools = extractAvailableToolCalls('openai', openAIParams);
|
|
927
|
+
const formattedOutput = formatResponseOpenAI({
|
|
928
|
+
output: result.output
|
|
929
|
+
});
|
|
792
930
|
await sendEventToPosthog({
|
|
793
931
|
client: this.phClient,
|
|
794
932
|
...posthogParams,
|
|
@@ -796,9 +934,7 @@ class WrappedResponses extends Responses {
|
|
|
796
934
|
model: openAIParams.model,
|
|
797
935
|
provider: 'openai',
|
|
798
936
|
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
799
|
-
output:
|
|
800
|
-
output: result.output
|
|
801
|
-
}),
|
|
937
|
+
output: formattedOutput,
|
|
802
938
|
latency,
|
|
803
939
|
baseURL: this.baseURL,
|
|
804
940
|
params: body,
|
|
@@ -807,7 +943,8 @@ class WrappedResponses extends Responses {
|
|
|
807
943
|
inputTokens: result.usage?.input_tokens ?? 0,
|
|
808
944
|
outputTokens: result.usage?.output_tokens ?? 0,
|
|
809
945
|
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
810
|
-
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0
|
|
946
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
947
|
+
webSearchCount: calculateWebSearchCount(result)
|
|
811
948
|
},
|
|
812
949
|
tools: availableTools
|
|
813
950
|
});
|
|
@@ -845,9 +982,9 @@ class WrappedResponses extends Responses {
|
|
|
845
982
|
} = extractPosthogParams(body);
|
|
846
983
|
const startTime = Date.now();
|
|
847
984
|
const originalCreate = super.create.bind(this);
|
|
848
|
-
const
|
|
849
|
-
const tempCreate =
|
|
850
|
-
|
|
985
|
+
const originalSelfRecord = this;
|
|
986
|
+
const tempCreate = originalSelfRecord['create'];
|
|
987
|
+
originalSelfRecord['create'] = originalCreate;
|
|
851
988
|
try {
|
|
852
989
|
const parentPromise = super.parse(openAIParams, options);
|
|
853
990
|
const wrappedPromise = parentPromise.then(async result => {
|
|
@@ -896,7 +1033,7 @@ class WrappedResponses extends Responses {
|
|
|
896
1033
|
return wrappedPromise;
|
|
897
1034
|
} finally {
|
|
898
1035
|
// Restore our wrapped create method
|
|
899
|
-
|
|
1036
|
+
originalSelfRecord['create'] = tempCreate;
|
|
900
1037
|
}
|
|
901
1038
|
}
|
|
902
1039
|
}
|