@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.
- package/dist/{agent-LrKyX9KN.d.ts → agent-DcBmoTR4.d.ts} +7 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +83 -7
- package/dist/agent.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +83 -7
- package/dist/index.js.map +1 -1
- package/dist/server/agent-server.js +102 -8
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +102 -8
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +1 -1
- package/src/server/agent-server.ts +21 -1
- package/src/session-log-writer.test.ts +41 -0
- package/src/session-log-writer.ts +91 -5
|
@@ -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
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.
|
|
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
|
|
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)
|
|
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)
|
|
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.
|
|
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
|
|
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
|
};
|