@posthog/agent 2.1.47 → 2.1.53

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.
@@ -44,6 +44,8 @@ interface SessionLogWriterOptions {
44
44
  posthogAPI?: PostHogAPIClient;
45
45
  /** Logger instance */
46
46
  logger?: Logger;
47
+ /** Local cache path for instant log loading (e.g., ~/.twig) */
48
+ localCachePath?: string;
47
49
  }
48
50
  declare class SessionLogWriter {
49
51
  private static readonly FLUSH_DEBOUNCE_MS;
@@ -58,6 +60,7 @@ declare class SessionLogWriter {
58
60
  private sessions;
59
61
  private messageCounts;
60
62
  private logger;
63
+ private localCachePath?;
61
64
  constructor(options?: SessionLogWriterOptions);
62
65
  flushAll(): Promise<void>;
63
66
  register(sessionId: string, context: SessionContext): void;
@@ -68,6 +71,7 @@ declare class SessionLogWriter {
68
71
  private extractChunkText;
69
72
  private emitCoalescedMessage;
70
73
  private scheduleFlush;
74
+ private writeToLocalCache;
71
75
  }
72
76
 
73
77
  type StreamPair = {
@@ -94,8 +98,6 @@ type AcpConnectionConfig = {
94
98
  /** Deployment environment - "local" for desktop, "cloud" for cloud sandbox */
95
99
  deviceType?: "local" | "cloud";
96
100
  logger?: Logger;
97
- /** Enable dev-only instrumentation (timing, verbose logging) */
98
- debug?: boolean;
99
101
  processCallbacks?: ProcessSpawnedCallback;
100
102
  codexOptions?: CodexProcessOptions;
101
103
  allowedModelIds?: Set<string>;
package/dist/agent.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { b as Agent } from './agent-BJ7Uacyp.js';
1
+ export { b as Agent } from './agent-9gv5HohC.js';
2
2
  import './types.js';
3
3
  import '@agentclientprotocol/sdk';
4
4
  import './logger-DDBiMOOD.js';
package/dist/agent.js CHANGED
@@ -271,49 +271,12 @@ import {
271
271
  import {
272
272
  query
273
273
  } from "@anthropic-ai/claude-agent-sdk";
274
-
275
- // ../shared/dist/index.js
276
- var NOOP_COLLECTOR = {
277
- time: (_label, fn) => fn(),
278
- timeSync: (_label, fn) => fn(),
279
- record: () => {
280
- },
281
- summarize: () => {
282
- }
283
- };
284
- function createTimingCollector(enabled, log) {
285
- if (!enabled) return NOOP_COLLECTOR;
286
- const steps = {};
287
- return {
288
- async time(label, fn) {
289
- const start = Date.now();
290
- const result = await fn();
291
- steps[label] = Date.now() - start;
292
- return result;
293
- },
294
- timeSync(label, fn) {
295
- const start = Date.now();
296
- const result = fn();
297
- steps[label] = Date.now() - start;
298
- return result;
299
- },
300
- record(label, ms) {
301
- steps[label] = ms;
302
- },
303
- summarize(label) {
304
- const total = Object.values(steps).reduce((a, b) => a + b, 0);
305
- log(`[timing] ${label}: ${total}ms`, steps);
306
- }
307
- };
308
- }
309
-
310
- // src/adapters/claude/claude-agent.ts
311
274
  import { v7 as uuidv7 } from "uuid";
312
275
 
313
276
  // package.json
314
277
  var package_default = {
315
278
  name: "@posthog/agent",
316
- version: "2.1.47",
279
+ version: "2.1.53",
317
280
  repository: "https://github.com/PostHog/twig",
318
281
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
319
282
  exports: {
@@ -727,8 +690,8 @@ var ToolContentBuilder = class {
727
690
  this.items.push({ type: "content", content: image(data, mimeType, uri) });
728
691
  return this;
729
692
  }
730
- diff(path4, oldText, newText) {
731
- this.items.push({ type: "diff", path: path4, oldText, newText });
693
+ diff(path5, oldText, newText) {
694
+ this.items.push({ type: "diff", path: path5, oldText, newText });
732
695
  return this;
733
696
  }
734
697
  build() {
@@ -918,13 +881,13 @@ function toolInfoFromToolUse(toolUse, cachedFileContent, logger = new Logger({ d
918
881
  locations: []
919
882
  };
920
883
  case "Edit": {
921
- const path4 = input?.file_path ? String(input.file_path) : void 0;
884
+ const path5 = input?.file_path ? String(input.file_path) : void 0;
922
885
  let oldText = input?.old_string ? String(input.old_string) : null;
923
886
  let newText = input?.new_string ? String(input.new_string) : "";
924
887
  let affectedLines = [];
925
- if (path4 && oldText) {
888
+ if (path5 && oldText) {
926
889
  try {
927
- const oldContent = cachedFileContent[path4] || "";
890
+ const oldContent = cachedFileContent[path5] || "";
928
891
  const newContent = replaceAndCalculateLocation(oldContent, [
929
892
  {
930
893
  oldText,
@@ -940,17 +903,17 @@ function toolInfoFromToolUse(toolUse, cachedFileContent, logger = new Logger({ d
940
903
  }
941
904
  }
942
905
  return {
943
- title: path4 ? `Edit \`${path4}\`` : "Edit",
906
+ title: path5 ? `Edit \`${path5}\`` : "Edit",
944
907
  kind: "edit",
945
- content: input && path4 ? [
908
+ content: input && path5 ? [
946
909
  {
947
910
  type: "diff",
948
- path: path4,
911
+ path: path5,
949
912
  oldText,
950
913
  newText
951
914
  }
952
915
  ] : [],
953
- locations: path4 ? affectedLines.length > 0 ? affectedLines.map((line) => ({ line, path: path4 })) : [{ path: path4 }] : []
916
+ locations: path5 ? affectedLines.length > 0 ? affectedLines.map((line) => ({ line, path: path5 })) : [{ path: path5 }] : []
954
917
  };
955
918
  }
956
919
  case "Write": {
@@ -2424,12 +2387,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
2424
2387
  logWriter;
2425
2388
  options;
2426
2389
  lastSentConfigOptions;
2427
- debug;
2428
2390
  constructor(client, logWriter, options) {
2429
2391
  super(client);
2430
2392
  this.logWriter = logWriter;
2431
2393
  this.options = options;
2432
- this.debug = options?.debug ?? false;
2433
2394
  this.toolUseCache = {};
2434
2395
  this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
2435
2396
  }
@@ -2472,36 +2433,26 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
2472
2433
  }
2473
2434
  async newSession(params) {
2474
2435
  this.checkAuthStatus();
2475
- const tc = createTimingCollector(
2476
- this.debug,
2477
- (msg, data) => this.logger.info(msg, data)
2478
- );
2479
2436
  const meta = params._meta;
2480
2437
  const sessionId = uuidv7();
2481
2438
  const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
2482
- const mcpServers = tc.timeSync(
2483
- "parseMcpServers",
2484
- () => parseMcpServers(params)
2485
- );
2486
- const options = tc.timeSync(
2487
- "buildSessionOptions",
2488
- () => buildSessionOptions({
2489
- cwd: params.cwd,
2490
- mcpServers,
2491
- permissionMode,
2492
- canUseTool: this.createCanUseTool(sessionId),
2493
- logger: this.logger,
2494
- systemPrompt: buildSystemPrompt(meta?.systemPrompt),
2495
- userProvidedOptions: meta?.claudeCode?.options,
2496
- sessionId,
2497
- isResume: false,
2498
- onModeChange: this.createOnModeChange(sessionId),
2499
- onProcessSpawned: this.options?.onProcessSpawned,
2500
- onProcessExited: this.options?.onProcessExited
2501
- })
2502
- );
2439
+ const mcpServers = parseMcpServers(params);
2440
+ const options = buildSessionOptions({
2441
+ cwd: params.cwd,
2442
+ mcpServers,
2443
+ permissionMode,
2444
+ canUseTool: this.createCanUseTool(sessionId),
2445
+ logger: this.logger,
2446
+ systemPrompt: buildSystemPrompt(meta?.systemPrompt),
2447
+ userProvidedOptions: meta?.claudeCode?.options,
2448
+ sessionId,
2449
+ isResume: false,
2450
+ onModeChange: this.createOnModeChange(sessionId),
2451
+ onProcessSpawned: this.options?.onProcessSpawned,
2452
+ onProcessExited: this.options?.onProcessExited
2453
+ });
2503
2454
  const input = new Pushable();
2504
- const q = tc.timeSync("sdkQuery", () => query({ prompt: input, options }));
2455
+ const q = query({ prompt: input, options });
2505
2456
  const session = this.createSession(
2506
2457
  sessionId,
2507
2458
  q,
@@ -2513,27 +2464,17 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
2513
2464
  session.taskRunId = meta?.taskRunId;
2514
2465
  this.registerPersistence(sessionId, meta);
2515
2466
  if (meta?.taskRunId) {
2516
- await tc.time(
2517
- "extNotification",
2518
- () => this.client.extNotification("_posthog/sdk_session", {
2519
- taskRunId: meta.taskRunId,
2520
- sessionId,
2521
- adapter: "claude"
2522
- })
2523
- );
2467
+ await this.client.extNotification("_posthog/sdk_session", {
2468
+ taskRunId: meta.taskRunId,
2469
+ sessionId,
2470
+ adapter: "claude"
2471
+ });
2524
2472
  }
2525
- const modelOptions = await tc.time(
2526
- "fetchModels",
2527
- () => this.getModelConfigOptions()
2528
- );
2529
- this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
2473
+ const modelOptions = await this.getModelConfigOptions();
2474
+ this.deferBackgroundFetches(q, sessionId, mcpServers);
2530
2475
  session.modelId = modelOptions.currentModelId;
2531
2476
  await this.trySetModel(q, modelOptions.currentModelId);
2532
- const configOptions = await tc.time(
2533
- "buildConfigOptions",
2534
- () => this.buildConfigOptions(modelOptions)
2535
- );
2536
- tc.summarize("newSession");
2477
+ const configOptions = await this.buildConfigOptions(modelOptions);
2537
2478
  return {
2538
2479
  sessionId,
2539
2480
  configOptions
@@ -2543,10 +2484,6 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
2543
2484
  return this.resumeSession(params);
2544
2485
  }
2545
2486
  async resumeSession(params) {
2546
- const tc = createTimingCollector(
2547
- this.debug,
2548
- (msg, data) => this.logger.info(msg, data)
2549
- );
2550
2487
  const meta = params._meta;
2551
2488
  const sessionId = meta?.sessionId;
2552
2489
  if (!sessionId) {
@@ -2555,32 +2492,22 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
2555
2492
  if (this.sessionId === sessionId) {
2556
2493
  return {};
2557
2494
  }
2558
- const mcpServers = tc.timeSync(
2559
- "parseMcpServers",
2560
- () => parseMcpServers(params)
2561
- );
2495
+ const mcpServers = parseMcpServers(params);
2562
2496
  const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
2563
- const { query: q, session } = await tc.time(
2564
- "initializeQuery",
2565
- () => this.initializeQuery({
2566
- cwd: params.cwd,
2567
- permissionMode,
2568
- mcpServers,
2569
- systemPrompt: buildSystemPrompt(meta?.systemPrompt),
2570
- userProvidedOptions: meta?.claudeCode?.options,
2571
- sessionId,
2572
- isResume: true,
2573
- additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
2574
- })
2575
- );
2497
+ const { query: q, session } = await this.initializeQuery({
2498
+ cwd: params.cwd,
2499
+ permissionMode,
2500
+ mcpServers,
2501
+ systemPrompt: buildSystemPrompt(meta?.systemPrompt),
2502
+ userProvidedOptions: meta?.claudeCode?.options,
2503
+ sessionId,
2504
+ isResume: true,
2505
+ additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
2506
+ });
2576
2507
  session.taskRunId = meta?.taskRunId;
2577
2508
  this.registerPersistence(sessionId, meta);
2578
- this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
2579
- const configOptions = await tc.time(
2580
- "buildConfigOptions",
2581
- () => this.buildConfigOptions()
2582
- );
2583
- tc.summarize("resumeSession");
2509
+ this.deferBackgroundFetches(q, sessionId, mcpServers);
2510
+ const configOptions = await this.buildConfigOptions();
2584
2511
  return { configOptions };
2585
2512
  }
2586
2513
  async prompt(params) {
@@ -2768,13 +2695,10 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
2768
2695
  * Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
2769
2696
  * Both populate caches used later — neither is needed to return configOptions.
2770
2697
  */
2771
- deferBackgroundFetches(tc, q, sessionId, mcpServers) {
2698
+ deferBackgroundFetches(q, sessionId, mcpServers) {
2772
2699
  Promise.all([
2773
- tc.time("slashCommands", () => getAvailableSlashCommands(q)),
2774
- tc.time(
2775
- "mcpMetadata",
2776
- () => fetchMcpToolMetadata(mcpServers, this.logger)
2777
- )
2700
+ getAvailableSlashCommands(q),
2701
+ fetchMcpToolMetadata(mcpServers, this.logger)
2778
2702
  ]).then(([slashCommands]) => {
2779
2703
  this.sendAvailableCommandsUpdate(sessionId, slashCommands);
2780
2704
  }).catch((err) => {
@@ -3068,10 +2992,7 @@ function createClaudeConnection(config) {
3068
2992
  const agentStream = ndJsonStream(agentWritable, streams.agent.readable);
3069
2993
  let agent = null;
3070
2994
  const agentConnection = new AgentSideConnection((client) => {
3071
- agent = new ClaudeAcpAgent(client, logWriter, {
3072
- ...config.processCallbacks,
3073
- debug: config.debug
3074
- });
2995
+ agent = new ClaudeAcpAgent(client, logWriter, config.processCallbacks);
3075
2996
  logger.info(`Created ${agent.adapterName} agent`);
3076
2997
  return agent;
3077
2998
  }, agentStream);
@@ -3486,6 +3407,8 @@ var PostHogAPIClient = class {
3486
3407
  };
3487
3408
 
3488
3409
  // src/session-log-writer.ts
3410
+ import fs3 from "fs";
3411
+ import path4 from "path";
3489
3412
  var SessionLogWriter = class _SessionLogWriter {
3490
3413
  static FLUSH_DEBOUNCE_MS = 500;
3491
3414
  static FLUSH_MAX_INTERVAL_MS = 5e3;
@@ -3499,8 +3422,10 @@ var SessionLogWriter = class _SessionLogWriter {
3499
3422
  sessions = /* @__PURE__ */ new Map();
3500
3423
  messageCounts = /* @__PURE__ */ new Map();
3501
3424
  logger;
3425
+ localCachePath;
3502
3426
  constructor(options = {}) {
3503
3427
  this.posthogAPI = options.posthogAPI;
3428
+ this.localCachePath = options.localCachePath;
3504
3429
  this.logger = options.logger ?? new Logger({ debug: false, prefix: "[SessionLogWriter]" });
3505
3430
  }
3506
3431
  async flushAll() {
@@ -3530,6 +3455,21 @@ var SessionLogWriter = class _SessionLogWriter {
3530
3455
  });
3531
3456
  this.sessions.set(sessionId, { context });
3532
3457
  this.lastFlushAttemptTime.set(sessionId, Date.now());
3458
+ if (this.localCachePath) {
3459
+ const sessionDir = path4.join(
3460
+ this.localCachePath,
3461
+ "sessions",
3462
+ context.runId
3463
+ );
3464
+ try {
3465
+ fs3.mkdirSync(sessionDir, { recursive: true });
3466
+ } catch (error) {
3467
+ this.logger.warn("Failed to create local cache directory", {
3468
+ sessionDir,
3469
+ error
3470
+ });
3471
+ }
3472
+ }
3533
3473
  }
3534
3474
  isRegistered(sessionId) {
3535
3475
  return this.sessions.has(sessionId);
@@ -3567,6 +3507,7 @@ var SessionLogWriter = class _SessionLogWriter {
3567
3507
  timestamp,
3568
3508
  notification: message
3569
3509
  };
3510
+ this.writeToLocalCache(sessionId, entry);
3570
3511
  if (this.posthogAPI) {
3571
3512
  const pending = this.pendingEntries.get(sessionId) ?? [];
3572
3513
  pending.push(entry);
@@ -3667,6 +3608,7 @@ var SessionLogWriter = class _SessionLogWriter {
3667
3608
  }
3668
3609
  }
3669
3610
  };
3611
+ this.writeToLocalCache(sessionId, entry);
3670
3612
  if (this.posthogAPI) {
3671
3613
  const pending = this.pendingEntries.get(sessionId) ?? [];
3672
3614
  pending.push(entry);
@@ -3694,6 +3636,23 @@ var SessionLogWriter = class _SessionLogWriter {
3694
3636
  const timeout = setTimeout(() => this.flush(sessionId), delay);
3695
3637
  this.flushTimeouts.set(sessionId, timeout);
3696
3638
  }
3639
+ writeToLocalCache(sessionId, entry) {
3640
+ if (!this.localCachePath) return;
3641
+ const session = this.sessions.get(sessionId);
3642
+ if (!session) return;
3643
+ const logPath = path4.join(
3644
+ this.localCachePath,
3645
+ "sessions",
3646
+ session.context.runId,
3647
+ "logs.ndjson"
3648
+ );
3649
+ try {
3650
+ fs3.appendFileSync(logPath, `${JSON.stringify(entry)}
3651
+ `);
3652
+ } catch (error) {
3653
+ this.logger.warn("Failed to write to local cache", { logPath, error });
3654
+ }
3655
+ }
3697
3656
  };
3698
3657
 
3699
3658
  // src/agent.ts
@@ -3717,7 +3676,8 @@ var Agent = class {
3717
3676
  if (config.posthog && !config.skipLogPersistence) {
3718
3677
  this.sessionLogWriter = new SessionLogWriter({
3719
3678
  posthogAPI: this.posthogAPI,
3720
- logger: this.logger.child("SessionLogWriter")
3679
+ logger: this.logger.child("SessionLogWriter"),
3680
+ localCachePath: config.localCachePath
3721
3681
  });
3722
3682
  }
3723
3683
  }
@@ -3771,7 +3731,6 @@ var Agent = class {
3771
3731
  taskId,
3772
3732
  deviceType: "local",
3773
3733
  logger: this.logger,
3774
- debug: this.debug,
3775
3734
  processCallbacks: options.processCallbacks,
3776
3735
  allowedModelIds,
3777
3736
  codexOptions: options.adapter === "codex" && gatewayConfig ? {