@posthog/agent 2.3.354 → 2.3.363

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@posthog/agent",
3
- "version": "2.3.354",
3
+ "version": "2.3.363",
4
4
  "repository": "https://github.com/PostHog/code",
5
5
  "description": "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
6
6
  "exports": {
@@ -86,9 +86,9 @@
86
86
  "tsx": "^4.20.6",
87
87
  "typescript": "^5.5.0",
88
88
  "vitest": "^2.1.8",
89
- "@posthog/git": "1.0.0",
89
+ "@posthog/shared": "1.0.0",
90
90
  "@posthog/enricher": "1.0.0",
91
- "@posthog/shared": "1.0.0"
91
+ "@posthog/git": "1.0.0"
92
92
  },
93
93
  "dependencies": {
94
94
  "@agentclientprotocol/sdk": "0.19.0",
@@ -55,6 +55,9 @@ export const POSTHOG_NOTIFICATIONS = {
55
55
  /** Agent status update (thinking, working, etc.) */
56
56
  STATUS: "_posthog/status",
57
57
 
58
+ /** Structured backend progress notification; events in the same turn group into one card on the client */
59
+ PROGRESS: "_posthog/progress",
60
+
58
61
  /** Task-level notification (progress, milestones) */
59
62
  TASK_NOTIFICATION: "_posthog/task_notification",
60
63
 
@@ -127,11 +127,10 @@ export type OnModeChange = (mode: CodeExecutionMode) => Promise<void>;
127
127
 
128
128
  interface CreatePostToolUseHookParams {
129
129
  onModeChange?: OnModeChange;
130
- logger?: Logger;
131
130
  }
132
131
 
133
132
  export const createPostToolUseHook =
134
- ({ onModeChange, logger }: CreatePostToolUseHookParams): HookCallback =>
133
+ ({ onModeChange }: CreatePostToolUseHookParams): HookCallback =>
135
134
  async (
136
135
  input: HookInput,
137
136
  toolUseID: string | undefined,
@@ -119,7 +119,7 @@ function buildHooks(
119
119
  enrichedReadCache: EnrichedReadCache | undefined,
120
120
  registeredAgents: ReadonlySet<string>,
121
121
  ): Options["hooks"] {
122
- const postToolUseHooks = [createPostToolUseHook({ onModeChange, logger })];
122
+ const postToolUseHooks = [createPostToolUseHook({ onModeChange })];
123
123
  if (enrichmentDeps && enrichedReadCache) {
124
124
  postToolUseHooks.push(
125
125
  createReadEnrichmentHook(enrichmentDeps, enrichedReadCache),
@@ -460,7 +460,9 @@ export class AgentServer {
460
460
  port: this.config.port,
461
461
  },
462
462
  () => {
463
- this.logger.info(`HTTP server listening on port ${this.config.port}`);
463
+ this.logger.debug(
464
+ `HTTP server listening on port ${this.config.port}`,
465
+ );
464
466
  resolve();
465
467
  },
466
468
  );
@@ -472,12 +474,12 @@ export class AgentServer {
472
474
  private async autoInitializeSession(): Promise<void> {
473
475
  const { taskId, runId, mode, projectId } = this.config;
474
476
 
475
- this.logger.info("Auto-initializing session", { taskId, runId, mode });
477
+ this.logger.debug("Auto-initializing session", { taskId, runId, mode });
476
478
 
477
479
  // Check if this is a resume from a previous run
478
480
  const resumeRunId = process.env.POSTHOG_RESUME_RUN_ID;
479
481
  if (resumeRunId) {
480
- this.logger.info("Resuming from previous run", {
482
+ this.logger.debug("Resuming from previous run", {
481
483
  resumeRunId,
482
484
  currentRunId: runId,
483
485
  });
@@ -489,13 +491,13 @@ export class AgentServer {
489
491
  apiClient: this.posthogAPI,
490
492
  logger: new Logger({ debug: true, prefix: "[Resume]" }),
491
493
  });
492
- this.logger.info("Resume state loaded", {
494
+ this.logger.debug("Resume state loaded", {
493
495
  conversationTurns: this.resumeState.conversation.length,
494
496
  snapshotApplied: this.resumeState.snapshotApplied,
495
497
  logEntries: this.resumeState.logEntryCount,
496
498
  });
497
499
  } catch (error) {
498
- this.logger.warn("Failed to load resume state, starting fresh", {
500
+ this.logger.debug("Failed to load resume state, starting fresh", {
499
501
  error,
500
502
  });
501
503
  this.resumeState = null;
@@ -516,7 +518,7 @@ export class AgentServer {
516
518
  }
517
519
 
518
520
  async stop(): Promise<void> {
519
- this.logger.info("Stopping agent server...");
521
+ this.logger.debug("Stopping agent server...");
520
522
 
521
523
  if (this.session) {
522
524
  await this.cleanupSession();
@@ -527,7 +529,7 @@ export class AgentServer {
527
529
  this.server = null;
528
530
  }
529
531
 
530
- this.logger.info("Agent server stopped");
532
+ this.logger.debug("Agent server stopped");
531
533
  }
532
534
 
533
535
  private authenticateRequest(
@@ -589,7 +591,7 @@ export class AgentServer {
589
591
  });
590
592
  const promptPreview = promptBlocksToText(prompt);
591
593
 
592
- this.logger.info(
594
+ this.logger.debug(
593
595
  `Processing user message (detectedPrUrl=${this.detectedPrUrl ?? "none"}): ${promptPreview.substring(0, 100)}...`,
594
596
  );
595
597
 
@@ -607,7 +609,7 @@ export class AgentServer {
607
609
  }),
608
610
  });
609
611
 
610
- this.logger.info("User message completed", {
612
+ this.logger.debug("User message completed", {
611
613
  stopReason: result.stopReason,
612
614
  });
613
615
 
@@ -621,7 +623,7 @@ export class AgentServer {
621
623
  // Relay the response to Slack. For follow-ups this is the primary
622
624
  // delivery path — the HTTP caller only handles reactions.
623
625
  this.relayAgentResponse(this.session.payload).catch((err) =>
624
- this.logger.warn("Failed to relay follow-up response", err),
626
+ this.logger.debug("Failed to relay follow-up response", err),
625
627
  );
626
628
  }
627
629
 
@@ -637,7 +639,7 @@ export class AgentServer {
637
639
  this.session.payload.run_id,
638
640
  );
639
641
  } catch {
640
- this.logger.warn("Failed to extract assistant message from logs");
642
+ this.logger.debug("Failed to extract assistant message from logs");
641
643
  }
642
644
 
643
645
  return {
@@ -648,7 +650,7 @@ export class AgentServer {
648
650
 
649
651
  case POSTHOG_NOTIFICATIONS.CANCEL:
650
652
  case "cancel": {
651
- this.logger.info("Cancel requested", {
653
+ this.logger.debug("Cancel requested", {
652
654
  acpSessionId: this.session.acpSessionId,
653
655
  });
654
656
  await this.session.clientConnection.cancel({
@@ -659,7 +661,7 @@ export class AgentServer {
659
661
 
660
662
  case POSTHOG_NOTIFICATIONS.CLOSE:
661
663
  case "close": {
662
- this.logger.info("Close requested");
664
+ this.logger.debug("Close requested");
663
665
  await this.cleanupSession();
664
666
  return { closed: true };
665
667
  }
@@ -669,7 +671,7 @@ export class AgentServer {
669
671
  const configId = params.configId as string;
670
672
  const value = params.value as string;
671
673
 
672
- this.logger.info("Set config option requested", { configId, value });
674
+ this.logger.debug("Set config option requested", { configId, value });
673
675
 
674
676
  const result =
675
677
  await this.session.clientConnection.setSessionConfigOption({
@@ -707,7 +709,7 @@ export class AgentServer {
707
709
  const customInput = params.customInput as string | undefined;
708
710
  const answers = params.answers as Record<string, string> | undefined;
709
711
 
710
- this.logger.info("Permission response received", {
712
+ this.logger.debug("Permission response received", {
711
713
  requestId,
712
714
  optionId,
713
715
  });
@@ -742,7 +744,7 @@ export class AgentServer {
742
744
  // duplicate Slack messages. This lock ensures the second caller waits for the first
743
745
  // initialization to finish and reuses the session.
744
746
  if (this.initializationPromise) {
745
- this.logger.info("Waiting for in-progress initialization", {
747
+ this.logger.debug("Waiting for in-progress initialization", {
746
748
  runId: payload.run_id,
747
749
  });
748
750
  await this.initializationPromise;
@@ -774,7 +776,7 @@ export class AgentServer {
774
776
  await this.cleanupSession();
775
777
  }
776
778
 
777
- this.logger.info("Initializing session", {
779
+ this.logger.debug("Initializing session", {
778
780
  runId: payload.run_id,
779
781
  taskId: payload.task_id,
780
782
  });
@@ -790,7 +792,7 @@ export class AgentServer {
790
792
  this.posthogAPI
791
793
  .getTaskRun(payload.task_id, payload.run_id)
792
794
  .catch((err) => {
793
- this.logger.warn("Failed to fetch task run for session context", {
795
+ this.logger.debug("Failed to fetch task run for session context", {
794
796
  taskId: payload.task_id,
795
797
  runId: payload.run_id,
796
798
  error: err,
@@ -798,7 +800,7 @@ export class AgentServer {
798
800
  return null;
799
801
  }),
800
802
  this.posthogAPI.getTask(payload.task_id).catch((err) => {
801
- this.logger.warn("Failed to fetch task for session context", {
803
+ this.logger.debug("Failed to fetch task for session context", {
802
804
  taskId: payload.task_id,
803
805
  error: err,
804
806
  });
@@ -941,7 +943,7 @@ export class AgentServer {
941
943
  });
942
944
 
943
945
  const acpSessionId = sessionResponse.sessionId;
944
- this.logger.info("ACP session created", {
946
+ this.logger.debug("ACP session created", {
945
947
  acpSessionId,
946
948
  runId: payload.run_id,
947
949
  });
@@ -963,18 +965,15 @@ export class AgentServer {
963
965
  debug: true,
964
966
  prefix: "[AgentServer]",
965
967
  onLog: (level, scope, message, data) => {
966
- // Preserve console output (onLog suppresses default console.*)
967
- const _formatted =
968
- data !== undefined ? `${message} ${JSON.stringify(data)}` : message;
969
968
  this.emitConsoleLog(level, scope, message, data);
970
969
  },
971
970
  });
972
971
 
973
- this.logger.info("Session initialized successfully");
974
- this.logger.info(
972
+ this.logger.debug("Session initialized successfully");
973
+ this.logger.debug(
975
974
  `Agent version: ${this.config.version ?? packageJson.version}`,
976
975
  );
977
- this.logger.info(`Initial permission mode: ${initialPermissionMode}`);
976
+ this.logger.debug(`Initial permission mode: ${initialPermissionMode}`);
978
977
 
979
978
  // Signal in_progress so the UI can start polling for updates
980
979
  this.posthogAPI
@@ -982,7 +981,7 @@ export class AgentServer {
982
981
  status: "in_progress",
983
982
  })
984
983
  .catch((err) =>
985
- this.logger.warn("Failed to set task run to in_progress", err),
984
+ this.logger.debug("Failed to set task run to in_progress", err),
986
985
  );
987
986
 
988
987
  await this.sendInitialTaskMessage(payload, preTaskRun);
@@ -1038,7 +1037,7 @@ export class AgentServer {
1038
1037
  payload.run_id,
1039
1038
  );
1040
1039
  } catch (error) {
1041
- this.logger.warn("Failed to fetch task run", {
1040
+ this.logger.debug("Failed to fetch task run", {
1042
1041
  taskId: payload.task_id,
1043
1042
  runId: payload.run_id,
1044
1043
  error,
@@ -1050,7 +1049,7 @@ export class AgentServer {
1050
1049
  if (!this.resumeState) {
1051
1050
  const resumeRunId = this.getResumeRunId(taskRun);
1052
1051
  if (resumeRunId) {
1053
- this.logger.info("Resuming from previous run (via TaskRun state)", {
1052
+ this.logger.debug("Resuming from previous run (via TaskRun state)", {
1054
1053
  resumeRunId,
1055
1054
  currentRunId: payload.run_id,
1056
1055
  });
@@ -1062,13 +1061,13 @@ export class AgentServer {
1062
1061
  apiClient: this.posthogAPI,
1063
1062
  logger: new Logger({ debug: true, prefix: "[Resume]" }),
1064
1063
  });
1065
- this.logger.info("Resume state loaded (via TaskRun state)", {
1064
+ this.logger.debug("Resume state loaded (via TaskRun state)", {
1066
1065
  conversationTurns: this.resumeState.conversation.length,
1067
1066
  snapshotApplied: this.resumeState.snapshotApplied,
1068
1067
  logEntries: this.resumeState.logEntryCount,
1069
1068
  });
1070
1069
  } catch (error) {
1071
- this.logger.warn("Failed to load resume state, starting fresh", {
1070
+ this.logger.debug("Failed to load resume state, starting fresh", {
1072
1071
  error,
1073
1072
  });
1074
1073
  this.resumeState = null;
@@ -1099,11 +1098,11 @@ export class AgentServer {
1099
1098
  }
1100
1099
 
1101
1100
  if (initialPrompt.length === 0) {
1102
- this.logger.warn("Task has no description, skipping initial message");
1101
+ this.logger.debug("Task has no description, skipping initial message");
1103
1102
  return;
1104
1103
  }
1105
1104
 
1106
- this.logger.info("Sending initial task message", {
1105
+ this.logger.debug("Sending initial task message", {
1107
1106
  taskId: payload.task_id,
1108
1107
  descriptionLength: promptBlocksToText(initialPrompt).length,
1109
1108
  usedInitialPromptOverride: !!initialPromptOverride,
@@ -1117,7 +1116,7 @@ export class AgentServer {
1117
1116
  prompt: initialPrompt,
1118
1117
  });
1119
1118
 
1120
- this.logger.info("Initial task message completed", {
1119
+ this.logger.debug("Initial task message completed", {
1121
1120
  stopReason: result.stopReason,
1122
1121
  });
1123
1122
 
@@ -1190,7 +1189,7 @@ export class AgentServer {
1190
1189
  ];
1191
1190
  }
1192
1191
 
1193
- this.logger.info("Sending resume message", {
1192
+ this.logger.debug("Sending resume message", {
1194
1193
  taskId: payload.task_id,
1195
1194
  conversationTurns: this.resumeState.conversation.length,
1196
1195
  promptLength: promptBlocksToText(resumePromptBlocks).length,
@@ -1208,7 +1207,7 @@ export class AgentServer {
1208
1207
  prompt: resumePromptBlocks,
1209
1208
  });
1210
1209
 
1211
- this.logger.info("Resume message completed", {
1210
+ this.logger.debug("Resume message completed", {
1212
1211
  stopReason: result.stopReason,
1213
1212
  });
1214
1213
 
@@ -1674,7 +1673,7 @@ ${attributionInstructions}
1674
1673
  try {
1675
1674
  return await getCurrentBranch(this.config.repositoryPath);
1676
1675
  } catch (error) {
1677
- this.logger.warn("Failed to determine current git branch", {
1676
+ this.logger.debug("Failed to determine current git branch", {
1678
1677
  repositoryPath: this.config.repositoryPath,
1679
1678
  error,
1680
1679
  });
@@ -1695,7 +1694,7 @@ ${attributionInstructions}
1695
1694
  });
1696
1695
  this.lastReportedBranch = branchName;
1697
1696
  } catch (error) {
1698
- this.logger.warn("Failed to attach current branch to task run", {
1697
+ this.logger.debug("Failed to attach current branch to task run", {
1699
1698
  taskId: payload.task_id,
1700
1699
  runId: payload.run_id,
1701
1700
  branchName,
@@ -1715,7 +1714,7 @@ ${attributionInstructions}
1715
1714
  coalesce: true,
1716
1715
  });
1717
1716
  } catch (error) {
1718
- this.logger.warn("Failed to flush session logs before completion", {
1717
+ this.logger.debug("Failed to flush session logs before completion", {
1719
1718
  taskId: payload.task_id,
1720
1719
  runId: payload.run_id,
1721
1720
  error,
@@ -1724,7 +1723,7 @@ ${attributionInstructions}
1724
1723
  }
1725
1724
 
1726
1725
  if (stopReason !== "error") {
1727
- this.logger.info("Skipping status update for non-error stop reason", {
1726
+ this.logger.debug("Skipping status update for non-error stop reason", {
1728
1727
  stopReason,
1729
1728
  });
1730
1729
  return;
@@ -1737,7 +1736,7 @@ ${attributionInstructions}
1737
1736
  status,
1738
1737
  error_message: errorMessage ?? "Agent error",
1739
1738
  });
1740
- this.logger.info("Task completion signaled", { status, stopReason });
1739
+ this.logger.debug("Task completion signaled", { status, stopReason });
1741
1740
  } catch (error) {
1742
1741
  this.logger.error("Failed to signal task completion", error);
1743
1742
  }
@@ -1874,7 +1873,7 @@ ${attributionInstructions}
1874
1873
  isPlanApproval ||
1875
1874
  (needsDesktopApproval && this.session?.hasDesktopConnected)
1876
1875
  ) {
1877
- this.logger.info("Relaying permission request", {
1876
+ this.logger.debug("Relaying permission request", {
1878
1877
  kind: params.toolCall?.kind,
1879
1878
  isQuestion,
1880
1879
  hasDesktopConnected: this.session?.hasDesktopConnected ?? false,
@@ -1919,7 +1918,7 @@ ${attributionInstructions}
1919
1918
  ) {
1920
1919
  this.session.permissionMode = params.update
1921
1920
  .currentModeId as PermissionMode;
1922
- this.logger.info("Permission mode updated", {
1921
+ this.logger.debug("Permission mode updated", {
1923
1922
  mode: params.update.currentModeId,
1924
1923
  });
1925
1924
  }
@@ -1965,7 +1964,7 @@ ${attributionInstructions}
1965
1964
  try {
1966
1965
  await this.session.logWriter.flush(payload.run_id, { coalesce: true });
1967
1966
  } catch (error) {
1968
- this.logger.warn("Failed to flush logs before Slack relay", {
1967
+ this.logger.debug("Failed to flush logs before Slack relay", {
1969
1968
  taskId: payload.task_id,
1970
1969
  runId: payload.run_id,
1971
1970
  error,
@@ -1974,7 +1973,7 @@ ${attributionInstructions}
1974
1973
 
1975
1974
  const message = this.session.logWriter.getFullAgentResponse(payload.run_id);
1976
1975
  if (!message) {
1977
- this.logger.warn("No agent message found for Slack relay", {
1976
+ this.logger.debug("No agent message found for Slack relay", {
1978
1977
  taskId: payload.task_id,
1979
1978
  runId: payload.run_id,
1980
1979
  sessionRegistered: this.session.logWriter.isRegistered(payload.run_id),
@@ -1989,7 +1988,7 @@ ${attributionInstructions}
1989
1988
  message,
1990
1989
  );
1991
1990
  } catch (error) {
1992
- this.logger.warn("Failed to relay initial agent response to Slack", {
1991
+ this.logger.debug("Failed to relay initial agent response to Slack", {
1993
1992
  taskId: payload.task_id,
1994
1993
  runId: payload.run_id,
1995
1994
  error,
@@ -2022,7 +2021,7 @@ ${attributionInstructions}
2022
2021
  this.posthogAPI
2023
2022
  .relayMessage(payload.task_id, payload.run_id, message)
2024
2023
  .catch((err) =>
2025
- this.logger.warn("Failed to relay question to Slack", { err }),
2024
+ this.logger.debug("Failed to relay question to Slack", { err }),
2026
2025
  );
2027
2026
  }
2028
2027
 
@@ -2120,7 +2119,7 @@ ${attributionInstructions}
2120
2119
 
2121
2120
  const prUrl = prUrlMatch[0];
2122
2121
  this.detectedPrUrl = prUrl;
2123
- this.logger.info("Detected PR URL in bash output", {
2122
+ this.logger.debug("Detected PR URL in bash output", {
2124
2123
  runId: payload.run_id,
2125
2124
  prUrl,
2126
2125
  });
@@ -2131,7 +2130,7 @@ ${attributionInstructions}
2131
2130
  output: { pr_url: prUrl },
2132
2131
  })
2133
2132
  .then(() => {
2134
- this.logger.info("PR URL attached to task run", {
2133
+ this.logger.debug("PR URL attached to task run", {
2135
2134
  taskId: payload.task_id,
2136
2135
  runId: payload.run_id,
2137
2136
  prUrl,
@@ -2157,7 +2156,7 @@ ${attributionInstructions}
2157
2156
  private async cleanupSession(): Promise<void> {
2158
2157
  if (!this.session) return;
2159
2158
 
2160
- this.logger.info("Cleaning up session");
2159
+ this.logger.debug("Cleaning up session");
2161
2160
 
2162
2161
  try {
2163
2162
  await this.captureTreeState();