@posthog/ai 8.6.5 → 8.6.7
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 +4 -2
- package/dist/anthropic/index.cjs.map +1 -1
- package/dist/anthropic/index.mjs +4 -2
- package/dist/anthropic/index.mjs.map +1 -1
- package/dist/gemini/index.cjs +4 -2
- package/dist/gemini/index.cjs.map +1 -1
- package/dist/gemini/index.mjs +4 -2
- package/dist/gemini/index.mjs.map +1 -1
- package/dist/index.cjs +5 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +5 -3
- package/dist/index.mjs.map +1 -1
- package/dist/langchain/index.cjs +1 -1
- package/dist/langchain/index.mjs +1 -1
- package/dist/openai/index.cjs +303 -7
- package/dist/openai/index.cjs.map +1 -1
- package/dist/openai/index.d.ts +13 -1
- package/dist/openai/index.mjs +303 -7
- package/dist/openai/index.mjs.map +1 -1
- package/dist/openai-agents/index.cjs +1 -1
- package/dist/openai-agents/index.mjs +1 -1
- package/dist/vercel/index.cjs +5 -3
- package/dist/vercel/index.cjs.map +1 -1
- package/dist/vercel/index.mjs +5 -3
- package/dist/vercel/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/openai/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import OpenAIOrignal, { AzureOpenAI, APIPromise, OpenAI, ClientOptions } from 'openai';
|
|
2
2
|
import { PostHog } from 'posthog-node';
|
|
3
3
|
import { Stream } from 'openai/streaming';
|
|
4
|
-
import { ParsedResponse } from 'openai/resources/responses/responses';
|
|
4
|
+
import { ResponseRetrieveParamsNonStreaming, ResponseRetrieveParamsStreaming, ResponseRetrieveParamsBase, ParsedResponse } from 'openai/resources/responses/responses';
|
|
5
5
|
import { ResponseCreateParamsWithTools, ExtractParsedContentFromParams } from 'openai/lib/ResponsesParser';
|
|
6
6
|
import { AzureClientOptions } from 'openai/azure';
|
|
7
7
|
|
|
@@ -62,10 +62,16 @@ declare class WrappedCompletions$1 extends AzureOpenAI.Chat.Completions {
|
|
|
62
62
|
declare class WrappedResponses$1 extends AzureOpenAI.Responses {
|
|
63
63
|
private readonly phClient;
|
|
64
64
|
private readonly baseURL;
|
|
65
|
+
private readonly backgroundResponses;
|
|
65
66
|
constructor(client: AzureOpenAI, phClient: PostHog);
|
|
67
|
+
private captureBackgroundResponse;
|
|
66
68
|
create(body: ResponsesCreateParamsNonStreaming$1 & MonitoringParams, options?: RequestOptions$1): APIPromise<OpenAIOrignal.Responses.Response>;
|
|
67
69
|
create(body: ResponsesCreateParamsStreaming$1 & MonitoringParams, options?: RequestOptions$1): APIPromise<Stream<OpenAIOrignal.Responses.ResponseStreamEvent>>;
|
|
68
70
|
create(body: ResponsesCreateParamsBase$1 & MonitoringParams, options?: RequestOptions$1): APIPromise<OpenAIOrignal.Responses.Response | Stream<OpenAIOrignal.Responses.ResponseStreamEvent>>;
|
|
71
|
+
retrieve(responseID: string, query?: ResponseRetrieveParamsNonStreaming, options?: RequestOptions$1): APIPromise<OpenAIOrignal.Responses.Response>;
|
|
72
|
+
retrieve(responseID: string, query: ResponseRetrieveParamsStreaming, options?: RequestOptions$1): APIPromise<Stream<OpenAIOrignal.Responses.ResponseStreamEvent>>;
|
|
73
|
+
retrieve(responseID: string, query?: ResponseRetrieveParamsBase, options?: RequestOptions$1): APIPromise<OpenAIOrignal.Responses.Response | Stream<OpenAIOrignal.Responses.ResponseStreamEvent>>;
|
|
74
|
+
cancel(responseID: string, options?: RequestOptions$1): APIPromise<OpenAIOrignal.Responses.Response>;
|
|
69
75
|
parse<Params extends ResponseCreateParamsWithTools, ParsedT = ExtractParsedContentFromParams<Params>>(body: Params & MonitoringParams, options?: RequestOptions$1): APIPromise<ParsedResponse<ParsedT>>;
|
|
70
76
|
}
|
|
71
77
|
declare class WrappedEmbeddings$1 extends AzureOpenAI.Embeddings {
|
|
@@ -120,10 +126,16 @@ declare class WrappedCompletions extends Completions {
|
|
|
120
126
|
declare class WrappedResponses extends Responses {
|
|
121
127
|
private readonly phClient;
|
|
122
128
|
private readonly baseURL;
|
|
129
|
+
private readonly backgroundResponses;
|
|
123
130
|
constructor(client: OpenAI, phClient: PostHog);
|
|
131
|
+
private captureBackgroundResponse;
|
|
124
132
|
create(body: ResponsesCreateParamsNonStreaming & MonitoringParams, options?: RequestOptions): APIPromise<OpenAI.Responses.Response>;
|
|
125
133
|
create(body: ResponsesCreateParamsStreaming & MonitoringParams, options?: RequestOptions): APIPromise<Stream<OpenAI.Responses.ResponseStreamEvent>>;
|
|
126
134
|
create(body: ResponsesCreateParamsBase & MonitoringParams, options?: RequestOptions): APIPromise<OpenAI.Responses.Response | Stream<OpenAI.Responses.ResponseStreamEvent>>;
|
|
135
|
+
retrieve(responseID: string, query?: ResponseRetrieveParamsNonStreaming, options?: RequestOptions): APIPromise<OpenAI.Responses.Response>;
|
|
136
|
+
retrieve(responseID: string, query: ResponseRetrieveParamsStreaming, options?: RequestOptions): APIPromise<Stream<OpenAI.Responses.ResponseStreamEvent>>;
|
|
137
|
+
retrieve(responseID: string, query?: ResponseRetrieveParamsBase, options?: RequestOptions): APIPromise<OpenAI.Responses.Response | Stream<OpenAI.Responses.ResponseStreamEvent>>;
|
|
138
|
+
cancel(responseID: string, options?: RequestOptions): APIPromise<OpenAI.Responses.Response>;
|
|
127
139
|
parse<Params extends ResponseCreateParamsWithTools, ParsedT = ExtractParsedContentFromParams<Params>>(body: Params & MonitoringParams, options?: RequestOptions): APIPromise<ParsedResponse<ParsedT>>;
|
|
128
140
|
}
|
|
129
141
|
declare class WrappedEmbeddings extends Embeddings {
|
package/dist/openai/index.mjs
CHANGED
|
@@ -544,7 +544,7 @@ function formatOpenAIResponsesInput(input, instructions) {
|
|
|
544
544
|
return messages;
|
|
545
545
|
}
|
|
546
546
|
|
|
547
|
-
var version = "8.6.
|
|
547
|
+
var version = "8.6.7";
|
|
548
548
|
|
|
549
549
|
const DEFAULT_MAX_DEPTH = 3;
|
|
550
550
|
const MAX_STACK_LINES = 20;
|
|
@@ -742,7 +742,9 @@ const captureAiGeneration$1 = async (client, options) => {
|
|
|
742
742
|
$ai_output_tokens: usage.outputTokens
|
|
743
743
|
} : {}),
|
|
744
744
|
...additionalTokenValues,
|
|
745
|
-
|
|
745
|
+
...(options.latency !== undefined ? {
|
|
746
|
+
$ai_latency: options.latency
|
|
747
|
+
} : {}),
|
|
746
748
|
...(options.timeToFirstToken !== undefined ? {
|
|
747
749
|
$ai_time_to_first_token: options.timeToFirstToken
|
|
748
750
|
} : {}),
|
|
@@ -883,6 +885,77 @@ function getResponseFailure(response) {
|
|
|
883
885
|
} : new Error(`OpenAI response ${response.id} failed without error details`);
|
|
884
886
|
}
|
|
885
887
|
|
|
888
|
+
function isPendingBackgroundResponse(params, response) {
|
|
889
|
+
return params.background === true && !!response.status && !isTerminalResponse(response);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
/**
|
|
893
|
+
* Uses provider timestamps so background polling cadence does not inflate
|
|
894
|
+
* generation latency. Non-completed responses do not expose a terminal time.
|
|
895
|
+
*/
|
|
896
|
+
function getBackgroundResponseLatency(response) {
|
|
897
|
+
if (typeof response.created_at !== 'number' || typeof response.completed_at !== 'number') {
|
|
898
|
+
return undefined;
|
|
899
|
+
}
|
|
900
|
+
return Math.max(0, response.completed_at - response.created_at);
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
/**
|
|
904
|
+
* Keeps the original create context available while a background response is
|
|
905
|
+
* polled. Entries are insertion ordered, so the oldest context is discarded
|
|
906
|
+
* when the bound is reached.
|
|
907
|
+
*/
|
|
908
|
+
class BackgroundResponseTracker {
|
|
909
|
+
contexts = new Map();
|
|
910
|
+
constructor(maxEntries = 1000) {
|
|
911
|
+
this.maxEntries = maxEntries;
|
|
912
|
+
}
|
|
913
|
+
set(responseID, context) {
|
|
914
|
+
// Refresh an existing response's insertion order.
|
|
915
|
+
this.contexts.delete(responseID);
|
|
916
|
+
this.contexts.set(responseID, context);
|
|
917
|
+
while (this.contexts.size > this.maxEntries) {
|
|
918
|
+
const oldestResponseID = this.contexts.keys().next().value;
|
|
919
|
+
if (oldestResponseID === undefined) {
|
|
920
|
+
break;
|
|
921
|
+
}
|
|
922
|
+
this.contexts.delete(oldestResponseID);
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
get(responseID) {
|
|
926
|
+
return this.contexts.get(responseID);
|
|
927
|
+
}
|
|
928
|
+
take(responseID) {
|
|
929
|
+
const context = this.contexts.get(responseID);
|
|
930
|
+
if (context !== undefined) {
|
|
931
|
+
this.contexts.delete(responseID);
|
|
932
|
+
}
|
|
933
|
+
return context;
|
|
934
|
+
}
|
|
935
|
+
}
|
|
936
|
+
|
|
937
|
+
/**
|
|
938
|
+
* Inspects a streamed background retrieval without consuming it on the
|
|
939
|
+
* caller's behalf. The stored create context is consumed only by a terminal
|
|
940
|
+
* response; an interrupted or nonterminal stream may be followed by another
|
|
941
|
+
* retrieval while the background job continues.
|
|
942
|
+
*/
|
|
943
|
+
function wrapBackgroundResponseStream(stream, responseID, tracker, captureTerminalResponse) {
|
|
944
|
+
async function* inspectStream() {
|
|
945
|
+
for await (const event of stream) {
|
|
946
|
+
if ('response' in event && isTerminalResponse(event.response)) {
|
|
947
|
+
const context = tracker.take(responseID);
|
|
948
|
+
if (context) {
|
|
949
|
+
// Monitoring must not delay or disrupt delivery of the provider stream.
|
|
950
|
+
void captureTerminalResponse(event.response, context).catch(() => undefined);
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
yield event;
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
return new Stream(() => inspectStream(), stream.controller);
|
|
957
|
+
}
|
|
958
|
+
|
|
886
959
|
function addRequestId(result, response, requestIdHeader) {
|
|
887
960
|
if (!result || typeof result !== 'object' || Array.isArray(result)) {
|
|
888
961
|
return result;
|
|
@@ -1462,11 +1535,43 @@ let WrappedCompletions$1 = class WrappedCompletions extends AzureOpenAI.Chat.Com
|
|
|
1462
1535
|
}
|
|
1463
1536
|
};
|
|
1464
1537
|
let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
1538
|
+
backgroundResponses = new BackgroundResponseTracker();
|
|
1465
1539
|
constructor(client, phClient) {
|
|
1466
1540
|
super(client);
|
|
1467
1541
|
this.phClient = phClient;
|
|
1468
1542
|
this.baseURL = client.baseURL;
|
|
1469
1543
|
}
|
|
1544
|
+
async captureBackgroundResponse(result, context) {
|
|
1545
|
+
const {
|
|
1546
|
+
openAIParams,
|
|
1547
|
+
posthogParams
|
|
1548
|
+
} = context;
|
|
1549
|
+
await captureAiGeneration(this.phClient, {
|
|
1550
|
+
...posthogParams,
|
|
1551
|
+
model: openAIParams.model ?? result.model,
|
|
1552
|
+
provider: 'azure',
|
|
1553
|
+
input: formatOpenAIResponsesInput(openAIParams.input, openAIParams.instructions),
|
|
1554
|
+
output: result.output,
|
|
1555
|
+
latency: getBackgroundResponseLatency(result),
|
|
1556
|
+
baseURL: this.baseURL,
|
|
1557
|
+
modelParameters: getModelParams(openAIParams, result.service_tier),
|
|
1558
|
+
httpStatus: 200,
|
|
1559
|
+
usage: {
|
|
1560
|
+
inputTokens: result.usage?.input_tokens ?? 0,
|
|
1561
|
+
outputTokens: result.usage?.output_tokens ?? 0,
|
|
1562
|
+
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
1563
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
1564
|
+
rawUsage: result.usage
|
|
1565
|
+
},
|
|
1566
|
+
stopReason: result.status ?? undefined,
|
|
1567
|
+
completionId: result.id,
|
|
1568
|
+
providerMetadata: buildProviderMetadata({
|
|
1569
|
+
requestId: extractRequestId(result),
|
|
1570
|
+
incompleteDetails: result.incomplete_details
|
|
1571
|
+
}),
|
|
1572
|
+
error: getResponseFailure(result)
|
|
1573
|
+
});
|
|
1574
|
+
}
|
|
1470
1575
|
|
|
1471
1576
|
// --- Overload #1: Non-streaming
|
|
1472
1577
|
|
|
@@ -1513,6 +1618,12 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1513
1618
|
if (!completionIdFromResponse && chunk.response.id) {
|
|
1514
1619
|
completionIdFromResponse = chunk.response.id;
|
|
1515
1620
|
}
|
|
1621
|
+
if (openAIParams.background === true && !this.backgroundResponses.get(chunk.response.id)) {
|
|
1622
|
+
this.backgroundResponses.set(chunk.response.id, {
|
|
1623
|
+
openAIParams,
|
|
1624
|
+
posthogParams
|
|
1625
|
+
});
|
|
1626
|
+
}
|
|
1516
1627
|
if (chunk.response.service_tier != null) {
|
|
1517
1628
|
serviceTierFromResponse = chunk.response.service_tier;
|
|
1518
1629
|
}
|
|
@@ -1530,6 +1641,15 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1530
1641
|
};
|
|
1531
1642
|
}
|
|
1532
1643
|
}
|
|
1644
|
+
if (openAIParams.background === true) {
|
|
1645
|
+
if (terminalResponse) {
|
|
1646
|
+
const context = this.backgroundResponses.take(terminalResponse.id);
|
|
1647
|
+
if (context) {
|
|
1648
|
+
await this.captureBackgroundResponse(terminalResponse, context).catch(() => undefined);
|
|
1649
|
+
}
|
|
1650
|
+
}
|
|
1651
|
+
return;
|
|
1652
|
+
}
|
|
1533
1653
|
const latency = (Date.now() - startTime) / 1000;
|
|
1534
1654
|
const timeToFirstToken = firstTokenTime !== undefined ? (firstTokenTime - startTime) / 1000 : undefined;
|
|
1535
1655
|
await captureAiGeneration(this.phClient, {
|
|
@@ -1552,6 +1672,9 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1552
1672
|
error: getResponseFailure(terminalResponse)
|
|
1553
1673
|
});
|
|
1554
1674
|
} catch (error) {
|
|
1675
|
+
if (openAIParams.background === true && completionIdFromResponse && this.backgroundResponses.get(completionIdFromResponse)) {
|
|
1676
|
+
throw error;
|
|
1677
|
+
}
|
|
1555
1678
|
await captureAiGeneration(this.phClient, {
|
|
1556
1679
|
...posthogParams,
|
|
1557
1680
|
model: openAIParams.model,
|
|
@@ -1584,6 +1707,13 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1584
1707
|
} else {
|
|
1585
1708
|
const wrappedPromise = parentPromise.then(async result => {
|
|
1586
1709
|
if ('output' in result) {
|
|
1710
|
+
if (isPendingBackgroundResponse(openAIParams, result)) {
|
|
1711
|
+
this.backgroundResponses.set(result.id, {
|
|
1712
|
+
openAIParams,
|
|
1713
|
+
posthogParams
|
|
1714
|
+
});
|
|
1715
|
+
return result;
|
|
1716
|
+
}
|
|
1587
1717
|
const latency = (Date.now() - startTime) / 1000;
|
|
1588
1718
|
await captureAiGeneration(this.phClient, {
|
|
1589
1719
|
...posthogParams,
|
|
@@ -1599,7 +1729,8 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1599
1729
|
inputTokens: result.usage?.input_tokens ?? 0,
|
|
1600
1730
|
outputTokens: result.usage?.output_tokens ?? 0,
|
|
1601
1731
|
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
1602
|
-
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0
|
|
1732
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
1733
|
+
rawUsage: result.usage
|
|
1603
1734
|
},
|
|
1604
1735
|
stopReason: result.status ?? undefined,
|
|
1605
1736
|
completionId: result.id,
|
|
@@ -1634,6 +1765,55 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1634
1765
|
return preserveProviderPromise(parentPromise, wrappedPromise);
|
|
1635
1766
|
}
|
|
1636
1767
|
}
|
|
1768
|
+
retrieve(responseID, query = {}, options) {
|
|
1769
|
+
const parentPromise = super.retrieve(responseID, query, options);
|
|
1770
|
+
|
|
1771
|
+
// Preserve the upstream promise and stream unchanged for responses that
|
|
1772
|
+
// were not created through this client.
|
|
1773
|
+
if (!this.backgroundResponses.get(responseID)) {
|
|
1774
|
+
return parentPromise;
|
|
1775
|
+
}
|
|
1776
|
+
if (query.stream) {
|
|
1777
|
+
return parentPromise._thenUnwrap(result => {
|
|
1778
|
+
if ('controller' in result) {
|
|
1779
|
+
return wrapBackgroundResponseStream(result, responseID, this.backgroundResponses, (response, context) => this.captureBackgroundResponse(response, context));
|
|
1780
|
+
}
|
|
1781
|
+
return result;
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
return parentPromise._thenUnwrap(async result => {
|
|
1785
|
+
if (!('output' in result) || !isTerminalResponse(result)) {
|
|
1786
|
+
return result;
|
|
1787
|
+
}
|
|
1788
|
+
|
|
1789
|
+
// Removing the context before capture makes concurrent or repeated
|
|
1790
|
+
// terminal polls idempotent.
|
|
1791
|
+
const context = this.backgroundResponses.take(responseID);
|
|
1792
|
+
if (context) {
|
|
1793
|
+
await this.captureBackgroundResponse(result, context).catch(() => undefined);
|
|
1794
|
+
}
|
|
1795
|
+
return result;
|
|
1796
|
+
});
|
|
1797
|
+
}
|
|
1798
|
+
cancel(responseID, options) {
|
|
1799
|
+
const parentPromise = super.cancel(responseID, options);
|
|
1800
|
+
|
|
1801
|
+
// Avoid wrapping calls that do not belong to a background response created
|
|
1802
|
+
// through this client, preserving the upstream APIPromise unchanged.
|
|
1803
|
+
if (!this.backgroundResponses.get(responseID)) {
|
|
1804
|
+
return parentPromise;
|
|
1805
|
+
}
|
|
1806
|
+
return parentPromise._thenUnwrap(async result => {
|
|
1807
|
+
if (!isTerminalResponse(result)) {
|
|
1808
|
+
return result;
|
|
1809
|
+
}
|
|
1810
|
+
const context = this.backgroundResponses.take(responseID);
|
|
1811
|
+
if (context) {
|
|
1812
|
+
await this.captureBackgroundResponse(result, context).catch(() => undefined);
|
|
1813
|
+
}
|
|
1814
|
+
return result;
|
|
1815
|
+
});
|
|
1816
|
+
}
|
|
1637
1817
|
parse(body, options) {
|
|
1638
1818
|
const {
|
|
1639
1819
|
providerParams: openAIParams,
|
|
@@ -1642,6 +1822,13 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1642
1822
|
const startTime = Date.now();
|
|
1643
1823
|
const parentPromise = callWithOriginalCreate(this, super.create.bind(this), () => super.parse(openAIParams, options));
|
|
1644
1824
|
const wrappedPromise = parentPromise.then(async result => {
|
|
1825
|
+
if (isPendingBackgroundResponse(openAIParams, result)) {
|
|
1826
|
+
this.backgroundResponses.set(result.id, {
|
|
1827
|
+
openAIParams,
|
|
1828
|
+
posthogParams
|
|
1829
|
+
});
|
|
1830
|
+
return result;
|
|
1831
|
+
}
|
|
1645
1832
|
const latency = (Date.now() - startTime) / 1000;
|
|
1646
1833
|
await captureAiGeneration(this.phClient, {
|
|
1647
1834
|
...posthogParams,
|
|
@@ -1657,7 +1844,8 @@ let WrappedResponses$1 = class WrappedResponses extends AzureOpenAI.Responses {
|
|
|
1657
1844
|
inputTokens: result.usage?.input_tokens ?? 0,
|
|
1658
1845
|
outputTokens: result.usage?.output_tokens ?? 0,
|
|
1659
1846
|
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
1660
|
-
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0
|
|
1847
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
1848
|
+
rawUsage: result.usage
|
|
1661
1849
|
},
|
|
1662
1850
|
stopReason: result.status ?? undefined,
|
|
1663
1851
|
completionId: result.id,
|
|
@@ -1763,9 +1951,6 @@ async function captureAiGenerationAfterSuccess(...args) {
|
|
|
1763
1951
|
captureAiGenerationInBackground(...args);
|
|
1764
1952
|
}
|
|
1765
1953
|
}
|
|
1766
|
-
function isPendingBackgroundResponse(params, response) {
|
|
1767
|
-
return params.background === true && !response.usage && !!response.status && !isTerminalResponse(response);
|
|
1768
|
-
}
|
|
1769
1954
|
class PostHogOpenAI extends OpenAI {
|
|
1770
1955
|
constructor(config) {
|
|
1771
1956
|
const {
|
|
@@ -2068,11 +2253,47 @@ class WrappedCompletions extends Completions {
|
|
|
2068
2253
|
}
|
|
2069
2254
|
}
|
|
2070
2255
|
class WrappedResponses extends Responses {
|
|
2256
|
+
backgroundResponses = new BackgroundResponseTracker();
|
|
2071
2257
|
constructor(client, phClient) {
|
|
2072
2258
|
super(client);
|
|
2073
2259
|
this.phClient = phClient;
|
|
2074
2260
|
this.baseURL = client.baseURL;
|
|
2075
2261
|
}
|
|
2262
|
+
async captureBackgroundResponse(result, context) {
|
|
2263
|
+
const {
|
|
2264
|
+
openAIParams,
|
|
2265
|
+
posthogParams
|
|
2266
|
+
} = context;
|
|
2267
|
+
await captureAiGenerationAfterSuccess(this.phClient, {
|
|
2268
|
+
...posthogParams,
|
|
2269
|
+
model: openAIParams.model ?? result.model,
|
|
2270
|
+
provider: 'openai',
|
|
2271
|
+
input: formatOpenAIResponsesInput(sanitizeOpenAIResponse(openAIParams.input), openAIParams.instructions),
|
|
2272
|
+
output: formatResponseOpenAI({
|
|
2273
|
+
output: result.output
|
|
2274
|
+
}),
|
|
2275
|
+
latency: getBackgroundResponseLatency(result),
|
|
2276
|
+
baseURL: this.baseURL,
|
|
2277
|
+
modelParameters: getModelParams(openAIParams, result.service_tier),
|
|
2278
|
+
httpStatus: 200,
|
|
2279
|
+
usage: {
|
|
2280
|
+
inputTokens: result.usage?.input_tokens ?? 0,
|
|
2281
|
+
outputTokens: result.usage?.output_tokens ?? 0,
|
|
2282
|
+
reasoningTokens: result.usage?.output_tokens_details?.reasoning_tokens ?? 0,
|
|
2283
|
+
cacheReadInputTokens: result.usage?.input_tokens_details?.cached_tokens ?? 0,
|
|
2284
|
+
webSearchCount: calculateWebSearchCount(result),
|
|
2285
|
+
rawUsage: result.usage
|
|
2286
|
+
},
|
|
2287
|
+
stopReason: result.status ?? undefined,
|
|
2288
|
+
tools: extractAvailableToolCalls('openai', openAIParams),
|
|
2289
|
+
completionId: result.id,
|
|
2290
|
+
providerMetadata: buildProviderMetadata({
|
|
2291
|
+
requestId: extractRequestId(result),
|
|
2292
|
+
incompleteDetails: result.incomplete_details
|
|
2293
|
+
}),
|
|
2294
|
+
error: getResponseFailure(result)
|
|
2295
|
+
});
|
|
2296
|
+
}
|
|
2076
2297
|
|
|
2077
2298
|
// --- Overload #1: Non-streaming
|
|
2078
2299
|
|
|
@@ -2122,6 +2343,12 @@ class WrappedResponses extends Responses {
|
|
|
2122
2343
|
if (!completionIdFromResponse && chunk.response.id) {
|
|
2123
2344
|
completionIdFromResponse = chunk.response.id;
|
|
2124
2345
|
}
|
|
2346
|
+
if (openAIParams.background === true && !this.backgroundResponses.get(chunk.response.id)) {
|
|
2347
|
+
this.backgroundResponses.set(chunk.response.id, {
|
|
2348
|
+
openAIParams,
|
|
2349
|
+
posthogParams
|
|
2350
|
+
});
|
|
2351
|
+
}
|
|
2125
2352
|
if (chunk.response.service_tier != null) {
|
|
2126
2353
|
serviceTierFromResponse = chunk.response.service_tier;
|
|
2127
2354
|
}
|
|
@@ -2146,6 +2373,15 @@ class WrappedResponses extends Responses {
|
|
|
2146
2373
|
};
|
|
2147
2374
|
}
|
|
2148
2375
|
}
|
|
2376
|
+
if (openAIParams.background === true) {
|
|
2377
|
+
if (terminalResponse) {
|
|
2378
|
+
const context = this.backgroundResponses.take(terminalResponse.id);
|
|
2379
|
+
if (context) {
|
|
2380
|
+
await this.captureBackgroundResponse(terminalResponse, context).catch(() => undefined);
|
|
2381
|
+
}
|
|
2382
|
+
}
|
|
2383
|
+
return;
|
|
2384
|
+
}
|
|
2149
2385
|
const latency = (Date.now() - startTime) / 1000;
|
|
2150
2386
|
const timeToFirstToken = firstTokenTime !== undefined ? (firstTokenTime - startTime) / 1000 : undefined;
|
|
2151
2387
|
const availableTools = extractAvailableToolCalls('openai', openAIParams);
|
|
@@ -2177,6 +2413,9 @@ class WrappedResponses extends Responses {
|
|
|
2177
2413
|
error: getResponseFailure(terminalResponse)
|
|
2178
2414
|
});
|
|
2179
2415
|
} catch (error) {
|
|
2416
|
+
if (openAIParams.background === true && completionIdFromResponse && this.backgroundResponses.get(completionIdFromResponse)) {
|
|
2417
|
+
throw error;
|
|
2418
|
+
}
|
|
2180
2419
|
await captureAiGeneration(this.phClient, {
|
|
2181
2420
|
...posthogParams,
|
|
2182
2421
|
model: openAIParams.model,
|
|
@@ -2210,6 +2449,10 @@ class WrappedResponses extends Responses {
|
|
|
2210
2449
|
const wrappedPromise = parentPromise.then(async result => {
|
|
2211
2450
|
if ('output' in result) {
|
|
2212
2451
|
if (isPendingBackgroundResponse(openAIParams, result)) {
|
|
2452
|
+
this.backgroundResponses.set(result.id, {
|
|
2453
|
+
openAIParams,
|
|
2454
|
+
posthogParams
|
|
2455
|
+
});
|
|
2213
2456
|
return result;
|
|
2214
2457
|
}
|
|
2215
2458
|
const latency = (Date.now() - startTime) / 1000;
|
|
@@ -2269,6 +2512,55 @@ class WrappedResponses extends Responses {
|
|
|
2269
2512
|
return preserveProviderPromise(parentPromise, wrappedPromise);
|
|
2270
2513
|
}
|
|
2271
2514
|
}
|
|
2515
|
+
retrieve(responseID, query = {}, options) {
|
|
2516
|
+
const parentPromise = super.retrieve(responseID, query, options);
|
|
2517
|
+
|
|
2518
|
+
// Preserve the upstream promise and stream unchanged for responses that
|
|
2519
|
+
// were not created through this client.
|
|
2520
|
+
if (!this.backgroundResponses.get(responseID)) {
|
|
2521
|
+
return parentPromise;
|
|
2522
|
+
}
|
|
2523
|
+
if (query.stream) {
|
|
2524
|
+
return parentPromise._thenUnwrap(result => {
|
|
2525
|
+
if ('controller' in result) {
|
|
2526
|
+
return wrapBackgroundResponseStream(result, responseID, this.backgroundResponses, (response, context) => this.captureBackgroundResponse(response, context));
|
|
2527
|
+
}
|
|
2528
|
+
return result;
|
|
2529
|
+
});
|
|
2530
|
+
}
|
|
2531
|
+
return parentPromise._thenUnwrap(async result => {
|
|
2532
|
+
if (!('output' in result) || !isTerminalResponse(result)) {
|
|
2533
|
+
return result;
|
|
2534
|
+
}
|
|
2535
|
+
|
|
2536
|
+
// Removing the context before capture makes concurrent or repeated
|
|
2537
|
+
// terminal polls idempotent.
|
|
2538
|
+
const context = this.backgroundResponses.take(responseID);
|
|
2539
|
+
if (context) {
|
|
2540
|
+
await this.captureBackgroundResponse(result, context).catch(() => undefined);
|
|
2541
|
+
}
|
|
2542
|
+
return result;
|
|
2543
|
+
});
|
|
2544
|
+
}
|
|
2545
|
+
cancel(responseID, options) {
|
|
2546
|
+
const parentPromise = super.cancel(responseID, options);
|
|
2547
|
+
|
|
2548
|
+
// Avoid wrapping calls that do not belong to a background response created
|
|
2549
|
+
// through this client, preserving the upstream APIPromise unchanged.
|
|
2550
|
+
if (!this.backgroundResponses.get(responseID)) {
|
|
2551
|
+
return parentPromise;
|
|
2552
|
+
}
|
|
2553
|
+
return parentPromise._thenUnwrap(async result => {
|
|
2554
|
+
if (!isTerminalResponse(result)) {
|
|
2555
|
+
return result;
|
|
2556
|
+
}
|
|
2557
|
+
const context = this.backgroundResponses.take(responseID);
|
|
2558
|
+
if (context) {
|
|
2559
|
+
await this.captureBackgroundResponse(result, context).catch(() => undefined);
|
|
2560
|
+
}
|
|
2561
|
+
return result;
|
|
2562
|
+
});
|
|
2563
|
+
}
|
|
2272
2564
|
parse(body, options) {
|
|
2273
2565
|
const {
|
|
2274
2566
|
providerParams: openAIParams,
|
|
@@ -2278,6 +2570,10 @@ class WrappedResponses extends Responses {
|
|
|
2278
2570
|
const parentPromise = callWithOriginalCreate(this, super.create.bind(this), () => super.parse(openAIParams, options));
|
|
2279
2571
|
const wrappedPromise = parentPromise.then(async result => {
|
|
2280
2572
|
if (isPendingBackgroundResponse(openAIParams, result)) {
|
|
2573
|
+
this.backgroundResponses.set(result.id, {
|
|
2574
|
+
openAIParams,
|
|
2575
|
+
posthogParams
|
|
2576
|
+
});
|
|
2281
2577
|
return result;
|
|
2282
2578
|
}
|
|
2283
2579
|
const latency = (Date.now() - startTime) / 1000;
|