@posthog/agent 2.3.520 → 2.3.524

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.
@@ -3945,7 +3945,7 @@ function isSupportedReasoningEffort(adapter, modelId, value) {
3945
3945
 
3946
3946
  // src/server/agent-server.ts
3947
3947
  var import_promises6 = require("fs/promises");
3948
- var import_node_path8 = require("path");
3948
+ var import_node_path9 = require("path");
3949
3949
  var import_node_url2 = require("url");
3950
3950
  var import_sdk5 = require("@agentclientprotocol/sdk");
3951
3951
  var import_node_server = require("@hono/node-server");
@@ -8755,7 +8755,7 @@ var import_zod3 = require("zod");
8755
8755
  // package.json
8756
8756
  var package_default = {
8757
8757
  name: "@posthog/agent",
8758
- version: "2.3.520",
8758
+ version: "2.3.524",
8759
8759
  repository: "https://github.com/PostHog/code",
8760
8760
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
8761
8761
  exports: {
@@ -8872,7 +8872,6 @@ var package_default = {
8872
8872
  },
8873
8873
  dependencies: {
8874
8874
  "@agentclientprotocol/sdk": "0.19.0",
8875
- ajv: "^8.17.1",
8876
8875
  "@anthropic-ai/claude-agent-sdk": "0.2.112",
8877
8876
  "@anthropic-ai/sdk": "0.89.0",
8878
8877
  "@hono/node-server": "^1.19.9",
@@ -8886,6 +8885,7 @@ var package_default = {
8886
8885
  hono: "^4.11.7",
8887
8886
  jsonwebtoken: "^9.0.2",
8888
8887
  minimatch: "^10.0.3",
8888
+ "@modelcontextprotocol/sdk": "1.29.0",
8889
8889
  tar: "^7.5.0",
8890
8890
  uuid: "13.0.0",
8891
8891
  "yoga-wasm-web": "^0.3.3",
@@ -17841,9 +17841,26 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17841
17841
  };
17842
17842
 
17843
17843
  // src/adapters/codex/codex-agent.ts
17844
+ var import_node_fs3 = require("fs");
17845
+ var import_node_path5 = require("path");
17844
17846
  var import_sdk3 = require("@agentclientprotocol/sdk");
17845
17847
 
17848
+ // src/adapters/codex/structured-output-constants.ts
17849
+ var STRUCTURED_OUTPUT_MCP_NAME = "posthog_output";
17850
+ var STRUCTURED_OUTPUT_TOOL_NAME = "create_output";
17851
+
17846
17852
  // src/adapters/codex/codex-client.ts
17853
+ function isStructuredOutputToolCall(title) {
17854
+ if (!title) return false;
17855
+ if (title === STRUCTURED_OUTPUT_TOOL_NAME) return true;
17856
+ return title.includes(STRUCTURED_OUTPUT_MCP_NAME) && title.includes(STRUCTURED_OUTPUT_TOOL_NAME);
17857
+ }
17858
+ function toRecord(value) {
17859
+ if (value && typeof value === "object" && !Array.isArray(value)) {
17860
+ return value;
17861
+ }
17862
+ return null;
17863
+ }
17847
17864
  var AUTO_APPROVED_KINDS = {
17848
17865
  default: /* @__PURE__ */ new Set(["read", "search", "fetch", "think"]),
17849
17866
  acceptEdits: /* @__PURE__ */ new Set(["read", "edit", "search", "fetch", "think"]),
@@ -17882,6 +17899,7 @@ function shouldAutoApprove(mode, kind) {
17882
17899
  }
17883
17900
  function createCodexClient(upstreamClient, logger, sessionState, callbacks) {
17884
17901
  const terminalHandles = /* @__PURE__ */ new Map();
17902
+ const structuredOutputState = /* @__PURE__ */ new Map();
17885
17903
  return {
17886
17904
  async requestPermission(params) {
17887
17905
  const kind = params.toolCall?.kind;
@@ -17905,6 +17923,26 @@ function createCodexClient(upstreamClient, logger, sessionState, callbacks) {
17905
17923
  },
17906
17924
  async sessionUpdate(params) {
17907
17925
  const update = params.update;
17926
+ if (callbacks?.onStructuredOutput && (update?.sessionUpdate === "tool_call" || update?.sessionUpdate === "tool_call_update")) {
17927
+ const toolCallId = update.toolCallId;
17928
+ const title = update.title;
17929
+ if (toolCallId && isStructuredOutputToolCall(title)) {
17930
+ const entry = structuredOutputState.get(toolCallId) ?? {
17931
+ fired: false
17932
+ };
17933
+ const rawInput = toRecord(update.rawInput);
17934
+ if (rawInput) entry.rawInput = rawInput;
17935
+ structuredOutputState.set(toolCallId, entry);
17936
+ if (update.status === "completed" && !entry.fired && entry.rawInput) {
17937
+ entry.fired = true;
17938
+ try {
17939
+ await callbacks.onStructuredOutput(entry.rawInput);
17940
+ } catch (err2) {
17941
+ logger.warn("onStructuredOutput callback threw", { error: err2 });
17942
+ }
17943
+ }
17944
+ }
17945
+ }
17908
17946
  if (update?.sessionUpdate === "usage_update") {
17909
17947
  const used = update.used;
17910
17948
  const size = update.size;
@@ -18194,6 +18232,7 @@ function spawnCodexProcess(options) {
18194
18232
  }
18195
18233
 
18196
18234
  // src/adapters/codex/codex-agent.ts
18235
+ var import_meta2 = {};
18197
18236
  function toCodexPermissionMode(mode) {
18198
18237
  if (mode && (isCodexNativeMode(mode) || isCodeExecutionMode(mode))) {
18199
18238
  return mode;
@@ -18232,6 +18271,33 @@ function getCurrentPermissionMode(currentModeId, fallbackMode) {
18232
18271
  }
18233
18272
  return toCodexPermissionMode(fallbackMode);
18234
18273
  }
18274
+ var STRUCTURED_OUTPUT_INSTRUCTIONS = `
18275
+
18276
+ When you have completed the task, call the \`${STRUCTURED_OUTPUT_TOOL_NAME}\` tool with the final structured result. The tool's input schema matches the required output format for this task. Do not describe the result in a plain message \u2014 submitting it via the tool is required for the task to be considered complete.`;
18277
+ function resolveStructuredOutputMcpScript() {
18278
+ const rel = "adapters/codex/structured-output-mcp-server.js";
18279
+ let dir = import_meta2.dirname ?? __dirname;
18280
+ for (let i2 = 0; i2 < 5; i2++) {
18281
+ const candidate = (0, import_node_path5.resolve)(dir, rel);
18282
+ if ((0, import_node_fs3.existsSync)(candidate)) return candidate;
18283
+ dir = (0, import_node_path5.resolve)(dir, "..");
18284
+ }
18285
+ throw new Error(
18286
+ `Could not locate ${rel} relative to ${import_meta2.dirname ?? __dirname}.`
18287
+ );
18288
+ }
18289
+ function buildStructuredOutputMcpServer(jsonSchema) {
18290
+ const scriptPath = resolveStructuredOutputMcpScript();
18291
+ const schemaBase64 = Buffer.from(JSON.stringify(jsonSchema)).toString(
18292
+ "base64"
18293
+ );
18294
+ return {
18295
+ name: STRUCTURED_OUTPUT_MCP_NAME,
18296
+ command: process.execPath,
18297
+ args: [scriptPath],
18298
+ env: [{ name: "POSTHOG_OUTPUT_SCHEMA", value: schemaBase64 }]
18299
+ };
18300
+ }
18235
18301
  var CodexAcpAgent = class extends BaseAcpAgent {
18236
18302
  adapterName = "codex";
18237
18303
  codexProcess;
@@ -18250,6 +18316,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18250
18316
  promptMutex = Promise.resolve();
18251
18317
  codexProcessOptions;
18252
18318
  processCallbacks;
18319
+ onStructuredOutput;
18253
18320
  // Snapshot of the initialize() request so refreshSession can replay the
18254
18321
  // same handshake against a respawned codex-acp subprocess.
18255
18322
  lastInitRequest;
@@ -18261,6 +18328,7 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18261
18328
  const settingsManager = new CodexSettingsManager(cwd);
18262
18329
  this.codexProcessOptions = options.codexProcessOptions;
18263
18330
  this.processCallbacks = options.processCallbacks;
18331
+ this.onStructuredOutput = options.onStructuredOutput;
18264
18332
  this.codexProcess = spawnCodexProcess({
18265
18333
  ...options.codexProcessOptions,
18266
18334
  settings: settingsManager.getSettings(),
@@ -18282,7 +18350,8 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18282
18350
  this.enrichment = createEnrichment(options.posthogApiConfig, this.logger);
18283
18351
  this.codexConnection = new import_sdk3.ClientSideConnection(
18284
18352
  (_agent) => createCodexClient(this.client, this.logger, this.sessionState, {
18285
- enrichmentDeps: this.enrichment?.deps
18353
+ enrichmentDeps: this.enrichment?.deps,
18354
+ onStructuredOutput: this.onStructuredOutput
18286
18355
  }),
18287
18356
  codexStream
18288
18357
  );
@@ -18316,7 +18385,8 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18316
18385
  async newSession(params) {
18317
18386
  const meta = params._meta;
18318
18387
  const requestedPermissionMode = toCodexPermissionMode(meta?.permissionMode);
18319
- const response = await this.codexConnection.newSession(params);
18388
+ const injectedParams = this.applyStructuredOutput(params, meta);
18389
+ const response = await this.codexConnection.newSession(injectedParams);
18320
18390
  response.configOptions = normalizeCodexConfigOptions(
18321
18391
  response.configOptions
18322
18392
  );
@@ -18348,11 +18418,12 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18348
18418
  return response;
18349
18419
  }
18350
18420
  async loadSession(params) {
18351
- const response = await this.codexConnection.loadSession(params);
18421
+ const meta = params._meta;
18422
+ const injectedParams = this.applyStructuredOutput(params, meta);
18423
+ const response = await this.codexConnection.loadSession(injectedParams);
18352
18424
  response.configOptions = normalizeCodexConfigOptions(
18353
18425
  response.configOptions
18354
18426
  );
18355
- const meta = params._meta;
18356
18427
  const currentPermissionMode = getCurrentPermissionMode(
18357
18428
  response.modes?.currentModeId,
18358
18429
  meta?.permissionMode
@@ -18375,15 +18446,20 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18375
18446
  return response;
18376
18447
  }
18377
18448
  async unstable_resumeSession(params) {
18378
- const loadResponse = await this.codexConnection.loadSession({
18379
- sessionId: params.sessionId,
18380
- cwd: params.cwd,
18381
- mcpServers: params.mcpServers ?? []
18382
- });
18449
+ const meta = params._meta;
18450
+ const injectedParams = this.applyStructuredOutput(
18451
+ {
18452
+ sessionId: params.sessionId,
18453
+ cwd: params.cwd,
18454
+ mcpServers: params.mcpServers ?? [],
18455
+ _meta: params._meta
18456
+ },
18457
+ meta
18458
+ );
18459
+ const loadResponse = await this.codexConnection.loadSession(injectedParams);
18383
18460
  loadResponse.configOptions = normalizeCodexConfigOptions(
18384
18461
  loadResponse.configOptions
18385
18462
  );
18386
- const meta = params._meta;
18387
18463
  const currentPermissionMode = getCurrentPermissionMode(
18388
18464
  loadResponse.modes?.currentModeId,
18389
18465
  meta?.permissionMode
@@ -18410,15 +18486,19 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18410
18486
  };
18411
18487
  }
18412
18488
  async unstable_forkSession(params) {
18413
- const newResponse = await this.codexConnection.newSession({
18414
- cwd: params.cwd,
18415
- mcpServers: params.mcpServers ?? [],
18416
- _meta: params._meta
18417
- });
18489
+ const meta = params._meta;
18490
+ const injectedParams = this.applyStructuredOutput(
18491
+ {
18492
+ cwd: params.cwd,
18493
+ mcpServers: params.mcpServers ?? [],
18494
+ _meta: params._meta
18495
+ },
18496
+ meta
18497
+ );
18498
+ const newResponse = await this.codexConnection.newSession(injectedParams);
18418
18499
  newResponse.configOptions = normalizeCodexConfigOptions(
18419
18500
  newResponse.configOptions
18420
18501
  );
18421
- const meta = params._meta;
18422
18502
  const requestedPermissionMode = toCodexPermissionMode(meta?.permissionMode);
18423
18503
  this.sessionState = createSessionState(newResponse.sessionId, params.cwd, {
18424
18504
  taskRunId: meta?.taskRunId,
@@ -18435,6 +18515,30 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18435
18515
  );
18436
18516
  return newResponse;
18437
18517
  }
18518
+ /**
18519
+ * When the caller wires up `onStructuredOutput` and provides a JSON schema
18520
+ * via `_meta.jsonSchema`, inject the stdio MCP server that exposes
18521
+ * `create_output` and append instructions telling the model to use it.
18522
+ *
18523
+ * Codex has no native equivalent of Claude's `outputFormat`, so we lean on
18524
+ * MCP tool-calling to get validated structured output back.
18525
+ */
18526
+ applyStructuredOutput(request, meta) {
18527
+ if (!meta?.jsonSchema || !this.onStructuredOutput) {
18528
+ return request;
18529
+ }
18530
+ const mcpServer = buildStructuredOutputMcpServer(meta.jsonSchema);
18531
+ const existingMeta = request._meta ?? {};
18532
+ const existingSystemPrompt = typeof existingMeta.systemPrompt === "string" ? existingMeta.systemPrompt : "";
18533
+ return {
18534
+ ...request,
18535
+ mcpServers: [...request.mcpServers ?? [], mcpServer],
18536
+ _meta: {
18537
+ ...existingMeta,
18538
+ systemPrompt: existingSystemPrompt + STRUCTURED_OUTPUT_INSTRUCTIONS
18539
+ }
18540
+ };
18541
+ }
18438
18542
  async applyInitialPermissionMode(sessionId, permissionMode, currentModeId) {
18439
18543
  if (!permissionMode) {
18440
18544
  return;
@@ -18593,7 +18697,9 @@ var CodexAcpAgent = class extends BaseAcpAgent {
18593
18697
  const codexStream = (0, import_sdk3.ndJsonStream)(codexWritable, codexReadable);
18594
18698
  const newAbortController = new AbortController();
18595
18699
  const newConnection = new import_sdk3.ClientSideConnection(
18596
- (_agent) => createCodexClient(this.client, this.logger, this.sessionState),
18700
+ (_agent) => createCodexClient(this.client, this.logger, this.sessionState, {
18701
+ onStructuredOutput: this.onStructuredOutput
18702
+ }),
18597
18703
  codexStream
18598
18704
  );
18599
18705
  const initRequest = this.lastInitRequest ?? {
@@ -18773,7 +18879,8 @@ function createCodexConnection(config) {
18773
18879
  agent = new CodexAcpAgent(client, {
18774
18880
  codexProcessOptions: config.codexOptions ?? {},
18775
18881
  processCallbacks: config.processCallbacks,
18776
- posthogApiConfig: resolveEnricherApiConfig(config)
18882
+ posthogApiConfig: resolveEnricherApiConfig(config),
18883
+ onStructuredOutput: config.onStructuredOutput
18777
18884
  });
18778
18885
  return agent;
18779
18886
  }, agentStream);
@@ -18803,13 +18910,13 @@ function createCodexConnection(config) {
18803
18910
  // src/handoff-checkpoint.ts
18804
18911
  var import_promises3 = require("fs/promises");
18805
18912
  var import_node_os2 = require("os");
18806
- var import_node_path6 = require("path");
18913
+ var import_node_path7 = require("path");
18807
18914
 
18808
18915
  // ../git/dist/handoff.js
18809
18916
  var import_node_child_process4 = require("child_process");
18810
18917
  var import_promises2 = require("fs/promises");
18811
18918
  var import_node_os = require("os");
18812
- var import_node_path5 = __toESM(require("path"), 1);
18919
+ var import_node_path6 = __toESM(require("path"), 1);
18813
18920
 
18814
18921
  // ../git/dist/sagas/checkpoint.js
18815
18922
  var import_node_crypto2 = require("crypto");
@@ -19310,7 +19417,7 @@ var GitHandoffTracker = class {
19310
19417
  packBaseline ? `^${packBaseline}` : null
19311
19418
  ].filter((ref) => !!ref);
19312
19419
  const headRef = checkpoint.head ? `${HANDOFF_HEAD_REF_PREFIX}${checkpoint.checkpointId}` : void 0;
19313
- const packPrefix = import_node_path5.default.join(tempDir, checkpoint.checkpointId);
19420
+ const packPrefix = import_node_path6.default.join(tempDir, checkpoint.checkpointId);
19314
19421
  const [headPack, indexFile, tracking] = await Promise.all([
19315
19422
  this.captureObjectPack(packPrefix, packRefs),
19316
19423
  this.statFileArtifact(reconciledIndex.indexFilePath),
@@ -19385,7 +19492,7 @@ var GitHandoffTracker = class {
19385
19492
  }
19386
19493
  async reconcileHandoffIndex(git, head, indexTree, tempDir, checkpointId) {
19387
19494
  const realIndexPath = await this.getGitPath(git, "index");
19388
- const tempIndexPath = import_node_path5.default.join(tempDir, `${checkpointId}.index`);
19495
+ const tempIndexPath = import_node_path6.default.join(tempDir, `${checkpointId}.index`);
19389
19496
  await (0, import_promises2.copyFile)(realIndexPath, tempIndexPath);
19390
19497
  const largePaths = await this.listLargeBlobsInTree(indexTree, MAX_HANDOFF_FILE_BYTES);
19391
19498
  if (largePaths.length === 0) {
@@ -19607,7 +19714,7 @@ var GitHandoffTracker = class {
19607
19714
  async getGitPath(git, gitPath) {
19608
19715
  const raw = await git.raw(["rev-parse", "--git-path", gitPath]);
19609
19716
  const resolved = raw.trim();
19610
- return import_node_path5.default.isAbsolute(resolved) ? resolved : import_node_path5.default.resolve(this.repositoryPath, resolved);
19717
+ return import_node_path6.default.isAbsolute(resolved) ? resolved : import_node_path6.default.resolve(this.repositoryPath, resolved);
19611
19718
  }
19612
19719
  async getFileSize(filePath) {
19613
19720
  return (await (0, import_promises2.stat)(filePath)).size;
@@ -19697,7 +19804,7 @@ var GitHandoffTracker = class {
19697
19804
  }
19698
19805
  };
19699
19806
  function joinTempPrefix(checkpointId) {
19700
- return import_node_path5.default.join((0, import_node_os.tmpdir)(), `posthog-code-handoff-${checkpointId}-`);
19807
+ return import_node_path6.default.join((0, import_node_os.tmpdir)(), `posthog-code-handoff-${checkpointId}-`);
19701
19808
  }
19702
19809
  async function getCurrentBranchName(git) {
19703
19810
  try {
@@ -19785,7 +19892,7 @@ var HandoffCheckpointTracker = class {
19785
19892
  indexArtifactPath: uploads.index?.storagePath
19786
19893
  };
19787
19894
  } finally {
19788
- const tempDir = capture.headPack?.path ? (0, import_node_path6.dirname)(capture.headPack.path) : (0, import_node_path6.dirname)(capture.indexFile.path);
19895
+ const tempDir = capture.headPack?.path ? (0, import_node_path7.dirname)(capture.headPack.path) : (0, import_node_path7.dirname)(capture.indexFile.path);
19789
19896
  await this.removeIfPresent(capture.headPack?.path);
19790
19897
  await this.removeIfPresent(capture.indexFile.path);
19791
19898
  await (0, import_promises3.rm)(tempDir, { recursive: true, force: true }).catch(() => {
@@ -19800,10 +19907,10 @@ var HandoffCheckpointTracker = class {
19800
19907
  }
19801
19908
  const gitTracker = this.createGitTracker();
19802
19909
  const tmpDir = await (0, import_promises3.mkdtemp)(
19803
- (0, import_node_path6.join)((0, import_node_os2.tmpdir)(), `posthog-code-handoff-${checkpoint.checkpointId}-`)
19910
+ (0, import_node_path7.join)((0, import_node_os2.tmpdir)(), `posthog-code-handoff-${checkpoint.checkpointId}-`)
19804
19911
  );
19805
- const packPath = (0, import_node_path6.join)(tmpDir, `${checkpoint.checkpointId}.pack`);
19806
- const indexPath = (0, import_node_path6.join)(tmpDir, `${checkpoint.checkpointId}.index`);
19912
+ const packPath = (0, import_node_path7.join)(tmpDir, `${checkpoint.checkpointId}.pack`);
19913
+ const indexPath = (0, import_node_path7.join)(tmpDir, `${checkpoint.checkpointId}.index`);
19807
19914
  try {
19808
19915
  const downloads = await this.downloadArtifacts([
19809
19916
  {
@@ -20491,9 +20598,9 @@ ${toolSummary}`);
20491
20598
  }
20492
20599
 
20493
20600
  // src/session-log-writer.ts
20494
- var import_node_fs3 = __toESM(require("fs"), 1);
20601
+ var import_node_fs4 = __toESM(require("fs"), 1);
20495
20602
  var import_promises4 = __toESM(require("fs/promises"), 1);
20496
- var import_node_path7 = __toESM(require("path"), 1);
20603
+ var import_node_path8 = __toESM(require("path"), 1);
20497
20604
  var SessionLogWriter = class _SessionLogWriter {
20498
20605
  static FLUSH_DEBOUNCE_MS = 500;
20499
20606
  static FLUSH_MAX_INTERVAL_MS = 5e3;
@@ -20529,13 +20636,13 @@ var SessionLogWriter = class _SessionLogWriter {
20529
20636
  this.sessions.set(sessionId, { context, currentTurnMessages: [] });
20530
20637
  this.lastFlushAttemptTime.set(sessionId, Date.now());
20531
20638
  if (this.localCachePath) {
20532
- const sessionDir = import_node_path7.default.join(
20639
+ const sessionDir = import_node_path8.default.join(
20533
20640
  this.localCachePath,
20534
20641
  "sessions",
20535
20642
  context.runId
20536
20643
  );
20537
20644
  try {
20538
- import_node_fs3.default.mkdirSync(sessionDir, { recursive: true });
20645
+ import_node_fs4.default.mkdirSync(sessionDir, { recursive: true });
20539
20646
  } catch (error) {
20540
20647
  this.logger.warn("Failed to create local cache directory", {
20541
20648
  sessionDir,
@@ -20787,14 +20894,14 @@ var SessionLogWriter = class _SessionLogWriter {
20787
20894
  if (!this.localCachePath) return;
20788
20895
  const session = this.sessions.get(sessionId);
20789
20896
  if (!session) return;
20790
- const logPath = import_node_path7.default.join(
20897
+ const logPath = import_node_path8.default.join(
20791
20898
  this.localCachePath,
20792
20899
  "sessions",
20793
20900
  session.context.runId,
20794
20901
  "logs.ndjson"
20795
20902
  );
20796
20903
  try {
20797
- import_node_fs3.default.appendFileSync(logPath, `${JSON.stringify(entry)}
20904
+ import_node_fs4.default.appendFileSync(logPath, `${JSON.stringify(entry)}
20798
20905
  `);
20799
20906
  } catch (error) {
20800
20907
  this.logger.warn("Failed to write to local cache", {
@@ -20806,13 +20913,13 @@ var SessionLogWriter = class _SessionLogWriter {
20806
20913
  }
20807
20914
  }
20808
20915
  static async cleanupOldSessions(localCachePath) {
20809
- const sessionsDir = import_node_path7.default.join(localCachePath, "sessions");
20916
+ const sessionsDir = import_node_path8.default.join(localCachePath, "sessions");
20810
20917
  let deleted = 0;
20811
20918
  try {
20812
20919
  const entries = await import_promises4.default.readdir(sessionsDir);
20813
20920
  const now = Date.now();
20814
20921
  for (const entry of entries) {
20815
- const entryPath = import_node_path7.default.join(sessionsDir, entry);
20922
+ const entryPath = import_node_path8.default.join(sessionsDir, entry);
20816
20923
  try {
20817
20924
  const stats = await import_promises4.default.stat(entryPath);
20818
20925
  if (stats.isDirectory() && now - stats.birthtimeMs > _SessionLogWriter.SESSIONS_MAX_AGE_MS) {
@@ -22104,7 +22211,7 @@ Continue from where you left off. The user is waiting for your response.`
22104
22211
  throw new Error(`Failed to download artifact ${artifact.name}`);
22105
22212
  }
22106
22213
  const safeName = this.getSafeArtifactName(artifact.name);
22107
- const artifactDir = (0, import_node_path8.join)(
22214
+ const artifactDir = (0, import_node_path9.join)(
22108
22215
  this.config.repositoryPath ?? "/tmp/workspace",
22109
22216
  ".posthog",
22110
22217
  "attachments",
@@ -22112,7 +22219,7 @@ Continue from where you left off. The user is waiting for your response.`
22112
22219
  artifact.id ?? safeName
22113
22220
  );
22114
22221
  await (0, import_promises6.mkdir)(artifactDir, { recursive: true });
22115
- const artifactPath = (0, import_node_path8.join)(artifactDir, safeName);
22222
+ const artifactPath = (0, import_node_path9.join)(artifactDir, safeName);
22116
22223
  await (0, import_promises6.writeFile)(artifactPath, Buffer.from(data));
22117
22224
  return resourceLink((0, import_node_url2.pathToFileURL)(artifactPath).toString(), artifact.name, {
22118
22225
  ...artifact.content_type ? { mimeType: artifact.content_type } : {},
@@ -22120,7 +22227,7 @@ Continue from where you left off. The user is waiting for your response.`
22120
22227
  });
22121
22228
  }
22122
22229
  getSafeArtifactName(name2) {
22123
- const baseName = (0, import_node_path8.basename)(name2).trim();
22230
+ const baseName = (0, import_node_path9.basename)(name2).trim();
22124
22231
  const normalizedName = baseName.replace(/[^\w.-]/g, "_");
22125
22232
  return normalizedName.length > 0 ? normalizedName : "attachment";
22126
22233
  }