@posthog/agent 2.3.508 → 2.3.513

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.
@@ -513,7 +513,7 @@ var require_has_flag = __commonJS({
513
513
  var require_supports_color = __commonJS({
514
514
  "../../node_modules/supports-color/index.js"(exports2, module2) {
515
515
  "use strict";
516
- var os7 = __require("os");
516
+ var os8 = __require("os");
517
517
  var tty = __require("tty");
518
518
  var hasFlag = require_has_flag();
519
519
  var { env } = process;
@@ -561,7 +561,7 @@ var require_supports_color = __commonJS({
561
561
  return min;
562
562
  }
563
563
  if (process.platform === "win32") {
564
- const osRelease = os7.release().split(".");
564
+ const osRelease = os8.release().split(".");
565
565
  if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
566
566
  return Number(osRelease[2]) >= 14931 ? 3 : 2;
567
567
  }
@@ -809,10 +809,10 @@ var require_src2 = __commonJS({
809
809
  var fs_1 = __require("fs");
810
810
  var debug_1 = __importDefault(require_src());
811
811
  var log = debug_1.default("@kwsites/file-exists");
812
- function check(path16, isFile2, isDirectory) {
813
- log(`checking %s`, path16);
812
+ function check(path17, isFile2, isDirectory) {
813
+ log(`checking %s`, path17);
814
814
  try {
815
- const stat4 = fs_1.statSync(path16);
815
+ const stat4 = fs_1.statSync(path17);
816
816
  if (stat4.isFile() && isFile2) {
817
817
  log(`[OK] path represents a file`);
818
818
  return true;
@@ -832,8 +832,8 @@ var require_src2 = __commonJS({
832
832
  throw e;
833
833
  }
834
834
  }
835
- function exists2(path16, type = exports2.READABLE) {
836
- return check(path16, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
835
+ function exists2(path17, type = exports2.READABLE) {
836
+ return check(path17, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
837
837
  }
838
838
  exports2.exists = exists2;
839
839
  exports2.FILE = 1;
@@ -929,11 +929,11 @@ var require_tree_sitter = __commonJS({
929
929
  throw toThrow;
930
930
  };
931
931
  var scriptDirectory = "";
932
- function locateFile(path16) {
932
+ function locateFile(path17) {
933
933
  if (Module["locateFile"]) {
934
- return Module["locateFile"](path16, scriptDirectory);
934
+ return Module["locateFile"](path17, scriptDirectory);
935
935
  }
936
- return scriptDirectory + path16;
936
+ return scriptDirectory + path17;
937
937
  }
938
938
  var readAsync, readBinary;
939
939
  if (ENVIRONMENT_IS_NODE) {
@@ -3454,8 +3454,8 @@ var require_tree_sitter = __commonJS({
3454
3454
  } else {
3455
3455
  const url = input;
3456
3456
  if (typeof process !== "undefined" && process.versions && process.versions.node) {
3457
- const fs13 = __require("fs");
3458
- bytes = Promise.resolve(fs13.readFileSync(url));
3457
+ const fs14 = __require("fs");
3458
+ bytes = Promise.resolve(fs14.readFileSync(url));
3459
3459
  } else {
3460
3460
  bytes = fetch(url).then((response) => response.arrayBuffer().then((buffer) => {
3461
3461
  if (response.ok) {
@@ -3785,7 +3785,7 @@ ${JSON.stringify(symbolNames, null, 2)}`);
3785
3785
 
3786
3786
  // src/server/agent-server.ts
3787
3787
  import { mkdir as mkdir4, writeFile as writeFile4 } from "fs/promises";
3788
- import { basename as basename2, join as join11 } from "path";
3788
+ import { basename as basename2, join as join12 } from "path";
3789
3789
  import { pathToFileURL } from "url";
3790
3790
  import {
3791
3791
  ClientSideConnection as ClientSideConnection2,
@@ -3835,8 +3835,8 @@ function pathspec(...paths) {
3835
3835
  cache.set(key, paths);
3836
3836
  return key;
3837
3837
  }
3838
- function isPathSpec(path16) {
3839
- return path16 instanceof String && cache.has(path16);
3838
+ function isPathSpec(path17) {
3839
+ return path17 instanceof String && cache.has(path17);
3840
3840
  }
3841
3841
  function toPaths(pathSpec) {
3842
3842
  return cache.get(pathSpec) || [];
@@ -3925,8 +3925,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
3925
3925
  function forEachLineWithContent(input, callback) {
3926
3926
  return toLinesWithContent(input, true).map((line) => callback(line));
3927
3927
  }
3928
- function folderExists(path16) {
3929
- return (0, import_file_exists.exists)(path16, import_file_exists.FOLDER);
3928
+ function folderExists(path17) {
3929
+ return (0, import_file_exists.exists)(path17, import_file_exists.FOLDER);
3930
3930
  }
3931
3931
  function append(target, item) {
3932
3932
  if (Array.isArray(target)) {
@@ -4330,8 +4330,8 @@ function checkIsRepoRootTask() {
4330
4330
  commands,
4331
4331
  format: "utf-8",
4332
4332
  onError,
4333
- parser(path16) {
4334
- return /^\.(git)?$/.test(path16.trim());
4333
+ parser(path17) {
4334
+ return /^\.(git)?$/.test(path17.trim());
4335
4335
  }
4336
4336
  };
4337
4337
  }
@@ -4765,11 +4765,11 @@ function parseGrep(grep) {
4765
4765
  const paths = /* @__PURE__ */ new Set();
4766
4766
  const results = {};
4767
4767
  forEachLineWithContent(grep, (input) => {
4768
- const [path16, line, preview] = input.split(NULL);
4769
- paths.add(path16);
4770
- (results[path16] = results[path16] || []).push({
4768
+ const [path17, line, preview] = input.split(NULL);
4769
+ paths.add(path17);
4770
+ (results[path17] = results[path17] || []).push({
4771
4771
  line: asNumber(line),
4772
- path: path16,
4772
+ path: path17,
4773
4773
  preview
4774
4774
  });
4775
4775
  });
@@ -5534,14 +5534,14 @@ var init_hash_object = __esm({
5534
5534
  init_task();
5535
5535
  }
5536
5536
  });
5537
- function parseInit(bare, path16, text2) {
5537
+ function parseInit(bare, path17, text2) {
5538
5538
  const response = String(text2).trim();
5539
5539
  let result;
5540
5540
  if (result = initResponseRegex.exec(response)) {
5541
- return new InitSummary(bare, path16, false, result[1]);
5541
+ return new InitSummary(bare, path17, false, result[1]);
5542
5542
  }
5543
5543
  if (result = reInitResponseRegex.exec(response)) {
5544
- return new InitSummary(bare, path16, true, result[1]);
5544
+ return new InitSummary(bare, path17, true, result[1]);
5545
5545
  }
5546
5546
  let gitDir = "";
5547
5547
  const tokens = response.split(" ");
@@ -5552,7 +5552,7 @@ function parseInit(bare, path16, text2) {
5552
5552
  break;
5553
5553
  }
5554
5554
  }
5555
- return new InitSummary(bare, path16, /^re/i.test(response), gitDir);
5555
+ return new InitSummary(bare, path17, /^re/i.test(response), gitDir);
5556
5556
  }
5557
5557
  var InitSummary;
5558
5558
  var initResponseRegex;
@@ -5561,9 +5561,9 @@ var init_InitSummary = __esm({
5561
5561
  "src/lib/responses/InitSummary.ts"() {
5562
5562
  "use strict";
5563
5563
  InitSummary = class {
5564
- constructor(bare, path16, existing, gitDir) {
5564
+ constructor(bare, path17, existing, gitDir) {
5565
5565
  this.bare = bare;
5566
- this.path = path16;
5566
+ this.path = path17;
5567
5567
  this.existing = existing;
5568
5568
  this.gitDir = gitDir;
5569
5569
  }
@@ -5575,7 +5575,7 @@ var init_InitSummary = __esm({
5575
5575
  function hasBareCommand(command) {
5576
5576
  return command.includes(bareCommand);
5577
5577
  }
5578
- function initTask(bare = false, path16, customArgs) {
5578
+ function initTask(bare = false, path17, customArgs) {
5579
5579
  const commands = ["init", ...customArgs];
5580
5580
  if (bare && !hasBareCommand(commands)) {
5581
5581
  commands.splice(1, 0, bareCommand);
@@ -5584,7 +5584,7 @@ function initTask(bare = false, path16, customArgs) {
5584
5584
  commands,
5585
5585
  format: "utf-8",
5586
5586
  parser(text2) {
5587
- return parseInit(commands.includes("--bare"), path16, text2);
5587
+ return parseInit(commands.includes("--bare"), path17, text2);
5588
5588
  }
5589
5589
  };
5590
5590
  }
@@ -6400,12 +6400,12 @@ var init_FileStatusSummary = __esm({
6400
6400
  "use strict";
6401
6401
  fromPathRegex = /^(.+)\0(.+)$/;
6402
6402
  FileStatusSummary = class {
6403
- constructor(path16, index, working_dir) {
6404
- this.path = path16;
6403
+ constructor(path17, index, working_dir) {
6404
+ this.path = path17;
6405
6405
  this.index = index;
6406
6406
  this.working_dir = working_dir;
6407
6407
  if (index === "R" || working_dir === "R") {
6408
- const detail = fromPathRegex.exec(path16) || [null, path16, path16];
6408
+ const detail = fromPathRegex.exec(path17) || [null, path17, path17];
6409
6409
  this.from = detail[2] || "";
6410
6410
  this.path = detail[1] || "";
6411
6411
  }
@@ -6436,14 +6436,14 @@ function splitLine(result, lineStr) {
6436
6436
  default:
6437
6437
  return;
6438
6438
  }
6439
- function data(index, workingDir, path16) {
6439
+ function data(index, workingDir, path17) {
6440
6440
  const raw = `${index}${workingDir}`;
6441
6441
  const handler = parsers6.get(raw);
6442
6442
  if (handler) {
6443
- handler(result, path16);
6443
+ handler(result, path17);
6444
6444
  }
6445
6445
  if (raw !== "##" && raw !== "!!") {
6446
- result.files.push(new FileStatusSummary(path16, index, workingDir));
6446
+ result.files.push(new FileStatusSummary(path17, index, workingDir));
6447
6447
  }
6448
6448
  }
6449
6449
  }
@@ -6756,9 +6756,9 @@ var init_simple_git_api = __esm({
6756
6756
  next
6757
6757
  );
6758
6758
  }
6759
- hashObject(path16, write) {
6759
+ hashObject(path17, write) {
6760
6760
  return this._runTask(
6761
- hashObjectTask(path16, write === true),
6761
+ hashObjectTask(path17, write === true),
6762
6762
  trailingFunctionArgument(arguments)
6763
6763
  );
6764
6764
  }
@@ -7111,8 +7111,8 @@ var init_branch = __esm({
7111
7111
  }
7112
7112
  });
7113
7113
  function toPath(input) {
7114
- const path16 = input.trim().replace(/^["']|["']$/g, "");
7115
- return path16 && normalize(path16);
7114
+ const path17 = input.trim().replace(/^["']|["']$/g, "");
7115
+ return path17 && normalize(path17);
7116
7116
  }
7117
7117
  var parseCheckIgnore;
7118
7118
  var init_CheckIgnore = __esm({
@@ -7426,8 +7426,8 @@ __export(sub_module_exports, {
7426
7426
  subModuleTask: () => subModuleTask,
7427
7427
  updateSubModuleTask: () => updateSubModuleTask
7428
7428
  });
7429
- function addSubModuleTask(repo, path16) {
7430
- return subModuleTask(["add", repo, path16]);
7429
+ function addSubModuleTask(repo, path17) {
7430
+ return subModuleTask(["add", repo, path17]);
7431
7431
  }
7432
7432
  function initSubModuleTask(customArgs) {
7433
7433
  return subModuleTask(["init", ...customArgs]);
@@ -7757,8 +7757,8 @@ var require_git = __commonJS2({
7757
7757
  }
7758
7758
  return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
7759
7759
  };
7760
- Git2.prototype.submoduleAdd = function(repo, path16, then) {
7761
- return this._runTask(addSubModuleTask2(repo, path16), trailingFunctionArgument2(arguments));
7760
+ Git2.prototype.submoduleAdd = function(repo, path17, then) {
7761
+ return this._runTask(addSubModuleTask2(repo, path17), trailingFunctionArgument2(arguments));
7762
7762
  };
7763
7763
  Git2.prototype.submoduleUpdate = function(args2, then) {
7764
7764
  return this._runTask(
@@ -8599,7 +8599,7 @@ import { z as z4 } from "zod";
8599
8599
  // package.json
8600
8600
  var package_default = {
8601
8601
  name: "@posthog/agent",
8602
- version: "2.3.508",
8602
+ version: "2.3.513",
8603
8603
  repository: "https://github.com/PostHog/code",
8604
8604
  description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
8605
8605
  exports: {
@@ -9035,9 +9035,9 @@ function nodeWritableToWebWritable(nodeStream) {
9035
9035
 
9036
9036
  // src/adapters/claude/claude-agent.ts
9037
9037
  import { randomUUID } from "crypto";
9038
- import * as fs8 from "fs";
9039
- import * as os4 from "os";
9040
- import * as path10 from "path";
9038
+ import * as fs9 from "fs";
9039
+ import * as os5 from "os";
9040
+ import * as path11 from "path";
9041
9041
  import {
9042
9042
  RequestError as RequestError2
9043
9043
  } from "@agentclientprotocol/sdk";
@@ -13449,8 +13449,8 @@ var ToolContentBuilder = class {
13449
13449
  this.items.push({ type: "content", content: image(data, mimeType, uri) });
13450
13450
  return this;
13451
13451
  }
13452
- diff(path16, oldText, newText) {
13453
- this.items.push({ type: "diff", path: path16, oldText, newText });
13452
+ diff(path17, oldText, newText) {
13453
+ this.items.push({ type: "diff", path: path17, oldText, newText });
13454
13454
  return this;
13455
13455
  }
13456
13456
  build() {
@@ -13461,6 +13461,54 @@ function toolContent() {
13461
13461
  return new ToolContentBuilder();
13462
13462
  }
13463
13463
 
13464
+ // src/utils/partial-json.ts
13465
+ function tryParsePartialJson(s) {
13466
+ const trimmed2 = s.trim();
13467
+ if (!trimmed2) return null;
13468
+ try {
13469
+ return JSON.parse(trimmed2);
13470
+ } catch {
13471
+ }
13472
+ const closers = [];
13473
+ let inString = false;
13474
+ let escaped = false;
13475
+ for (let i2 = 0; i2 < trimmed2.length; i2++) {
13476
+ const ch = trimmed2[i2];
13477
+ if (inString) {
13478
+ if (escaped) {
13479
+ escaped = false;
13480
+ } else if (ch === "\\") {
13481
+ escaped = true;
13482
+ } else if (ch === '"') {
13483
+ inString = false;
13484
+ }
13485
+ continue;
13486
+ }
13487
+ if (ch === '"') inString = true;
13488
+ else if (ch === "{") closers.push("}");
13489
+ else if (ch === "[") closers.push("]");
13490
+ else if (ch === "}" || ch === "]") closers.pop();
13491
+ }
13492
+ const closeBrackets = (str) => {
13493
+ let out2 = str;
13494
+ for (let i2 = closers.length - 1; i2 >= 0; i2--) out2 += closers[i2];
13495
+ return out2;
13496
+ };
13497
+ const candidates = [];
13498
+ const closedString = inString ? `${trimmed2}"` : trimmed2;
13499
+ candidates.push(closeBrackets(closedString));
13500
+ let stripped = closedString.replace(/[,:]\s*$/, "");
13501
+ stripped = stripped.replace(/,?\s*"[^"]*"\s*:?\s*$/, "");
13502
+ candidates.push(closeBrackets(stripped));
13503
+ for (const candidate of candidates) {
13504
+ try {
13505
+ return JSON.parse(candidate);
13506
+ } catch {
13507
+ }
13508
+ }
13509
+ return null;
13510
+ }
13511
+
13464
13512
  // src/adapters/claude/permissions/posthog-exec-gate.ts
13465
13513
  var POSTHOG_EXEC_TOOL_RE = /^mcp__posthog(?:_[^_]+)*__exec$/;
13466
13514
  var POSTHOG_CALL_COMMAND_RE = /^\s*call\s+(?:--json\s+)?([a-zA-Z0-9_-]+)/;
@@ -14627,12 +14675,19 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentC
14627
14675
  }
14628
14676
  return output;
14629
14677
  }
14630
- function streamEventToAcpNotifications(message, sessionId, toolUseCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache) {
14678
+ function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUseStreamCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache) {
14631
14679
  const event = message.event;
14632
14680
  switch (event.type) {
14633
- case "content_block_start":
14681
+ case "content_block_start": {
14682
+ const block = event.content_block;
14683
+ if (block.type === "tool_use" || block.type === "mcp_tool_use") {
14684
+ toolUseStreamCache.set(event.index, {
14685
+ toolUseId: block.id,
14686
+ partialJson: ""
14687
+ });
14688
+ }
14634
14689
  return toAcpNotifications(
14635
- [event.content_block],
14690
+ [block],
14636
14691
  "assistant",
14637
14692
  sessionId,
14638
14693
  toolUseCache,
@@ -14646,7 +14701,16 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, fileCon
14646
14701
  void 0,
14647
14702
  enrichedReadCache
14648
14703
  );
14649
- case "content_block_delta":
14704
+ }
14705
+ case "content_block_delta": {
14706
+ if (event.delta.type === "input_json_delta") {
14707
+ return inputJsonDeltaToAcpNotifications(
14708
+ event.index,
14709
+ event.delta.partial_json,
14710
+ sessionId,
14711
+ toolUseStreamCache
14712
+ );
14713
+ }
14650
14714
  return toAcpNotifications(
14651
14715
  [event.delta],
14652
14716
  "assistant",
@@ -14662,16 +14726,36 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, fileCon
14662
14726
  void 0,
14663
14727
  enrichedReadCache
14664
14728
  );
14729
+ }
14730
+ case "content_block_stop":
14731
+ toolUseStreamCache.delete(event.index);
14732
+ return [];
14665
14733
  case "message_start":
14666
14734
  case "message_delta":
14667
14735
  case "message_stop":
14668
- case "content_block_stop":
14669
14736
  return [];
14670
14737
  default:
14671
14738
  unreachable(event, logger);
14672
14739
  return [];
14673
14740
  }
14674
14741
  }
14742
+ function inputJsonDeltaToAcpNotifications(index, partialJson, sessionId, toolUseStreamCache) {
14743
+ const entry = toolUseStreamCache.get(index);
14744
+ if (!entry) return [];
14745
+ entry.partialJson += partialJson;
14746
+ const parsed = tryParsePartialJson(entry.partialJson);
14747
+ if (!parsed || typeof parsed !== "object") return [];
14748
+ return [
14749
+ {
14750
+ sessionId,
14751
+ update: {
14752
+ sessionUpdate: "tool_call_update",
14753
+ toolCallId: entry.toolUseId,
14754
+ rawInput: parsed
14755
+ }
14756
+ }
14757
+ ];
14758
+ }
14675
14759
  async function handleSystemMessage(message, context) {
14676
14760
  const { session, sessionId, client, logger } = context;
14677
14761
  switch (message.subtype) {
@@ -14815,12 +14899,20 @@ function extractUsageFromResult(message) {
14815
14899
  };
14816
14900
  }
14817
14901
  async function handleStreamEvent(message, context) {
14818
- const { sessionId, client, toolUseCache, fileContentCache, logger } = context;
14902
+ const {
14903
+ sessionId,
14904
+ client,
14905
+ toolUseCache,
14906
+ toolUseStreamCache,
14907
+ fileContentCache,
14908
+ logger
14909
+ } = context;
14819
14910
  const parentToolCallId = message.parent_tool_use_id ?? void 0;
14820
14911
  for (const notification of streamEventToAcpNotifications(
14821
14912
  message,
14822
14913
  sessionId,
14823
14914
  toolUseCache,
14915
+ toolUseStreamCache,
14824
14916
  fileContentCache,
14825
14917
  client,
14826
14918
  logger,
@@ -15733,6 +15825,31 @@ function getAvailableSlashCommands(commands) {
15733
15825
  }
15734
15826
 
15735
15827
  // src/adapters/claude/session/mcp-config.ts
15828
+ import * as fs6 from "fs";
15829
+ import * as os2 from "os";
15830
+ import * as path8 from "path";
15831
+ function loadUserClaudeJsonMcpServers(cwd, logger, homeDir = os2.homedir()) {
15832
+ const claudeJsonPath = path8.join(homeDir, ".claude.json");
15833
+ let raw;
15834
+ try {
15835
+ raw = fs6.readFileSync(claudeJsonPath, "utf8");
15836
+ } catch {
15837
+ return {};
15838
+ }
15839
+ let cfg;
15840
+ try {
15841
+ cfg = JSON.parse(raw);
15842
+ } catch (err2) {
15843
+ logger?.warn("Failed to parse ~/.claude.json", {
15844
+ error: err2 instanceof Error ? err2.message : String(err2)
15845
+ });
15846
+ return {};
15847
+ }
15848
+ const topLevel = cfg.mcpServers && typeof cfg.mcpServers === "object" ? cfg.mcpServers : {};
15849
+ const project = cfg.projects?.[cwd];
15850
+ const projectScoped = project?.mcpServers && typeof project.mcpServers === "object" ? project.mcpServers : {};
15851
+ return { ...topLevel, ...projectScoped };
15852
+ }
15736
15853
  function parseMcpServers(params) {
15737
15854
  const mcpServers = {};
15738
15855
  if (!Array.isArray(params.mcpServers)) {
@@ -15866,9 +15983,9 @@ function resolveModelPreference(preference, options) {
15866
15983
 
15867
15984
  // src/adapters/claude/session/options.ts
15868
15985
  import { spawn as spawn2 } from "child_process";
15869
- import * as fs6 from "fs";
15870
- import * as os2 from "os";
15871
- import * as path8 from "path";
15986
+ import * as fs7 from "fs";
15987
+ import * as os3 from "os";
15988
+ import * as path9 from "path";
15872
15989
 
15873
15990
  // src/adapters/claude/session/instructions.ts
15874
15991
  var BRANCH_NAMING = `
@@ -15919,8 +16036,9 @@ function buildSystemPrompt(customPrompt) {
15919
16036
  }
15920
16037
  return defaultPrompt;
15921
16038
  }
15922
- function buildMcpServers(userServers, acpServers) {
16039
+ function buildMcpServers(userServers, acpServers, projectScopedServers) {
15923
16040
  return {
16041
+ ...projectScopedServers,
15924
16042
  ...userServers || {},
15925
16043
  ...acpServers
15926
16044
  };
@@ -16069,12 +16187,12 @@ function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited, logger)
16069
16187
  };
16070
16188
  }
16071
16189
  function ensureLocalSettings(cwd) {
16072
- const claudeDir = path8.join(cwd, ".claude");
16073
- const localSettingsPath = path8.join(claudeDir, "settings.local.json");
16190
+ const claudeDir = path9.join(cwd, ".claude");
16191
+ const localSettingsPath = path9.join(claudeDir, "settings.local.json");
16074
16192
  try {
16075
- if (!fs6.existsSync(localSettingsPath)) {
16076
- fs6.mkdirSync(claudeDir, { recursive: true });
16077
- fs6.writeFileSync(localSettingsPath, "{}\n", { flag: "wx" });
16193
+ if (!fs7.existsSync(localSettingsPath)) {
16194
+ fs7.mkdirSync(claudeDir, { recursive: true });
16195
+ fs7.writeFileSync(localSettingsPath, "{}\n", { flag: "wx" });
16078
16196
  }
16079
16197
  } catch {
16080
16198
  }
@@ -16104,7 +16222,8 @@ function buildSessionOptions(params) {
16104
16222
  },
16105
16223
  mcpServers: buildMcpServers(
16106
16224
  params.userProvidedOptions?.mcpServers,
16107
- params.mcpServers
16225
+ params.mcpServers,
16226
+ loadUserClaudeJsonMcpServers(params.cwd, params.logger)
16108
16227
  ),
16109
16228
  env: buildEnvironment(),
16110
16229
  hooks: buildHooks(
@@ -16149,18 +16268,18 @@ function buildSessionOptions(params) {
16149
16268
  return options;
16150
16269
  }
16151
16270
  function clearStatsigCache() {
16152
- const statsigPath = path8.join(
16153
- process.env.CLAUDE_CONFIG_DIR || path8.join(os2.homedir(), ".claude"),
16271
+ const statsigPath = path9.join(
16272
+ process.env.CLAUDE_CONFIG_DIR || path9.join(os3.homedir(), ".claude"),
16154
16273
  "statsig"
16155
16274
  );
16156
- fs6.rm(statsigPath, { recursive: true, force: true }, () => {
16275
+ fs7.rm(statsigPath, { recursive: true, force: true }, () => {
16157
16276
  });
16158
16277
  }
16159
16278
 
16160
16279
  // src/adapters/claude/session/settings.ts
16161
- import * as fs7 from "fs";
16162
- import * as os3 from "os";
16163
- import * as path9 from "path";
16280
+ import * as fs8 from "fs";
16281
+ import * as os4 from "os";
16282
+ import * as path10 from "path";
16164
16283
  import { minimatch } from "minimatch";
16165
16284
 
16166
16285
  // src/utils/async-mutex.ts
@@ -16241,13 +16360,13 @@ function parseRule(rule) {
16241
16360
  function normalizePath(filePath, cwd) {
16242
16361
  let resolved = filePath;
16243
16362
  if (resolved.startsWith("~/")) {
16244
- resolved = path9.join(os3.homedir(), resolved.slice(2));
16363
+ resolved = path10.join(os4.homedir(), resolved.slice(2));
16245
16364
  } else if (resolved.startsWith("./")) {
16246
- resolved = path9.join(cwd, resolved.slice(2));
16247
- } else if (!path9.isAbsolute(resolved)) {
16248
- resolved = path9.join(cwd, resolved);
16365
+ resolved = path10.join(cwd, resolved.slice(2));
16366
+ } else if (!path10.isAbsolute(resolved)) {
16367
+ resolved = path10.join(cwd, resolved);
16249
16368
  }
16250
- return path9.normalize(resolved).replace(/\\/g, "/");
16369
+ return path10.normalize(resolved).replace(/\\/g, "/");
16251
16370
  }
16252
16371
  function matchesGlob(pattern, filePath, cwd) {
16253
16372
  const normalizedPattern = normalizePath(pattern, cwd);
@@ -16294,11 +16413,11 @@ function formatRule(rule) {
16294
16413
  }
16295
16414
  async function writeFileAtomic(filePath, data) {
16296
16415
  const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
16297
- await fs7.promises.writeFile(tmpPath, data);
16416
+ await fs8.promises.writeFile(tmpPath, data);
16298
16417
  try {
16299
- await fs7.promises.rename(tmpPath, filePath);
16418
+ await fs8.promises.rename(tmpPath, filePath);
16300
16419
  } catch (error) {
16301
- await fs7.promises.rm(tmpPath, { force: true });
16420
+ await fs8.promises.rm(tmpPath, { force: true });
16302
16421
  throw error;
16303
16422
  }
16304
16423
  }
@@ -16307,7 +16426,7 @@ async function loadSettingsFile(filePath) {
16307
16426
  return {};
16308
16427
  }
16309
16428
  try {
16310
- const content = await fs7.promises.readFile(filePath, "utf-8");
16429
+ const content = await fs8.promises.readFile(filePath, "utf-8");
16311
16430
  return JSON.parse(content);
16312
16431
  } catch (error) {
16313
16432
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -16322,7 +16441,7 @@ async function loadSettingsFile(filePath) {
16322
16441
  }
16323
16442
  async function readSettingsFileForUpdate(filePath) {
16324
16443
  try {
16325
- const content = await fs7.promises.readFile(filePath, "utf-8");
16444
+ const content = await fs8.promises.readFile(filePath, "utf-8");
16326
16445
  return JSON.parse(content);
16327
16446
  } catch (error) {
16328
16447
  if (error instanceof Error && "code" in error && error.code === "ENOENT") {
@@ -16368,11 +16487,11 @@ var SettingsManager = class {
16368
16487
  return this.initPromise;
16369
16488
  }
16370
16489
  getUserSettingsPath() {
16371
- const configDir = process.env.CLAUDE_CONFIG_DIR || path9.join(os3.homedir(), ".claude");
16372
- return path9.join(configDir, "settings.json");
16490
+ const configDir = process.env.CLAUDE_CONFIG_DIR || path10.join(os4.homedir(), ".claude");
16491
+ return path10.join(configDir, "settings.json");
16373
16492
  }
16374
16493
  getProjectSettingsPath() {
16375
- return path9.join(this.cwd, ".claude", "settings.json");
16494
+ return path10.join(this.cwd, ".claude", "settings.json");
16376
16495
  }
16377
16496
  /**
16378
16497
  * Local settings are anchored to the primary worktree so every worktree of
@@ -16380,7 +16499,7 @@ var SettingsManager = class {
16380
16499
  * avoids re-prompting for the same permission in every worktree.
16381
16500
  */
16382
16501
  getLocalSettingsPath() {
16383
- return path9.join(this.repoRoot, ".claude", "settings.local.json");
16502
+ return path10.join(this.repoRoot, ".claude", "settings.local.json");
16384
16503
  }
16385
16504
  async loadAllSettings() {
16386
16505
  this.repoRoot = await resolveMainRepoPath(this.cwd);
@@ -16507,7 +16626,7 @@ var SettingsManager = class {
16507
16626
  }
16508
16627
  permissions.allow = Array.from(current2);
16509
16628
  const next = { ...existing, permissions };
16510
- await fs7.promises.mkdir(path9.dirname(filePath), { recursive: true });
16629
+ await fs8.promises.mkdir(path10.dirname(filePath), { recursive: true });
16511
16630
  await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
16512
16631
  `);
16513
16632
  this.localSettings = next;
@@ -16540,7 +16659,7 @@ var SettingsManager = class {
16540
16659
  ...existing,
16541
16660
  posthogApprovedExecTools: Array.from(current2)
16542
16661
  };
16543
- await fs7.promises.mkdir(path9.dirname(filePath), { recursive: true });
16662
+ await fs8.promises.mkdir(path10.dirname(filePath), { recursive: true });
16544
16663
  await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
16545
16664
  `);
16546
16665
  this.localSettings = next;
@@ -16583,6 +16702,7 @@ function shouldEmitRawMessage(config, message) {
16583
16702
  var ClaudeAcpAgent = class extends BaseAcpAgent {
16584
16703
  adapterName = "claude";
16585
16704
  toolUseCache;
16705
+ toolUseStreamCache;
16586
16706
  backgroundTerminals = {};
16587
16707
  clientCapabilities;
16588
16708
  options;
@@ -16592,6 +16712,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
16592
16712
  super(client);
16593
16713
  this.options = options;
16594
16714
  this.toolUseCache = {};
16715
+ this.toolUseStreamCache = /* @__PURE__ */ new Map();
16595
16716
  this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
16596
16717
  this.enrichment = createEnrichment(options?.posthogApiConfig, this.logger);
16597
16718
  }
@@ -16644,7 +16765,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
16644
16765
  };
16645
16766
  }
16646
16767
  async newSession(params) {
16647
- if (fs8.existsSync(path10.resolve(os4.homedir(), ".claude.json.backup")) && !fs8.existsSync(path10.resolve(os4.homedir(), ".claude.json"))) {
16768
+ if (fs9.existsSync(path11.resolve(os5.homedir(), ".claude.json.backup")) && !fs9.existsSync(path11.resolve(os5.homedir(), ".claude.json"))) {
16648
16769
  throw RequestError2.authRequired();
16649
16770
  }
16650
16771
  const response = await this.createSession(params, {
@@ -16786,6 +16907,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
16786
16907
  sessionId: params.sessionId,
16787
16908
  client: this.client,
16788
16909
  toolUseCache: this.toolUseCache,
16910
+ toolUseStreamCache: this.toolUseStreamCache,
16789
16911
  fileContentCache: this.fileContentCache,
16790
16912
  enrichedReadCache: this.enrichedReadCache,
16791
16913
  logger: this.logger,
@@ -17038,6 +17160,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17038
17160
  }
17039
17161
  throw error;
17040
17162
  } finally {
17163
+ this.toolUseStreamCache.clear();
17041
17164
  if (!handedOff) {
17042
17165
  this.session.promptRunning = false;
17043
17166
  for (const [key, pending] of this.session.pendingMessages) {
@@ -17612,6 +17735,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
17612
17735
  sessionId,
17613
17736
  client: this.client,
17614
17737
  toolUseCache: this.toolUseCache,
17738
+ toolUseStreamCache: this.toolUseStreamCache,
17615
17739
  fileContentCache: this.fileContentCache,
17616
17740
  enrichedReadCache: this.enrichedReadCache,
17617
17741
  logger: this.logger,
@@ -17884,9 +18008,9 @@ function resetUsage(state) {
17884
18008
  }
17885
18009
 
17886
18010
  // src/adapters/codex/settings.ts
17887
- import * as fs9 from "fs";
17888
- import * as os5 from "os";
17889
- import * as path11 from "path";
18011
+ import * as fs10 from "fs";
18012
+ import * as os6 from "os";
18013
+ import * as path12 from "path";
17890
18014
  var CodexSettingsManager = class {
17891
18015
  cwd;
17892
18016
  settings = { mcpServerNames: [] };
@@ -17897,12 +18021,12 @@ var CodexSettingsManager = class {
17897
18021
  async initialize() {
17898
18022
  }
17899
18023
  getConfigPath() {
17900
- return path11.join(os5.homedir(), ".codex", "config.toml");
18024
+ return path12.join(os6.homedir(), ".codex", "config.toml");
17901
18025
  }
17902
18026
  loadSettings() {
17903
18027
  const configPath = this.getConfigPath();
17904
18028
  try {
17905
- const content = fs9.readFileSync(configPath, "utf-8");
18029
+ const content = fs10.readFileSync(configPath, "utf-8");
17906
18030
  this.settings = parseCodexToml(content, this.cwd);
17907
18031
  } catch {
17908
18032
  this.settings = { mcpServerNames: [] };
@@ -18673,18 +18797,18 @@ function createCodexConnection(config) {
18673
18797
  // src/handoff-checkpoint.ts
18674
18798
  import { mkdtemp as mkdtemp2, readFile as readFile4, rm as rm4, writeFile as writeFile2 } from "fs/promises";
18675
18799
  import { tmpdir as tmpdir2 } from "os";
18676
- import { dirname as dirname6, join as join9 } from "path";
18800
+ import { dirname as dirname6, join as join10 } from "path";
18677
18801
 
18678
18802
  // ../git/dist/handoff.js
18679
18803
  import { spawn as spawn4 } from "child_process";
18680
18804
  import { copyFile, mkdtemp, readFile as readFile3, rm as rm3, stat as stat3 } from "fs/promises";
18681
18805
  import { tmpdir } from "os";
18682
- import path13 from "path";
18806
+ import path14 from "path";
18683
18807
 
18684
18808
  // ../git/dist/sagas/checkpoint.js
18685
18809
  import { randomUUID as randomUUID2 } from "crypto";
18686
- import * as fs10 from "fs/promises";
18687
- import * as path12 from "path";
18810
+ import * as fs11 from "fs/promises";
18811
+ import * as path13 from "path";
18688
18812
 
18689
18813
  // ../shared/dist/index.js
18690
18814
  var CLOUD_PROMPT_PREFIX = "__twig_cloud_prompt_v1__:";
@@ -18957,12 +19081,12 @@ async function getGitBusyState(git) {
18957
19081
  const toplevel = (await git.raw(["rev-parse", "--show-toplevel"])).trim();
18958
19082
  const resolveGitPath = async (gitPath) => {
18959
19083
  const relative = (await git.raw(["rev-parse", "--git-path", gitPath])).trim();
18960
- return path12.isAbsolute(relative) ? relative : path12.resolve(toplevel, relative);
19084
+ return path13.isAbsolute(relative) ? relative : path13.resolve(toplevel, relative);
18961
19085
  };
18962
19086
  const pathExists = async (gitPath) => {
18963
19087
  const resolved = await resolveGitPath(gitPath);
18964
19088
  try {
18965
- await fs10.access(resolved);
19089
+ await fs11.access(resolved);
18966
19090
  return true;
18967
19091
  } catch {
18968
19092
  return false;
@@ -18971,7 +19095,7 @@ async function getGitBusyState(git) {
18971
19095
  const dirExists = async (gitPath) => {
18972
19096
  const resolved = await resolveGitPath(gitPath);
18973
19097
  try {
18974
- const stat4 = await fs10.stat(resolved);
19098
+ const stat4 = await fs11.stat(resolved);
18975
19099
  return stat4.isDirectory();
18976
19100
  } catch {
18977
19101
  return false;
@@ -18991,6 +19115,7 @@ async function getGitBusyState(git) {
18991
19115
  }
18992
19116
  return { busy: false };
18993
19117
  }
19118
+ var MAX_WORKTREE_FILE_BYTES = 1024 * 1024;
18994
19119
  async function createWorktreeTree(git, baseDir, head) {
18995
19120
  const { tempGit, tempIndexPath } = await createTempIndexGit(git, baseDir, "checkpoint-worktree");
18996
19121
  try {
@@ -19000,13 +19125,85 @@ async function createWorktreeTree(git, baseDir, head) {
19000
19125
  await tempGit.raw(["read-tree", "--empty"]);
19001
19126
  }
19002
19127
  await tempGit.raw(["add", "-A", "--", "."]);
19128
+ await reconcileLargeBlobs(tempGit, head, MAX_WORKTREE_FILE_BYTES);
19003
19129
  const treeHash = await tempGit.raw(["write-tree"]);
19004
19130
  return treeHash.trim();
19005
19131
  } finally {
19006
- await fs10.rm(tempIndexPath, { force: true }).catch(() => {
19132
+ await fs11.rm(tempIndexPath, { force: true }).catch(() => {
19007
19133
  });
19008
19134
  }
19009
19135
  }
19136
+ async function reconcileLargeBlobs(tempGit, head, maxBytes) {
19137
+ const intermediateTree = (await tempGit.raw(["write-tree"])).trim();
19138
+ const largePaths = await listLargeBlobPaths(tempGit, intermediateTree, maxBytes);
19139
+ if (largePaths.length === 0)
19140
+ return;
19141
+ const headEntries = head ? await readHeadBlobEntries(tempGit, head, largePaths) : /* @__PURE__ */ new Map();
19142
+ for (const filePath of largePaths) {
19143
+ const headEntry = headEntries.get(filePath);
19144
+ if (headEntry) {
19145
+ await tempGit.raw([
19146
+ "update-index",
19147
+ "--cacheinfo",
19148
+ `${headEntry.mode},${headEntry.hash},${filePath}`
19149
+ ]);
19150
+ } else {
19151
+ await tempGit.raw(["update-index", "--force-remove", filePath]).catch(() => {
19152
+ });
19153
+ }
19154
+ }
19155
+ }
19156
+ async function listLargeBlobPaths(tempGit, tree, maxBytes) {
19157
+ const output = await tempGit.raw(["ls-tree", "-r", "-l", tree]);
19158
+ const result = [];
19159
+ for (const line of output.split("\n")) {
19160
+ if (!line)
19161
+ continue;
19162
+ const tabIndex = line.indexOf(" ");
19163
+ if (tabIndex < 0)
19164
+ continue;
19165
+ const meta = line.slice(0, tabIndex);
19166
+ const filePath = line.slice(tabIndex + 1);
19167
+ const parts2 = meta.split(/\s+/);
19168
+ if (parts2.length < 4)
19169
+ continue;
19170
+ const [, type, , sizeStr] = parts2;
19171
+ if (type !== "blob")
19172
+ continue;
19173
+ if (sizeStr === "-")
19174
+ continue;
19175
+ const size = Number.parseInt(sizeStr, 10);
19176
+ if (Number.isFinite(size) && size > maxBytes) {
19177
+ result.push(filePath);
19178
+ }
19179
+ }
19180
+ return result;
19181
+ }
19182
+ async function readHeadBlobEntries(tempGit, head, paths) {
19183
+ const result = /* @__PURE__ */ new Map();
19184
+ const CHUNK_SIZE = 100;
19185
+ for (let i2 = 0; i2 < paths.length; i2 += CHUNK_SIZE) {
19186
+ const chunk = paths.slice(i2, i2 + CHUNK_SIZE);
19187
+ const output = await tempGit.raw(["ls-tree", "-r", head, "--", ...chunk]).catch(() => "");
19188
+ for (const line of output.split("\n")) {
19189
+ if (!line)
19190
+ continue;
19191
+ const tabIndex = line.indexOf(" ");
19192
+ if (tabIndex < 0)
19193
+ continue;
19194
+ const meta = line.slice(0, tabIndex);
19195
+ const filePath = line.slice(tabIndex + 1);
19196
+ const parts2 = meta.split(/\s+/);
19197
+ if (parts2.length < 3)
19198
+ continue;
19199
+ const [mode, type, hash] = parts2;
19200
+ if (type !== "blob")
19201
+ continue;
19202
+ result.set(filePath, { mode, hash });
19203
+ }
19204
+ }
19205
+ return result;
19206
+ }
19010
19207
  async function createMetaTree(git, baseDir, indexTree, worktreeTree) {
19011
19208
  const { tempGit, tempIndexPath } = await createTempIndexGit(git, baseDir, "checkpoint-meta");
19012
19209
  try {
@@ -19030,7 +19227,7 @@ async function createMetaTree(git, baseDir, indexTree, worktreeTree) {
19030
19227
  const metaTree = await tempGit.raw(["write-tree"]);
19031
19228
  return metaTree.trim();
19032
19229
  } finally {
19033
- await fs10.rm(tempIndexPath, { force: true }).catch(() => {
19230
+ await fs11.rm(tempIndexPath, { force: true }).catch(() => {
19034
19231
  });
19035
19232
  }
19036
19233
  }
@@ -19047,12 +19244,12 @@ function formatCheckpointMessage(meta) {
19047
19244
  async function getGitCommonDir(git, baseDir) {
19048
19245
  const raw = await git.raw(["rev-parse", "--git-common-dir"]);
19049
19246
  const dir = raw.trim() || ".git";
19050
- return path12.isAbsolute(dir) ? dir : path12.resolve(baseDir, dir);
19247
+ return path13.isAbsolute(dir) ? dir : path13.resolve(baseDir, dir);
19051
19248
  }
19052
19249
  async function createTempIndexGit(git, baseDir, label) {
19053
- const tmpDir = path12.join(await getGitCommonDir(git, baseDir), "posthog-code-tmp");
19054
- await fs10.mkdir(tmpDir, { recursive: true });
19055
- const tempIndexPath = path12.join(tmpDir, `${label}-${Date.now()}-${randomUUID2()}`);
19250
+ const tmpDir = path13.join(await getGitCommonDir(git, baseDir), "posthog-code-tmp");
19251
+ await fs11.mkdir(tmpDir, { recursive: true });
19252
+ const tempIndexPath = path13.join(tmpDir, `${label}-${Date.now()}-${randomUUID2()}`);
19056
19253
  const tempGit = createGitClient(baseDir).env({
19057
19254
  ...process.env,
19058
19255
  GIT_INDEX_FILE: tempIndexPath
@@ -19079,6 +19276,7 @@ async function deleteCheckpoint(git, checkpointId) {
19079
19276
  // ../git/dist/handoff.js
19080
19277
  var HANDOFF_HEAD_REF_PREFIX = "refs/posthog-code-handoff/head/";
19081
19278
  var CHECKPOINT_REF_PREFIX2 = "refs/posthog-code-checkpoint/";
19279
+ var MAX_HANDOFF_FILE_BYTES = 1024 * 1024;
19082
19280
  var GitHandoffTracker = class {
19083
19281
  repositoryPath;
19084
19282
  logger;
@@ -19086,7 +19284,7 @@ var GitHandoffTracker = class {
19086
19284
  this.repositoryPath = config.repositoryPath;
19087
19285
  this.logger = config.logger;
19088
19286
  }
19089
- async captureForHandoff(_localGitState) {
19287
+ async captureForHandoff(localGitState) {
19090
19288
  const captureSaga = new CaptureCheckpointSaga(this.logger);
19091
19289
  const result = await captureSaga.run({ baseDir: this.repositoryPath });
19092
19290
  if (!result.success) {
@@ -19096,17 +19294,20 @@ var GitHandoffTracker = class {
19096
19294
  const git = createGitClient(this.repositoryPath);
19097
19295
  const tempDir = await this.createTempDir(checkpoint.checkpointId);
19098
19296
  const checkpointRef = `${CHECKPOINT_REF_PREFIX2}${checkpoint.checkpointId}`;
19099
- const packRefs = [
19100
- checkpoint.head,
19101
- checkpoint.indexTree,
19102
- checkpoint.worktreeTree
19103
- ].filter((ref) => !!ref);
19104
- const headRef = checkpoint.head ? `${HANDOFF_HEAD_REF_PREFIX}${checkpoint.checkpointId}` : void 0;
19105
- const packPrefix = path13.join(tempDir, checkpoint.checkpointId);
19106
19297
  try {
19298
+ const reconciledIndex = await this.reconcileHandoffIndex(git, checkpoint.head, checkpoint.indexTree, tempDir, checkpoint.checkpointId);
19299
+ const packBaseline = localGitState?.upstreamHead ?? null;
19300
+ const packRefs = [
19301
+ checkpoint.head,
19302
+ reconciledIndex.indexTree,
19303
+ checkpoint.worktreeTree,
19304
+ packBaseline ? `^${packBaseline}` : null
19305
+ ].filter((ref) => !!ref);
19306
+ const headRef = checkpoint.head ? `${HANDOFF_HEAD_REF_PREFIX}${checkpoint.checkpointId}` : void 0;
19307
+ const packPrefix = path14.join(tempDir, checkpoint.checkpointId);
19107
19308
  const [headPack, indexFile, tracking] = await Promise.all([
19108
19309
  this.captureObjectPack(packPrefix, packRefs),
19109
- this.copyIndexFile(git, checkpoint.checkpointId, tempDir),
19310
+ this.statFileArtifact(reconciledIndex.indexFilePath),
19110
19311
  getTrackingMetadata(git, checkpoint.branch)
19111
19312
  ]);
19112
19313
  return {
@@ -19117,7 +19318,7 @@ var GitHandoffTracker = class {
19117
19318
  headRef,
19118
19319
  head: checkpoint.head,
19119
19320
  branch: checkpoint.branch,
19120
- indexTree: checkpoint.indexTree,
19321
+ indexTree: reconciledIndex.indexTree,
19121
19322
  worktreeTree: checkpoint.worktreeTree,
19122
19323
  timestamp: checkpoint.timestamp,
19123
19324
  upstreamRemote: tracking.upstreamRemote,
@@ -19137,6 +19338,7 @@ var GitHandoffTracker = class {
19137
19338
  const { checkpoint, headPackPath, indexPath, localGitState, onDivergedBranch } = input;
19138
19339
  const git = createGitClient(this.repositoryPath);
19139
19340
  if (headPackPath) {
19341
+ await this.ensureBaselineForApply(git, checkpoint, localGitState);
19140
19342
  await this.unpackPackFile(headPackPath);
19141
19343
  }
19142
19344
  if (checkpoint.branch && checkpoint.head) {
@@ -19175,14 +19377,89 @@ var GitHandoffTracker = class {
19175
19377
  });
19176
19378
  return { path: packPath, rawBytes };
19177
19379
  }
19178
- async copyIndexFile(git, checkpointId, tempDir) {
19179
- const indexPath = await this.getGitPath(git, "index");
19180
- const copiedIndexPath = path13.join(tempDir, `${checkpointId}.index`);
19181
- await copyFile(indexPath, copiedIndexPath);
19182
- return {
19183
- path: copiedIndexPath,
19184
- rawBytes: await this.getFileSize(copiedIndexPath)
19185
- };
19380
+ async reconcileHandoffIndex(git, head, indexTree, tempDir, checkpointId) {
19381
+ const realIndexPath = await this.getGitPath(git, "index");
19382
+ const tempIndexPath = path14.join(tempDir, `${checkpointId}.index`);
19383
+ await copyFile(realIndexPath, tempIndexPath);
19384
+ const largePaths = await this.listLargeBlobsInTree(indexTree, MAX_HANDOFF_FILE_BYTES);
19385
+ if (largePaths.length === 0) {
19386
+ return { indexTree, indexFilePath: tempIndexPath };
19387
+ }
19388
+ const headBlobs = head ? await this.readHeadBlobsForPaths(head, largePaths) : /* @__PURE__ */ new Map();
19389
+ const env = { ...process.env, GIT_INDEX_FILE: tempIndexPath };
19390
+ for (const filePath of largePaths) {
19391
+ const headBlob = headBlobs.get(filePath);
19392
+ if (headBlob) {
19393
+ await this.runGitWithEnv(env, [
19394
+ "update-index",
19395
+ "--cacheinfo",
19396
+ `${headBlob.mode},${headBlob.hash},${filePath}`
19397
+ ]);
19398
+ } else {
19399
+ await this.runGitWithEnv(env, [
19400
+ "update-index",
19401
+ "--force-remove",
19402
+ filePath
19403
+ ]).catch(() => {
19404
+ });
19405
+ }
19406
+ }
19407
+ const reconciledTree = (await this.runGitWithEnv(env, ["write-tree"])).trim();
19408
+ return { indexTree: reconciledTree, indexFilePath: tempIndexPath };
19409
+ }
19410
+ async listLargeBlobsInTree(tree, maxBytes) {
19411
+ const { stdout } = await this.runGitProcess(["ls-tree", "-r", "-l", tree], "");
19412
+ const result = [];
19413
+ for (const line of stdout.split("\n")) {
19414
+ if (!line)
19415
+ continue;
19416
+ const tabIndex = line.indexOf(" ");
19417
+ if (tabIndex < 0)
19418
+ continue;
19419
+ const meta = line.slice(0, tabIndex);
19420
+ const filePath = line.slice(tabIndex + 1);
19421
+ const parts2 = meta.split(/\s+/);
19422
+ if (parts2.length < 4)
19423
+ continue;
19424
+ const [, type, , sizeStr] = parts2;
19425
+ if (type !== "blob")
19426
+ continue;
19427
+ if (sizeStr === "-")
19428
+ continue;
19429
+ const size = Number.parseInt(sizeStr, 10);
19430
+ if (Number.isFinite(size) && size > maxBytes) {
19431
+ result.push(filePath);
19432
+ }
19433
+ }
19434
+ return result;
19435
+ }
19436
+ async readHeadBlobsForPaths(head, paths) {
19437
+ const result = /* @__PURE__ */ new Map();
19438
+ const CHUNK_SIZE = 100;
19439
+ for (let i2 = 0; i2 < paths.length; i2 += CHUNK_SIZE) {
19440
+ const chunk = paths.slice(i2, i2 + CHUNK_SIZE);
19441
+ const { stdout } = await this.runGitProcess(["ls-tree", "-r", head, "--", ...chunk], "").catch(() => ({ stdout: "", stderr: "" }));
19442
+ for (const line of stdout.split("\n")) {
19443
+ if (!line)
19444
+ continue;
19445
+ const tabIndex = line.indexOf(" ");
19446
+ if (tabIndex < 0)
19447
+ continue;
19448
+ const meta = line.slice(0, tabIndex);
19449
+ const filePath = line.slice(tabIndex + 1);
19450
+ const parts2 = meta.split(/\s+/);
19451
+ if (parts2.length < 3)
19452
+ continue;
19453
+ const [mode, type, hash] = parts2;
19454
+ if (type !== "blob")
19455
+ continue;
19456
+ result.set(filePath, { mode, hash });
19457
+ }
19458
+ }
19459
+ return result;
19460
+ }
19461
+ async statFileArtifact(filePath) {
19462
+ return { path: filePath, rawBytes: await this.getFileSize(filePath) };
19186
19463
  }
19187
19464
  async restoreIndexFile(git, indexPath) {
19188
19465
  const gitIndexPath = await this.getGitPath(git, "index");
@@ -19210,6 +19487,20 @@ var GitHandoffTracker = class {
19210
19487
  shouldRestoreTracking(branchStatus2, localGitState, tracking) {
19211
19488
  return branchStatus2.kind === "missing" || !hasTrackingConfig(localGitState) && (tracking.upstreamRemote !== null || tracking.upstreamMergeRef !== null);
19212
19489
  }
19490
+ async ensureBaselineForApply(git, checkpoint, localGitState) {
19491
+ const tracking = this.getPreferredTracking(localGitState, checkpoint);
19492
+ if (!tracking.upstreamRemote || !tracking.upstreamMergeRef)
19493
+ return;
19494
+ await this.ensureRemoteForTracking(git, tracking).catch(() => {
19495
+ });
19496
+ await git.raw(["fetch", tracking.upstreamRemote, tracking.upstreamMergeRef]).catch((err2) => {
19497
+ this.logger?.error("Handoff baseline fetch failed; if the pack excludes commits the receiver does not already have, the subsequent unpack/read-tree will fail with an object-missing error", {
19498
+ err: String(err2),
19499
+ remote: tracking.upstreamRemote,
19500
+ ref: tracking.upstreamMergeRef
19501
+ });
19502
+ });
19503
+ }
19213
19504
  async ensureRemoteForTracking(git, tracking) {
19214
19505
  if (!tracking.upstreamRemote || !tracking.remoteUrl)
19215
19506
  return;
@@ -19310,7 +19601,7 @@ var GitHandoffTracker = class {
19310
19601
  async getGitPath(git, gitPath) {
19311
19602
  const raw = await git.raw(["rev-parse", "--git-path", gitPath]);
19312
19603
  const resolved = raw.trim();
19313
- return path13.isAbsolute(resolved) ? resolved : path13.resolve(this.repositoryPath, resolved);
19604
+ return path14.isAbsolute(resolved) ? resolved : path14.resolve(this.repositoryPath, resolved);
19314
19605
  }
19315
19606
  async getFileSize(filePath) {
19316
19607
  return (await stat3(filePath)).size;
@@ -19346,6 +19637,31 @@ var GitHandoffTracker = class {
19346
19637
  });
19347
19638
  });
19348
19639
  }
19640
+ async runGitWithEnv(env, args2) {
19641
+ return new Promise((resolve7, reject) => {
19642
+ const child = spawn4("git", args2, {
19643
+ cwd: this.repositoryPath,
19644
+ stdio: ["ignore", "pipe", "pipe"],
19645
+ env
19646
+ });
19647
+ let stdout = "";
19648
+ let stderr = "";
19649
+ child.stdout.on("data", (chunk) => {
19650
+ stdout += chunk.toString();
19651
+ });
19652
+ child.stderr.on("data", (chunk) => {
19653
+ stderr += chunk.toString();
19654
+ });
19655
+ child.on("error", reject);
19656
+ child.on("close", (code) => {
19657
+ if (code === 0) {
19658
+ resolve7(stdout);
19659
+ return;
19660
+ }
19661
+ reject(new Error(stderr || `git ${args2.join(" ")} failed with code ${code}`));
19662
+ });
19663
+ });
19664
+ }
19349
19665
  runGitProcess(args2, input) {
19350
19666
  return new Promise((resolve7, reject) => {
19351
19667
  const child = spawn4("git", args2, {
@@ -19368,12 +19684,14 @@ var GitHandoffTracker = class {
19368
19684
  }
19369
19685
  reject(new Error(stderr || `git ${args2.join(" ")} failed with code ${code}`));
19370
19686
  });
19687
+ child.stdin.on("error", () => {
19688
+ });
19371
19689
  child.stdin.end(input);
19372
19690
  });
19373
19691
  }
19374
19692
  };
19375
19693
  function joinTempPrefix(checkpointId) {
19376
- return path13.join(tmpdir(), `posthog-code-handoff-${checkpointId}-`);
19694
+ return path14.join(tmpdir(), `posthog-code-handoff-${checkpointId}-`);
19377
19695
  }
19378
19696
  async function getCurrentBranchName(git) {
19379
19697
  try {
@@ -19476,10 +19794,10 @@ var HandoffCheckpointTracker = class {
19476
19794
  }
19477
19795
  const gitTracker = this.createGitTracker();
19478
19796
  const tmpDir = await mkdtemp2(
19479
- join9(tmpdir2(), `posthog-code-handoff-${checkpoint.checkpointId}-`)
19797
+ join10(tmpdir2(), `posthog-code-handoff-${checkpoint.checkpointId}-`)
19480
19798
  );
19481
- const packPath = join9(tmpDir, `${checkpoint.checkpointId}.pack`);
19482
- const indexPath = join9(tmpDir, `${checkpoint.checkpointId}.index`);
19799
+ const packPath = join10(tmpDir, `${checkpoint.checkpointId}.pack`);
19800
+ const indexPath = join10(tmpDir, `${checkpoint.checkpointId}.index`);
19483
19801
  try {
19484
19802
  const downloads = await this.downloadArtifacts([
19485
19803
  {
@@ -19858,9 +20176,9 @@ var PostHogAPIClient = class {
19858
20176
 
19859
20177
  // src/adapters/claude/session/jsonl-hydration.ts
19860
20178
  import { randomUUID as randomUUID3 } from "crypto";
19861
- import * as fs11 from "fs/promises";
19862
- import * as os6 from "os";
19863
- import * as path14 from "path";
20179
+ import * as fs12 from "fs/promises";
20180
+ import * as os7 from "os";
20181
+ import * as path15 from "path";
19864
20182
  var CHARS_PER_TOKEN = 4;
19865
20183
  var DEFAULT_MAX_TOKENS = 15e4;
19866
20184
  function estimateTurnTokens(turn) {
@@ -20167,9 +20485,9 @@ ${toolSummary}`);
20167
20485
  }
20168
20486
 
20169
20487
  // src/session-log-writer.ts
20170
- import fs12 from "fs";
20488
+ import fs13 from "fs";
20171
20489
  import fsp from "fs/promises";
20172
- import path15 from "path";
20490
+ import path16 from "path";
20173
20491
  var SessionLogWriter = class _SessionLogWriter {
20174
20492
  static FLUSH_DEBOUNCE_MS = 500;
20175
20493
  static FLUSH_MAX_INTERVAL_MS = 5e3;
@@ -20205,13 +20523,13 @@ var SessionLogWriter = class _SessionLogWriter {
20205
20523
  this.sessions.set(sessionId, { context, currentTurnMessages: [] });
20206
20524
  this.lastFlushAttemptTime.set(sessionId, Date.now());
20207
20525
  if (this.localCachePath) {
20208
- const sessionDir = path15.join(
20526
+ const sessionDir = path16.join(
20209
20527
  this.localCachePath,
20210
20528
  "sessions",
20211
20529
  context.runId
20212
20530
  );
20213
20531
  try {
20214
- fs12.mkdirSync(sessionDir, { recursive: true });
20532
+ fs13.mkdirSync(sessionDir, { recursive: true });
20215
20533
  } catch (error) {
20216
20534
  this.logger.warn("Failed to create local cache directory", {
20217
20535
  sessionDir,
@@ -20463,14 +20781,14 @@ var SessionLogWriter = class _SessionLogWriter {
20463
20781
  if (!this.localCachePath) return;
20464
20782
  const session = this.sessions.get(sessionId);
20465
20783
  if (!session) return;
20466
- const logPath = path15.join(
20784
+ const logPath = path16.join(
20467
20785
  this.localCachePath,
20468
20786
  "sessions",
20469
20787
  session.context.runId,
20470
20788
  "logs.ndjson"
20471
20789
  );
20472
20790
  try {
20473
- fs12.appendFileSync(logPath, `${JSON.stringify(entry)}
20791
+ fs13.appendFileSync(logPath, `${JSON.stringify(entry)}
20474
20792
  `);
20475
20793
  } catch (error) {
20476
20794
  this.logger.warn("Failed to write to local cache", {
@@ -20482,13 +20800,13 @@ var SessionLogWriter = class _SessionLogWriter {
20482
20800
  }
20483
20801
  }
20484
20802
  static async cleanupOldSessions(localCachePath) {
20485
- const sessionsDir = path15.join(localCachePath, "sessions");
20803
+ const sessionsDir = path16.join(localCachePath, "sessions");
20486
20804
  let deleted = 0;
20487
20805
  try {
20488
20806
  const entries = await fsp.readdir(sessionsDir);
20489
20807
  const now = Date.now();
20490
20808
  for (const entry of entries) {
20491
- const entryPath = path15.join(sessionsDir, entry);
20809
+ const entryPath = path16.join(sessionsDir, entry);
20492
20810
  try {
20493
20811
  const stats = await fsp.stat(entryPath);
20494
20812
  if (stats.isDirectory() && now - stats.birthtimeMs > _SessionLogWriter.SESSIONS_MAX_AGE_MS) {
@@ -20526,7 +20844,7 @@ async function getAgentshVersion() {
20526
20844
  }
20527
20845
  async function resolveAgentshRuntimeInfo({
20528
20846
  sessionIdPath = AGENTSH_SESSION_ID_FILE,
20529
- readSessionId = async (path16) => readFile5(path16, "utf8"),
20847
+ readSessionId = async (path17) => readFile5(path17, "utf8"),
20530
20848
  getVersion = getAgentshVersion
20531
20849
  } = {}) {
20532
20850
  let sessionId;
@@ -21752,7 +22070,7 @@ Continue from where you left off. The user is waiting for your response.`
21752
22070
  throw new Error(`Failed to download artifact ${artifact.name}`);
21753
22071
  }
21754
22072
  const safeName = this.getSafeArtifactName(artifact.name);
21755
- const artifactDir = join11(
22073
+ const artifactDir = join12(
21756
22074
  this.config.repositoryPath ?? "/tmp/workspace",
21757
22075
  ".posthog",
21758
22076
  "attachments",
@@ -21760,7 +22078,7 @@ Continue from where you left off. The user is waiting for your response.`
21760
22078
  artifact.id ?? safeName
21761
22079
  );
21762
22080
  await mkdir4(artifactDir, { recursive: true });
21763
- const artifactPath = join11(artifactDir, safeName);
22081
+ const artifactPath = join12(artifactDir, safeName);
21764
22082
  await writeFile4(artifactPath, Buffer.from(data));
21765
22083
  return resourceLink(pathToFileURL(artifactPath).toString(), artifact.name, {
21766
22084
  ...artifact.content_type ? { mimeType: artifact.content_type } : {},