@posthog/agent 2.3.312 → 2.3.316

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 CHANGED
@@ -245,7 +245,7 @@ import { v7 as uuidv7 } from "uuid";
245
245
  // package.json
246
246
  var package_default = {
247
247
  name: "@posthog/agent",
248
- version: "2.3.312",
248
+ version: "2.3.316",
249
249
  repository: "https://github.com/PostHog/code",
250
250
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
251
251
  exports: {
@@ -4299,7 +4299,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
4299
4299
  // src/adapters/codex/codex-agent.ts
4300
4300
  import {
4301
4301
  ClientSideConnection,
4302
- ndJsonStream
4302
+ ndJsonStream,
4303
+ RequestError as RequestError3
4303
4304
  } from "@agentclientprotocol/sdk";
4304
4305
 
4305
4306
  // src/adapters/codex/codex-client.ts
@@ -4699,11 +4700,18 @@ var CodexAcpAgent = class extends BaseAcpAgent {
4699
4700
  * single-owner.
4700
4701
  */
4701
4702
  promptMutex = Promise.resolve();
4703
+ codexProcessOptions;
4704
+ processCallbacks;
4705
+ // Snapshot of the initialize() request so refreshSession can replay the
4706
+ // same handshake against a respawned codex-acp subprocess.
4707
+ lastInitRequest;
4702
4708
  constructor(client, options) {
4703
4709
  super(client);
4704
4710
  this.logger = new Logger({ debug: true, prefix: "[CodexAcpAgent]" });
4705
4711
  const cwd = options.codexProcessOptions.cwd ?? process.cwd();
4706
4712
  const settingsManager = new CodexSettingsManager(cwd);
4713
+ this.codexProcessOptions = options.codexProcessOptions;
4714
+ this.processCallbacks = options.processCallbacks;
4707
4715
  this.codexProcess = spawnCodexProcess({
4708
4716
  ...options.codexProcessOptions,
4709
4717
  settings: settingsManager.getSettings(),
@@ -4718,7 +4726,8 @@ var CodexAcpAgent = class extends BaseAcpAgent {
4718
4726
  abortController,
4719
4727
  settingsManager,
4720
4728
  notificationHistory: [],
4721
- cancelled: false
4729
+ cancelled: false,
4730
+ promptRunning: false
4722
4731
  };
4723
4732
  this.sessionState = createSessionState("", cwd);
4724
4733
  this.codexConnection = new ClientSideConnection(
@@ -4728,6 +4737,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
4728
4737
  }
4729
4738
  async initialize(request) {
4730
4739
  await this.session.settingsManager.initialize();
4740
+ this.lastInitRequest = request;
4731
4741
  const response = await this.codexConnection.initialize(request);
4732
4742
  return {
4733
4743
  ...response,
@@ -4896,9 +4906,13 @@ var CodexAcpAgent = class extends BaseAcpAgent {
4896
4906
  this.session.interruptReason = void 0;
4897
4907
  resetUsage(this.sessionState);
4898
4908
  await this.broadcastUserMessage(params);
4899
- const response = await this.codexConnection.prompt(
4900
- prependPrContext(params)
4901
- );
4909
+ this.session.promptRunning = true;
4910
+ let response;
4911
+ try {
4912
+ response = await this.codexConnection.prompt(prependPrContext(params));
4913
+ } finally {
4914
+ this.session.promptRunning = false;
4915
+ }
4902
4916
  if (this.sessionState.taskRunId) {
4903
4917
  const { accumulatedUsage } = this.sessionState;
4904
4918
  await this.client.extNotification(POSTHOG_NOTIFICATIONS.TURN_COMPLETE, {
@@ -4945,6 +4959,94 @@ var CodexAcpAgent = class extends BaseAcpAgent {
4945
4959
  this.appendNotification(params.sessionId, notification);
4946
4960
  }
4947
4961
  }
4962
+ /**
4963
+ * Refresh the session between turns. Currently the only refreshable field
4964
+ * is `mcpServers`. Unlike Claude (where we rebuild an in-process Query with
4965
+ * `resume`), Codex runs as a `codex-acp` subprocess whose MCP set is bound
4966
+ * at `newSession`/`loadSession` time and whose user-local MCPs are disabled
4967
+ * via spawn-time `-c mcp_servers.<name>.enabled=false` CLI args. To
4968
+ * guarantee the caller-supplied set fully wins, we respawn the subprocess
4969
+ * and rehydrate the session via `loadSession` — codex-acp persists sessions
4970
+ * to disk, so conversation history is preserved.
4971
+ *
4972
+ * This is an `extMethod` (request/response), not `extNotification`, so the
4973
+ * caller can await completion before sending the next prompt.
4974
+ *
4975
+ * Caller contract: only call REFRESH_SESSION between turns (no prompt in flight).
4976
+ */
4977
+ async extMethod(method, params) {
4978
+ if (!isMethod(method, POSTHOG_METHODS.REFRESH_SESSION)) {
4979
+ throw RequestError3.methodNotFound(method);
4980
+ }
4981
+ if (params.mcpServers === void 0) {
4982
+ throw new RequestError3(
4983
+ -32602,
4984
+ "refresh_session requires at least one refreshable field (e.g. mcpServers)"
4985
+ );
4986
+ }
4987
+ if (!Array.isArray(params.mcpServers)) {
4988
+ throw new RequestError3(
4989
+ -32602,
4990
+ "refresh_session: mcpServers must be an array"
4991
+ );
4992
+ }
4993
+ await this.refreshSession(params.mcpServers);
4994
+ return { refreshed: true };
4995
+ }
4996
+ async refreshSession(mcpServers) {
4997
+ const prev = this.session;
4998
+ if (prev.promptRunning) {
4999
+ throw new RequestError3(
5000
+ -32002,
5001
+ "Cannot refresh session while a prompt turn is in flight"
5002
+ );
5003
+ }
5004
+ this.logger.info("Refreshing Codex session with fresh MCP servers", {
5005
+ serverCount: mcpServers.length,
5006
+ sessionId: this.sessionId
5007
+ });
5008
+ prev.abortController.abort();
5009
+ try {
5010
+ await this.codexConnection.cancel({ sessionId: this.sessionId });
5011
+ } catch (err) {
5012
+ this.logger.warn("cancel() during refresh failed (non-fatal)", {
5013
+ error: err
5014
+ });
5015
+ }
5016
+ this.codexProcess.kill();
5017
+ const cwd = prev.settingsManager.getCwd();
5018
+ const newSettingsManager = new CodexSettingsManager(cwd);
5019
+ await newSettingsManager.initialize();
5020
+ const newProcess = spawnCodexProcess({
5021
+ ...this.codexProcessOptions,
5022
+ cwd,
5023
+ settings: newSettingsManager.getSettings(),
5024
+ logger: this.logger,
5025
+ processCallbacks: this.processCallbacks
5026
+ });
5027
+ const codexReadable = nodeReadableToWebReadable(newProcess.stdout);
5028
+ const codexWritable = nodeWritableToWebWritable(newProcess.stdin);
5029
+ const codexStream = ndJsonStream(codexWritable, codexReadable);
5030
+ const newAbortController = new AbortController();
5031
+ const newConnection = new ClientSideConnection(
5032
+ (_agent) => createCodexClient(this.client, this.logger, this.sessionState),
5033
+ codexStream
5034
+ );
5035
+ const initRequest = this.lastInitRequest ?? {
5036
+ protocolVersion: 1
5037
+ };
5038
+ await newConnection.initialize(initRequest);
5039
+ await newConnection.loadSession({
5040
+ sessionId: this.sessionId,
5041
+ cwd: this.sessionState.cwd,
5042
+ mcpServers
5043
+ });
5044
+ this.codexProcess = newProcess;
5045
+ this.codexConnection = newConnection;
5046
+ prev.settingsManager.dispose();
5047
+ prev.settingsManager = newSettingsManager;
5048
+ prev.abortController = newAbortController;
5049
+ }
4948
5050
  async setSessionMode(params) {
4949
5051
  const requestedMode = toCodexPermissionMode(params.modeId);
4950
5052
  const nativeMode = toCodexNativeMode(params.modeId);