@posthog/agent 2.3.126 → 2.3.131

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/agent",
3
- "version": "2.3.126",
3
+ "version": "2.3.131",
4
4
  "repository": "https://github.com/PostHog/code",
5
5
  "description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
6
6
  "exports": {
@@ -169,6 +169,12 @@ export class AgentServer {
169
169
  private initializationPromise: Promise<void> | null = null;
170
170
  private pendingEvents: Record<string, unknown>[] = [];
171
171
 
172
+ private detachSseController(controller: SseController): void {
173
+ if (this.session?.sseController === controller) {
174
+ this.session.sseController = null;
175
+ }
176
+ }
177
+
172
178
  private emitConsoleLog = (
173
179
  level: LogLevel,
174
180
  _scope: string,
@@ -250,18 +256,15 @@ export class AgentServer {
250
256
  controller.enqueue(
251
257
  new TextEncoder().encode(`data: ${JSON.stringify(data)}\n\n`),
252
258
  );
253
- } catch (error) {
254
- this.logger.debug(
255
- "SSE send failed (stream may be closed)",
256
- error,
257
- );
259
+ } catch {
260
+ this.detachSseController(sseController);
258
261
  }
259
262
  },
260
263
  close: () => {
261
264
  try {
262
265
  controller.close();
263
- } catch (error) {
264
- this.logger.debug("SSE close failed (already closed)", error);
266
+ } catch {
267
+ this.detachSseController(sseController);
265
268
  }
266
269
  },
267
270
  };
@@ -1577,6 +1580,10 @@ Important:
1577
1580
  }
1578
1581
 
1579
1582
  private sendSseEvent(controller: SseController, data: unknown): void {
1580
- controller.send(data);
1583
+ try {
1584
+ controller.send(data);
1585
+ } catch {
1586
+ this.detachSseController(controller);
1587
+ }
1581
1588
  }
1582
1589
  }
@@ -235,6 +235,71 @@ describe("Question relay", () => {
235
235
 
236
236
  expect(result.outcome.outcome).toBe("selected");
237
237
  });
238
+
239
+ it("keeps auto-approving permissions after SSE send failures", async () => {
240
+ const appendRawLine = vi.fn();
241
+ const brokenSseController = {
242
+ send: vi.fn(() => {
243
+ throw new Error("stream closed");
244
+ }),
245
+ close: vi.fn(),
246
+ };
247
+
248
+ const cloudPermissionServer = server as TestableAgentServer & {
249
+ emitConsoleLog: (
250
+ level: "debug" | "info" | "warn" | "error",
251
+ scope: string,
252
+ message: string,
253
+ data?: unknown,
254
+ ) => void;
255
+ logger: { debug: (message: string, data?: unknown) => void };
256
+ session: {
257
+ payload: typeof TEST_PAYLOAD;
258
+ sseController: typeof brokenSseController | null;
259
+ logWriter: {
260
+ appendRawLine: (runId: string, line: string) => void;
261
+ };
262
+ };
263
+ };
264
+
265
+ cloudPermissionServer.session = {
266
+ payload: TEST_PAYLOAD,
267
+ sseController: brokenSseController,
268
+ logWriter: {
269
+ appendRawLine,
270
+ },
271
+ };
272
+ cloudPermissionServer.logger = {
273
+ debug: (message: string, data?: unknown) => {
274
+ cloudPermissionServer.emitConsoleLog(
275
+ "debug",
276
+ "agent",
277
+ message,
278
+ data,
279
+ );
280
+ },
281
+ };
282
+
283
+ const client = cloudPermissionServer.createCloudClient(TEST_PAYLOAD);
284
+
285
+ const firstResult = await client.requestPermission({
286
+ options: ALLOW_OPTIONS,
287
+ toolCall: { _meta: { codeToolKind: "bash" } },
288
+ });
289
+
290
+ expect(firstResult.outcome.outcome).toBe("selected");
291
+ expect(brokenSseController.send).toHaveBeenCalledTimes(1);
292
+ expect(cloudPermissionServer.session.sseController).toBeNull();
293
+
294
+ const secondResult = await client.requestPermission({
295
+ options: ALLOW_OPTIONS,
296
+ toolCall: { _meta: { codeToolKind: "bash" } },
297
+ });
298
+
299
+ expect(secondResult.outcome.outcome).toBe("selected");
300
+ expect(brokenSseController.send).toHaveBeenCalledTimes(1);
301
+ expect(appendRawLine).toHaveBeenCalledTimes(2);
302
+ });
238
303
  });
239
304
  });
240
305