@posthog/agent 2.1.45 → 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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AcpConnection, a as AcpConnectionConfig, b as Agent, c as AgentAdapter, C as CodexProcessOptions, I as InProcessAcpConnection, O as OtelLogConfig, d as OtelLogWriter, S as SessionContext, e as SessionLogWriter, f as SessionLogWriterOptions, g as createAcpConnection } from './agent-DcBmoTR4.js';
1
+ export { A as AcpConnection, a as AcpConnectionConfig, b as Agent, c as AgentAdapter, C as CodexProcessOptions, I as InProcessAcpConnection, O as OtelLogConfig, d as OtelLogWriter, S as SessionContext, e as SessionLogWriter, f as SessionLogWriterOptions, g as createAcpConnection } from './agent-BJ7Uacyp.js';
2
2
  import { McpServerConfig } from '@anthropic-ai/claude-agent-sdk';
3
3
  import { L as Logger } from './logger-DDBiMOOD.js';
4
4
  export { a as LoggerConfig } from './logger-DDBiMOOD.js';
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.45",
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: {
@@ -3291,12 +3453,14 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3291
3453
  backgroundTerminals = {};
3292
3454
  clientCapabilities;
3293
3455
  logWriter;
3294
- processCallbacks;
3456
+ options;
3295
3457
  lastSentConfigOptions;
3296
- constructor(client, logWriter, processCallbacks) {
3458
+ debug;
3459
+ constructor(client, logWriter, options) {
3297
3460
  super(client);
3298
3461
  this.logWriter = logWriter;
3299
- this.processCallbacks = processCallbacks;
3462
+ this.options = options;
3463
+ this.debug = options?.debug ?? false;
3300
3464
  this.toolUseCache = {};
3301
3465
  this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
3302
3466
  }
@@ -3339,27 +3503,36 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3339
3503
  }
3340
3504
  async newSession(params) {
3341
3505
  this.checkAuthStatus();
3506
+ const tc = createTimingCollector(
3507
+ this.debug,
3508
+ (msg, data) => this.logger.info(msg, data)
3509
+ );
3342
3510
  const meta = params._meta;
3343
3511
  const sessionId = uuidv7();
3344
3512
  const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
3345
- const mcpServers = parseMcpServers(params);
3346
- const mcpMetadataPromise = fetchMcpToolMetadata(mcpServers, this.logger);
3347
- const options = buildSessionOptions({
3348
- cwd: params.cwd,
3349
- mcpServers,
3350
- permissionMode,
3351
- canUseTool: this.createCanUseTool(sessionId),
3352
- logger: this.logger,
3353
- systemPrompt: buildSystemPrompt(meta?.systemPrompt),
3354
- userProvidedOptions: meta?.claudeCode?.options,
3355
- sessionId,
3356
- isResume: false,
3357
- onModeChange: this.createOnModeChange(sessionId),
3358
- onProcessSpawned: this.processCallbacks?.onProcessSpawned,
3359
- onProcessExited: this.processCallbacks?.onProcessExited
3360
- });
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
+ );
3361
3534
  const input = new Pushable();
3362
- const q = query({ prompt: input, options });
3535
+ const q = tc.timeSync("sdkQuery", () => query({ prompt: input, options }));
3363
3536
  const session = this.createSession(
3364
3537
  sessionId,
3365
3538
  q,
@@ -3371,29 +3544,40 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3371
3544
  session.taskRunId = meta?.taskRunId;
3372
3545
  this.registerPersistence(sessionId, meta);
3373
3546
  if (meta?.taskRunId) {
3374
- await this.client.extNotification("_posthog/sdk_session", {
3375
- taskRunId: meta.taskRunId,
3376
- sessionId,
3377
- adapter: "claude"
3378
- });
3547
+ await tc.time(
3548
+ "extNotification",
3549
+ () => this.client.extNotification("_posthog/sdk_session", {
3550
+ taskRunId: meta.taskRunId,
3551
+ sessionId,
3552
+ adapter: "claude"
3553
+ })
3554
+ );
3379
3555
  }
3380
- const [modelOptions, slashCommands] = await Promise.all([
3381
- this.getModelConfigOptions(),
3382
- getAvailableSlashCommands(q),
3383
- mcpMetadataPromise
3384
- ]);
3556
+ const modelOptions = await tc.time(
3557
+ "fetchModels",
3558
+ () => this.getModelConfigOptions()
3559
+ );
3560
+ this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
3385
3561
  session.modelId = modelOptions.currentModelId;
3386
3562
  await this.trySetModel(q, modelOptions.currentModelId);
3387
- this.sendAvailableCommandsUpdate(sessionId, slashCommands);
3563
+ const configOptions = await tc.time(
3564
+ "buildConfigOptions",
3565
+ () => this.buildConfigOptions(modelOptions)
3566
+ );
3567
+ tc.summarize("newSession");
3388
3568
  return {
3389
3569
  sessionId,
3390
- configOptions: await this.buildConfigOptions(modelOptions)
3570
+ configOptions
3391
3571
  };
3392
3572
  }
3393
3573
  async loadSession(params) {
3394
3574
  return this.resumeSession(params);
3395
3575
  }
3396
3576
  async resumeSession(params) {
3577
+ const tc = createTimingCollector(
3578
+ this.debug,
3579
+ (msg, data) => this.logger.info(msg, data)
3580
+ );
3397
3581
  const meta = params._meta;
3398
3582
  const sessionId = meta?.sessionId;
3399
3583
  if (!sessionId) {
@@ -3402,29 +3586,33 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3402
3586
  if (this.sessionId === sessionId) {
3403
3587
  return {};
3404
3588
  }
3405
- const mcpServers = parseMcpServers(params);
3406
- const mcpMetadataPromise = fetchMcpToolMetadata(mcpServers, this.logger);
3589
+ const mcpServers = tc.timeSync(
3590
+ "parseMcpServers",
3591
+ () => parseMcpServers(params)
3592
+ );
3407
3593
  const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
3408
- const { query: q, session } = await this.initializeQuery({
3409
- cwd: params.cwd,
3410
- permissionMode,
3411
- mcpServers,
3412
- systemPrompt: buildSystemPrompt(meta?.systemPrompt),
3413
- userProvidedOptions: meta?.claudeCode?.options,
3414
- sessionId,
3415
- isResume: true,
3416
- additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
3417
- });
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
+ );
3418
3607
  session.taskRunId = meta?.taskRunId;
3419
3608
  this.registerPersistence(sessionId, meta);
3420
- const [slashCommands] = await Promise.all([
3421
- getAvailableSlashCommands(q),
3422
- mcpMetadataPromise
3423
- ]);
3424
- this.sendAvailableCommandsUpdate(sessionId, slashCommands);
3425
- return {
3426
- configOptions: await this.buildConfigOptions()
3427
- };
3609
+ this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
3610
+ const configOptions = await tc.time(
3611
+ "buildConfigOptions",
3612
+ () => this.buildConfigOptions()
3613
+ );
3614
+ tc.summarize("resumeSession");
3615
+ return { configOptions };
3428
3616
  }
3429
3617
  async prompt(params) {
3430
3618
  this.session.cancelled = false;
@@ -3496,8 +3684,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3496
3684
  isResume: config.isResume,
3497
3685
  additionalDirectories: config.additionalDirectories,
3498
3686
  onModeChange: this.createOnModeChange(config.sessionId),
3499
- onProcessSpawned: this.processCallbacks?.onProcessSpawned,
3500
- onProcessExited: this.processCallbacks?.onProcessExited
3687
+ onProcessSpawned: this.options?.onProcessSpawned,
3688
+ onProcessExited: this.options?.onProcessExited
3501
3689
  });
3502
3690
  const q = query({ prompt: input, options });
3503
3691
  const abortController = options.abortController;
@@ -3607,6 +3795,23 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
3607
3795
  await q.setModel(fallback);
3608
3796
  }
3609
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
+ }
3610
3815
  registerPersistence(sessionId, meta) {
3611
3816
  const persistence = meta?.persistence;
3612
3817
  if (persistence && this.logWriter) {
@@ -3894,7 +4099,10 @@ function createClaudeConnection(config) {
3894
4099
  const agentStream = ndJsonStream(agentWritable, streams.agent.readable);
3895
4100
  let agent = null;
3896
4101
  const agentConnection = new AgentSideConnection((client) => {
3897
- agent = new ClaudeAcpAgent(client, logWriter, config.processCallbacks);
4102
+ agent = new ClaudeAcpAgent(client, logWriter, {
4103
+ ...config.processCallbacks,
4104
+ debug: config.debug
4105
+ });
3898
4106
  logger.info(`Created ${agent.adapterName} agent`);
3899
4107
  return agent;
3900
4108
  }, agentStream);
@@ -4594,6 +4802,7 @@ var Agent = class {
4594
4802
  taskId,
4595
4803
  deviceType: "local",
4596
4804
  logger: this.logger,
4805
+ debug: this.debug,
4597
4806
  processCallbacks: options.processCallbacks,
4598
4807
  allowedModelIds,
4599
4808
  codexOptions: options.adapter === "codex" && gatewayConfig ? {
@@ -4694,133 +4903,6 @@ var OtelLogWriter = class {
4694
4903
  }
4695
4904
  };
4696
4905
 
4697
- // ../shared/dist/index.js
4698
- var consoleLogger = {
4699
- info: (_message, _data) => {
4700
- },
4701
- debug: (_message, _data) => {
4702
- },
4703
- error: (_message, _data) => {
4704
- },
4705
- warn: (_message, _data) => {
4706
- }
4707
- };
4708
- var Saga = class {
4709
- completedSteps = [];
4710
- currentStepName = "unknown";
4711
- stepTimings = [];
4712
- log;
4713
- constructor(logger) {
4714
- this.log = logger ?? consoleLogger;
4715
- }
4716
- /**
4717
- * Run the saga with the given input.
4718
- * Returns a discriminated union result - either success with data or failure with error details.
4719
- */
4720
- async run(input) {
4721
- this.completedSteps = [];
4722
- this.currentStepName = "unknown";
4723
- this.stepTimings = [];
4724
- const sagaStart = performance.now();
4725
- this.log.info("Starting saga", { sagaName: this.constructor.name });
4726
- try {
4727
- const result = await this.execute(input);
4728
- const totalDuration = performance.now() - sagaStart;
4729
- this.log.debug("Saga completed successfully", {
4730
- sagaName: this.constructor.name,
4731
- stepsCompleted: this.completedSteps.length,
4732
- totalDurationMs: Math.round(totalDuration),
4733
- stepTimings: this.stepTimings
4734
- });
4735
- return { success: true, data: result };
4736
- } catch (error) {
4737
- this.log.error("Saga failed, initiating rollback", {
4738
- sagaName: this.constructor.name,
4739
- failedStep: this.currentStepName,
4740
- error: error instanceof Error ? error.message : String(error)
4741
- });
4742
- await this.rollback();
4743
- return {
4744
- success: false,
4745
- error: error instanceof Error ? error.message : String(error),
4746
- failedStep: this.currentStepName
4747
- };
4748
- }
4749
- }
4750
- /**
4751
- * Execute a step with its rollback action.
4752
- * If the step succeeds, its rollback action is stored for potential rollback.
4753
- * The step name is automatically tracked for error reporting.
4754
- *
4755
- * @param config - Step configuration with name, execute, and rollback functions
4756
- * @returns The result of the execute function
4757
- * @throws Re-throws any error from the execute function (triggers rollback)
4758
- */
4759
- async step(config) {
4760
- this.currentStepName = config.name;
4761
- this.log.debug(`Executing step: ${config.name}`);
4762
- const stepStart = performance.now();
4763
- const result = await config.execute();
4764
- const durationMs = Math.round(performance.now() - stepStart);
4765
- this.stepTimings.push({ name: config.name, durationMs });
4766
- this.log.debug(`Step completed: ${config.name}`, { durationMs });
4767
- this.completedSteps.push({
4768
- name: config.name,
4769
- rollback: () => config.rollback(result)
4770
- });
4771
- return result;
4772
- }
4773
- /**
4774
- * Execute a step that doesn't need rollback.
4775
- * Useful for read-only operations or operations that are idempotent.
4776
- * The step name is automatically tracked for error reporting.
4777
- *
4778
- * @param name - Step name for logging and error tracking
4779
- * @param execute - The action to execute
4780
- * @returns The result of the execute function
4781
- */
4782
- async readOnlyStep(name, execute) {
4783
- this.currentStepName = name;
4784
- this.log.debug(`Executing read-only step: ${name}`);
4785
- const stepStart = performance.now();
4786
- const result = await execute();
4787
- const durationMs = Math.round(performance.now() - stepStart);
4788
- this.stepTimings.push({ name, durationMs });
4789
- this.log.debug(`Read-only step completed: ${name}`, { durationMs });
4790
- return result;
4791
- }
4792
- /**
4793
- * Roll back all completed steps in reverse order.
4794
- * Rollback errors are logged but don't stop the rollback of other steps.
4795
- */
4796
- async rollback() {
4797
- this.log.info("Rolling back saga", {
4798
- stepsToRollback: this.completedSteps.length
4799
- });
4800
- const stepsReversed = [...this.completedSteps].reverse();
4801
- for (const step of stepsReversed) {
4802
- try {
4803
- this.log.debug(`Rolling back step: ${step.name}`);
4804
- await step.rollback();
4805
- this.log.debug(`Step rolled back: ${step.name}`);
4806
- } catch (error) {
4807
- this.log.error(`Failed to rollback step: ${step.name}`, {
4808
- error: error instanceof Error ? error.message : String(error)
4809
- });
4810
- }
4811
- }
4812
- this.log.info("Rollback completed", {
4813
- stepsAttempted: this.completedSteps.length
4814
- });
4815
- }
4816
- /**
4817
- * Get the number of completed steps (useful for testing)
4818
- */
4819
- getCompletedStepCount() {
4820
- return this.completedSteps.length;
4821
- }
4822
- };
4823
-
4824
4906
  // ../git/dist/queries.js
4825
4907
  import * as fs4 from "fs/promises";
4826
4908
  import * as path5 from "path";