@fern-api/fern-api-dev 4.62.3-2-g207f4f8f41a → 4.62.3-22-ga624085d56a

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.
Files changed (2) hide show
  1. package/cli.cjs +983 -85
  2. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -363452,9 +363452,9 @@ var require_diff3 = __commonJS({
363452
363452
  }
363453
363453
  });
363454
363454
 
363455
- // ../../../node_modules/.pnpm/@fern-api+replay@0.8.0/node_modules/@fern-api/replay/dist/index.cjs
363455
+ // ../../../node_modules/.pnpm/@fern-api+replay@0.9.1/node_modules/@fern-api/replay/dist/index.cjs
363456
363456
  var require_dist11 = __commonJS({
363457
- "../../../node_modules/.pnpm/@fern-api+replay@0.8.0/node_modules/@fern-api/replay/dist/index.cjs"(exports2, module4) {
363457
+ "../../../node_modules/.pnpm/@fern-api+replay@0.9.1/node_modules/@fern-api/replay/dist/index.cjs"(exports2, module4) {
363458
363458
  "use strict";
363459
363459
  var __defProp4 = Object.defineProperty;
363460
363460
  var __getOwnPropDesc4 = Object.getOwnPropertyDescriptor;
@@ -363579,6 +363579,14 @@ var require_dist11 = __commonJS({
363579
363579
  return false;
363580
363580
  }
363581
363581
  }
363582
+ async treeExists(treeHash) {
363583
+ try {
363584
+ const type8 = await this.exec(["cat-file", "-t", treeHash]);
363585
+ return type8.trim() === "tree";
363586
+ } catch {
363587
+ return false;
363588
+ }
363589
+ }
363582
363590
  async getCommitBody(commitSha) {
363583
363591
  return this.exec(["log", "-1", "--format=%B", commitSha]);
363584
363592
  }
@@ -363588,6 +363596,253 @@ var require_dist11 = __commonJS({
363588
363596
  };
363589
363597
  }
363590
363598
  });
363599
+ var HybridReconstruction_exports = {};
363600
+ __export4(HybridReconstruction_exports, {
363601
+ assembleHybrid: () => assembleHybrid,
363602
+ locateHunksInOurs: () => locateHunksInOurs,
363603
+ parseHunks: () => parseHunks,
363604
+ reconstructFromGhostPatch: () => reconstructFromGhostPatch
363605
+ });
363606
+ function parseHunks(fileDiff) {
363607
+ const lines = fileDiff.split("\n");
363608
+ const hunks = [];
363609
+ let currentHunk = null;
363610
+ for (const line of lines) {
363611
+ const headerMatch = line.match(
363612
+ /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/
363613
+ );
363614
+ if (headerMatch) {
363615
+ if (currentHunk) {
363616
+ hunks.push(currentHunk);
363617
+ }
363618
+ currentHunk = {
363619
+ oldStart: parseInt(headerMatch[1], 10),
363620
+ oldCount: headerMatch[2] != null ? parseInt(headerMatch[2], 10) : 1,
363621
+ newStart: parseInt(headerMatch[3], 10),
363622
+ newCount: headerMatch[4] != null ? parseInt(headerMatch[4], 10) : 1,
363623
+ lines: []
363624
+ };
363625
+ continue;
363626
+ }
363627
+ if (!currentHunk) continue;
363628
+ if (line.startsWith("diff --git") || line.startsWith("index ") || line.startsWith("---") || line.startsWith("+++") || line.startsWith("old mode") || line.startsWith("new mode") || line.startsWith("similarity index") || line.startsWith("rename from") || line.startsWith("rename to") || line.startsWith("new file mode") || line.startsWith("deleted file mode")) {
363629
+ continue;
363630
+ }
363631
+ if (line === "\") {
363632
+ continue;
363633
+ }
363634
+ if (line.startsWith("-")) {
363635
+ currentHunk.lines.push({ type: "remove", content: line.slice(1) });
363636
+ } else if (line.startsWith("+")) {
363637
+ currentHunk.lines.push({ type: "add", content: line.slice(1) });
363638
+ } else if (line.startsWith(" ") || line === "") {
363639
+ currentHunk.lines.push({
363640
+ type: "context",
363641
+ content: line.startsWith(" ") ? line.slice(1) : line
363642
+ });
363643
+ }
363644
+ }
363645
+ if (currentHunk) {
363646
+ hunks.push(currentHunk);
363647
+ }
363648
+ return hunks;
363649
+ }
363650
+ function extractLeadingContext(hunk) {
363651
+ const result = [];
363652
+ for (const line of hunk.lines) {
363653
+ if (line.type !== "context") break;
363654
+ result.push(line.content);
363655
+ }
363656
+ return result;
363657
+ }
363658
+ function extractTrailingContext(hunk) {
363659
+ const result = [];
363660
+ for (let i11 = hunk.lines.length - 1; i11 >= 0; i11--) {
363661
+ if (hunk.lines[i11].type !== "context") break;
363662
+ result.unshift(hunk.lines[i11].content);
363663
+ }
363664
+ return result;
363665
+ }
363666
+ function countOursLinesBeforeTrailing(hunk) {
363667
+ let count = 0;
363668
+ const trailingStart = findTrailingContextStart(hunk);
363669
+ for (let i11 = 0; i11 < trailingStart; i11++) {
363670
+ if (hunk.lines[i11].type === "context") count++;
363671
+ }
363672
+ return count;
363673
+ }
363674
+ function findTrailingContextStart(hunk) {
363675
+ let i11 = hunk.lines.length - 1;
363676
+ while (i11 >= 0 && hunk.lines[i11].type === "context") {
363677
+ i11--;
363678
+ }
363679
+ return i11 + 1;
363680
+ }
363681
+ function matchesAt(needle, haystack, offset2) {
363682
+ for (let i11 = 0; i11 < needle.length; i11++) {
363683
+ if (haystack[offset2 + i11] !== needle[i11]) return false;
363684
+ }
363685
+ return true;
363686
+ }
363687
+ function findContextInOurs(contextLines, oursLines, minIndex, hint) {
363688
+ const SEARCH_WINDOW = 200;
363689
+ const maxStart = oursLines.length - contextLines.length;
363690
+ const clampedHint = Math.max(minIndex, Math.min(hint, maxStart));
363691
+ if (clampedHint >= minIndex && clampedHint <= maxStart) {
363692
+ if (matchesAt(contextLines, oursLines, clampedHint)) {
363693
+ return clampedHint;
363694
+ }
363695
+ }
363696
+ for (let delta = 1; delta <= SEARCH_WINDOW; delta++) {
363697
+ for (const sign2 of [1, -1]) {
363698
+ const idx = clampedHint + delta * sign2;
363699
+ if (idx < minIndex || idx > maxStart) continue;
363700
+ if (matchesAt(contextLines, oursLines, idx)) {
363701
+ return idx;
363702
+ }
363703
+ }
363704
+ }
363705
+ return -1;
363706
+ }
363707
+ function computeOursSpan(hunk, oursLines, oursOffset) {
363708
+ const leading = extractLeadingContext(hunk);
363709
+ const trailing = extractTrailingContext(hunk);
363710
+ if (trailing.length === 0) {
363711
+ const contextCount2 = hunk.lines.filter(
363712
+ (l14) => l14.type === "context"
363713
+ ).length;
363714
+ return Math.min(contextCount2, oursLines.length - oursOffset);
363715
+ }
363716
+ const searchStart = oursOffset + leading.length;
363717
+ for (let i11 = searchStart; i11 <= oursLines.length - trailing.length; i11++) {
363718
+ if (matchesAt(trailing, oursLines, i11)) {
363719
+ return i11 + trailing.length - oursOffset;
363720
+ }
363721
+ }
363722
+ const contextCount = hunk.lines.filter(
363723
+ (l14) => l14.type === "context"
363724
+ ).length;
363725
+ return Math.min(contextCount, oursLines.length - oursOffset);
363726
+ }
363727
+ function locateHunksInOurs(hunks, oursLines) {
363728
+ const located = [];
363729
+ let minOursIndex = 0;
363730
+ for (const hunk of hunks) {
363731
+ const contextLines = extractLeadingContext(hunk);
363732
+ let oursOffset;
363733
+ if (contextLines.length > 0) {
363734
+ const found = findContextInOurs(
363735
+ contextLines,
363736
+ oursLines,
363737
+ minOursIndex,
363738
+ hunk.newStart - 1
363739
+ );
363740
+ if (found === -1) {
363741
+ const trailingContext = extractTrailingContext(hunk);
363742
+ if (trailingContext.length > 0) {
363743
+ const trailingFound = findContextInOurs(
363744
+ trailingContext,
363745
+ oursLines,
363746
+ minOursIndex,
363747
+ hunk.newStart - 1
363748
+ );
363749
+ if (trailingFound === -1) return null;
363750
+ const nonTrailingCount = countOursLinesBeforeTrailing(hunk);
363751
+ oursOffset = trailingFound - nonTrailingCount;
363752
+ if (oursOffset < minOursIndex) return null;
363753
+ } else {
363754
+ return null;
363755
+ }
363756
+ } else {
363757
+ oursOffset = found;
363758
+ }
363759
+ } else if (hunk.oldStart === 1 && hunk.oldCount === 0) {
363760
+ oursOffset = 0;
363761
+ } else {
363762
+ oursOffset = Math.max(hunk.newStart - 1, minOursIndex);
363763
+ }
363764
+ const oursSpan = computeOursSpan(hunk, oursLines, oursOffset);
363765
+ located.push({ hunk, oursOffset, oursSpan });
363766
+ minOursIndex = oursOffset + oursSpan;
363767
+ }
363768
+ return located;
363769
+ }
363770
+ function assembleHybrid(locatedHunks, oursLines) {
363771
+ const baseLines = [];
363772
+ const theirsLines = [];
363773
+ let oursCursor = 0;
363774
+ for (const { hunk, oursOffset, oursSpan } of locatedHunks) {
363775
+ if (oursOffset > oursCursor) {
363776
+ const gapLines = oursLines.slice(oursCursor, oursOffset);
363777
+ baseLines.push(...gapLines);
363778
+ theirsLines.push(...gapLines);
363779
+ }
363780
+ for (const line of hunk.lines) {
363781
+ switch (line.type) {
363782
+ case "context":
363783
+ baseLines.push(line.content);
363784
+ theirsLines.push(line.content);
363785
+ break;
363786
+ case "remove":
363787
+ baseLines.push(line.content);
363788
+ break;
363789
+ case "add":
363790
+ theirsLines.push(line.content);
363791
+ break;
363792
+ }
363793
+ }
363794
+ oursCursor = oursOffset + oursSpan;
363795
+ }
363796
+ if (oursCursor < oursLines.length) {
363797
+ const gapLines = oursLines.slice(oursCursor);
363798
+ baseLines.push(...gapLines);
363799
+ theirsLines.push(...gapLines);
363800
+ }
363801
+ return {
363802
+ base: baseLines.join("\n"),
363803
+ theirs: theirsLines.join("\n")
363804
+ };
363805
+ }
363806
+ function reconstructFromGhostPatch(fileDiff, ours) {
363807
+ const hunks = parseHunks(fileDiff);
363808
+ if (hunks.length === 0) {
363809
+ return null;
363810
+ }
363811
+ const isPureAddition = hunks.every(
363812
+ (h14) => h14.oldCount === 0 && h14.lines.every((l14) => l14.type !== "remove")
363813
+ );
363814
+ if (isPureAddition) {
363815
+ return null;
363816
+ }
363817
+ const isPureDeletion = hunks.every(
363818
+ (h14) => h14.newCount === 0 && h14.lines.every((l14) => l14.type !== "add")
363819
+ );
363820
+ if (isPureDeletion) {
363821
+ const baseLines = [];
363822
+ for (const hunk of hunks) {
363823
+ for (const line of hunk.lines) {
363824
+ if (line.type === "context" || line.type === "remove") {
363825
+ baseLines.push(line.content);
363826
+ }
363827
+ }
363828
+ }
363829
+ return {
363830
+ base: baseLines.join("\n"),
363831
+ theirs: ""
363832
+ };
363833
+ }
363834
+ const oursLines = ours.split("\n");
363835
+ const located = locateHunksInOurs(hunks, oursLines);
363836
+ if (!located) {
363837
+ return null;
363838
+ }
363839
+ return assembleHybrid(located, oursLines);
363840
+ }
363841
+ var init_HybridReconstruction = __esm3({
363842
+ "src/HybridReconstruction.ts"() {
363843
+ "use strict";
363844
+ }
363845
+ });
363591
363846
  var index_exports = {};
363592
363847
  __export4(index_exports, {
363593
363848
  FERN_BOT_EMAIL: () => FERN_BOT_EMAIL,
@@ -363631,7 +363886,7 @@ var require_dist11 = __commonJS({
363631
363886
  return commit.message.startsWith("[fern-replay]");
363632
363887
  }
363633
363888
  function isRevertCommit(message) {
363634
- return message.startsWith('Revert "');
363889
+ return /^Revert ".+"$/.test(message);
363635
363890
  }
363636
363891
  function parseRevertedSha(fullBody) {
363637
363892
  const match3 = fullBody.match(/This reverts commit ([0-9a-f]{40})\./);
@@ -363730,6 +363985,15 @@ var require_dist11 = __commonJS({
363730
363985
  this.ensureLoaded();
363731
363986
  this.lock.patches = [];
363732
363987
  }
363988
+ addForgottenHash(hash5) {
363989
+ this.ensureLoaded();
363990
+ if (!this.lock.forgotten_hashes) {
363991
+ this.lock.forgotten_hashes = [];
363992
+ }
363993
+ if (!this.lock.forgotten_hashes.includes(hash5)) {
363994
+ this.lock.forgotten_hashes.push(hash5);
363995
+ }
363996
+ }
363733
363997
  getUnresolvedPatches() {
363734
363998
  this.ensureLoaded();
363735
363999
  return this.lock.patches.filter((p10) => p10.status === "unresolved");
@@ -363824,6 +364088,7 @@ var require_dist11 = __commonJS({
363824
364088
  }
363825
364089
  const commits = this.parseGitLog(log4);
363826
364090
  const newPatches = [];
364091
+ const forgottenHashes = new Set(lock.forgotten_hashes ?? []);
363827
364092
  for (const commit of commits) {
363828
364093
  if (isGenerationCommit(commit)) {
363829
364094
  continue;
@@ -363837,7 +364102,7 @@ var require_dist11 = __commonJS({
363837
364102
  }
363838
364103
  const patchContent = await this.git.formatPatch(commit.sha);
363839
364104
  const contentHash = this.computeContentHash(patchContent);
363840
- if (lock.patches.find((p10) => p10.content_hash === contentHash)) {
364105
+ if (lock.patches.find((p10) => p10.content_hash === contentHash) || forgottenHashes.has(contentHash)) {
363841
364106
  continue;
363842
364107
  }
363843
364108
  const filesOutput = await this.git.exec(["diff-tree", "--no-commit-id", "--name-only", "-r", commit.sha]);
@@ -363907,6 +364172,9 @@ var require_dist11 = __commonJS({
363907
364172
  revertIndicesToRemove.add(idx);
363908
364173
  }
363909
364174
  }
364175
+ if (!matchedExisting && !matchedNew) {
364176
+ revertIndicesToRemove.add(i11);
364177
+ }
363910
364178
  }
363911
364179
  const filteredPatches = newPatches.filter((_16, i11) => !revertIndicesToRemove.has(i11));
363912
364180
  return { patches: filteredPatches, revertedPatchIds: [...revertedPatchIdSet] };
@@ -363933,7 +364201,7 @@ var require_dist11 = __commonJS({
363933
364201
  if (!diff2.trim()) return { patches: [], revertedPatchIds: [] };
363934
364202
  const contentHash = this.computeContentHash(diff2);
363935
364203
  const lock = this.lockManager.read();
363936
- if (lock.patches.some((p10) => p10.content_hash === contentHash)) {
364204
+ if (lock.patches.some((p10) => p10.content_hash === contentHash) || (lock.forgotten_hashes ?? []).includes(contentHash)) {
363937
364205
  return { patches: [], revertedPatchIds: [] };
363938
364206
  }
363939
364207
  const headSha = (await this.git.exec(["rev-parse", "HEAD"])).trim();
@@ -363999,6 +364267,32 @@ var require_dist11 = __commonJS({
363999
364267
  var import_node_os15 = require("os");
364000
364268
  var import_node_path210 = require("path");
364001
364269
  var import_minimatch8 = require_commonjs3();
364270
+ function stripConflictMarkers(content5) {
364271
+ const lines = content5.split("\n");
364272
+ const result = [];
364273
+ let inConflict = false;
364274
+ let inOurs = false;
364275
+ for (const line of lines) {
364276
+ if (line.startsWith("<<<<<<< ")) {
364277
+ inConflict = true;
364278
+ inOurs = true;
364279
+ continue;
364280
+ }
364281
+ if (inConflict && line === "=======") {
364282
+ inOurs = false;
364283
+ continue;
364284
+ }
364285
+ if (inConflict && line.startsWith(">>>>>>> ")) {
364286
+ inConflict = false;
364287
+ inOurs = false;
364288
+ continue;
364289
+ }
364290
+ if (!inConflict || inOurs) {
364291
+ result.push(line);
364292
+ }
364293
+ }
364294
+ return result.join("\n");
364295
+ }
364002
364296
  var BINARY_EXTENSIONS2 = /* @__PURE__ */ new Set([
364003
364297
  ".png",
364004
364298
  ".jpg",
@@ -364053,6 +364347,7 @@ var require_dist11 = __commonJS({
364053
364347
  lockManager;
364054
364348
  outputDir;
364055
364349
  renameCache = /* @__PURE__ */ new Map();
364350
+ treeExistsCache = /* @__PURE__ */ new Map();
364056
364351
  fileTheirsAccumulator = /* @__PURE__ */ new Map();
364057
364352
  constructor(git, lockManager, outputDir) {
364058
364353
  this.git = git;
@@ -364070,7 +364365,8 @@ var require_dist11 = __commonJS({
364070
364365
  async applyPatches(patches) {
364071
364366
  this.resetAccumulator();
364072
364367
  const results = [];
364073
- for (const patch5 of patches) {
364368
+ for (let i11 = 0; i11 < patches.length; i11++) {
364369
+ const patch5 = patches[i11];
364074
364370
  if (this.isExcluded(patch5)) {
364075
364371
  results.push({
364076
364372
  patch: patch5,
@@ -364081,6 +364377,33 @@ var require_dist11 = __commonJS({
364081
364377
  }
364082
364378
  const result = await this.applyPatchWithFallback(patch5);
364083
364379
  results.push(result);
364380
+ if (result.status === "conflict" && result.fileResults) {
364381
+ const laterFiles = /* @__PURE__ */ new Set();
364382
+ for (let j16 = i11 + 1; j16 < patches.length; j16++) {
364383
+ for (const f10 of patches[j16].files) {
364384
+ laterFiles.add(f10);
364385
+ }
364386
+ }
364387
+ const resolvedToOriginal = /* @__PURE__ */ new Map();
364388
+ if (result.resolvedFiles) {
364389
+ for (const [orig, resolved] of Object.entries(result.resolvedFiles)) {
364390
+ resolvedToOriginal.set(resolved, orig);
364391
+ }
364392
+ }
364393
+ for (const fileResult of result.fileResults) {
364394
+ if (fileResult.status !== "conflict") continue;
364395
+ const originalPath = resolvedToOriginal.get(fileResult.file) ?? fileResult.file;
364396
+ if (laterFiles.has(fileResult.file) || laterFiles.has(originalPath)) {
364397
+ const filePath = (0, import_node_path210.join)(this.outputDir, fileResult.file);
364398
+ try {
364399
+ const content5 = await (0, import_promises181.readFile)(filePath, "utf-8");
364400
+ const stripped = stripConflictMarkers(content5);
364401
+ await (0, import_promises181.writeFile)(filePath, stripped);
364402
+ } catch {
364403
+ }
364404
+ }
364405
+ }
364406
+ }
364084
364407
  }
364085
364408
  return results;
364086
364409
  }
@@ -364099,7 +364422,7 @@ var require_dist11 = __commonJS({
364099
364422
  const resolvedPath = await this.resolveFilePath(filePath, baseGen.tree_hash, currentTreeHash);
364100
364423
  const base4 = await this.git.showFile(baseGen.tree_hash, filePath);
364101
364424
  const theirs = await this.applyPatchToContent(base4, patch5.patch_content, filePath, tempGit, tempDir2);
364102
- if (theirs && base4) {
364425
+ if (theirs) {
364103
364426
  this.fileTheirsAccumulator.set(resolvedPath, {
364104
364427
  content: theirs,
364105
364428
  baseGeneration: patch5.base_generation
@@ -364221,17 +364544,36 @@ var require_dist11 = __commonJS({
364221
364544
  }
364222
364545
  const oursPath = (0, import_node_path210.join)(this.outputDir, resolvedPath);
364223
364546
  const ours = await (0, import_promises181.readFile)(oursPath, "utf-8").catch(() => null);
364224
- let theirs = await this.applyPatchToContent(
364225
- base4,
364226
- patch5.patch_content,
364227
- filePath,
364228
- tempGit,
364229
- tempDir2,
364230
- renameSourcePath
364231
- );
364547
+ let ghostReconstructed = false;
364548
+ let theirs = null;
364549
+ if (!base4 && ours && !renameSourcePath) {
364550
+ const treeReachable = await this.isTreeReachable(baseGen.tree_hash);
364551
+ if (!treeReachable) {
364552
+ const fileDiff = this.extractFileDiff(patch5.patch_content, filePath);
364553
+ if (fileDiff) {
364554
+ const { reconstructFromGhostPatch: reconstructFromGhostPatch2 } = await Promise.resolve().then(() => (init_HybridReconstruction(), HybridReconstruction_exports));
364555
+ const result = reconstructFromGhostPatch2(fileDiff, ours);
364556
+ if (result) {
364557
+ base4 = result.base;
364558
+ theirs = result.theirs;
364559
+ ghostReconstructed = true;
364560
+ }
364561
+ }
364562
+ }
364563
+ }
364564
+ if (!ghostReconstructed) {
364565
+ theirs = await this.applyPatchToContent(
364566
+ base4,
364567
+ patch5.patch_content,
364568
+ filePath,
364569
+ tempGit,
364570
+ tempDir2,
364571
+ renameSourcePath
364572
+ );
364573
+ }
364232
364574
  let useAccumulatorAsMergeBase = false;
364233
364575
  const accumulatorEntry = this.fileTheirsAccumulator.get(resolvedPath);
364234
- if (!theirs && base4 && accumulatorEntry) {
364576
+ if (!theirs && accumulatorEntry) {
364235
364577
  theirs = await this.applyPatchToContent(
364236
364578
  accumulatorEntry.content,
364237
364579
  patch5.patch_content,
@@ -364261,13 +364603,13 @@ var require_dist11 = __commonJS({
364261
364603
  baseMismatchSkipped = true;
364262
364604
  }
364263
364605
  }
364264
- if (!base4 && !ours && effective_theirs) {
364606
+ if (base4 == null && !ours && effective_theirs) {
364265
364607
  const outDir2 = (0, import_node_path210.dirname)(oursPath);
364266
364608
  await (0, import_promises181.mkdir)(outDir2, { recursive: true });
364267
364609
  await (0, import_promises181.writeFile)(oursPath, effective_theirs);
364268
364610
  return { file: resolvedPath, status: "merged", reason: "new-file" };
364269
364611
  }
364270
- if (!base4 && ours && effective_theirs) {
364612
+ if (base4 == null && ours && effective_theirs) {
364271
364613
  const merged2 = threeWayMerge("", ours, effective_theirs);
364272
364614
  const outDir2 = (0, import_node_path210.dirname)(oursPath);
364273
364615
  await (0, import_promises181.mkdir)(outDir2, { recursive: true });
@@ -364290,7 +364632,7 @@ var require_dist11 = __commonJS({
364290
364632
  reason: "missing-content"
364291
364633
  };
364292
364634
  }
364293
- if (!base4 || !ours) {
364635
+ if (base4 == null && !useAccumulatorAsMergeBase || !ours) {
364294
364636
  return {
364295
364637
  file: resolvedPath,
364296
364638
  status: "skipped",
@@ -364298,11 +364640,18 @@ var require_dist11 = __commonJS({
364298
364640
  };
364299
364641
  }
364300
364642
  const mergeBase = useAccumulatorAsMergeBase && accumulatorEntry ? accumulatorEntry.content : base4;
364643
+ if (mergeBase == null) {
364644
+ return {
364645
+ file: resolvedPath,
364646
+ status: "skipped",
364647
+ reason: "missing-content"
364648
+ };
364649
+ }
364301
364650
  const merged = threeWayMerge(mergeBase, ours, effective_theirs);
364302
364651
  const outDir = (0, import_node_path210.dirname)(oursPath);
364303
364652
  await (0, import_promises181.mkdir)(outDir, { recursive: true });
364304
364653
  await (0, import_promises181.writeFile)(oursPath, merged.content);
364305
- if (effective_theirs && base4) {
364654
+ if (effective_theirs) {
364306
364655
  this.fileTheirsAccumulator.set(resolvedPath, {
364307
364656
  content: effective_theirs,
364308
364657
  baseGeneration: patch5.base_generation
@@ -364326,6 +364675,14 @@ var require_dist11 = __commonJS({
364326
364675
  };
364327
364676
  }
364328
364677
  }
364678
+ async isTreeReachable(treeHash) {
364679
+ let result = this.treeExistsCache.get(treeHash);
364680
+ if (result === void 0) {
364681
+ result = await this.git.treeExists(treeHash);
364682
+ this.treeExistsCache.set(treeHash, result);
364683
+ }
364684
+ return result;
364685
+ }
364329
364686
  isExcluded(patch5) {
364330
364687
  const config5 = this.lockManager.getCustomizationsConfig();
364331
364688
  if (!config5.exclude) return false;
@@ -364541,32 +364898,6 @@ CLI Version: ${options2.cliVersion}`;
364541
364898
  var import_node_path310 = require("path");
364542
364899
  var import_minimatch22 = require_commonjs3();
364543
364900
  init_GitClient();
364544
- function stripConflictMarkers(content5) {
364545
- const lines = content5.split("\n");
364546
- const result = [];
364547
- let inConflict = false;
364548
- let inOurs = false;
364549
- for (const line of lines) {
364550
- if (line.startsWith("<<<<<<< ")) {
364551
- inConflict = true;
364552
- inOurs = true;
364553
- continue;
364554
- }
364555
- if (inConflict && line === "=======") {
364556
- inOurs = false;
364557
- continue;
364558
- }
364559
- if (inConflict && line.startsWith(">>>>>>> ")) {
364560
- inConflict = false;
364561
- inOurs = false;
364562
- continue;
364563
- }
364564
- if (!inConflict || inOurs) {
364565
- result.push(line);
364566
- }
364567
- }
364568
- return result.join("\n");
364569
- }
364570
364901
  var ReplayService = class {
364571
364902
  git;
364572
364903
  detector;
@@ -365418,6 +365749,7 @@ CLI Version: ${options2.cliVersion}`;
365418
365749
  }
365419
365750
  lockManager.save();
365420
365751
  const fernignoreUpdated = ensureFernignoreEntries(outputDir);
365752
+ ensureGitattributesEntries(outputDir);
365421
365753
  if (migrator.fernignoreExists() && fernignorePatterns.length > 0) {
365422
365754
  const action = options2?.fernignoreAction ?? "skip";
365423
365755
  if (action === "migrate") {
@@ -365499,7 +365831,7 @@ CLI Version: ${options2.cliVersion}`;
365499
365831
  return { sha, authorName, authorEmail, message };
365500
365832
  });
365501
365833
  }
365502
- var REPLAY_FERNIGNORE_ENTRIES = [".fern/replay.lock", ".fern/replay.yml"];
365834
+ var REPLAY_FERNIGNORE_ENTRIES = [".fern/replay.lock", ".fern/replay.yml", ".gitattributes"];
365503
365835
  function ensureFernignoreEntries(outputDir) {
365504
365836
  const fernignorePath = (0, import_node_path52.join)(outputDir, ".fernignore");
365505
365837
  let content5 = "";
@@ -365523,35 +365855,173 @@ CLI Version: ${options2.cliVersion}`;
365523
365855
  (0, import_node_fs42.writeFileSync)(fernignorePath, content5, "utf-8");
365524
365856
  return true;
365525
365857
  }
365858
+ var GITATTRIBUTES_ENTRIES = [".fern/replay.lock linguist-generated=true"];
365859
+ function ensureGitattributesEntries(outputDir) {
365860
+ const gitattributesPath = (0, import_node_path52.join)(outputDir, ".gitattributes");
365861
+ let content5 = "";
365862
+ if ((0, import_node_fs42.existsSync)(gitattributesPath)) {
365863
+ content5 = (0, import_node_fs42.readFileSync)(gitattributesPath, "utf-8");
365864
+ }
365865
+ const lines = content5.split("\n");
365866
+ const toAdd = [];
365867
+ for (const entry of GITATTRIBUTES_ENTRIES) {
365868
+ if (!lines.some((line) => line.trim() === entry)) {
365869
+ toAdd.push(entry);
365870
+ }
365871
+ }
365872
+ if (toAdd.length === 0) {
365873
+ return;
365874
+ }
365875
+ if (content5 && !content5.endsWith("\n")) {
365876
+ content5 += "\n";
365877
+ }
365878
+ content5 += toAdd.join("\n") + "\n";
365879
+ (0, import_node_fs42.writeFileSync)(gitattributesPath, content5, "utf-8");
365880
+ }
365526
365881
  function computeContentHash(patchContent) {
365527
365882
  const normalized = patchContent.split("\n").filter((line) => !line.startsWith("From ") && !line.startsWith("index ") && !line.startsWith("Date: ")).join("\n");
365528
365883
  return `sha256:${(0, import_node_crypto32.createHash)("sha256").update(normalized).digest("hex")}`;
365529
365884
  }
365530
365885
  var import_minimatch42 = require_commonjs3();
365531
- function forget(outputDir, filePattern, options2) {
365886
+ function parseDiffStat(patchContent) {
365887
+ let additions = 0;
365888
+ let deletions = 0;
365889
+ let inDiffHunk = false;
365890
+ for (const line of patchContent.split("\n")) {
365891
+ if (line.startsWith("diff --git ")) {
365892
+ inDiffHunk = true;
365893
+ continue;
365894
+ }
365895
+ if (!inDiffHunk) continue;
365896
+ if (line.startsWith("+") && !line.startsWith("+++")) {
365897
+ additions++;
365898
+ } else if (line.startsWith("-") && !line.startsWith("---")) {
365899
+ deletions++;
365900
+ }
365901
+ }
365902
+ return { additions, deletions };
365903
+ }
365904
+ function toMatchedPatch(patch5) {
365905
+ return {
365906
+ id: patch5.id,
365907
+ message: patch5.original_message,
365908
+ files: patch5.files,
365909
+ diffstat: parseDiffStat(patch5.patch_content),
365910
+ ...patch5.status ? { status: patch5.status } : {}
365911
+ };
365912
+ }
365913
+ function matchesPatch(patch5, pattern) {
365914
+ const fileMatch = patch5.files.some(
365915
+ (file4) => file4 === pattern || (0, import_minimatch42.minimatch)(file4, pattern)
365916
+ );
365917
+ if (fileMatch) return true;
365918
+ return patch5.original_message.toLowerCase().includes(pattern.toLowerCase());
365919
+ }
365920
+ function buildWarnings(patches) {
365921
+ const warnings = [];
365922
+ for (const patch5 of patches) {
365923
+ if (patch5.status === "resolving") {
365924
+ warnings.push(
365925
+ `patch ${patch5.id} has conflict markers in these files: ${patch5.files.join(", ")}. Run \`git checkout -- <files>\` to restore the generated versions.`
365926
+ );
365927
+ } else if (patch5.status === "unresolved") {
365928
+ warnings.push(
365929
+ `patch ${patch5.id} had unresolved conflicts (files: ${patch5.files.join(", ")}).`
365930
+ );
365931
+ }
365932
+ }
365933
+ return warnings;
365934
+ }
365935
+ var EMPTY_RESULT = {
365936
+ initialized: false,
365937
+ removed: [],
365938
+ remaining: 0,
365939
+ notFound: false,
365940
+ alreadyForgotten: [],
365941
+ totalPatches: 0,
365942
+ warnings: []
365943
+ };
365944
+ function forget(outputDir, options2) {
365532
365945
  const lockManager = new LockfileManager(outputDir);
365533
365946
  if (!lockManager.exists()) {
365534
- return { removed: [], notFound: true };
365947
+ return { ...EMPTY_RESULT };
365535
365948
  }
365536
365949
  const lock = lockManager.read();
365537
- const matchingPatches = lock.patches.filter(
365538
- (patch5) => patch5.files.some((file4) => file4 === filePattern || (0, import_minimatch42.minimatch)(file4, filePattern))
365539
- );
365540
- if (matchingPatches.length === 0) {
365541
- return { removed: [], notFound: true };
365950
+ const totalPatches = lock.patches.length;
365951
+ if (options2?.all) {
365952
+ const removed = lock.patches.map(toMatchedPatch);
365953
+ const warnings = buildWarnings(lock.patches);
365954
+ if (!options2.dryRun) {
365955
+ for (const patch5 of lock.patches) {
365956
+ lockManager.addForgottenHash(patch5.content_hash);
365957
+ }
365958
+ lockManager.clearPatches();
365959
+ lockManager.save();
365960
+ }
365961
+ return {
365962
+ initialized: true,
365963
+ removed,
365964
+ remaining: 0,
365965
+ notFound: false,
365966
+ alreadyForgotten: [],
365967
+ totalPatches,
365968
+ warnings
365969
+ };
365542
365970
  }
365543
- const removed = matchingPatches.map((p10) => ({
365544
- id: p10.id,
365545
- message: p10.original_message,
365546
- files: p10.files
365547
- }));
365548
- if (!options2?.dryRun) {
365549
- for (const patch5 of matchingPatches) {
365550
- lockManager.removePatch(patch5.id);
365971
+ if (options2?.patchIds && options2.patchIds.length > 0) {
365972
+ const removed = [];
365973
+ const alreadyForgotten = [];
365974
+ const patchesToRemove = [];
365975
+ for (const id2 of options2.patchIds) {
365976
+ const patch5 = lock.patches.find((p10) => p10.id === id2);
365977
+ if (patch5) {
365978
+ removed.push(toMatchedPatch(patch5));
365979
+ patchesToRemove.push(patch5);
365980
+ } else {
365981
+ alreadyForgotten.push(id2);
365982
+ }
365551
365983
  }
365552
- lockManager.save();
365984
+ const warnings = buildWarnings(patchesToRemove);
365985
+ if (!options2.dryRun) {
365986
+ for (const patch5 of patchesToRemove) {
365987
+ lockManager.addForgottenHash(patch5.content_hash);
365988
+ lockManager.removePatch(patch5.id);
365989
+ }
365990
+ lockManager.save();
365991
+ }
365992
+ return {
365993
+ initialized: true,
365994
+ removed,
365995
+ remaining: totalPatches - removed.length,
365996
+ notFound: removed.length === 0 && alreadyForgotten.length > 0,
365997
+ alreadyForgotten,
365998
+ totalPatches,
365999
+ warnings
366000
+ };
366001
+ }
366002
+ if (options2?.pattern) {
366003
+ const matched = lock.patches.filter((p10) => matchesPatch(p10, options2.pattern)).map(toMatchedPatch);
366004
+ return {
366005
+ initialized: true,
366006
+ removed: [],
366007
+ remaining: totalPatches,
366008
+ notFound: matched.length === 0,
366009
+ alreadyForgotten: [],
366010
+ totalPatches,
366011
+ warnings: [],
366012
+ matched
366013
+ };
365553
366014
  }
365554
- return { removed, notFound: false };
366015
+ return {
366016
+ initialized: true,
366017
+ removed: [],
366018
+ remaining: totalPatches,
366019
+ notFound: totalPatches === 0,
366020
+ alreadyForgotten: [],
366021
+ totalPatches,
366022
+ warnings: [],
366023
+ matched: lock.patches.map(toMatchedPatch)
366024
+ };
365555
366025
  }
365556
366026
  var import_node_fs52 = require("fs");
365557
366027
  function reset2(outputDir, options2) {
@@ -365667,24 +366137,49 @@ CLI Version: ${options2.cliVersion}`;
365667
366137
  function status(outputDir) {
365668
366138
  const lockManager = new LockfileManager(outputDir);
365669
366139
  if (!lockManager.exists()) {
365670
- return { initialized: false, patches: [], lastGeneration: void 0 };
366140
+ return {
366141
+ initialized: false,
366142
+ generationCount: 0,
366143
+ lastGeneration: void 0,
366144
+ patches: [],
366145
+ unresolvedCount: 0,
366146
+ excludePatterns: []
366147
+ };
365671
366148
  }
365672
366149
  const lock = lockManager.read();
365673
366150
  const patches = lock.patches.map((patch5) => ({
365674
- sha: patch5.original_commit.slice(0, 7),
365675
- author: patch5.original_author.split("<")[0]?.trim() ?? "unknown",
366151
+ id: patch5.id,
366152
+ type: patch5.patch_content.includes("new file mode") ? "added" : "modified",
365676
366153
  message: patch5.original_message,
365677
- files: patch5.files
366154
+ author: patch5.original_author.split("<")[0]?.trim() || "unknown",
366155
+ sha: patch5.original_commit.slice(0, 7),
366156
+ files: patch5.files,
366157
+ fileCount: patch5.files.length,
366158
+ ...patch5.status ? { status: patch5.status } : {}
365678
366159
  }));
366160
+ const unresolvedCount = lock.patches.filter(
366161
+ (p10) => p10.status === "unresolved" || p10.status === "resolving"
366162
+ ).length;
365679
366163
  let lastGeneration;
365680
366164
  const lastGen = lock.generations.find((g19) => g19.commit_sha === lock.current_generation);
365681
366165
  if (lastGen) {
365682
366166
  lastGeneration = {
365683
- sha: lastGen.commit_sha,
365684
- timestamp: lastGen.timestamp
366167
+ sha: lastGen.commit_sha.slice(0, 7),
366168
+ timestamp: lastGen.timestamp,
366169
+ cliVersion: lastGen.cli_version,
366170
+ generatorVersions: lastGen.generator_versions
365685
366171
  };
365686
366172
  }
365687
- return { initialized: true, patches, lastGeneration };
366173
+ const config5 = lockManager.getCustomizationsConfig();
366174
+ const excludePatterns = config5.exclude ?? [];
366175
+ return {
366176
+ initialized: true,
366177
+ generationCount: lock.generations.length,
366178
+ lastGeneration,
366179
+ patches,
366180
+ unresolvedCount,
366181
+ excludePatterns
366182
+ };
365688
366183
  }
365689
366184
  }
365690
366185
  });
@@ -366044,6 +366539,19 @@ var require_pipeline2 = __commonJS({
366044
366539
  }
366045
366540
  });
366046
366541
 
366542
+ // ../../generator-cli/lib/replay/replay-forget.js
366543
+ var require_replay_forget = __commonJS({
366544
+ "../../generator-cli/lib/replay/replay-forget.js"(exports2) {
366545
+ "use strict";
366546
+ Object.defineProperty(exports2, "__esModule", { value: true });
366547
+ exports2.replayForget = replayForget2;
366548
+ var replay_1 = require_dist11();
366549
+ function replayForget2(params2) {
366550
+ return (0, replay_1.forget)(params2.outputDir, params2.options);
366551
+ }
366552
+ }
366553
+ });
366554
+
366047
366555
  // ../../generator-cli/lib/replay/replay-init.js
366048
366556
  var require_replay_init = __commonJS({
366049
366557
  "../../generator-cli/lib/replay/replay-init.js"(exports2) {
@@ -366208,12 +366716,25 @@ var require_replay_resolve = __commonJS({
366208
366716
  }
366209
366717
  });
366210
366718
 
366719
+ // ../../generator-cli/lib/replay/replay-status.js
366720
+ var require_replay_status = __commonJS({
366721
+ "../../generator-cli/lib/replay/replay-status.js"(exports2) {
366722
+ "use strict";
366723
+ Object.defineProperty(exports2, "__esModule", { value: true });
366724
+ exports2.replayStatus = replayStatus2;
366725
+ var replay_1 = require_dist11();
366726
+ function replayStatus2(params2) {
366727
+ return (0, replay_1.status)(params2.outputDir);
366728
+ }
366729
+ }
366730
+ });
366731
+
366211
366732
  // ../../generator-cli/lib/api.js
366212
366733
  var require_api5 = __commonJS({
366213
366734
  "../../generator-cli/lib/api.js"(exports2) {
366214
366735
  "use strict";
366215
366736
  Object.defineProperty(exports2, "__esModule", { value: true });
366216
- exports2.replayRun = exports2.replayResolve = exports2.replayInit = exports2.formatBootstrapSummary = exports2.PostGenerationPipeline = exports2.logReplaySummary = exports2.formatReplayPrBody = exports2.consolePipelineLogger = exports2.githubRelease = exports2.githubPush = exports2.githubPr = exports2.generateReferenceToStream = exports2.generateReference = exports2.generateReadmeToStream = exports2.generateReadme = void 0;
366737
+ exports2.replayStatus = exports2.replayRun = exports2.replayResolve = exports2.replayInit = exports2.formatBootstrapSummary = exports2.replayForget = exports2.PostGenerationPipeline = exports2.logReplaySummary = exports2.formatReplayPrBody = exports2.consolePipelineLogger = exports2.githubRelease = exports2.githubPush = exports2.githubPr = exports2.generateReferenceToStream = exports2.generateReference = exports2.generateReadmeToStream = exports2.generateReadme = void 0;
366217
366738
  var generate_readme_js_1 = require_generate_readme();
366218
366739
  Object.defineProperty(exports2, "generateReadme", { enumerable: true, get: function() {
366219
366740
  return generate_readme_js_1.generateReadme;
@@ -366253,6 +366774,10 @@ var require_api5 = __commonJS({
366253
366774
  Object.defineProperty(exports2, "PostGenerationPipeline", { enumerable: true, get: function() {
366254
366775
  return index_js_1.PostGenerationPipeline;
366255
366776
  } });
366777
+ var replay_forget_js_1 = require_replay_forget();
366778
+ Object.defineProperty(exports2, "replayForget", { enumerable: true, get: function() {
366779
+ return replay_forget_js_1.replayForget;
366780
+ } });
366256
366781
  var replay_init_js_1 = require_replay_init();
366257
366782
  Object.defineProperty(exports2, "formatBootstrapSummary", { enumerable: true, get: function() {
366258
366783
  return replay_init_js_1.formatBootstrapSummary;
@@ -366268,6 +366793,10 @@ var require_api5 = __commonJS({
366268
366793
  Object.defineProperty(exports2, "replayRun", { enumerable: true, get: function() {
366269
366794
  return replay_run_js_1.replayRun;
366270
366795
  } });
366796
+ var replay_status_js_1 = require_replay_status();
366797
+ Object.defineProperty(exports2, "replayStatus", { enumerable: true, get: function() {
366798
+ return replay_status_js_1.replayStatus;
366799
+ } });
366271
366800
  }
366272
366801
  });
366273
366802
 
@@ -588535,7 +589064,7 @@ var RequestBodyConverter = class extends converters_exports.AbstractConverters.A
588535
589064
  contentType
588536
589065
  });
588537
589066
  if (convertedSchema == null) {
588538
- return void 0;
589067
+ return this.handleSchemalessJsonContent({ contentType, mediaTypeObject });
588539
589068
  }
588540
589069
  const requestBodyTypeShape = convertedSchema.schema?.typeDeclaration.shape;
588541
589070
  if (requestBodyTypeShape?.type === "object") {
@@ -588591,6 +589120,55 @@ var RequestBodyConverter = class extends converters_exports.AbstractConverters.A
588591
589120
  };
588592
589121
  }
588593
589122
  }
589123
+ /**
589124
+ * Handles JSON request bodies that have no schema but DO have native OpenAPI
589125
+ * examples. Creates an unknown-typed reference request body so that examples
589126
+ * are preserved for docs rendering and code snippet generation.
589127
+ */
589128
+ handleSchemalessJsonContent({ contentType, mediaTypeObject }) {
589129
+ const hasExamples = mediaTypeObject.example != null || mediaTypeObject.examples != null && Object.keys(mediaTypeObject.examples).length > 0;
589130
+ if (!hasExamples) {
589131
+ return void 0;
589132
+ }
589133
+ const v2Examples = {
589134
+ userSpecifiedExamples: {},
589135
+ autogeneratedExamples: {}
589136
+ };
589137
+ const examples = this.context.getNamedExamplesFromMediaTypeObject({
589138
+ mediaTypeObject,
589139
+ breadcrumbs: this.breadcrumbs,
589140
+ defaultExampleName: `${[...this.group, this.method].join("_")}_example`
589141
+ });
589142
+ const usedExampleNames = /* @__PURE__ */ new Set();
589143
+ for (const [key2, example] of examples) {
589144
+ const resolvedExample = this.context.resolveExampleWithValue(example);
589145
+ const resolvedExampleObject = this.context.resolveExampleRecursively({
589146
+ example,
589147
+ breadcrumbs: this.breadcrumbs
589148
+ });
589149
+ let exampleName = key2;
589150
+ if (this.context.isExampleWithSummary(resolvedExampleObject)) {
589151
+ const summary = resolvedExampleObject.summary;
589152
+ if (!usedExampleNames.has(summary)) {
589153
+ exampleName = summary;
589154
+ }
589155
+ }
589156
+ usedExampleNames.add(exampleName);
589157
+ if (resolvedExample != null) {
589158
+ v2Examples.userSpecifiedExamples[exampleName] = resolvedExample;
589159
+ }
589160
+ }
589161
+ return {
589162
+ requestBody: HttpRequestBody.reference({
589163
+ contentType,
589164
+ docs: this.description,
589165
+ requestBodyType: TypeReference2.unknown(),
589166
+ v2Examples
589167
+ }),
589168
+ streamRequestBody: void 0,
589169
+ inlinedTypes: {}
589170
+ };
589171
+ }
588594
589172
  handleMultipartContent({ contentType }) {
588595
589173
  const mediaTypeObject = this.mediaType;
588596
589174
  if (mediaTypeObject == null || mediaTypeObject.schema == null) {
@@ -590440,6 +591018,18 @@ var OperationConverter = class _OperationConverter extends AbstractOperationConv
590440
591018
  httpMethod,
590441
591019
  baseUrl
590442
591020
  });
591021
+ if (Object.keys(fernExamples.examples).length === 0 && Object.keys(fernExamples.streamExamples).length === 0) {
591022
+ const nativeExamples = this.synthesizeEndpointExamplesFromNativeRequestBody({
591023
+ httpPath: path97,
591024
+ httpMethod,
591025
+ baseUrl
591026
+ });
591027
+ if (nativeExamples != null) {
591028
+ for (const [name2, example] of Object.entries(nativeExamples)) {
591029
+ fernExamples.examples[name2] = example;
591030
+ }
591031
+ }
591032
+ }
590443
591033
  const endpointLevelSecuritySchemes = new Set(this.operation.security?.flatMap((securityRequirement) => Object.keys(securityRequirement)) ?? []);
590444
591034
  const securityHeaders = this.authSchemeToHeaders(Array.from(endpointLevelSecuritySchemes));
590445
591035
  if (securityHeaders.length > 0) {
@@ -590876,6 +591466,107 @@ var OperationConverter = class _OperationConverter extends AbstractOperationConv
590876
591466
  streamExamples: {}
590877
591467
  };
590878
591468
  }
591469
+ /**
591470
+ * Synthesizes endpoint-level v2Examples from native OpenAPI request body
591471
+ * examples (mediaType.example / mediaType.examples) when no x-fern-examples
591472
+ * or x-code-samples extensions are present.
591473
+ *
591474
+ * This ensures that specs like Close's, which have native examples on
591475
+ * schemaless request bodies, get rendered in docs and code snippets.
591476
+ *
591477
+ * Also extracts native response examples from the operation's successful (2xx)
591478
+ * responses so that the 200 response panel is preserved in docs.
591479
+ */
591480
+ synthesizeEndpointExamplesFromNativeRequestBody({ httpPath, httpMethod, baseUrl }) {
591481
+ if (this.operation.requestBody == null) {
591482
+ return void 0;
591483
+ }
591484
+ const resolvedRequestBody = this.context.resolveMaybeReference({
591485
+ schemaOrReference: this.operation.requestBody,
591486
+ breadcrumbs: [...this.breadcrumbs, "requestBody"]
591487
+ });
591488
+ if (resolvedRequestBody == null) {
591489
+ return void 0;
591490
+ }
591491
+ const responseExample = this.extractNativeResponseExample();
591492
+ const result = {};
591493
+ for (const [, mediaType] of Object.entries(resolvedRequestBody.content)) {
591494
+ if (mediaType.schema != null) {
591495
+ continue;
591496
+ }
591497
+ const namedExamples = this.context.getNamedExamplesFromMediaTypeObject({
591498
+ mediaTypeObject: mediaType,
591499
+ breadcrumbs: [...this.breadcrumbs, "requestBody"],
591500
+ defaultExampleName: "Example"
591501
+ });
591502
+ for (const [name2, example] of namedExamples) {
591503
+ const resolvedValue = this.context.resolveExampleWithValue(example);
591504
+ if (resolvedValue != null) {
591505
+ result[name2] = {
591506
+ displayName: void 0,
591507
+ request: {
591508
+ docs: void 0,
591509
+ endpoint: {
591510
+ method: httpMethod,
591511
+ path: this.buildExamplePath(httpPath, {})
591512
+ },
591513
+ baseUrl: void 0,
591514
+ environment: baseUrl,
591515
+ auth: void 0,
591516
+ pathParameters: {},
591517
+ queryParameters: {},
591518
+ headers: {},
591519
+ requestBody: resolvedValue
591520
+ },
591521
+ response: responseExample,
591522
+ codeSamples: void 0
591523
+ };
591524
+ }
591525
+ }
591526
+ }
591527
+ return Object.keys(result).length > 0 ? result : void 0;
591528
+ }
591529
+ /**
591530
+ * Extracts the first native example from the operation's successful (2xx) response.
591531
+ * This is used to populate the response body in synthesized endpoint examples
591532
+ * so that the 200 response panel is preserved in docs.
591533
+ */
591534
+ extractNativeResponseExample() {
591535
+ if (this.operation.responses == null) {
591536
+ return void 0;
591537
+ }
591538
+ for (const [statusCode, response] of Object.entries(this.operation.responses)) {
591539
+ const statusCodeNum = parseInt(statusCode);
591540
+ if (isNaN(statusCodeNum) || statusCodeNum < 200 || statusCodeNum >= 300) {
591541
+ continue;
591542
+ }
591543
+ const resolvedResponse = this.context.resolveMaybeReference({
591544
+ schemaOrReference: response,
591545
+ breadcrumbs: [...this.breadcrumbs, "responses", statusCode]
591546
+ });
591547
+ if (resolvedResponse?.content == null) {
591548
+ continue;
591549
+ }
591550
+ for (const [, responseMediaType] of Object.entries(resolvedResponse.content)) {
591551
+ const namedExamples = this.context.getNamedExamplesFromMediaTypeObject({
591552
+ mediaTypeObject: responseMediaType,
591553
+ breadcrumbs: [...this.breadcrumbs, "responses", statusCode],
591554
+ defaultExampleName: "Example"
591555
+ });
591556
+ for (const [, example] of namedExamples) {
591557
+ const resolvedValue = this.context.resolveExampleWithValue(example);
591558
+ if (resolvedValue != null) {
591559
+ return {
591560
+ docs: void 0,
591561
+ statusCode: statusCodeNum,
591562
+ body: api_exports.V2HttpEndpointResponseBody.json(resolvedValue)
591563
+ };
591564
+ }
591565
+ }
591566
+ }
591567
+ }
591568
+ return void 0;
591569
+ }
590879
591570
  convertStreamConditionExamples({ httpPath, httpMethod, baseUrl, fernExamples }) {
590880
591571
  const filteredJsonExamples = fernExamples.filter((example) => !(example.response != null && "stream" in example.response));
590881
591572
  const filteredStreamExamples = fernExamples.filter((example) => example.response != null && "stream" in example.response);
@@ -602754,7 +603445,7 @@ var AccessTokenPosthogManager = class {
602754
603445
  properties: {
602755
603446
  ...event,
602756
603447
  ...event.properties,
602757
- version: "4.62.3-2-g207f4f8f41a",
603448
+ version: "4.62.3-22-ga624085d56a",
602758
603449
  usingAccessToken: true
602759
603450
  }
602760
603451
  });
@@ -602805,7 +603496,7 @@ var UserPosthogManager = class {
602805
603496
  distinctId: this.userId ?? await this.getPersistedDistinctId(),
602806
603497
  event: "CLI",
602807
603498
  properties: {
602808
- version: "4.62.3-2-g207f4f8f41a",
603499
+ version: "4.62.3-22-ga624085d56a",
602809
603500
  ...event,
602810
603501
  ...event.properties,
602811
603502
  usingAccessToken: false,
@@ -622192,7 +622883,7 @@ function getClientOptions(options2, getDefaultIntegrationsImpl) {
622192
622883
  const tracesSampleRate = getTracesSampleRate(options2.tracesSampleRate);
622193
622884
  const mergedOptions = {
622194
622885
  ...options2,
622195
- dsn: options2.dsn ?? "https://84f58b5e457f06999d92f11ce4b79158@o4509504076185600.ingest.us.sentry.io/4511021546602496",
622886
+ dsn: options2.dsn ?? "",
622196
622887
  environment: options2.environment ?? "development",
622197
622888
  sendClientReports: options2.sendClientReports ?? true,
622198
622889
  transport: options2.transport ?? makeNodeTransport,
@@ -626786,7 +627477,7 @@ var TelemetryClient = class {
626786
627477
  usingAccessToken: process.env.FERN_TOKEN != null
626787
627478
  };
626788
627479
  this.posthog = apiKey != null && apiKey.length > 0 && isTelemetryEnabled ? new PostHog(apiKey) : void 0;
626789
- const sentryDsn = "https://84f58b5e457f06999d92f11ce4b79158@o4509504076185600.ingest.us.sentry.io/4511021546602496";
627480
+ const sentryDsn = "";
626790
627481
  if (sentryDsn != null && sentryDsn.length > 0 && isTelemetryEnabled) {
626791
627482
  const sentryEnvironment = "development";
626792
627483
  if (sentryEnvironment == null || sentryEnvironment.length === 0) {
@@ -752793,7 +753484,7 @@ var V66_TO_V65_MIGRATION = {
752793
753484
  [GeneratorName.JAVA_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR,
752794
753485
  [GeneratorName.JAVA_SPRING]: GeneratorWasNeverUpdatedToConsumeNewIR,
752795
753486
  [GeneratorName.OPENAPI_PYTHON_CLIENT]: GeneratorWasNeverUpdatedToConsumeNewIR,
752796
- [GeneratorName.OPENAPI]: GeneratorWasNeverUpdatedToConsumeNewIR,
753487
+ [GeneratorName.OPENAPI]: "0.4.0-rc.0",
752797
753488
  [GeneratorName.PYTHON_FASTAPI]: GeneratorWasNeverUpdatedToConsumeNewIR,
752798
753489
  [GeneratorName.PYTHON_PYDANTIC]: GeneratorWasNeverUpdatedToConsumeNewIR,
752799
753490
  [GeneratorName.PYTHON_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR,
@@ -752808,8 +753499,8 @@ var V66_TO_V65_MIGRATION = {
752808
753499
  [GeneratorName.SWIFT_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR,
752809
753500
  [GeneratorName.PHP_MODEL]: "0.1.0-rc.0",
752810
753501
  [GeneratorName.PHP_SDK]: "2.3.2-rc.0",
752811
- [GeneratorName.RUST_MODEL]: GeneratorWasNeverUpdatedToConsumeNewIR,
752812
- [GeneratorName.RUST_SDK]: GeneratorWasNeverUpdatedToConsumeNewIR
753502
+ [GeneratorName.RUST_MODEL]: "0.5.0-rc.0",
753503
+ [GeneratorName.RUST_SDK]: "0.32.0-rc.0"
752813
753504
  },
752814
753505
  jsonifyEarlierVersion: (ir15) => IrSerialization_exports.V65.IntermediateRepresentation.jsonOrThrow(ir15, {
752815
753506
  unrecognizedObjectKeys: "passthrough",
@@ -756093,7 +756784,7 @@ function addLogoutCommand(cli) {
756093
756784
 
756094
756785
  // ../cli-v2/lib/constants.js
756095
756786
  var FERN_TOKEN_ENV_VAR2 = "FERN_TOKEN";
756096
- var FETCH_API_SPEC_REQUEST_TIMEOUT_MS = 3e3;
756787
+ var FETCH_API_SPEC_REQUEST_TIMEOUT_MS = 3e4;
756097
756788
  var GENERATE_COMMAND_TIMEOUT_MS = 10 * 60 * 1e3;
756098
756789
 
756099
756790
  // ../cli-v2/lib/commands/auth/status/command.js
@@ -840101,7 +840792,7 @@ var import_path54 = __toESM(require("path"), 1);
840101
840792
  var LOCAL_STORAGE_FOLDER4 = ".fern-dev";
840102
840793
  var LOGS_FOLDER_NAME = "logs";
840103
840794
  function getCliSource() {
840104
- const version7 = "4.62.3-2-g207f4f8f41a";
840795
+ const version7 = "4.62.3-22-ga624085d56a";
840105
840796
  return `cli@${version7}`;
840106
840797
  }
840107
840798
  var DebugLogger = class {
@@ -851209,7 +851900,7 @@ var LegacyDocsPublisher = class {
851209
851900
  previewId,
851210
851901
  disableTemplates: void 0,
851211
851902
  skipUpload,
851212
- cliVersion: "4.62.3-2-g207f4f8f41a"
851903
+ cliVersion: "4.62.3-22-ga624085d56a"
851213
851904
  });
851214
851905
  if (taskContext.getResult() === TaskResult.Failure) {
851215
851906
  return { success: false };
@@ -923948,7 +924639,7 @@ var SentryClient = class {
923948
924639
  sentry;
923949
924640
  constructor({ release: release2 }) {
923950
924641
  const isTelemetryEnabled = process.env.FERN_DISABLE_TELEMETRY !== "true";
923951
- const sentryDsn = "https://84f58b5e457f06999d92f11ce4b79158@o4509504076185600.ingest.us.sentry.io/4511021546602496";
924642
+ const sentryDsn = "";
923952
924643
  if (isTelemetryEnabled && sentryDsn != null && sentryDsn.length > 0) {
923953
924644
  const sentryEnvironment = "development";
923954
924645
  if (sentryEnvironment == null || sentryEnvironment.length === 0) {
@@ -924509,7 +925200,7 @@ var CliContext = class {
924509
925200
  if (false) {
924510
925201
  this.logger.error("CLI_VERSION is not defined");
924511
925202
  }
924512
- return "4.62.3-2-g207f4f8f41a";
925203
+ return "4.62.3-22-ga624085d56a";
924513
925204
  }
924514
925205
  getCliName() {
924515
925206
  if (false) {
@@ -944317,6 +945008,8 @@ function addReplayCommand(cli, cliContext) {
944317
945008
  builder: (yargs) => {
944318
945009
  addReplayInitCommand(yargs, cliContext);
944319
945010
  addReplayResolveCommand(yargs, cliContext);
945011
+ addReplayStatusCommand(yargs, cliContext);
945012
+ addReplayForgetCommand(yargs, cliContext);
944320
945013
  return yargs;
944321
945014
  },
944322
945015
  handler: () => {
@@ -944507,6 +945200,211 @@ Resolve the conflicts in your editor, then run \`fern replay resolve\` again to
944507
945200
  }
944508
945201
  );
944509
945202
  }
945203
+ function addReplayStatusCommand(cli, cliContext) {
945204
+ cli.command(
945205
+ "status [directory]",
945206
+ false,
945207
+ // hidden from --help
945208
+ (yargs) => yargs.positional("directory", {
945209
+ type: "string",
945210
+ default: ".",
945211
+ description: "SDK directory containing .fern/replay.lock"
945212
+ }).option("verbose", {
945213
+ type: "boolean",
945214
+ alias: "v",
945215
+ default: false,
945216
+ description: "Show all patches with full details"
945217
+ }),
945218
+ async (argv) => {
945219
+ await cliContext.instrumentPostHogEvent({
945220
+ command: "fern replay status"
945221
+ });
945222
+ const outputDir = resolve5(cwd(), argv.directory ?? ".");
945223
+ try {
945224
+ const result = (0, import_generator_cli2.replayStatus)({ outputDir });
945225
+ if (!result.initialized) {
945226
+ cliContext.logger.info("Replay is not initialized. Run `fern replay init` to get started.");
945227
+ return;
945228
+ }
945229
+ cliContext.logger.info(
945230
+ `Replay: ${result.patches.length} customization(s) tracked, ${result.generationCount} generation(s)`
945231
+ );
945232
+ if (result.lastGeneration) {
945233
+ cliContext.logger.info(
945234
+ `Last generation: ${result.lastGeneration.sha} (${result.lastGeneration.timestamp})`
945235
+ );
945236
+ }
945237
+ if (result.patches.length === 0) {
945238
+ cliContext.logger.info("No customizations tracked.");
945239
+ return;
945240
+ }
945241
+ const patchesToShow = argv.verbose ? result.patches : result.patches.slice(0, 10);
945242
+ for (const patch5 of patchesToShow) {
945243
+ const statusTag = patch5.status ? ` [${patch5.status}]` : "";
945244
+ if (argv.verbose) {
945245
+ cliContext.logger.info(
945246
+ `
945247
+ ${patch5.id} (${patch5.type})${statusTag}
945248
+ ${patch5.message}
945249
+ Author: ${patch5.author} (${patch5.sha})
945250
+ Files (${patch5.fileCount}): ${patch5.files.join(", ")}`
945251
+ );
945252
+ } else {
945253
+ cliContext.logger.info(
945254
+ ` ${patch5.id}: ${patch5.message} (${patch5.fileCount} file(s))${statusTag}`
945255
+ );
945256
+ }
945257
+ }
945258
+ if (!argv.verbose && result.patches.length > 10) {
945259
+ cliContext.logger.info(` ... and ${result.patches.length - 10} more (use --verbose to see all)`);
945260
+ }
945261
+ if (result.unresolvedCount > 0) {
945262
+ cliContext.logger.warn(
945263
+ `
945264
+ ${result.unresolvedCount} patch(es) have unresolved conflicts. Run \`fern replay resolve\` to fix.`
945265
+ );
945266
+ }
945267
+ if (result.excludePatterns.length > 0) {
945268
+ cliContext.logger.info(`
945269
+ Exclude patterns: ${result.excludePatterns.join(", ")}`);
945270
+ }
945271
+ } catch (error50) {
945272
+ cliContext.failAndThrow(`Failed to get Replay status: ${extractErrorMessage(error50)}`);
945273
+ }
945274
+ }
945275
+ );
945276
+ }
945277
+ function addReplayForgetCommand(cli, cliContext) {
945278
+ cli.command(
945279
+ "forget [args..]",
945280
+ false,
945281
+ // hidden from --help
945282
+ (yargs) => yargs.positional("args", {
945283
+ type: "string",
945284
+ array: true,
945285
+ description: "Patch IDs (e.g. patch-abc12345) or a search pattern"
945286
+ }).option("dry-run", {
945287
+ type: "boolean",
945288
+ default: false,
945289
+ description: "Show what would be removed without actually removing"
945290
+ }).option("yes", {
945291
+ type: "boolean",
945292
+ alias: "y",
945293
+ default: false,
945294
+ description: "Skip confirmation prompts"
945295
+ }).option("all", {
945296
+ type: "boolean",
945297
+ default: false,
945298
+ description: "Remove all tracked patches"
945299
+ }),
945300
+ async (argv) => {
945301
+ await cliContext.instrumentPostHogEvent({
945302
+ command: "fern replay forget"
945303
+ });
945304
+ const outputDir = resolve5(cwd(), ".");
945305
+ const args = argv.args ?? [];
945306
+ const dryRun = argv.dryRun;
945307
+ try {
945308
+ if (argv.all) {
945309
+ const result2 = (0, import_generator_cli2.replayForget)({ outputDir, options: { all: true, dryRun } });
945310
+ if (!result2.initialized) {
945311
+ cliContext.logger.info("Replay is not initialized. Nothing to forget.");
945312
+ return;
945313
+ }
945314
+ if (result2.removed.length === 0) {
945315
+ cliContext.logger.info("No patches to remove.");
945316
+ return;
945317
+ }
945318
+ if (dryRun) {
945319
+ cliContext.logger.info(`Would remove ${result2.removed.length} patch(es):`);
945320
+ } else {
945321
+ cliContext.logger.info(`Removed ${result2.removed.length} patch(es):`);
945322
+ }
945323
+ for (const patch5 of result2.removed) {
945324
+ cliContext.logger.info(` ${patch5.id}: ${patch5.message}`);
945325
+ }
945326
+ for (const warning of result2.warnings) {
945327
+ cliContext.logger.warn(warning);
945328
+ }
945329
+ return;
945330
+ }
945331
+ if (args.length > 0 && args.every((a10) => a10.startsWith("patch-"))) {
945332
+ const result2 = (0, import_generator_cli2.replayForget)({ outputDir, options: { patchIds: args, dryRun } });
945333
+ if (!result2.initialized) {
945334
+ cliContext.logger.info("Replay is not initialized. Nothing to forget.");
945335
+ return;
945336
+ }
945337
+ if (result2.removed.length > 0) {
945338
+ const verb = dryRun ? "Would remove" : "Removed";
945339
+ for (const patch5 of result2.removed) {
945340
+ cliContext.logger.info(`${verb}: ${patch5.id} \u2014 ${patch5.message}`);
945341
+ }
945342
+ }
945343
+ for (const id2 of result2.alreadyForgotten) {
945344
+ cliContext.logger.info(`Already forgotten: ${id2}`);
945345
+ }
945346
+ for (const warning of result2.warnings) {
945347
+ cliContext.logger.warn(warning);
945348
+ }
945349
+ return;
945350
+ }
945351
+ const pattern = args.length === 1 ? args[0] : void 0;
945352
+ const result = (0, import_generator_cli2.replayForget)({ outputDir, options: { pattern } });
945353
+ if (!result.initialized) {
945354
+ cliContext.logger.info("Replay is not initialized. Nothing to forget.");
945355
+ return;
945356
+ }
945357
+ const matched = result.matched ?? [];
945358
+ if (matched.length === 0) {
945359
+ if (pattern) {
945360
+ cliContext.logger.info(`No patches matching "${pattern}".`);
945361
+ } else {
945362
+ cliContext.logger.info("No patches tracked.");
945363
+ }
945364
+ return;
945365
+ }
945366
+ cliContext.logger.info(`${matched.length} patch(es) matched:`);
945367
+ for (const patch5 of matched) {
945368
+ const stat6 = `+${patch5.diffstat.additions}/-${patch5.diffstat.deletions}`;
945369
+ cliContext.logger.info(` ${patch5.id}: ${patch5.message} (${stat6})`);
945370
+ }
945371
+ if (dryRun) {
945372
+ cliContext.logger.info("\nDry run \u2014 no patches removed.");
945373
+ return;
945374
+ }
945375
+ if (!argv.yes) {
945376
+ if (!process.stdout.isTTY) {
945377
+ cliContext.failAndThrow(
945378
+ "Confirmation required. Use --yes to skip confirmation in non-interactive mode."
945379
+ );
945380
+ return;
945381
+ }
945382
+ const readline7 = await import("readline");
945383
+ const rl3 = readline7.createInterface({ input: process.stdin, output: process.stderr });
945384
+ const answer = await new Promise((resolvePrompt) => {
945385
+ rl3.question(`
945386
+ Remove ${matched.length} patch(es)? [y/N] `, resolvePrompt);
945387
+ });
945388
+ rl3.close();
945389
+ if (answer.toLowerCase() !== "y") {
945390
+ cliContext.logger.info("Cancelled.");
945391
+ return;
945392
+ }
945393
+ }
945394
+ const patchIds = matched.map((p10) => p10.id);
945395
+ const removeResult = (0, import_generator_cli2.replayForget)({ outputDir, options: { patchIds, dryRun: false } });
945396
+ cliContext.logger.info(
945397
+ `Removed ${removeResult.removed.length} patch(es). ${removeResult.remaining} remaining.`
945398
+ );
945399
+ for (const warning of removeResult.warnings) {
945400
+ cliContext.logger.warn(warning);
945401
+ }
945402
+ } catch (error50) {
945403
+ cliContext.failAndThrow(`Failed to forget patches: ${extractErrorMessage(error50)}`);
945404
+ }
945405
+ }
945406
+ );
945407
+ }
944510
945408
  function parseOwnerRepo(githubRepo) {
944511
945409
  const cleaned = githubRepo.replace(/^https?:\/\//, "").replace(/\.git$/, "").replace(/^github\.com\//, "");
944512
945410
  const parts = cleaned.split("/");