@posthog/agent 2.3.656 → 2.3.658

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.
@@ -0,0 +1,160 @@
1
+ import { Buffer } from "node:buffer";
2
+ import {
3
+ type ClientRequest,
4
+ request as httpRequest,
5
+ type IncomingHttpHeaders,
6
+ } from "node:http";
7
+ import { request as httpsRequest } from "node:https";
8
+ import { URL } from "node:url";
9
+
10
+ export interface StreamingUpload {
11
+ write(chunk: Uint8Array): Promise<void>;
12
+ close(): Promise<void>;
13
+ abort(): Promise<void>;
14
+ responsePromise: Promise<Response>;
15
+ }
16
+
17
+ export interface StreamingUploadFactoryInput {
18
+ url: string;
19
+ headers: Record<string, string>;
20
+ abortController: AbortController;
21
+ }
22
+
23
+ export type StreamingUploadFactory = (
24
+ input: StreamingUploadFactoryInput,
25
+ ) => StreamingUpload;
26
+
27
+ function headersFromIncoming(headers: IncomingHttpHeaders): Headers {
28
+ const result = new Headers();
29
+ for (const [name, value] of Object.entries(headers)) {
30
+ if (value === undefined) {
31
+ continue;
32
+ }
33
+ if (Array.isArray(value)) {
34
+ for (const item of value) {
35
+ result.append(name, item);
36
+ }
37
+ } else {
38
+ result.set(name, String(value));
39
+ }
40
+ }
41
+ return result;
42
+ }
43
+
44
+ function abortError(): Error {
45
+ const error = new Error("aborted");
46
+ error.name = "AbortError";
47
+ return error;
48
+ }
49
+
50
+ function writeRequestChunk(
51
+ request: ClientRequest,
52
+ chunk: Uint8Array,
53
+ ): Promise<void> {
54
+ return new Promise((resolve, reject) => {
55
+ const onError = (error: Error): void => {
56
+ request.off("error", onError);
57
+ reject(error);
58
+ };
59
+ request.once("error", onError);
60
+ request.write(Buffer.from(chunk), (error?: Error | null) => {
61
+ request.off("error", onError);
62
+ if (error) {
63
+ reject(error);
64
+ return;
65
+ }
66
+ resolve();
67
+ });
68
+ });
69
+ }
70
+
71
+ function closeRequest(request: ClientRequest): Promise<void> {
72
+ return new Promise((resolve, reject) => {
73
+ const onError = (error: Error): void => {
74
+ request.off("error", onError);
75
+ reject(error);
76
+ };
77
+ request.once("error", onError);
78
+ request.end(() => {
79
+ request.off("error", onError);
80
+ resolve();
81
+ });
82
+ });
83
+ }
84
+
85
+ export function createNodeStreamingUpload({
86
+ url,
87
+ headers,
88
+ abortController,
89
+ }: StreamingUploadFactoryInput): StreamingUpload {
90
+ const parsedUrl = new URL(url);
91
+ const requestFactory =
92
+ parsedUrl.protocol === "https:"
93
+ ? httpsRequest
94
+ : parsedUrl.protocol === "http:"
95
+ ? httpRequest
96
+ : undefined;
97
+ if (!requestFactory) {
98
+ throw new Error(`Unsupported event ingest protocol: ${parsedUrl.protocol}`);
99
+ }
100
+ const request = requestFactory(parsedUrl, {
101
+ method: "POST",
102
+ headers,
103
+ });
104
+
105
+ let closed = false;
106
+ const responsePromise = new Promise<Response>((resolve, reject) => {
107
+ request.on("response", (response) => {
108
+ const chunks: Buffer[] = [];
109
+ response.on("data", (chunk: Buffer | string) => {
110
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
111
+ });
112
+ response.on("end", () => {
113
+ resolve(
114
+ new Response(Buffer.concat(chunks), {
115
+ status: response.statusCode ?? 0,
116
+ statusText: response.statusMessage,
117
+ headers: headersFromIncoming(response.headers),
118
+ }),
119
+ );
120
+ });
121
+ response.on("error", reject);
122
+ });
123
+ request.on("error", reject);
124
+ });
125
+
126
+ const abortRequest = (): void => {
127
+ closed = true;
128
+ if (!request.destroyed) {
129
+ request.destroy(abortError());
130
+ }
131
+ };
132
+ abortController.signal.addEventListener("abort", abortRequest, {
133
+ once: true,
134
+ });
135
+ void responsePromise
136
+ .finally(() => {
137
+ abortController.signal.removeEventListener("abort", abortRequest);
138
+ })
139
+ .catch(() => undefined);
140
+
141
+ return {
142
+ async write(chunk: Uint8Array): Promise<void> {
143
+ if (closed) {
144
+ throw new Error("Cannot write to closed event ingest stream");
145
+ }
146
+ await writeRequestChunk(request, chunk);
147
+ },
148
+ async close(): Promise<void> {
149
+ if (closed) {
150
+ return;
151
+ }
152
+ closed = true;
153
+ await closeRequest(request);
154
+ },
155
+ async abort(): Promise<void> {
156
+ abortRequest();
157
+ },
158
+ responsePromise,
159
+ };
160
+ }
@@ -15,6 +15,8 @@ export interface AgentServerConfig {
15
15
  apiKey: string;
16
16
  projectId: number;
17
17
  jwtPublicKey: string; // RS256 public key for JWT verification
18
+ eventIngestToken?: string;
19
+ eventIngestStreamWindowMs?: number;
18
20
  mode: AgentMode;
19
21
  taskId: string;
20
22
  runId: string;