@posthog/agent 2.1.22 → 2.1.29

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.
@@ -46,10 +46,17 @@ interface SessionLogWriterOptions {
46
46
  logger?: Logger;
47
47
  }
48
48
  declare class SessionLogWriter {
49
+ private static readonly FLUSH_DEBOUNCE_MS;
50
+ private static readonly FLUSH_MAX_INTERVAL_MS;
51
+ private static readonly MAX_FLUSH_RETRIES;
52
+ private static readonly MAX_RETRY_DELAY_MS;
49
53
  private posthogAPI?;
50
54
  private pendingEntries;
51
55
  private flushTimeouts;
56
+ private lastFlushAttemptTime;
57
+ private retryCounts;
52
58
  private sessions;
59
+ private messageCounts;
53
60
  private logger;
54
61
  constructor(options?: SessionLogWriterOptions);
55
62
  flushAll(): Promise<void>;
package/dist/agent.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { b as Agent } from './agent-LrKyX9KN.js';
1
+ export { b as Agent } from './agent-DcBmoTR4.js';
2
2
  import './types.js';
3
3
  import '@agentclientprotocol/sdk';
4
4
  import './logger-DDBiMOOD.js';
package/dist/agent.js CHANGED
@@ -276,7 +276,7 @@ import { v7 as uuidv7 } from "uuid";
276
276
  // package.json
277
277
  var package_default = {
278
278
  name: "@posthog/agent",
279
- version: "2.1.22",
279
+ version: "2.1.29",
280
280
  repository: "https://github.com/PostHog/twig",
281
281
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
282
282
  exports: {
@@ -3386,19 +3386,36 @@ var PostHogAPIClient = class {
3386
3386
  };
3387
3387
 
3388
3388
  // src/session-log-writer.ts
3389
- var SessionLogWriter = class {
3389
+ var SessionLogWriter = class _SessionLogWriter {
3390
+ static FLUSH_DEBOUNCE_MS = 500;
3391
+ static FLUSH_MAX_INTERVAL_MS = 5e3;
3392
+ static MAX_FLUSH_RETRIES = 10;
3393
+ static MAX_RETRY_DELAY_MS = 3e4;
3390
3394
  posthogAPI;
3391
3395
  pendingEntries = /* @__PURE__ */ new Map();
3392
3396
  flushTimeouts = /* @__PURE__ */ new Map();
3397
+ lastFlushAttemptTime = /* @__PURE__ */ new Map();
3398
+ retryCounts = /* @__PURE__ */ new Map();
3393
3399
  sessions = /* @__PURE__ */ new Map();
3400
+ messageCounts = /* @__PURE__ */ new Map();
3394
3401
  logger;
3395
3402
  constructor(options = {}) {
3396
3403
  this.posthogAPI = options.posthogAPI;
3397
3404
  this.logger = options.logger ?? new Logger({ debug: false, prefix: "[SessionLogWriter]" });
3398
3405
  }
3399
3406
  async flushAll() {
3407
+ const sessionIds = [...this.sessions.keys()];
3408
+ const pendingCounts = sessionIds.map((id) => ({
3409
+ id,
3410
+ pending: this.pendingEntries.get(id)?.length ?? 0,
3411
+ messages: this.messageCounts.get(id) ?? 0
3412
+ }));
3413
+ this.logger.info("flushAll called", {
3414
+ sessions: sessionIds.length,
3415
+ pending: pendingCounts
3416
+ });
3400
3417
  const flushPromises = [];
3401
- for (const sessionId of this.sessions.keys()) {
3418
+ for (const sessionId of sessionIds) {
3402
3419
  flushPromises.push(this.flush(sessionId));
3403
3420
  }
3404
3421
  await Promise.all(flushPromises);
@@ -3407,7 +3424,12 @@ var SessionLogWriter = class {
3407
3424
  if (this.sessions.has(sessionId)) {
3408
3425
  return;
3409
3426
  }
3427
+ this.logger.info("Session registered", {
3428
+ sessionId,
3429
+ taskId: context.taskId
3430
+ });
3410
3431
  this.sessions.set(sessionId, { context });
3432
+ this.lastFlushAttemptTime.set(sessionId, Date.now());
3411
3433
  }
3412
3434
  isRegistered(sessionId) {
3413
3435
  return this.sessions.has(sessionId);
@@ -3415,8 +3437,16 @@ var SessionLogWriter = class {
3415
3437
  appendRawLine(sessionId, line) {
3416
3438
  const session = this.sessions.get(sessionId);
3417
3439
  if (!session) {
3440
+ this.logger.warn("appendRawLine called for unregistered session", {
3441
+ sessionId
3442
+ });
3418
3443
  return;
3419
3444
  }
3445
+ const count = (this.messageCounts.get(sessionId) ?? 0) + 1;
3446
+ this.messageCounts.set(sessionId, count);
3447
+ if (count % 10 === 1) {
3448
+ this.logger.info("Messages received", { count, sessionId });
3449
+ }
3420
3450
  try {
3421
3451
  const message = JSON.parse(line);
3422
3452
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
@@ -3452,24 +3482,56 @@ var SessionLogWriter = class {
3452
3482
  }
3453
3483
  async flush(sessionId) {
3454
3484
  const session = this.sessions.get(sessionId);
3455
- if (!session) return;
3485
+ if (!session) {
3486
+ this.logger.warn("flush: no session found", { sessionId });
3487
+ return;
3488
+ }
3456
3489
  this.emitCoalescedMessage(sessionId, session);
3457
3490
  const pending = this.pendingEntries.get(sessionId);
3458
- if (!this.posthogAPI || !pending?.length) return;
3491
+ if (!this.posthogAPI || !pending?.length) {
3492
+ this.logger.info("flush: nothing to persist", {
3493
+ sessionId,
3494
+ hasPosthogAPI: !!this.posthogAPI,
3495
+ pendingCount: pending?.length ?? 0
3496
+ });
3497
+ return;
3498
+ }
3459
3499
  this.pendingEntries.delete(sessionId);
3460
3500
  const timeout = this.flushTimeouts.get(sessionId);
3461
3501
  if (timeout) {
3462
3502
  clearTimeout(timeout);
3463
3503
  this.flushTimeouts.delete(sessionId);
3464
3504
  }
3505
+ this.lastFlushAttemptTime.set(sessionId, Date.now());
3465
3506
  try {
3466
3507
  await this.posthogAPI.appendTaskRunLog(
3467
3508
  session.context.taskId,
3468
3509
  session.context.runId,
3469
3510
  pending
3470
3511
  );
3512
+ this.retryCounts.set(sessionId, 0);
3513
+ this.logger.info("Flushed session logs", {
3514
+ sessionId,
3515
+ entryCount: pending.length
3516
+ });
3471
3517
  } catch (error) {
3472
- this.logger.error("Failed to persist session logs:", error);
3518
+ const retryCount = (this.retryCounts.get(sessionId) ?? 0) + 1;
3519
+ this.retryCounts.set(sessionId, retryCount);
3520
+ if (retryCount >= _SessionLogWriter.MAX_FLUSH_RETRIES) {
3521
+ this.logger.error(
3522
+ `Dropping ${pending.length} session log entries after ${retryCount} failed flush attempts`,
3523
+ { sessionId, error }
3524
+ );
3525
+ this.retryCounts.set(sessionId, 0);
3526
+ } else {
3527
+ this.logger.error(
3528
+ `Failed to persist session logs (attempt ${retryCount}/${_SessionLogWriter.MAX_FLUSH_RETRIES}):`,
3529
+ error
3530
+ );
3531
+ const currentPending = this.pendingEntries.get(sessionId) ?? [];
3532
+ this.pendingEntries.set(sessionId, [...pending, ...currentPending]);
3533
+ this.scheduleFlush(sessionId);
3534
+ }
3473
3535
  }
3474
3536
  }
3475
3537
  isAgentMessageChunk(message) {
@@ -3515,7 +3577,21 @@ var SessionLogWriter = class {
3515
3577
  scheduleFlush(sessionId) {
3516
3578
  const existing = this.flushTimeouts.get(sessionId);
3517
3579
  if (existing) clearTimeout(existing);
3518
- const timeout = setTimeout(() => this.flush(sessionId), 500);
3580
+ const retryCount = this.retryCounts.get(sessionId) ?? 0;
3581
+ const lastAttempt = this.lastFlushAttemptTime.get(sessionId) ?? 0;
3582
+ const elapsed = Date.now() - lastAttempt;
3583
+ let delay;
3584
+ if (retryCount > 0) {
3585
+ delay = Math.min(
3586
+ _SessionLogWriter.FLUSH_DEBOUNCE_MS * 2 ** retryCount,
3587
+ _SessionLogWriter.MAX_RETRY_DELAY_MS
3588
+ );
3589
+ } else if (elapsed >= _SessionLogWriter.FLUSH_MAX_INTERVAL_MS) {
3590
+ delay = 0;
3591
+ } else {
3592
+ delay = _SessionLogWriter.FLUSH_DEBOUNCE_MS;
3593
+ }
3594
+ const timeout = setTimeout(() => this.flush(sessionId), delay);
3519
3595
  this.flushTimeouts.set(sessionId, timeout);
3520
3596
  }
3521
3597
  };