@posthog/agent 2.1.148 → 2.1.150
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.js +53 -9
- package/dist/agent.js.map +1 -1
- package/dist/posthog-api.js +1 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.js +51 -11
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +63 -23
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +3 -3
- package/src/adapters/claude/session/options.ts +9 -0
- package/src/adapters/codex/spawn.ts +1 -1
- package/src/agent.ts +9 -1
- package/src/sagas/apply-snapshot-saga.ts +2 -0
- package/src/sagas/capture-tree-saga.ts +2 -0
- package/src/sagas/resume-saga.ts +2 -0
- package/src/session-log-writer.ts +39 -4
package/dist/server/bin.cjs
CHANGED
|
@@ -904,7 +904,7 @@ var import_hono = require("hono");
|
|
|
904
904
|
// package.json
|
|
905
905
|
var package_default = {
|
|
906
906
|
name: "@posthog/agent",
|
|
907
|
-
version: "2.1.
|
|
907
|
+
version: "2.1.150",
|
|
908
908
|
repository: "https://github.com/PostHog/twig",
|
|
909
909
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
910
910
|
exports: {
|
|
@@ -3416,7 +3416,7 @@ function getAbortController(userProvidedController) {
|
|
|
3416
3416
|
}
|
|
3417
3417
|
return controller;
|
|
3418
3418
|
}
|
|
3419
|
-
function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited) {
|
|
3419
|
+
function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited, logger) {
|
|
3420
3420
|
return (spawnOpts) => {
|
|
3421
3421
|
const child = (0, import_node_child_process.spawn)(spawnOpts.command, spawnOpts.args, {
|
|
3422
3422
|
cwd: spawnOpts.cwd,
|
|
@@ -3430,6 +3430,12 @@ function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited) {
|
|
|
3430
3430
|
sessionId
|
|
3431
3431
|
});
|
|
3432
3432
|
}
|
|
3433
|
+
child.stderr?.on("data", (data) => {
|
|
3434
|
+
const msg = data.toString().trim();
|
|
3435
|
+
if (msg && logger) {
|
|
3436
|
+
logger.debug(`[claude-code:${child.pid}] stderr: ${msg}`);
|
|
3437
|
+
}
|
|
3438
|
+
});
|
|
3433
3439
|
if (onProcessExited) {
|
|
3434
3440
|
child.on("exit", () => {
|
|
3435
3441
|
if (child.pid) {
|
|
@@ -3521,7 +3527,8 @@ function buildSessionOptions(params) {
|
|
|
3521
3527
|
spawnClaudeCodeProcess: buildSpawnWrapper(
|
|
3522
3528
|
params.sessionId,
|
|
3523
3529
|
params.onProcessSpawned,
|
|
3524
|
-
params.onProcessExited
|
|
3530
|
+
params.onProcessExited,
|
|
3531
|
+
params.logger
|
|
3525
3532
|
)
|
|
3526
3533
|
}
|
|
3527
3534
|
};
|
|
@@ -4524,7 +4531,7 @@ function spawnCodexProcess(options) {
|
|
|
4524
4531
|
detached: process.platform !== "win32"
|
|
4525
4532
|
});
|
|
4526
4533
|
child.stderr?.on("data", (data) => {
|
|
4527
|
-
logger.
|
|
4534
|
+
logger.warn("codex-acp stderr:", data.toString());
|
|
4528
4535
|
});
|
|
4529
4536
|
child.on("error", (err) => {
|
|
4530
4537
|
logger.error("codex-acp process error:", err);
|
|
@@ -5087,12 +5094,14 @@ var PostHogAPIClient = class {
|
|
|
5087
5094
|
|
|
5088
5095
|
// src/session-log-writer.ts
|
|
5089
5096
|
var import_node_fs2 = __toESM(require("fs"), 1);
|
|
5097
|
+
var import_promises = __toESM(require("fs/promises"), 1);
|
|
5090
5098
|
var import_node_path2 = __toESM(require("path"), 1);
|
|
5091
5099
|
var SessionLogWriter = class _SessionLogWriter {
|
|
5092
5100
|
static FLUSH_DEBOUNCE_MS = 500;
|
|
5093
5101
|
static FLUSH_MAX_INTERVAL_MS = 5e3;
|
|
5094
5102
|
static MAX_FLUSH_RETRIES = 10;
|
|
5095
5103
|
static MAX_RETRY_DELAY_MS = 3e4;
|
|
5104
|
+
static SESSIONS_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
5096
5105
|
posthogAPI;
|
|
5097
5106
|
pendingEntries = /* @__PURE__ */ new Map();
|
|
5098
5107
|
flushTimeouts = /* @__PURE__ */ new Map();
|
|
@@ -5229,10 +5238,16 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
5229
5238
|
);
|
|
5230
5239
|
this.retryCounts.set(sessionId, 0);
|
|
5231
5240
|
} else {
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5241
|
+
if (retryCount === 1) {
|
|
5242
|
+
this.logger.warn(
|
|
5243
|
+
`Failed to persist session logs, will retry (up to ${_SessionLogWriter.MAX_FLUSH_RETRIES} attempts)`,
|
|
5244
|
+
{
|
|
5245
|
+
taskId: session.context.taskId,
|
|
5246
|
+
runId: session.context.runId,
|
|
5247
|
+
error: error instanceof Error ? error.message : String(error)
|
|
5248
|
+
}
|
|
5249
|
+
);
|
|
5250
|
+
}
|
|
5236
5251
|
const currentPending = this.pendingEntries.get(sessionId) ?? [];
|
|
5237
5252
|
this.pendingEntries.set(sessionId, [...pending, ...currentPending]);
|
|
5238
5253
|
this.scheduleFlush(sessionId);
|
|
@@ -5346,6 +5361,27 @@ var SessionLogWriter = class _SessionLogWriter {
|
|
|
5346
5361
|
});
|
|
5347
5362
|
}
|
|
5348
5363
|
}
|
|
5364
|
+
static async cleanupOldSessions(localCachePath) {
|
|
5365
|
+
const sessionsDir = import_node_path2.default.join(localCachePath, "sessions");
|
|
5366
|
+
let deleted = 0;
|
|
5367
|
+
try {
|
|
5368
|
+
const entries = await import_promises.default.readdir(sessionsDir);
|
|
5369
|
+
const now = Date.now();
|
|
5370
|
+
for (const entry of entries) {
|
|
5371
|
+
const entryPath = import_node_path2.default.join(sessionsDir, entry);
|
|
5372
|
+
try {
|
|
5373
|
+
const stats = await import_promises.default.stat(entryPath);
|
|
5374
|
+
if (stats.isDirectory() && now - stats.birthtimeMs > _SessionLogWriter.SESSIONS_MAX_AGE_MS) {
|
|
5375
|
+
await import_promises.default.rm(entryPath, { recursive: true, force: true });
|
|
5376
|
+
deleted++;
|
|
5377
|
+
}
|
|
5378
|
+
} catch {
|
|
5379
|
+
}
|
|
5380
|
+
}
|
|
5381
|
+
} catch {
|
|
5382
|
+
}
|
|
5383
|
+
return deleted;
|
|
5384
|
+
}
|
|
5349
5385
|
};
|
|
5350
5386
|
|
|
5351
5387
|
// ../git/dist/queries.js
|
|
@@ -9913,7 +9949,7 @@ function createGitClient(baseDir, options) {
|
|
|
9913
9949
|
|
|
9914
9950
|
// ../git/dist/lock-detector.js
|
|
9915
9951
|
var import_node_child_process3 = require("child_process");
|
|
9916
|
-
var
|
|
9952
|
+
var import_promises2 = __toESM(require("fs/promises"), 1);
|
|
9917
9953
|
var import_node_path4 = __toESM(require("path"), 1);
|
|
9918
9954
|
var import_node_util = require("util");
|
|
9919
9955
|
var execFileAsync = (0, import_node_util.promisify)(import_node_child_process3.execFile);
|
|
@@ -9928,7 +9964,7 @@ async function getIndexLockPath(repoPath) {
|
|
|
9928
9964
|
async function getLockInfo(repoPath) {
|
|
9929
9965
|
const lockPath = await getIndexLockPath(repoPath);
|
|
9930
9966
|
try {
|
|
9931
|
-
const stat = await
|
|
9967
|
+
const stat = await import_promises2.default.stat(lockPath);
|
|
9932
9968
|
return {
|
|
9933
9969
|
path: lockPath,
|
|
9934
9970
|
ageMs: Date.now() - stat.mtimeMs
|
|
@@ -9939,7 +9975,7 @@ async function getLockInfo(repoPath) {
|
|
|
9939
9975
|
}
|
|
9940
9976
|
async function removeLock(repoPath) {
|
|
9941
9977
|
const lockPath = await getIndexLockPath(repoPath);
|
|
9942
|
-
await
|
|
9978
|
+
await import_promises2.default.rm(lockPath, { force: true });
|
|
9943
9979
|
}
|
|
9944
9980
|
async function isLocked(repoPath) {
|
|
9945
9981
|
return await getLockInfo(repoPath) !== null;
|
|
@@ -10105,7 +10141,7 @@ async function getHeadSha(baseDir, options) {
|
|
|
10105
10141
|
}
|
|
10106
10142
|
|
|
10107
10143
|
// src/sagas/apply-snapshot-saga.ts
|
|
10108
|
-
var
|
|
10144
|
+
var import_promises3 = require("fs/promises");
|
|
10109
10145
|
var import_node_path5 = require("path");
|
|
10110
10146
|
|
|
10111
10147
|
// ../shared/dist/index.js
|
|
@@ -10136,12 +10172,12 @@ var Saga = class {
|
|
|
10136
10172
|
this.currentStepName = "unknown";
|
|
10137
10173
|
this.stepTimings = [];
|
|
10138
10174
|
const sagaStart = performance.now();
|
|
10139
|
-
this.log.info("Starting saga", { sagaName: this.
|
|
10175
|
+
this.log.info("Starting saga", { sagaName: this.sagaName });
|
|
10140
10176
|
try {
|
|
10141
10177
|
const result = await this.execute(input);
|
|
10142
10178
|
const totalDuration = performance.now() - sagaStart;
|
|
10143
10179
|
this.log.debug("Saga completed successfully", {
|
|
10144
|
-
sagaName: this.
|
|
10180
|
+
sagaName: this.sagaName,
|
|
10145
10181
|
stepsCompleted: this.completedSteps.length,
|
|
10146
10182
|
totalDurationMs: Math.round(totalDuration),
|
|
10147
10183
|
stepTimings: this.stepTimings
|
|
@@ -10149,7 +10185,7 @@ var Saga = class {
|
|
|
10149
10185
|
return { success: true, data: result };
|
|
10150
10186
|
} catch (error) {
|
|
10151
10187
|
this.log.error("Saga failed, initiating rollback", {
|
|
10152
|
-
sagaName: this.
|
|
10188
|
+
sagaName: this.sagaName,
|
|
10153
10189
|
failedStep: this.currentStepName,
|
|
10154
10190
|
error: error instanceof Error ? error.message : String(error)
|
|
10155
10191
|
});
|
|
@@ -10261,6 +10297,7 @@ var GitSaga = class extends Saga {
|
|
|
10261
10297
|
|
|
10262
10298
|
// ../git/dist/sagas/tree.js
|
|
10263
10299
|
var CaptureTreeSaga = class extends GitSaga {
|
|
10300
|
+
sagaName = "CaptureTreeSaga";
|
|
10264
10301
|
tempIndexPath = null;
|
|
10265
10302
|
async executeGitOperations(input) {
|
|
10266
10303
|
const { baseDir, lastTreeHash, archivePath, signal } = input;
|
|
@@ -10381,6 +10418,7 @@ var CaptureTreeSaga = class extends GitSaga {
|
|
|
10381
10418
|
}
|
|
10382
10419
|
};
|
|
10383
10420
|
var ApplyTreeSaga = class extends GitSaga {
|
|
10421
|
+
sagaName = "ApplyTreeSaga";
|
|
10384
10422
|
originalHead = null;
|
|
10385
10423
|
originalBranch = null;
|
|
10386
10424
|
extractedFiles = [];
|
|
@@ -10515,6 +10553,7 @@ var ApplyTreeSaga = class extends GitSaga {
|
|
|
10515
10553
|
|
|
10516
10554
|
// src/sagas/apply-snapshot-saga.ts
|
|
10517
10555
|
var ApplySnapshotSaga = class extends Saga {
|
|
10556
|
+
sagaName = "ApplySnapshotSaga";
|
|
10518
10557
|
archivePath = null;
|
|
10519
10558
|
async execute(input) {
|
|
10520
10559
|
const { snapshot, repositoryPath, apiClient, taskId, runId } = input;
|
|
@@ -10525,7 +10564,7 @@ var ApplySnapshotSaga = class extends Saga {
|
|
|
10525
10564
|
const archiveUrl = snapshot.archiveUrl;
|
|
10526
10565
|
await this.step({
|
|
10527
10566
|
name: "create_tmp_dir",
|
|
10528
|
-
execute: () => (0,
|
|
10567
|
+
execute: () => (0, import_promises3.mkdir)(tmpDir, { recursive: true }),
|
|
10529
10568
|
rollback: async () => {
|
|
10530
10569
|
}
|
|
10531
10570
|
});
|
|
@@ -10544,11 +10583,11 @@ var ApplySnapshotSaga = class extends Saga {
|
|
|
10544
10583
|
}
|
|
10545
10584
|
const base64Content = Buffer.from(arrayBuffer).toString("utf-8");
|
|
10546
10585
|
const binaryContent = Buffer.from(base64Content, "base64");
|
|
10547
|
-
await (0,
|
|
10586
|
+
await (0, import_promises3.writeFile)(archivePath, binaryContent);
|
|
10548
10587
|
},
|
|
10549
10588
|
rollback: async () => {
|
|
10550
10589
|
if (this.archivePath) {
|
|
10551
|
-
await (0,
|
|
10590
|
+
await (0, import_promises3.rm)(this.archivePath, { force: true }).catch(() => {
|
|
10552
10591
|
});
|
|
10553
10592
|
}
|
|
10554
10593
|
}
|
|
@@ -10564,7 +10603,7 @@ var ApplySnapshotSaga = class extends Saga {
|
|
|
10564
10603
|
if (!applyResult.success) {
|
|
10565
10604
|
throw new Error(`Failed to apply tree: ${applyResult.error}`);
|
|
10566
10605
|
}
|
|
10567
|
-
await (0,
|
|
10606
|
+
await (0, import_promises3.rm)(this.archivePath, { force: true }).catch(() => {
|
|
10568
10607
|
});
|
|
10569
10608
|
this.log.info("Tree snapshot applied", {
|
|
10570
10609
|
treeHash: snapshot.treeHash,
|
|
@@ -10577,9 +10616,10 @@ var ApplySnapshotSaga = class extends Saga {
|
|
|
10577
10616
|
|
|
10578
10617
|
// src/sagas/capture-tree-saga.ts
|
|
10579
10618
|
var import_node_fs4 = require("fs");
|
|
10580
|
-
var
|
|
10619
|
+
var import_promises4 = require("fs/promises");
|
|
10581
10620
|
var import_node_path6 = require("path");
|
|
10582
10621
|
var CaptureTreeSaga2 = class extends Saga {
|
|
10622
|
+
sagaName = "CaptureTreeSaga";
|
|
10583
10623
|
async execute(input) {
|
|
10584
10624
|
const {
|
|
10585
10625
|
repositoryPath,
|
|
@@ -10626,7 +10666,7 @@ var CaptureTreeSaga2 = class extends Saga {
|
|
|
10626
10666
|
runId
|
|
10627
10667
|
);
|
|
10628
10668
|
} finally {
|
|
10629
|
-
await (0,
|
|
10669
|
+
await (0, import_promises4.rm)(createdArchivePath, { force: true }).catch(() => {
|
|
10630
10670
|
});
|
|
10631
10671
|
}
|
|
10632
10672
|
}
|
|
@@ -10650,7 +10690,7 @@ var CaptureTreeSaga2 = class extends Saga {
|
|
|
10650
10690
|
const archiveUrl = await this.step({
|
|
10651
10691
|
name: "upload_archive",
|
|
10652
10692
|
execute: async () => {
|
|
10653
|
-
const archiveContent = await (0,
|
|
10693
|
+
const archiveContent = await (0, import_promises4.readFile)(archivePath);
|
|
10654
10694
|
const base64Content = archiveContent.toString("base64");
|
|
10655
10695
|
const artifacts = await apiClient.uploadTaskArtifacts(taskId, runId, [
|
|
10656
10696
|
{
|
|
@@ -10670,7 +10710,7 @@ var CaptureTreeSaga2 = class extends Saga {
|
|
|
10670
10710
|
return void 0;
|
|
10671
10711
|
},
|
|
10672
10712
|
rollback: async () => {
|
|
10673
|
-
await (0,
|
|
10713
|
+
await (0, import_promises4.rm)(archivePath, { force: true }).catch(() => {
|
|
10674
10714
|
});
|
|
10675
10715
|
}
|
|
10676
10716
|
});
|