@posthog/agent 2.1.35 → 2.1.47

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/index.js CHANGED
@@ -1169,12 +1169,174 @@ import {
1169
1169
  import {
1170
1170
  query
1171
1171
  } from "@anthropic-ai/claude-agent-sdk";
1172
+
1173
+ // ../shared/dist/index.js
1174
+ var consoleLogger = {
1175
+ info: (_message, _data) => {
1176
+ },
1177
+ debug: (_message, _data) => {
1178
+ },
1179
+ error: (_message, _data) => {
1180
+ },
1181
+ warn: (_message, _data) => {
1182
+ }
1183
+ };
1184
+ var Saga = class {
1185
+ completedSteps = [];
1186
+ currentStepName = "unknown";
1187
+ stepTimings = [];
1188
+ log;
1189
+ constructor(logger) {
1190
+ this.log = logger ?? consoleLogger;
1191
+ }
1192
+ /**
1193
+ * Run the saga with the given input.
1194
+ * Returns a discriminated union result - either success with data or failure with error details.
1195
+ */
1196
+ async run(input) {
1197
+ this.completedSteps = [];
1198
+ this.currentStepName = "unknown";
1199
+ this.stepTimings = [];
1200
+ const sagaStart = performance.now();
1201
+ this.log.info("Starting saga", { sagaName: this.constructor.name });
1202
+ try {
1203
+ const result = await this.execute(input);
1204
+ const totalDuration = performance.now() - sagaStart;
1205
+ this.log.debug("Saga completed successfully", {
1206
+ sagaName: this.constructor.name,
1207
+ stepsCompleted: this.completedSteps.length,
1208
+ totalDurationMs: Math.round(totalDuration),
1209
+ stepTimings: this.stepTimings
1210
+ });
1211
+ return { success: true, data: result };
1212
+ } catch (error) {
1213
+ this.log.error("Saga failed, initiating rollback", {
1214
+ sagaName: this.constructor.name,
1215
+ failedStep: this.currentStepName,
1216
+ error: error instanceof Error ? error.message : String(error)
1217
+ });
1218
+ await this.rollback();
1219
+ return {
1220
+ success: false,
1221
+ error: error instanceof Error ? error.message : String(error),
1222
+ failedStep: this.currentStepName
1223
+ };
1224
+ }
1225
+ }
1226
+ /**
1227
+ * Execute a step with its rollback action.
1228
+ * If the step succeeds, its rollback action is stored for potential rollback.
1229
+ * The step name is automatically tracked for error reporting.
1230
+ *
1231
+ * @param config - Step configuration with name, execute, and rollback functions
1232
+ * @returns The result of the execute function
1233
+ * @throws Re-throws any error from the execute function (triggers rollback)
1234
+ */
1235
+ async step(config) {
1236
+ this.currentStepName = config.name;
1237
+ this.log.debug(`Executing step: ${config.name}`);
1238
+ const stepStart = performance.now();
1239
+ const result = await config.execute();
1240
+ const durationMs = Math.round(performance.now() - stepStart);
1241
+ this.stepTimings.push({ name: config.name, durationMs });
1242
+ this.log.debug(`Step completed: ${config.name}`, { durationMs });
1243
+ this.completedSteps.push({
1244
+ name: config.name,
1245
+ rollback: () => config.rollback(result)
1246
+ });
1247
+ return result;
1248
+ }
1249
+ /**
1250
+ * Execute a step that doesn't need rollback.
1251
+ * Useful for read-only operations or operations that are idempotent.
1252
+ * The step name is automatically tracked for error reporting.
1253
+ *
1254
+ * @param name - Step name for logging and error tracking
1255
+ * @param execute - The action to execute
1256
+ * @returns The result of the execute function
1257
+ */
1258
+ async readOnlyStep(name, execute) {
1259
+ this.currentStepName = name;
1260
+ this.log.debug(`Executing read-only step: ${name}`);
1261
+ const stepStart = performance.now();
1262
+ const result = await execute();
1263
+ const durationMs = Math.round(performance.now() - stepStart);
1264
+ this.stepTimings.push({ name, durationMs });
1265
+ this.log.debug(`Read-only step completed: ${name}`, { durationMs });
1266
+ return result;
1267
+ }
1268
+ /**
1269
+ * Roll back all completed steps in reverse order.
1270
+ * Rollback errors are logged but don't stop the rollback of other steps.
1271
+ */
1272
+ async rollback() {
1273
+ this.log.info("Rolling back saga", {
1274
+ stepsToRollback: this.completedSteps.length
1275
+ });
1276
+ const stepsReversed = [...this.completedSteps].reverse();
1277
+ for (const step of stepsReversed) {
1278
+ try {
1279
+ this.log.debug(`Rolling back step: ${step.name}`);
1280
+ await step.rollback();
1281
+ this.log.debug(`Step rolled back: ${step.name}`);
1282
+ } catch (error) {
1283
+ this.log.error(`Failed to rollback step: ${step.name}`, {
1284
+ error: error instanceof Error ? error.message : String(error)
1285
+ });
1286
+ }
1287
+ }
1288
+ this.log.info("Rollback completed", {
1289
+ stepsAttempted: this.completedSteps.length
1290
+ });
1291
+ }
1292
+ /**
1293
+ * Get the number of completed steps (useful for testing)
1294
+ */
1295
+ getCompletedStepCount() {
1296
+ return this.completedSteps.length;
1297
+ }
1298
+ };
1299
+ var NOOP_COLLECTOR = {
1300
+ time: (_label, fn) => fn(),
1301
+ timeSync: (_label, fn) => fn(),
1302
+ record: () => {
1303
+ },
1304
+ summarize: () => {
1305
+ }
1306
+ };
1307
+ function createTimingCollector(enabled, log) {
1308
+ if (!enabled) return NOOP_COLLECTOR;
1309
+ const steps = {};
1310
+ return {
1311
+ async time(label, fn) {
1312
+ const start = Date.now();
1313
+ const result = await fn();
1314
+ steps[label] = Date.now() - start;
1315
+ return result;
1316
+ },
1317
+ timeSync(label, fn) {
1318
+ const start = Date.now();
1319
+ const result = fn();
1320
+ steps[label] = Date.now() - start;
1321
+ return result;
1322
+ },
1323
+ record(label, ms) {
1324
+ steps[label] = ms;
1325
+ },
1326
+ summarize(label) {
1327
+ const total = Object.values(steps).reduce((a, b) => a + b, 0);
1328
+ log(`[timing] ${label}: ${total}ms`, steps);
1329
+ }
1330
+ };
1331
+ }
1332
+
1333
+ // src/adapters/claude/claude-agent.ts
1172
1334
  import { v7 as uuidv7 } from "uuid";
1173
1335
 
1174
1336
  // package.json
1175
1337
  var package_default = {
1176
1338
  name: "@posthog/agent",
1177
- version: "2.1.35",
1339
+ version: "2.1.47",
1178
1340
  repository: "https://github.com/PostHog/twig",
1179
1341
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
1180
1342
  exports: {
@@ -1305,11 +1467,16 @@ function unreachable(value, logger) {
1305
1467
  // src/gateway-models.ts
1306
1468
  var DEFAULT_GATEWAY_MODEL = "claude-opus-4-6";
1307
1469
  var BLOCKED_MODELS = /* @__PURE__ */ new Set(["gpt-5-mini", "openai/gpt-5-mini"]);
1470
+ var CACHE_TTL = 10 * 60 * 1e3;
1471
+ var gatewayModelsCache = null;
1308
1472
  async function fetchGatewayModels(options) {
1309
1473
  const gatewayUrl = options?.gatewayUrl ?? process.env.ANTHROPIC_BASE_URL;
1310
1474
  if (!gatewayUrl) {
1311
1475
  return [];
1312
1476
  }
1477
+ if (gatewayModelsCache && gatewayModelsCache.url === gatewayUrl && Date.now() < gatewayModelsCache.expiry) {
1478
+ return gatewayModelsCache.models;
1479
+ }
1313
1480
  const modelsUrl = `${gatewayUrl}/v1/models`;
1314
1481
  try {
1315
1482
  const response = await fetch(modelsUrl);
@@ -1317,8 +1484,13 @@ async function fetchGatewayModels(options) {
1317
1484
  return [];
1318
1485
  }
1319
1486
  const data = await response.json();
1320
- const models = data.data ?? [];
1321
- return models.filter((m) => !BLOCKED_MODELS.has(m.id));
1487
+ const models = (data.data ?? []).filter((m) => !BLOCKED_MODELS.has(m.id));
1488
+ gatewayModelsCache = {
1489
+ models,
1490
+ expiry: Date.now() + CACHE_TTL,
1491
+ url: gatewayUrl
1492
+ };
1493
+ return models;
1322
1494
  } catch {
1323
1495
  return [];
1324
1496
  }
@@ -1329,11 +1501,15 @@ function isAnthropicModel(model) {
1329
1501
  }
1330
1502
  return model.id.startsWith("claude-") || model.id.startsWith("anthropic/");
1331
1503
  }
1504
+ var arrayModelsCache = null;
1332
1505
  async function fetchArrayModels(options) {
1333
1506
  const gatewayUrl = options?.gatewayUrl ?? process.env.ANTHROPIC_BASE_URL;
1334
1507
  if (!gatewayUrl) {
1335
1508
  return [];
1336
1509
  }
1510
+ if (arrayModelsCache && arrayModelsCache.url === gatewayUrl && Date.now() < arrayModelsCache.expiry) {
1511
+ return arrayModelsCache.models;
1512
+ }
1337
1513
  try {
1338
1514
  const base = new URL(gatewayUrl);
1339
1515
  base.pathname = "/array/v1/models";
@@ -1351,6 +1527,11 @@ async function fetchArrayModels(options) {
1351
1527
  if (!id) continue;
1352
1528
  results.push({ id, owned_by: model?.owned_by });
1353
1529
  }
1530
+ arrayModelsCache = {
1531
+ models: results,
1532
+ expiry: Date.now() + CACHE_TTL,
1533
+ url: gatewayUrl
1534
+ };
1354
1535
  return results;
1355
1536
  } catch {
1356
1537
  return [];
@@ -3261,12 +3442,8 @@ function clearStatsigCache() {
3261
3442
  process.env.CLAUDE_CONFIG_DIR || path2.join(os2.homedir(), ".claude"),
3262
3443
  "statsig"
3263
3444
  );
3264
- try {
3265
- if (fs.existsSync(statsigPath)) {
3266
- fs.rmSync(statsigPath, { recursive: true, force: true });
3267
- }
3268
- } catch {
3269
- }
3445
+ fs.rm(statsigPath, { recursive: true, force: true }, () => {
3446
+ });
3270
3447
  }
3271
3448
 
3272
3449
  // src/adapters/claude/claude-agent.ts
@@ -3276,12 +3453,14 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3276
3453
  backgroundTerminals = {};
3277
3454
  clientCapabilities;
3278
3455
  logWriter;
3279
- processCallbacks;
3456
+ options;
3280
3457
  lastSentConfigOptions;
3281
- constructor(client, logWriter, processCallbacks) {
3458
+ debug;
3459
+ constructor(client, logWriter, options) {
3282
3460
  super(client);
3283
3461
  this.logWriter = logWriter;
3284
- this.processCallbacks = processCallbacks;
3462
+ this.options = options;
3463
+ this.debug = options?.debug ?? false;
3285
3464
  this.toolUseCache = {};
3286
3465
  this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
3287
3466
  }
@@ -3324,27 +3503,36 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3324
3503
  }
3325
3504
  async newSession(params) {
3326
3505
  this.checkAuthStatus();
3506
+ const tc = createTimingCollector(
3507
+ this.debug,
3508
+ (msg, data) => this.logger.info(msg, data)
3509
+ );
3327
3510
  const meta = params._meta;
3328
3511
  const sessionId = uuidv7();
3329
3512
  const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
3330
- const mcpServers = parseMcpServers(params);
3331
- await fetchMcpToolMetadata(mcpServers, this.logger);
3332
- const options = buildSessionOptions({
3333
- cwd: params.cwd,
3334
- mcpServers,
3335
- permissionMode,
3336
- canUseTool: this.createCanUseTool(sessionId),
3337
- logger: this.logger,
3338
- systemPrompt: buildSystemPrompt(meta?.systemPrompt),
3339
- userProvidedOptions: meta?.claudeCode?.options,
3340
- sessionId,
3341
- isResume: false,
3342
- onModeChange: this.createOnModeChange(sessionId),
3343
- onProcessSpawned: this.processCallbacks?.onProcessSpawned,
3344
- onProcessExited: this.processCallbacks?.onProcessExited
3345
- });
3513
+ const mcpServers = tc.timeSync(
3514
+ "parseMcpServers",
3515
+ () => parseMcpServers(params)
3516
+ );
3517
+ const options = tc.timeSync(
3518
+ "buildSessionOptions",
3519
+ () => buildSessionOptions({
3520
+ cwd: params.cwd,
3521
+ mcpServers,
3522
+ permissionMode,
3523
+ canUseTool: this.createCanUseTool(sessionId),
3524
+ logger: this.logger,
3525
+ systemPrompt: buildSystemPrompt(meta?.systemPrompt),
3526
+ userProvidedOptions: meta?.claudeCode?.options,
3527
+ sessionId,
3528
+ isResume: false,
3529
+ onModeChange: this.createOnModeChange(sessionId),
3530
+ onProcessSpawned: this.options?.onProcessSpawned,
3531
+ onProcessExited: this.options?.onProcessExited
3532
+ })
3533
+ );
3346
3534
  const input = new Pushable();
3347
- const q = query({ prompt: input, options });
3535
+ const q = tc.timeSync("sdkQuery", () => query({ prompt: input, options }));
3348
3536
  const session = this.createSession(
3349
3537
  sessionId,
3350
3538
  q,
@@ -3356,28 +3544,40 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3356
3544
  session.taskRunId = meta?.taskRunId;
3357
3545
  this.registerPersistence(sessionId, meta);
3358
3546
  if (meta?.taskRunId) {
3359
- await this.client.extNotification("_posthog/sdk_session", {
3360
- taskRunId: meta.taskRunId,
3361
- sessionId,
3362
- adapter: "claude"
3363
- });
3547
+ await tc.time(
3548
+ "extNotification",
3549
+ () => this.client.extNotification("_posthog/sdk_session", {
3550
+ taskRunId: meta.taskRunId,
3551
+ sessionId,
3552
+ adapter: "claude"
3553
+ })
3554
+ );
3364
3555
  }
3365
- const modelOptions = await this.getModelConfigOptions();
3556
+ const modelOptions = await tc.time(
3557
+ "fetchModels",
3558
+ () => this.getModelConfigOptions()
3559
+ );
3560
+ this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
3366
3561
  session.modelId = modelOptions.currentModelId;
3367
3562
  await this.trySetModel(q, modelOptions.currentModelId);
3368
- this.sendAvailableCommandsUpdate(
3369
- sessionId,
3370
- await getAvailableSlashCommands(q)
3563
+ const configOptions = await tc.time(
3564
+ "buildConfigOptions",
3565
+ () => this.buildConfigOptions(modelOptions)
3371
3566
  );
3567
+ tc.summarize("newSession");
3372
3568
  return {
3373
3569
  sessionId,
3374
- configOptions: await this.buildConfigOptions(modelOptions)
3570
+ configOptions
3375
3571
  };
3376
3572
  }
3377
3573
  async loadSession(params) {
3378
3574
  return this.resumeSession(params);
3379
3575
  }
3380
3576
  async resumeSession(params) {
3577
+ const tc = createTimingCollector(
3578
+ this.debug,
3579
+ (msg, data) => this.logger.info(msg, data)
3580
+ );
3381
3581
  const meta = params._meta;
3382
3582
  const sessionId = meta?.sessionId;
3383
3583
  if (!sessionId) {
@@ -3386,28 +3586,33 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3386
3586
  if (this.sessionId === sessionId) {
3387
3587
  return {};
3388
3588
  }
3389
- const mcpServers = parseMcpServers(params);
3390
- await fetchMcpToolMetadata(mcpServers, this.logger);
3589
+ const mcpServers = tc.timeSync(
3590
+ "parseMcpServers",
3591
+ () => parseMcpServers(params)
3592
+ );
3391
3593
  const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
3392
- const { query: q, session } = await this.initializeQuery({
3393
- cwd: params.cwd,
3394
- permissionMode,
3395
- mcpServers,
3396
- systemPrompt: buildSystemPrompt(meta?.systemPrompt),
3397
- userProvidedOptions: meta?.claudeCode?.options,
3398
- sessionId,
3399
- isResume: true,
3400
- additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
3401
- });
3594
+ const { query: q, session } = await tc.time(
3595
+ "initializeQuery",
3596
+ () => this.initializeQuery({
3597
+ cwd: params.cwd,
3598
+ permissionMode,
3599
+ mcpServers,
3600
+ systemPrompt: buildSystemPrompt(meta?.systemPrompt),
3601
+ userProvidedOptions: meta?.claudeCode?.options,
3602
+ sessionId,
3603
+ isResume: true,
3604
+ additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
3605
+ })
3606
+ );
3402
3607
  session.taskRunId = meta?.taskRunId;
3403
3608
  this.registerPersistence(sessionId, meta);
3404
- this.sendAvailableCommandsUpdate(
3405
- sessionId,
3406
- await getAvailableSlashCommands(q)
3609
+ this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
3610
+ const configOptions = await tc.time(
3611
+ "buildConfigOptions",
3612
+ () => this.buildConfigOptions()
3407
3613
  );
3408
- return {
3409
- configOptions: await this.buildConfigOptions()
3410
- };
3614
+ tc.summarize("resumeSession");
3615
+ return { configOptions };
3411
3616
  }
3412
3617
  async prompt(params) {
3413
3618
  this.session.cancelled = false;
@@ -3479,8 +3684,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3479
3684
  isResume: config.isResume,
3480
3685
  additionalDirectories: config.additionalDirectories,
3481
3686
  onModeChange: this.createOnModeChange(config.sessionId),
3482
- onProcessSpawned: this.processCallbacks?.onProcessSpawned,
3483
- onProcessExited: this.processCallbacks?.onProcessExited
3687
+ onProcessSpawned: this.options?.onProcessSpawned,
3688
+ onProcessExited: this.options?.onProcessExited
3484
3689
  });
3485
3690
  const q = query({ prompt: input, options });
3486
3691
  const abortController = options.abortController;
@@ -3590,6 +3795,23 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3590
3795
  await q.setModel(fallback);
3591
3796
  }
3592
3797
  }
3798
+ /**
3799
+ * Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
3800
+ * Both populate caches used later — neither is needed to return configOptions.
3801
+ */
3802
+ deferBackgroundFetches(tc, q, sessionId, mcpServers) {
3803
+ Promise.all([
3804
+ tc.time("slashCommands", () => getAvailableSlashCommands(q)),
3805
+ tc.time(
3806
+ "mcpMetadata",
3807
+ () => fetchMcpToolMetadata(mcpServers, this.logger)
3808
+ )
3809
+ ]).then(([slashCommands]) => {
3810
+ this.sendAvailableCommandsUpdate(sessionId, slashCommands);
3811
+ }).catch((err) => {
3812
+ this.logger.warn("Failed to fetch deferred session data", { err });
3813
+ });
3814
+ }
3593
3815
  registerPersistence(sessionId, meta) {
3594
3816
  const persistence = meta?.persistence;
3595
3817
  if (persistence && this.logWriter) {
@@ -3877,7 +4099,10 @@ function createClaudeConnection(config) {
3877
4099
  const agentStream = ndJsonStream(agentWritable, streams.agent.readable);
3878
4100
  let agent = null;
3879
4101
  const agentConnection = new AgentSideConnection((client) => {
3880
- agent = new ClaudeAcpAgent(client, logWriter, config.processCallbacks);
4102
+ agent = new ClaudeAcpAgent(client, logWriter, {
4103
+ ...config.processCallbacks,
4104
+ debug: config.debug
4105
+ });
3881
4106
  logger.info(`Created ${agent.adapterName} agent`);
3882
4107
  return agent;
3883
4108
  }, agentStream);
@@ -4577,6 +4802,7 @@ var Agent = class {
4577
4802
  taskId,
4578
4803
  deviceType: "local",
4579
4804
  logger: this.logger,
4805
+ debug: this.debug,
4580
4806
  processCallbacks: options.processCallbacks,
4581
4807
  allowedModelIds,
4582
4808
  codexOptions: options.adapter === "codex" && gatewayConfig ? {
@@ -4677,133 +4903,6 @@ var OtelLogWriter = class {
4677
4903
  }
4678
4904
  };
4679
4905
 
4680
- // ../shared/dist/index.js
4681
- var consoleLogger = {
4682
- info: (_message, _data) => {
4683
- },
4684
- debug: (_message, _data) => {
4685
- },
4686
- error: (_message, _data) => {
4687
- },
4688
- warn: (_message, _data) => {
4689
- }
4690
- };
4691
- var Saga = class {
4692
- completedSteps = [];
4693
- currentStepName = "unknown";
4694
- stepTimings = [];
4695
- log;
4696
- constructor(logger) {
4697
- this.log = logger ?? consoleLogger;
4698
- }
4699
- /**
4700
- * Run the saga with the given input.
4701
- * Returns a discriminated union result - either success with data or failure with error details.
4702
- */
4703
- async run(input) {
4704
- this.completedSteps = [];
4705
- this.currentStepName = "unknown";
4706
- this.stepTimings = [];
4707
- const sagaStart = performance.now();
4708
- this.log.info("Starting saga", { sagaName: this.constructor.name });
4709
- try {
4710
- const result = await this.execute(input);
4711
- const totalDuration = performance.now() - sagaStart;
4712
- this.log.debug("Saga completed successfully", {
4713
- sagaName: this.constructor.name,
4714
- stepsCompleted: this.completedSteps.length,
4715
- totalDurationMs: Math.round(totalDuration),
4716
- stepTimings: this.stepTimings
4717
- });
4718
- return { success: true, data: result };
4719
- } catch (error) {
4720
- this.log.error("Saga failed, initiating rollback", {
4721
- sagaName: this.constructor.name,
4722
- failedStep: this.currentStepName,
4723
- error: error instanceof Error ? error.message : String(error)
4724
- });
4725
- await this.rollback();
4726
- return {
4727
- success: false,
4728
- error: error instanceof Error ? error.message : String(error),
4729
- failedStep: this.currentStepName
4730
- };
4731
- }
4732
- }
4733
- /**
4734
- * Execute a step with its rollback action.
4735
- * If the step succeeds, its rollback action is stored for potential rollback.
4736
- * The step name is automatically tracked for error reporting.
4737
- *
4738
- * @param config - Step configuration with name, execute, and rollback functions
4739
- * @returns The result of the execute function
4740
- * @throws Re-throws any error from the execute function (triggers rollback)
4741
- */
4742
- async step(config) {
4743
- this.currentStepName = config.name;
4744
- this.log.debug(`Executing step: ${config.name}`);
4745
- const stepStart = performance.now();
4746
- const result = await config.execute();
4747
- const durationMs = Math.round(performance.now() - stepStart);
4748
- this.stepTimings.push({ name: config.name, durationMs });
4749
- this.log.debug(`Step completed: ${config.name}`, { durationMs });
4750
- this.completedSteps.push({
4751
- name: config.name,
4752
- rollback: () => config.rollback(result)
4753
- });
4754
- return result;
4755
- }
4756
- /**
4757
- * Execute a step that doesn't need rollback.
4758
- * Useful for read-only operations or operations that are idempotent.
4759
- * The step name is automatically tracked for error reporting.
4760
- *
4761
- * @param name - Step name for logging and error tracking
4762
- * @param execute - The action to execute
4763
- * @returns The result of the execute function
4764
- */
4765
- async readOnlyStep(name, execute) {
4766
- this.currentStepName = name;
4767
- this.log.debug(`Executing read-only step: ${name}`);
4768
- const stepStart = performance.now();
4769
- const result = await execute();
4770
- const durationMs = Math.round(performance.now() - stepStart);
4771
- this.stepTimings.push({ name, durationMs });
4772
- this.log.debug(`Read-only step completed: ${name}`, { durationMs });
4773
- return result;
4774
- }
4775
- /**
4776
- * Roll back all completed steps in reverse order.
4777
- * Rollback errors are logged but don't stop the rollback of other steps.
4778
- */
4779
- async rollback() {
4780
- this.log.info("Rolling back saga", {
4781
- stepsToRollback: this.completedSteps.length
4782
- });
4783
- const stepsReversed = [...this.completedSteps].reverse();
4784
- for (const step of stepsReversed) {
4785
- try {
4786
- this.log.debug(`Rolling back step: ${step.name}`);
4787
- await step.rollback();
4788
- this.log.debug(`Step rolled back: ${step.name}`);
4789
- } catch (error) {
4790
- this.log.error(`Failed to rollback step: ${step.name}`, {
4791
- error: error instanceof Error ? error.message : String(error)
4792
- });
4793
- }
4794
- }
4795
- this.log.info("Rollback completed", {
4796
- stepsAttempted: this.completedSteps.length
4797
- });
4798
- }
4799
- /**
4800
- * Get the number of completed steps (useful for testing)
4801
- */
4802
- getCompletedStepCount() {
4803
- return this.completedSteps.length;
4804
- }
4805
- };
4806
-
4807
4906
  // ../git/dist/queries.js
4808
4907
  import * as fs4 from "fs/promises";
4809
4908
  import * as path5 from "path";
@@ -9570,7 +9669,7 @@ async function isCommitOnRemote(baseDir, commit, options) {
9570
9669
  }
9571
9670
 
9572
9671
  // src/sagas/apply-snapshot-saga.ts
9573
- import { mkdir as mkdir3, rm as rm2, writeFile as writeFile3 } from "fs/promises";
9672
+ import { mkdir as mkdir3, rm as rm3, writeFile as writeFile3 } from "fs/promises";
9574
9673
  import { join as join5 } from "path";
9575
9674
 
9576
9675
  // ../git/dist/sagas/tree.js
@@ -9884,7 +9983,7 @@ var ApplySnapshotSaga = class extends Saga {
9884
9983
  },
9885
9984
  rollback: async () => {
9886
9985
  if (this.archivePath) {
9887
- await rm2(this.archivePath, { force: true }).catch(() => {
9986
+ await rm3(this.archivePath, { force: true }).catch(() => {
9888
9987
  });
9889
9988
  }
9890
9989
  }
@@ -9900,7 +9999,7 @@ var ApplySnapshotSaga = class extends Saga {
9900
9999
  if (!applyResult.success) {
9901
10000
  throw new Error(`Failed to apply tree: ${applyResult.error}`);
9902
10001
  }
9903
- await rm2(this.archivePath, { force: true }).catch(() => {
10002
+ await rm3(this.archivePath, { force: true }).catch(() => {
9904
10003
  });
9905
10004
  this.log.info("Tree snapshot applied", {
9906
10005
  treeHash: snapshot.treeHash,
@@ -9913,7 +10012,7 @@ var ApplySnapshotSaga = class extends Saga {
9913
10012
 
9914
10013
  // src/sagas/capture-tree-saga.ts
9915
10014
  import { existsSync as existsSync5 } from "fs";
9916
- import { readFile as readFile3, rm as rm3 } from "fs/promises";
10015
+ import { readFile as readFile3, rm as rm4 } from "fs/promises";
9917
10016
  import { join as join6 } from "path";
9918
10017
  var CaptureTreeSaga2 = class extends Saga {
9919
10018
  async execute(input) {
@@ -9962,7 +10061,7 @@ var CaptureTreeSaga2 = class extends Saga {
9962
10061
  runId
9963
10062
  );
9964
10063
  } finally {
9965
- await rm3(createdArchivePath, { force: true }).catch(() => {
10064
+ await rm4(createdArchivePath, { force: true }).catch(() => {
9966
10065
  });
9967
10066
  }
9968
10067
  }
@@ -10006,7 +10105,7 @@ var CaptureTreeSaga2 = class extends Saga {
10006
10105
  return void 0;
10007
10106
  },
10008
10107
  rollback: async () => {
10009
- await rm3(archivePath, { force: true }).catch(() => {
10108
+ await rm4(archivePath, { force: true }).catch(() => {
10010
10109
  });
10011
10110
  }
10012
10111
  });