pakhale 0.2.0 → 0.3.0

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 (3) hide show
  1. package/README.md +5 -0
  2. package/dist/cli.js +1018 -66
  3. package/package.json +2 -1
package/dist/cli.js CHANGED
@@ -6,6 +6,7 @@ import { homedir } from "node:os";
6
6
  import { parseArgs, styleText } from "node:util";
7
7
  import process$1, { stdin, stdout } from "node:process";
8
8
  import l__default from "node:readline";
9
+ import { createHash } from "node:crypto";
9
10
  import { spawn } from "node:child_process";
10
11
 
11
12
  //#region rolldown:runtime
@@ -104,7 +105,7 @@ var require_picocolors = /* @__PURE__ */ __commonJS({ "node_modules/picocolors/p
104
105
 
105
106
  //#endregion
106
107
  //#region config.ts
107
- var import_picocolors$3 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
108
+ var import_picocolors$4 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
108
109
  const config = {
109
110
  agents: ["claude-code", "opencode"],
110
111
  marketplaces: {
@@ -218,14 +219,14 @@ const config = {
218
219
  //#endregion
219
220
  //#region src/util/log.ts
220
221
  const log = {
221
- agent: (s) => console.log(`\n${import_picocolors$3.default.bold(import_picocolors$3.default.magenta(`■ ${s}`))}`),
222
- section: (s) => console.log(`\n${import_picocolors$3.default.bold(import_picocolors$3.default.cyan(`▸ ${s}`))}`),
223
- ok: (s) => console.log(` ${import_picocolors$3.default.green("✓")} ${s}`),
224
- skip: (s) => console.log(` ${import_picocolors$3.default.dim("·")} ${import_picocolors$3.default.dim(s)}`),
225
- warn: (s) => console.log(` ${import_picocolors$3.default.yellow("!")} ${s}`),
226
- fail: (s) => console.log(` ${import_picocolors$3.default.red("✗")} ${s}`),
227
- plan: (s) => console.log(` ${import_picocolors$3.default.yellow("would")} ${s}`),
228
- info: (s) => console.log(` ${import_picocolors$3.default.dim(s)}`)
222
+ agent: (s) => console.log(`\n${import_picocolors$4.default.bold(import_picocolors$4.default.magenta(`■ ${s}`))}`),
223
+ section: (s) => console.log(`\n${import_picocolors$4.default.bold(import_picocolors$4.default.cyan(`▸ ${s}`))}`),
224
+ ok: (s) => console.log(` ${import_picocolors$4.default.green("✓")} ${s}`),
225
+ skip: (s) => console.log(` ${import_picocolors$4.default.dim("·")} ${import_picocolors$4.default.dim(s)}`),
226
+ warn: (s) => console.log(` ${import_picocolors$4.default.yellow("!")} ${s}`),
227
+ fail: (s) => console.log(` ${import_picocolors$4.default.red("✗")} ${s}`),
228
+ plan: (s) => console.log(` ${import_picocolors$4.default.yellow("would")} ${s}`),
229
+ info: (s) => console.log(` ${import_picocolors$4.default.dim(s)}`)
229
230
  };
230
231
 
231
232
  //#endregion
@@ -633,7 +634,7 @@ function isActionKey(n$2, e) {
633
634
  for (const s of n$2) if (s !== void 0 && isActionKey(s, e)) return true;
634
635
  return false;
635
636
  }
636
- function diffLines(i$1, s) {
637
+ function diffLines$1(i$1, s) {
637
638
  if (i$1 === s) return;
638
639
  const e = i$1.split(`
639
640
  `), t = s.split(`
@@ -661,8 +662,8 @@ function wrapTextWithPrefix(e, r$1, o, t = o, s = o, n$2) {
661
662
  hard: true,
662
663
  trim: false
663
664
  }).split(`
664
- `).map((c, i$1, m$1) => {
665
- const d = n$2 ? n$2(c, i$1) : c;
665
+ `).map((c$1, i$1, m$1) => {
666
+ const d = n$2 ? n$2(c$1, i$1) : c$1;
666
667
  return i$1 === 0 ? `${t}${d}` : i$1 === m$1.length - 1 ? `${s}${d}` : `${o}${d}`;
667
668
  }).join(`
668
669
  `);
@@ -813,7 +814,7 @@ var V = class {
813
814
  if (t !== this._prevFrame) {
814
815
  if (this.state === "initial") this.output.write(import_src$1.cursor.hide);
815
816
  else {
816
- const e = diffLines(this._prevFrame, t), i$1 = getRows(this.output);
817
+ const e = diffLines$1(this._prevFrame, t), i$1 = getRows(this.output);
817
818
  if (this.restoreCursor(), e) {
818
819
  const n$2 = Math.max(0, e.numLinesAfter - i$1), s = Math.max(0, e.numLinesBefore - i$1);
819
820
  let r$1 = e.lines.find((o) => o >= n$2);
@@ -891,6 +892,34 @@ var a = class extends V {
891
892
  });
892
893
  }
893
894
  };
895
+ let n$1 = class n$2 extends V {
896
+ options;
897
+ cursor = 0;
898
+ get _selectedValue() {
899
+ return this.options[this.cursor];
900
+ }
901
+ changeValue() {
902
+ const e = this._selectedValue;
903
+ this.value = e === void 0 ? void 0 : e.value;
904
+ }
905
+ constructor(e) {
906
+ super(e, false), this.options = e.options;
907
+ const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t = o === -1 ? 0 : o;
908
+ this.cursor = this.options[t]?.disabled ? findCursor(t, 1, this.options) : t, this.changeValue(), this.on("cursor", (s) => {
909
+ switch (s) {
910
+ case "left":
911
+ case "up":
912
+ this.cursor = findCursor(this.cursor, -1, this.options);
913
+ break;
914
+ case "down":
915
+ case "right":
916
+ this.cursor = findCursor(this.cursor, 1, this.options);
917
+ break;
918
+ }
919
+ this.changeValue();
920
+ });
921
+ }
922
+ };
894
923
 
895
924
  //#endregion
896
925
  //#region node_modules/@clack/prompts/dist/index.mjs
@@ -939,11 +968,11 @@ const limitOptions = ({ cursor: l, options: e, style: w, output: p$1 = process.s
939
968
  const i$1 = getColumns(p$1) - C, m$1 = getRows(p$1), M = styleText("dim", "..."), v = Math.max(m$1 - r$1, 0), a$1 = Math.max(Math.min(b, v), 5);
940
969
  let f = 0;
941
970
  l >= a$1 - 3 && (f = Math.max(Math.min(l - a$1 + 3, e.length - a$1), 0));
942
- let d = a$1 < e.length && f > 0, c = a$1 < e.length && f + a$1 < e.length;
971
+ let d = a$1 < e.length && f > 0, c$1 = a$1 < e.length && f + a$1 < e.length;
943
972
  const W = Math.min(f + a$1, e.length), s = [];
944
973
  let g = 0;
945
- d && g++, c && g++;
946
- const T = f + (d ? 1 : 0), y = W - (c ? 1 : 0);
974
+ d && g++, c$1 && g++;
975
+ const T = f + (d ? 1 : 0), y = W - (c$1 ? 1 : 0);
947
976
  for (let t = T; t < y; t++) {
948
977
  const n$2 = e[t], h$1 = wrapAnsi(n$2 ? w(n$2, t === l) : "", i$1, {
949
978
  hard: true,
@@ -957,12 +986,12 @@ const limitOptions = ({ cursor: l, options: e, style: w, output: p$1 = process.s
957
986
  const h$1 = l - T;
958
987
  let u$4 = v;
959
988
  const L = () => I(s, o, 0, h$1, u$4), E = () => I(s, o, h$1 + 1, s.length, u$4, true);
960
- d ? ({lineCount: o, removals: t} = L(), o > u$4 && (c || (u$4 -= 1), {lineCount: o, removals: n$2} = E())) : (c || (u$4 -= 1), {lineCount: o, removals: n$2} = E(), o > u$4 && (u$4 -= 1, {lineCount: o, removals: t} = L())), t > 0 && (d = true, s.splice(0, t)), n$2 > 0 && (c = true, s.splice(s.length - n$2, n$2));
989
+ d ? ({lineCount: o, removals: t} = L(), o > u$4 && (c$1 || (u$4 -= 1), {lineCount: o, removals: n$2} = E())) : (c$1 || (u$4 -= 1), {lineCount: o, removals: n$2} = E(), o > u$4 && (u$4 -= 1, {lineCount: o, removals: t} = L())), t > 0 && (d = true, s.splice(0, t)), n$2 > 0 && (c$1 = true, s.splice(s.length - n$2, n$2));
961
990
  }
962
991
  const x = [];
963
992
  d && x.push(M);
964
993
  for (const t of s) for (const n$2 of t) x.push(n$2);
965
- return c && x.push(M), x;
994
+ return c$1 && x.push(M), x;
966
995
  };
967
996
  const MULTISELECT_INSTRUCTIONS = [
968
997
  `${styleText("dim", "↑/↓")} to navigate`,
@@ -1074,6 +1103,63 @@ const u$3 = {
1074
1103
  block: unicodeOr("█", "#")
1075
1104
  };
1076
1105
  const SELECT_INSTRUCTIONS = [`${styleText("dim", "↑/↓")} to navigate`, `${styleText("dim", "Enter:")} confirm`];
1106
+ const c = (t, o) => t.includes(`
1107
+ `) ? t.split(`
1108
+ `).map((d) => o(d)).join(`
1109
+ `) : o(t);
1110
+ const select$1 = (t) => {
1111
+ const o = (n$2, m$1) => {
1112
+ if (n$2 === void 0) return "";
1113
+ const s = n$2.label ?? String(n$2.value);
1114
+ switch (m$1) {
1115
+ case "disabled": return `${styleText("gray", S_RADIO_INACTIVE)} ${c(s, (i$1) => styleText("gray", i$1))}${n$2.hint ? ` ${styleText("dim", `(${n$2.hint ?? "disabled"})`)}` : ""}`;
1116
+ case "selected": return `${c(s, (i$1) => styleText("dim", i$1))}`;
1117
+ case "active": return `${styleText("green", S_RADIO_ACTIVE)} ${s}${n$2.hint ? ` ${styleText("dim", `(${n$2.hint})`)}` : ""}`;
1118
+ case "cancelled": return `${c(s, (i$1) => styleText(["strikethrough", "dim"], i$1))}`;
1119
+ default: return `${styleText("dim", S_RADIO_INACTIVE)} ${c(s, (i$1) => styleText("dim", i$1))}`;
1120
+ }
1121
+ }, d = t.showInstructions ?? true;
1122
+ return new n$1({
1123
+ options: t.options,
1124
+ signal: t.signal,
1125
+ input: t.input,
1126
+ output: t.output,
1127
+ initialValue: t.initialValue,
1128
+ render() {
1129
+ const n$2 = t.withGuide ?? settings.withGuide, m$1 = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i$1 = wrapTextWithPrefix(t.output, t.message, s, m$1), u$4 = `${n$2 ? `${styleText("gray", S_BAR)}
1130
+ ` : ""}${i$1}
1131
+ `;
1132
+ switch (this.state) {
1133
+ case "submit": {
1134
+ const r$1 = n$2 ? `${styleText("gray", S_BAR)} ` : "";
1135
+ return `${u$4}${wrapTextWithPrefix(t.output, o(this.options[this.cursor], "selected"), r$1)}`;
1136
+ }
1137
+ case "cancel": {
1138
+ const r$1 = n$2 ? `${styleText("gray", S_BAR)} ` : "";
1139
+ return `${u$4}${wrapTextWithPrefix(t.output, o(this.options[this.cursor], "cancelled"), r$1)}${n$2 ? `
1140
+ ${styleText("gray", S_BAR)}` : ""}`;
1141
+ }
1142
+ default: {
1143
+ const r$1 = n$2 ? `${styleText("cyan", S_BAR)} ` : "", a$1 = u$4.split(`
1144
+ `).length, p$1 = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n$2) : n$2 ? [styleText("cyan", S_BAR_END)] : [], b = p$1.join(`
1145
+ `), f = p$1.length + 1;
1146
+ return `${u$4}${r$1}${limitOptions({
1147
+ output: t.output,
1148
+ cursor: this.cursor,
1149
+ options: this.options,
1150
+ maxItems: t.maxItems,
1151
+ columnPadding: r$1.length,
1152
+ rowPadding: a$1 + f,
1153
+ style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
1154
+ }).join(`
1155
+ ${r$1}`)}
1156
+ ${b}
1157
+ `;
1158
+ }
1159
+ }
1160
+ }
1161
+ }).prompt();
1162
+ };
1077
1163
  const i = `${styleText("gray", S_BAR)} `;
1078
1164
 
1079
1165
  //#endregion
@@ -1083,12 +1169,12 @@ async function multiSelect(message, choices) {
1083
1169
  if (!choices.length) return [];
1084
1170
  const picked = await multiselect({
1085
1171
  message,
1086
- options: choices.map((c) => ({
1087
- value: c.value,
1088
- label: c.label,
1089
- hint: c.hint
1172
+ options: choices.map((c$1) => ({
1173
+ value: c$1.value,
1174
+ label: c$1.label,
1175
+ hint: c$1.hint
1090
1176
  })),
1091
- initialValues: choices.map((c) => c.value),
1177
+ initialValues: choices.map((c$1) => c$1.value),
1092
1178
  required: false
1093
1179
  });
1094
1180
  if (isCancel(picked)) {
@@ -1097,6 +1183,22 @@ async function multiSelect(message, choices) {
1097
1183
  }
1098
1184
  return picked;
1099
1185
  }
1186
+ /** One answer from a list. Cancelling returns null — the caller decides what safe means. */
1187
+ async function select(message, choices) {
1188
+ const picked = await select$1({
1189
+ message,
1190
+ options: choices.map((c$1) => ({
1191
+ value: c$1.value,
1192
+ label: c$1.label,
1193
+ hint: c$1.hint
1194
+ }))
1195
+ });
1196
+ if (isCancel(picked)) {
1197
+ cancel("cancelled");
1198
+ return null;
1199
+ }
1200
+ return picked;
1201
+ }
1100
1202
  function isInteractive() {
1101
1203
  return Boolean(process.stdin.isTTY && process.stdout.isTTY);
1102
1204
  }
@@ -1210,7 +1312,7 @@ function logCoverage(config$1) {
1210
1312
  const nameWidth = Math.max(...rows.map((r$1) => r$1.name.length));
1211
1313
  const cellWidths = config$1.agents.map((_, i$1) => Math.max(...rows.map((r$1) => r$1.cells[i$1].length)));
1212
1314
  for (const { name: name$1, cells } of rows) {
1213
- const line = cells.map((c, i$1) => c.padEnd(cellWidths[i$1])).join(" ");
1315
+ const line = cells.map((c$1, i$1) => c$1.padEnd(cellWidths[i$1])).join(" ");
1214
1316
  log.info(`${name$1.padEnd(nameWidth)} ${line.trimEnd()}`);
1215
1317
  }
1216
1318
  }
@@ -1300,6 +1402,36 @@ function skillInstalls(config$1, agent, home, linkDir) {
1300
1402
  });
1301
1403
  }
1302
1404
 
1405
+ //#endregion
1406
+ //#region src/commands/setup/agents/state.ts
1407
+ /** Machine-local bookkeeping, never a source of truth — do not sync or vendor it. */
1408
+ function stateFileFor(home) {
1409
+ return join(home, ".agents", ".setup-state.json");
1410
+ }
1411
+ function hashContent(content) {
1412
+ return createHash("sha256").update(content).digest("hex");
1413
+ }
1414
+ function hashValue(value) {
1415
+ return hashContent(stable(value));
1416
+ }
1417
+ async function loadState(file) {
1418
+ try {
1419
+ const parsed = JSON.parse(await readFile(file, "utf8"));
1420
+ return {
1421
+ files: parsed.files ?? {},
1422
+ keys: parsed.keys ?? {}
1423
+ };
1424
+ } catch {
1425
+ return {
1426
+ files: {},
1427
+ keys: {}
1428
+ };
1429
+ }
1430
+ }
1431
+ async function saveState(file, state) {
1432
+ await writeJson(file, state);
1433
+ }
1434
+
1303
1435
  //#endregion
1304
1436
  //#region src/commands/setup/agents/store.ts
1305
1437
  const AGENTS_STORE = ".agents/skills";
@@ -1312,6 +1444,7 @@ async function buildStorePlan(ctx) {
1312
1444
  const archiveDir = join(ctx.home, ".agents/.setup-backups", stamp);
1313
1445
  return {
1314
1446
  archiveDir,
1447
+ stateFile: stateFileFor(ctx.home),
1315
1448
  groups: [{
1316
1449
  section: "Skills store (~/.agents/skills)",
1317
1450
  artifacts: (await authoredSkillNames(ctx)).map((name$1) => ({
@@ -1398,6 +1531,7 @@ async function buildPlan$1(ctx) {
1398
1531
  });
1399
1532
  return {
1400
1533
  archiveDir,
1534
+ stateFile: stateFileFor(ctx.home),
1401
1535
  groups
1402
1536
  };
1403
1537
  }
@@ -1423,8 +1557,8 @@ function claudeMcp(server) {
1423
1557
  ...server.headers && { headers: server.headers }
1424
1558
  };
1425
1559
  }
1426
- function mapValues(record, fn) {
1427
- return Object.fromEntries(Object.entries(record).map(([k, v]) => [k, fn(v)]));
1560
+ function mapValues(record$1, fn) {
1561
+ return Object.fromEntries(Object.entries(record$1).map(([k, v]) => [k, fn(v)]));
1428
1562
  }
1429
1563
  async function authoredSkillLinks(ctx, root, archiveDir) {
1430
1564
  return (await authoredSkillNames(ctx)).map((name$1) => ({
@@ -1494,6 +1628,7 @@ async function buildPlan(ctx) {
1494
1628
  });
1495
1629
  return {
1496
1630
  archiveDir: join(root, ".setup-backups", stamp),
1631
+ stateFile: stateFileFor(ctx.home),
1497
1632
  groups
1498
1633
  };
1499
1634
  }
@@ -1561,14 +1696,631 @@ async function which(bin) {
1561
1696
  ])).ok;
1562
1697
  }
1563
1698
 
1699
+ //#endregion
1700
+ //#region node_modules/diff/libesm/diff/base.js
1701
+ var Diff = class {
1702
+ diff(oldStr, newStr, options = {}) {
1703
+ let callback;
1704
+ if (typeof options === "function") {
1705
+ callback = options;
1706
+ options = {};
1707
+ } else if ("callback" in options) callback = options.callback;
1708
+ const oldString = this.castInput(oldStr, options);
1709
+ const newString = this.castInput(newStr, options);
1710
+ const oldTokens = this.removeEmpty(this.tokenize(oldString, options));
1711
+ const newTokens = this.removeEmpty(this.tokenize(newString, options));
1712
+ return this.diffWithOptionsObj(oldTokens, newTokens, options, callback);
1713
+ }
1714
+ diffWithOptionsObj(oldTokens, newTokens, options, callback) {
1715
+ var _a;
1716
+ const done = (value) => {
1717
+ value = this.postProcess(value, options);
1718
+ if (callback) {
1719
+ setTimeout(function() {
1720
+ callback(value);
1721
+ }, 0);
1722
+ return;
1723
+ } else return value;
1724
+ };
1725
+ const newLen = newTokens.length, oldLen = oldTokens.length;
1726
+ let editLength = 1;
1727
+ let maxEditLength = newLen + oldLen;
1728
+ if (options.maxEditLength != null) maxEditLength = Math.min(maxEditLength, options.maxEditLength);
1729
+ const maxExecutionTime = (_a = options.timeout) !== null && _a !== void 0 ? _a : Infinity;
1730
+ const abortAfterTimestamp = Date.now() + maxExecutionTime;
1731
+ const bestPath = [{
1732
+ oldPos: -1,
1733
+ lastComponent: void 0
1734
+ }];
1735
+ let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options);
1736
+ if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
1737
+ let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
1738
+ const execEditLength = () => {
1739
+ for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
1740
+ let basePath;
1741
+ const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
1742
+ if (removePath) bestPath[diagonalPath - 1] = void 0;
1743
+ let canAdd = false;
1744
+ if (addPath) {
1745
+ const addPathNewPos = addPath.oldPos - diagonalPath;
1746
+ canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
1747
+ }
1748
+ const canRemove = removePath && removePath.oldPos + 1 < oldLen;
1749
+ if (!canAdd && !canRemove) {
1750
+ bestPath[diagonalPath] = void 0;
1751
+ continue;
1752
+ }
1753
+ if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) basePath = this.addToPath(addPath, true, false, 0, options);
1754
+ else basePath = this.addToPath(removePath, false, true, 1, options);
1755
+ newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options);
1756
+ if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
1757
+ else {
1758
+ bestPath[diagonalPath] = basePath;
1759
+ if (basePath.oldPos + 1 >= oldLen) maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
1760
+ if (newPos + 1 >= newLen) minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
1761
+ }
1762
+ }
1763
+ editLength++;
1764
+ };
1765
+ if (callback) (function exec$1() {
1766
+ setTimeout(function() {
1767
+ if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) return callback(void 0);
1768
+ if (!execEditLength()) exec$1();
1769
+ }, 0);
1770
+ })();
1771
+ else while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
1772
+ const ret = execEditLength();
1773
+ if (ret) return ret;
1774
+ }
1775
+ }
1776
+ addToPath(path, added, removed, oldPosInc, options) {
1777
+ const last = path.lastComponent;
1778
+ if (last && !options.oneChangePerToken && last.added === added && last.removed === removed) return {
1779
+ oldPos: path.oldPos + oldPosInc,
1780
+ lastComponent: {
1781
+ count: last.count + 1,
1782
+ added,
1783
+ removed,
1784
+ previousComponent: last.previousComponent
1785
+ }
1786
+ };
1787
+ else return {
1788
+ oldPos: path.oldPos + oldPosInc,
1789
+ lastComponent: {
1790
+ count: 1,
1791
+ added,
1792
+ removed,
1793
+ previousComponent: last
1794
+ }
1795
+ };
1796
+ }
1797
+ extractCommon(basePath, newTokens, oldTokens, diagonalPath, options) {
1798
+ const newLen = newTokens.length, oldLen = oldTokens.length;
1799
+ let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
1800
+ while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options)) {
1801
+ newPos++;
1802
+ oldPos++;
1803
+ commonCount++;
1804
+ if (options.oneChangePerToken) basePath.lastComponent = {
1805
+ count: 1,
1806
+ previousComponent: basePath.lastComponent,
1807
+ added: false,
1808
+ removed: false
1809
+ };
1810
+ }
1811
+ if (commonCount && !options.oneChangePerToken) basePath.lastComponent = {
1812
+ count: commonCount,
1813
+ previousComponent: basePath.lastComponent,
1814
+ added: false,
1815
+ removed: false
1816
+ };
1817
+ basePath.oldPos = oldPos;
1818
+ return newPos;
1819
+ }
1820
+ equals(left, right, options) {
1821
+ if (options.comparator) return options.comparator(left, right);
1822
+ else return left === right || !!options.ignoreCase && left.toLowerCase() === right.toLowerCase();
1823
+ }
1824
+ removeEmpty(array) {
1825
+ const ret = [];
1826
+ for (let i$1 = 0; i$1 < array.length; i$1++) if (array[i$1]) ret.push(array[i$1]);
1827
+ return ret;
1828
+ }
1829
+ castInput(value, options) {
1830
+ return value;
1831
+ }
1832
+ tokenize(value, options) {
1833
+ return Array.from(value);
1834
+ }
1835
+ join(chars) {
1836
+ return chars.join("");
1837
+ }
1838
+ postProcess(changeObjects, options) {
1839
+ return changeObjects;
1840
+ }
1841
+ get useLongestToken() {
1842
+ return false;
1843
+ }
1844
+ buildValues(lastComponent, newTokens, oldTokens) {
1845
+ const components = [];
1846
+ let nextComponent;
1847
+ while (lastComponent) {
1848
+ components.push(lastComponent);
1849
+ nextComponent = lastComponent.previousComponent;
1850
+ delete lastComponent.previousComponent;
1851
+ lastComponent = nextComponent;
1852
+ }
1853
+ components.reverse();
1854
+ const componentLen = components.length;
1855
+ let componentPos = 0, newPos = 0, oldPos = 0;
1856
+ for (; componentPos < componentLen; componentPos++) {
1857
+ const component = components[componentPos];
1858
+ if (!component.removed) {
1859
+ if (!component.added && this.useLongestToken) {
1860
+ let value = newTokens.slice(newPos, newPos + component.count);
1861
+ value = value.map(function(value$1, i$1) {
1862
+ const oldValue = oldTokens[oldPos + i$1];
1863
+ return oldValue.length > value$1.length ? oldValue : value$1;
1864
+ });
1865
+ component.value = this.join(value);
1866
+ } else component.value = this.join(newTokens.slice(newPos, newPos + component.count));
1867
+ newPos += component.count;
1868
+ if (!component.added) oldPos += component.count;
1869
+ } else {
1870
+ component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
1871
+ oldPos += component.count;
1872
+ }
1873
+ }
1874
+ return components;
1875
+ }
1876
+ };
1877
+
1878
+ //#endregion
1879
+ //#region node_modules/diff/libesm/diff/character.js
1880
+ var CharacterDiff = class extends Diff {};
1881
+ const characterDiff = new CharacterDiff();
1882
+
1883
+ //#endregion
1884
+ //#region node_modules/diff/libesm/util/string.js
1885
+ function longestCommonPrefix(str1, str2) {
1886
+ let i$1;
1887
+ for (i$1 = 0; i$1 < str1.length && i$1 < str2.length; i$1++) if (str1[i$1] != str2[i$1]) return str1.slice(0, i$1);
1888
+ return str1.slice(0, i$1);
1889
+ }
1890
+ function longestCommonSuffix(str1, str2) {
1891
+ let i$1;
1892
+ if (!str1 || !str2 || str1[str1.length - 1] != str2[str2.length - 1]) return "";
1893
+ for (i$1 = 0; i$1 < str1.length && i$1 < str2.length; i$1++) if (str1[str1.length - (i$1 + 1)] != str2[str2.length - (i$1 + 1)]) return str1.slice(-i$1);
1894
+ return str1.slice(-i$1);
1895
+ }
1896
+ function replacePrefix(string, oldPrefix, newPrefix) {
1897
+ if (string.slice(0, oldPrefix.length) != oldPrefix) throw Error(`string ${JSON.stringify(string)} doesn't start with prefix ${JSON.stringify(oldPrefix)}; this is a bug`);
1898
+ return newPrefix + string.slice(oldPrefix.length);
1899
+ }
1900
+ function replaceSuffix(string, oldSuffix, newSuffix) {
1901
+ if (!oldSuffix) return string + newSuffix;
1902
+ if (string.slice(-oldSuffix.length) != oldSuffix) throw Error(`string ${JSON.stringify(string)} doesn't end with suffix ${JSON.stringify(oldSuffix)}; this is a bug`);
1903
+ return string.slice(0, -oldSuffix.length) + newSuffix;
1904
+ }
1905
+ function removePrefix(string, oldPrefix) {
1906
+ return replacePrefix(string, oldPrefix, "");
1907
+ }
1908
+ function removeSuffix(string, oldSuffix) {
1909
+ return replaceSuffix(string, oldSuffix, "");
1910
+ }
1911
+ function maximumOverlap(string1, string2) {
1912
+ return string2.slice(0, overlapCount(string1, string2));
1913
+ }
1914
+ function overlapCount(a$1, b) {
1915
+ let startA = 0;
1916
+ if (a$1.length > b.length) startA = a$1.length - b.length;
1917
+ let endB = b.length;
1918
+ if (a$1.length < b.length) endB = a$1.length;
1919
+ const map = Array(endB);
1920
+ let k = 0;
1921
+ map[0] = 0;
1922
+ for (let j = 1; j < endB; j++) {
1923
+ if (b[j] == b[k]) map[j] = map[k];
1924
+ else map[j] = k;
1925
+ while (k > 0 && b[j] != b[k]) k = map[k];
1926
+ if (b[j] == b[k]) k++;
1927
+ }
1928
+ k = 0;
1929
+ for (let i$1 = startA; i$1 < a$1.length; i$1++) {
1930
+ while (k > 0 && a$1[i$1] != b[k]) k = map[k];
1931
+ if (a$1[i$1] == b[k]) k++;
1932
+ }
1933
+ return k;
1934
+ }
1935
+ /**
1936
+ * Split a string into segments using a word segmenter, merging consecutive
1937
+ * segments if they are both whitespace segments. Whitespace segments can
1938
+ * appear adjacent to one another for two reasons:
1939
+ * - newlines always get their own segment
1940
+ * - where a diacritic is attached to a whitespace character in the text, the
1941
+ * segment ends after the diacritic, so e.g. " \u0300 " becomes two segments.
1942
+ * This function therefore runs the segmenter's .segment() method and then
1943
+ * merges consecutive segments of whitespace into a single part.
1944
+ */
1945
+ function segment(string, segmenter) {
1946
+ const parts = [];
1947
+ for (const segmentObj of Array.from(segmenter.segment(string))) {
1948
+ const segment$1 = segmentObj.segment;
1949
+ if (parts.length && /\s/.test(parts[parts.length - 1]) && /\s/.test(segment$1)) parts[parts.length - 1] += segment$1;
1950
+ else parts.push(segment$1);
1951
+ }
1952
+ return parts;
1953
+ }
1954
+ function trailingWs(string, segmenter) {
1955
+ if (segmenter) return leadingAndTrailingWs(string, segmenter)[1];
1956
+ let i$1;
1957
+ for (i$1 = string.length - 1; i$1 >= 0; i$1--) if (!string[i$1].match(/\s/)) break;
1958
+ return string.substring(i$1 + 1);
1959
+ }
1960
+ function leadingWs(string, segmenter) {
1961
+ if (segmenter) return leadingAndTrailingWs(string, segmenter)[0];
1962
+ const match = string.match(/^\s*/);
1963
+ return match ? match[0] : "";
1964
+ }
1965
+ function leadingAndTrailingWs(string, segmenter) {
1966
+ if (!segmenter) return [leadingWs(string), trailingWs(string)];
1967
+ if (segmenter.resolvedOptions().granularity != "word") throw new Error("The segmenter passed must have a granularity of \"word\"");
1968
+ const segments = segment(string, segmenter);
1969
+ const firstSeg = segments[0];
1970
+ const lastSeg = segments[segments.length - 1];
1971
+ return [/\s/.test(firstSeg) ? firstSeg : "", /\s/.test(lastSeg) ? lastSeg : ""];
1972
+ }
1973
+
1974
+ //#endregion
1975
+ //#region node_modules/diff/libesm/diff/word.js
1976
+ const extendedWordChars = "a-zA-Z0-9_\\u{AD}\\u{C0}-\\u{D6}\\u{D8}-\\u{F6}\\u{F8}-\\u{2C6}\\u{2C8}-\\u{2D7}\\u{2DE}-\\u{2FF}\\u{1E00}-\\u{1EFF}";
1977
+ const tokenizeIncludingWhitespace = new RegExp(`[${extendedWordChars}]+|\\s+|[^${extendedWordChars}]`, "ug");
1978
+ var WordDiff = class extends Diff {
1979
+ equals(left, right, options) {
1980
+ if (options.ignoreCase) {
1981
+ left = left.toLowerCase();
1982
+ right = right.toLowerCase();
1983
+ }
1984
+ return left.trim() === right.trim();
1985
+ }
1986
+ tokenize(value, options = {}) {
1987
+ let parts;
1988
+ if (options.intlSegmenter) {
1989
+ const segmenter = options.intlSegmenter;
1990
+ if (segmenter.resolvedOptions().granularity != "word") throw new Error("The segmenter passed must have a granularity of \"word\"");
1991
+ parts = segment(value, segmenter);
1992
+ } else parts = value.match(tokenizeIncludingWhitespace) || [];
1993
+ const tokens = [];
1994
+ let prevPart = null;
1995
+ parts.forEach((part) => {
1996
+ if (/\s/.test(part)) if (prevPart == null) tokens.push(part);
1997
+ else tokens.push(tokens.pop() + part);
1998
+ else if (prevPart != null && /\s/.test(prevPart)) if (tokens[tokens.length - 1] == prevPart) tokens.push(tokens.pop() + part);
1999
+ else tokens.push(prevPart + part);
2000
+ else tokens.push(part);
2001
+ prevPart = part;
2002
+ });
2003
+ return tokens;
2004
+ }
2005
+ join(tokens) {
2006
+ return tokens.map((token, i$1) => {
2007
+ if (i$1 == 0) return token;
2008
+ else return token.replace(/^\s+/, "");
2009
+ }).join("");
2010
+ }
2011
+ postProcess(changes, options) {
2012
+ if (!changes || options.oneChangePerToken) return changes;
2013
+ let lastKeep = null;
2014
+ let insertion = null;
2015
+ let deletion = null;
2016
+ changes.forEach((change) => {
2017
+ if (change.added) insertion = change;
2018
+ else if (change.removed) deletion = change;
2019
+ else {
2020
+ if (insertion || deletion) dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, change, options.intlSegmenter);
2021
+ lastKeep = change;
2022
+ insertion = null;
2023
+ deletion = null;
2024
+ }
2025
+ });
2026
+ if (insertion || deletion) dedupeWhitespaceInChangeObjects(lastKeep, deletion, insertion, null, options.intlSegmenter);
2027
+ return changes;
2028
+ }
2029
+ };
2030
+ const wordDiff = new WordDiff();
2031
+ function dedupeWhitespaceInChangeObjects(startKeep, deletion, insertion, endKeep, segmenter) {
2032
+ if (deletion && insertion) {
2033
+ const [oldWsPrefix, oldWsSuffix] = leadingAndTrailingWs(deletion.value, segmenter);
2034
+ const [newWsPrefix, newWsSuffix] = leadingAndTrailingWs(insertion.value, segmenter);
2035
+ if (startKeep) {
2036
+ const commonWsPrefix = longestCommonPrefix(oldWsPrefix, newWsPrefix);
2037
+ startKeep.value = replaceSuffix(startKeep.value, newWsPrefix, commonWsPrefix);
2038
+ deletion.value = removePrefix(deletion.value, commonWsPrefix);
2039
+ insertion.value = removePrefix(insertion.value, commonWsPrefix);
2040
+ }
2041
+ if (endKeep) {
2042
+ const commonWsSuffix = longestCommonSuffix(oldWsSuffix, newWsSuffix);
2043
+ endKeep.value = replacePrefix(endKeep.value, newWsSuffix, commonWsSuffix);
2044
+ deletion.value = removeSuffix(deletion.value, commonWsSuffix);
2045
+ insertion.value = removeSuffix(insertion.value, commonWsSuffix);
2046
+ }
2047
+ } else if (insertion) {
2048
+ if (startKeep) {
2049
+ const ws = leadingWs(insertion.value, segmenter);
2050
+ insertion.value = insertion.value.substring(ws.length);
2051
+ }
2052
+ if (endKeep) {
2053
+ const ws = leadingWs(endKeep.value, segmenter);
2054
+ endKeep.value = endKeep.value.substring(ws.length);
2055
+ }
2056
+ } else if (startKeep && endKeep) {
2057
+ const newWsFull = leadingWs(endKeep.value, segmenter), [delWsStart, delWsEnd] = leadingAndTrailingWs(deletion.value, segmenter);
2058
+ const newWsStart = longestCommonPrefix(newWsFull, delWsStart);
2059
+ deletion.value = removePrefix(deletion.value, newWsStart);
2060
+ const newWsEnd = longestCommonSuffix(removePrefix(newWsFull, newWsStart), delWsEnd);
2061
+ deletion.value = removeSuffix(deletion.value, newWsEnd);
2062
+ endKeep.value = replacePrefix(endKeep.value, newWsFull, newWsEnd);
2063
+ startKeep.value = replaceSuffix(startKeep.value, newWsFull, newWsFull.slice(0, newWsFull.length - newWsEnd.length));
2064
+ } else if (endKeep) {
2065
+ const endKeepWsPrefix = leadingWs(endKeep.value, segmenter);
2066
+ const overlap = maximumOverlap(trailingWs(deletion.value, segmenter), endKeepWsPrefix);
2067
+ deletion.value = removeSuffix(deletion.value, overlap);
2068
+ } else if (startKeep) {
2069
+ const overlap = maximumOverlap(trailingWs(startKeep.value, segmenter), leadingWs(deletion.value, segmenter));
2070
+ deletion.value = removePrefix(deletion.value, overlap);
2071
+ }
2072
+ }
2073
+ var WordsWithSpaceDiff = class extends Diff {
2074
+ tokenize(value) {
2075
+ const regex = new RegExp(`(\\r?\\n)|[${extendedWordChars}]+|[^\\S\\n\\r]+|[^${extendedWordChars}]`, "ug");
2076
+ return value.match(regex) || [];
2077
+ }
2078
+ };
2079
+ const wordsWithSpaceDiff = new WordsWithSpaceDiff();
2080
+
2081
+ //#endregion
2082
+ //#region node_modules/diff/libesm/diff/line.js
2083
+ var LineDiff = class extends Diff {
2084
+ constructor() {
2085
+ super(...arguments);
2086
+ this.tokenize = tokenize;
2087
+ }
2088
+ equals(left, right, options) {
2089
+ if (options.ignoreWhitespace) {
2090
+ if (!options.newlineIsToken || !left.includes("\n")) left = left.trim();
2091
+ if (!options.newlineIsToken || !right.includes("\n")) right = right.trim();
2092
+ } else if (options.ignoreNewlineAtEof && !options.newlineIsToken) {
2093
+ if (left.endsWith("\n")) left = left.slice(0, -1);
2094
+ if (right.endsWith("\n")) right = right.slice(0, -1);
2095
+ }
2096
+ return super.equals(left, right, options);
2097
+ }
2098
+ };
2099
+ const lineDiff = new LineDiff();
2100
+ function diffLines(oldStr, newStr, options) {
2101
+ return lineDiff.diff(oldStr, newStr, options);
2102
+ }
2103
+ function tokenize(value, options) {
2104
+ if (options.stripTrailingCr) value = value.replace(/\r\n/g, "\n");
2105
+ const retLines = [], linesAndNewlines = value.split(/(\n|\r\n)/);
2106
+ if (!linesAndNewlines[linesAndNewlines.length - 1]) linesAndNewlines.pop();
2107
+ for (let i$1 = 0; i$1 < linesAndNewlines.length; i$1++) {
2108
+ const line = linesAndNewlines[i$1];
2109
+ if (i$1 % 2 && !options.newlineIsToken) retLines[retLines.length - 1] += line;
2110
+ else retLines.push(line);
2111
+ }
2112
+ return retLines;
2113
+ }
2114
+
2115
+ //#endregion
2116
+ //#region node_modules/diff/libesm/diff/sentence.js
2117
+ function isSentenceEndPunct(char) {
2118
+ return char == "." || char == "!" || char == "?";
2119
+ }
2120
+ var SentenceDiff = class extends Diff {
2121
+ tokenize(value) {
2122
+ var _a;
2123
+ const result = [];
2124
+ let tokenStartI = 0;
2125
+ for (let i$1 = 0; i$1 < value.length; i$1++) {
2126
+ if (i$1 == value.length - 1) {
2127
+ result.push(value.slice(tokenStartI));
2128
+ break;
2129
+ }
2130
+ if (isSentenceEndPunct(value[i$1]) && value[i$1 + 1].match(/\s/)) {
2131
+ result.push(value.slice(tokenStartI, i$1 + 1));
2132
+ i$1 = tokenStartI = i$1 + 1;
2133
+ while ((_a = value[i$1 + 1]) === null || _a === void 0 ? void 0 : _a.match(/\s/)) i$1++;
2134
+ result.push(value.slice(tokenStartI, i$1 + 1));
2135
+ tokenStartI = i$1 + 1;
2136
+ }
2137
+ }
2138
+ return result;
2139
+ }
2140
+ };
2141
+ const sentenceDiff = new SentenceDiff();
2142
+
2143
+ //#endregion
2144
+ //#region node_modules/diff/libesm/diff/css.js
2145
+ var CssDiff = class extends Diff {
2146
+ tokenize(value) {
2147
+ return value.split(/([{}:;,]|\s+)/);
2148
+ }
2149
+ };
2150
+ const cssDiff = new CssDiff();
2151
+
2152
+ //#endregion
2153
+ //#region node_modules/diff/libesm/diff/json.js
2154
+ var JsonDiff = class extends Diff {
2155
+ constructor() {
2156
+ super(...arguments);
2157
+ this.tokenize = tokenize;
2158
+ }
2159
+ get useLongestToken() {
2160
+ return true;
2161
+ }
2162
+ castInput(value, options) {
2163
+ const { undefinedReplacement, stringifyReplacer = (k, v) => typeof v === "undefined" ? undefinedReplacement : v } = options;
2164
+ return typeof value === "string" ? value : JSON.stringify(canonicalize(value, null, null, stringifyReplacer), null, " ");
2165
+ }
2166
+ equals(left, right, options) {
2167
+ return super.equals(left.replace(/,([\r\n])/g, "$1"), right.replace(/,([\r\n])/g, "$1"), options);
2168
+ }
2169
+ };
2170
+ const jsonDiff = new JsonDiff();
2171
+ function canonicalize(obj, stack, replacementStack, replacer, key) {
2172
+ stack = stack || [];
2173
+ replacementStack = replacementStack || [];
2174
+ if (replacer) obj = replacer(key === void 0 ? "" : key, obj);
2175
+ let i$1;
2176
+ for (i$1 = 0; i$1 < stack.length; i$1 += 1) if (stack[i$1] === obj) return replacementStack[i$1];
2177
+ let canonicalizedObj;
2178
+ if ("[object Array]" === Object.prototype.toString.call(obj)) {
2179
+ stack.push(obj);
2180
+ canonicalizedObj = new Array(obj.length);
2181
+ replacementStack.push(canonicalizedObj);
2182
+ for (i$1 = 0; i$1 < obj.length; i$1 += 1) canonicalizedObj[i$1] = canonicalize(obj[i$1], stack, replacementStack, replacer, String(i$1));
2183
+ stack.pop();
2184
+ replacementStack.pop();
2185
+ return canonicalizedObj;
2186
+ }
2187
+ if (obj && obj.toJSON) obj = obj.toJSON();
2188
+ if (typeof obj === "object" && obj !== null) {
2189
+ stack.push(obj);
2190
+ canonicalizedObj = {};
2191
+ replacementStack.push(canonicalizedObj);
2192
+ const sortedKeys = [];
2193
+ let key$1;
2194
+ for (key$1 in obj)
2195
+ /* istanbul ignore else */
2196
+ if (Object.prototype.hasOwnProperty.call(obj, key$1)) sortedKeys.push(key$1);
2197
+ sortedKeys.sort();
2198
+ for (i$1 = 0; i$1 < sortedKeys.length; i$1 += 1) {
2199
+ key$1 = sortedKeys[i$1];
2200
+ canonicalizedObj[key$1] = canonicalize(obj[key$1], stack, replacementStack, replacer, key$1);
2201
+ }
2202
+ stack.pop();
2203
+ replacementStack.pop();
2204
+ } else canonicalizedObj = obj;
2205
+ return canonicalizedObj;
2206
+ }
2207
+
2208
+ //#endregion
2209
+ //#region node_modules/diff/libesm/diff/array.js
2210
+ var ArrayDiff = class extends Diff {
2211
+ tokenize(value) {
2212
+ return value.slice();
2213
+ }
2214
+ join(value) {
2215
+ return value;
2216
+ }
2217
+ removeEmpty(value) {
2218
+ return value;
2219
+ }
2220
+ };
2221
+ const arrayDiff = new ArrayDiff();
2222
+
2223
+ //#endregion
2224
+ //#region node_modules/diff/libesm/patch/create.js
2225
+ function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options) {
2226
+ let optionsObj;
2227
+ if (!options) optionsObj = {};
2228
+ else if (typeof options === "function") optionsObj = { callback: options };
2229
+ else optionsObj = options;
2230
+ if (typeof optionsObj.context === "undefined") optionsObj.context = 4;
2231
+ const context = optionsObj.context;
2232
+ if (optionsObj.newlineIsToken) throw new Error("newlineIsToken may not be used with patch-generation functions, only with diffing functions");
2233
+ if (!optionsObj.callback) return diffLinesResultToPatch(diffLines(oldStr, newStr, optionsObj));
2234
+ else {
2235
+ const { callback } = optionsObj;
2236
+ diffLines(oldStr, newStr, Object.assign(Object.assign({}, optionsObj), { callback: (diff$1) => {
2237
+ callback(diffLinesResultToPatch(diff$1));
2238
+ } }));
2239
+ }
2240
+ function diffLinesResultToPatch(diff$1) {
2241
+ if (!diff$1) return;
2242
+ diff$1.push({
2243
+ value: "",
2244
+ lines: []
2245
+ });
2246
+ function contextLines(lines) {
2247
+ return lines.map(function(entry) {
2248
+ return " " + entry;
2249
+ });
2250
+ }
2251
+ const hunks = [];
2252
+ let oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1;
2253
+ for (let i$1 = 0; i$1 < diff$1.length; i$1++) {
2254
+ const current = diff$1[i$1], lines = current.lines || splitLines(current.value);
2255
+ current.lines = lines;
2256
+ if (current.added || current.removed) {
2257
+ if (!oldRangeStart) {
2258
+ const prev = diff$1[i$1 - 1];
2259
+ oldRangeStart = oldLine;
2260
+ newRangeStart = newLine;
2261
+ if (prev) {
2262
+ curRange = context > 0 ? contextLines(prev.lines.slice(-context)) : [];
2263
+ oldRangeStart -= curRange.length;
2264
+ newRangeStart -= curRange.length;
2265
+ }
2266
+ }
2267
+ for (const line of lines) curRange.push((current.added ? "+" : "-") + line);
2268
+ if (current.added) newLine += lines.length;
2269
+ else oldLine += lines.length;
2270
+ } else {
2271
+ if (oldRangeStart) if (lines.length <= context * 2 && i$1 < diff$1.length - 2) for (const line of contextLines(lines)) curRange.push(line);
2272
+ else {
2273
+ const contextSize = Math.min(lines.length, context);
2274
+ for (const line of contextLines(lines.slice(0, contextSize))) curRange.push(line);
2275
+ const hunk = {
2276
+ oldStart: oldRangeStart,
2277
+ oldLines: oldLine - oldRangeStart + contextSize,
2278
+ newStart: newRangeStart,
2279
+ newLines: newLine - newRangeStart + contextSize,
2280
+ lines: curRange
2281
+ };
2282
+ hunks.push(hunk);
2283
+ oldRangeStart = 0;
2284
+ newRangeStart = 0;
2285
+ curRange = [];
2286
+ }
2287
+ oldLine += lines.length;
2288
+ newLine += lines.length;
2289
+ }
2290
+ }
2291
+ for (const hunk of hunks) for (let i$1 = 0; i$1 < hunk.lines.length; i$1++) if (hunk.lines[i$1].endsWith("\n")) hunk.lines[i$1] = hunk.lines[i$1].slice(0, -1);
2292
+ else {
2293
+ hunk.lines.splice(i$1 + 1, 0, "\");
2294
+ i$1++;
2295
+ }
2296
+ return {
2297
+ oldFileName,
2298
+ newFileName,
2299
+ oldHeader,
2300
+ newHeader,
2301
+ hunks
2302
+ };
2303
+ }
2304
+ }
2305
+ /**
2306
+ * Split `text` into an array of lines, including the trailing newline character (where present)
2307
+ */
2308
+ function splitLines(text) {
2309
+ const hasTrailingNl = text.endsWith("\n");
2310
+ const result = text.split("\n").map((line) => line + "\n");
2311
+ if (hasTrailingNl) result.pop();
2312
+ else result.push(result.pop().slice(0, -1));
2313
+ return result;
2314
+ }
2315
+
1564
2316
  //#endregion
1565
2317
  //#region src/commands/setup/agents/diff.ts
1566
- async function diff(plan) {
2318
+ async function diff(plan, state) {
1567
2319
  const probes = new Probes();
1568
2320
  const sections = [];
1569
2321
  for (const group of plan.groups) {
1570
2322
  const changes = [];
1571
- for (const artifact of group.artifacts) changes.push(await changeFor(artifact, plan.archiveDir, probes));
2323
+ for (const artifact of group.artifacts) changes.push(await changeFor(artifact, plan.archiveDir, state, probes));
1572
2324
  sections.push({
1573
2325
  title: group.section,
1574
2326
  changes
@@ -1576,29 +2328,62 @@ async function diff(plan) {
1576
2328
  }
1577
2329
  return sections;
1578
2330
  }
1579
- function changeFor(a$1, archiveDir, probes) {
2331
+ function changeFor(a$1, archiveDir, state, probes) {
1580
2332
  switch (a$1.kind) {
1581
- case "file": return fileChange(a$1);
2333
+ case "file": return fileChange(a$1, archiveDir, state);
1582
2334
  case "symlink": return symlinkChange(a$1);
1583
- case "jsonMerge": return jsonMergeChange(a$1, archiveDir);
2335
+ case "jsonMerge": return jsonMergeChange(a$1, archiveDir, state);
1584
2336
  case "install": return installChange(a$1, probes);
1585
2337
  }
1586
2338
  }
1587
- async function fileChange(a$1) {
2339
+ async function fileChange(a$1, archiveDir, state) {
1588
2340
  const next = await readFile(a$1.src);
1589
- if ((await readFile(a$1.dest).catch(() => null))?.equals(next)) return {
2341
+ const current = await readFile(a$1.dest).catch(() => null);
2342
+ const record$1 = {
2343
+ file: a$1.dest,
2344
+ hash: hashContent(next)
2345
+ };
2346
+ if (current?.equals(next)) return {
1590
2347
  status: "unchanged",
1591
- label: a$1.dest
2348
+ label: a$1.dest,
2349
+ record: record$1
2350
+ };
2351
+ const action = {
2352
+ do: "write-file",
2353
+ src: a$1.src,
2354
+ dest: a$1.dest,
2355
+ ...a$1.mode && { mode: a$1.mode }
2356
+ };
2357
+ if (current === null && a$1.dest in state.files) return {
2358
+ status: "conflict",
2359
+ label: a$1.dest,
2360
+ summary: "was deleted on this machine",
2361
+ diffText: unified(basename(a$1.dest), "", next.toString()),
2362
+ apply: {
2363
+ action,
2364
+ record: record$1
2365
+ },
2366
+ keep: null
2367
+ };
2368
+ if (current !== null && state.files[a$1.dest] !== hashContent(current)) return {
2369
+ status: "conflict",
2370
+ label: a$1.dest,
2371
+ summary: "has content setup did not write",
2372
+ diffText: unified(basename(a$1.dest), current.toString(), next.toString()),
2373
+ apply: {
2374
+ action: {
2375
+ ...action,
2376
+ backupTo: archiveDir
2377
+ },
2378
+ record: record$1
2379
+ },
2380
+ keep: null
1592
2381
  };
1593
2382
  return {
1594
2383
  status: "pending",
1595
2384
  label: a$1.dest,
1596
- action: {
1597
- do: "write-file",
1598
- src: a$1.src,
1599
- dest: a$1.dest,
1600
- ...a$1.mode && { mode: a$1.mode }
1601
- }
2385
+ action,
2386
+ record: record$1
1602
2387
  };
1603
2388
  }
1604
2389
  async function symlinkChange(a$1) {
@@ -1613,7 +2398,8 @@ async function symlinkChange(a$1) {
1613
2398
  label,
1614
2399
  action: link
1615
2400
  };
1616
- if ((await lstat(a$1.linkPath)).isSymbolicLink()) {
2401
+ const st = await lstat(a$1.linkPath);
2402
+ if (st.isSymbolicLink()) {
1617
2403
  if (await readlink(a$1.linkPath) === a$1.target) return {
1618
2404
  status: "unchanged",
1619
2405
  label
@@ -1634,49 +2420,106 @@ async function symlinkChange(a$1) {
1634
2420
  };
1635
2421
  const archiveTo = join(a$1.archiveDisplaced, basename(a$1.linkPath));
1636
2422
  return {
1637
- status: "pending",
2423
+ status: "conflict",
1638
2424
  label,
1639
- action: {
2425
+ summary: `a real ${st.isDirectory() ? "directory" : "file"} sits where the link goes`,
2426
+ diffText: "",
2427
+ apply: { action: {
1640
2428
  ...link,
1641
2429
  archiveTo
1642
- }
2430
+ } },
2431
+ keep: null
1643
2432
  };
1644
2433
  }
1645
- async function jsonMergeChange(a$1, archiveDir) {
2434
+ async function jsonMergeChange(a$1, archiveDir, state) {
1646
2435
  const label = basename(a$1.dest);
1647
2436
  const raw = await readFile(a$1.dest, "utf8").catch(() => null);
1648
2437
  let current = {};
1649
- if (raw !== null) try {
1650
- current = JSON.parse(raw);
1651
- } catch {
1652
- return {
2438
+ if (raw !== null) {
2439
+ let parsed;
2440
+ try {
2441
+ parsed = JSON.parse(raw);
2442
+ } catch {
2443
+ return {
2444
+ status: "blocked",
2445
+ label,
2446
+ reason: "not parseable JSON (comments?)"
2447
+ };
2448
+ }
2449
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {
1653
2450
  status: "blocked",
1654
2451
  label,
1655
- reason: "not parseable JSON (comments?)"
2452
+ reason: "not a JSON object"
1656
2453
  };
2454
+ current = parsed;
1657
2455
  }
1658
- const value = {
1659
- ...current,
2456
+ const desired = {
1660
2457
  ...a$1.managed,
1661
2458
  ...a$1.derived
1662
2459
  };
2460
+ const value = {
2461
+ ...current,
2462
+ ...desired
2463
+ };
2464
+ const record$1 = {
2465
+ file: a$1.dest,
2466
+ keys: Object.fromEntries(Object.keys(desired).map((k) => [k, hashValue(desired[k])]))
2467
+ };
1663
2468
  if (stable(current) === stable(value)) return {
1664
2469
  status: "unchanged",
1665
- label
2470
+ label,
2471
+ record: record$1
1666
2472
  };
1667
2473
  const notes = Object.keys(value).filter((k) => stable(current[k]) !== stable(value[k])).map((k) => `set ${k}${k in a$1.derived ? " (derived)" : ""}`);
1668
2474
  const unmanaged = Object.keys(current).filter((k) => !(k in a$1.managed) && !(k in a$1.derived));
1669
2475
  if (unmanaged.length) notes.push(`preserved unmanaged keys: ${unmanaged.join(", ")}`);
1670
- return {
2476
+ const action = {
2477
+ do: "write-json",
2478
+ dest: a$1.dest,
2479
+ value,
2480
+ backupTo: archiveDir
2481
+ };
2482
+ const ours = state.keys[a$1.dest] ?? {};
2483
+ const contested = Object.keys(desired).filter((k) => {
2484
+ if (stable(current[k]) === stable(desired[k])) return false;
2485
+ if (k in current) return ours[k] !== hashValue(current[k]);
2486
+ return k in ours;
2487
+ });
2488
+ if (!contested.length) return {
1671
2489
  status: "pending",
1672
2490
  label,
2491
+ action,
2492
+ notes,
2493
+ record: record$1
2494
+ };
2495
+ const keepValue = { ...value };
2496
+ for (const k of contested) if (k in current) keepValue[k] = current[k];
2497
+ else delete keepValue[k];
2498
+ const keepRecord = {
2499
+ file: a$1.dest,
2500
+ keys: Object.fromEntries(Object.entries(record$1.keys).filter(([k]) => !contested.includes(k)))
2501
+ };
2502
+ const keep = stable(keepValue) === stable(current) ? null : {
1673
2503
  action: {
1674
2504
  do: "write-json",
1675
2505
  dest: a$1.dest,
1676
- value,
2506
+ value: keepValue,
1677
2507
  backupTo: archiveDir
1678
2508
  },
1679
- notes
2509
+ record: keepRecord,
2510
+ notes: [`kept your values: ${contested.join(", ")}`]
2511
+ };
2512
+ return {
2513
+ status: "conflict",
2514
+ label,
2515
+ summary: `set outside setup: ${contested.join(", ")}`,
2516
+ diffText: contested.map((k) => unified(k, k in current ? pretty(current[k]) : "", pretty(desired[k]))).join("\n"),
2517
+ apply: {
2518
+ action,
2519
+ record: record$1,
2520
+ notes
2521
+ },
2522
+ keep
1680
2523
  };
1681
2524
  }
1682
2525
  async function installChange(a$1, probes) {
@@ -1698,6 +2541,18 @@ async function installChange(a$1, probes) {
1698
2541
  }
1699
2542
  };
1700
2543
  }
2544
+ function pretty(value) {
2545
+ return `${JSON.stringify(value, null, 2) ?? "null"}\n`;
2546
+ }
2547
+ function unified(name$1, before, after) {
2548
+ const patch = structuredPatch(name$1, name$1, before, after);
2549
+ const lines = [`── ${name$1}`];
2550
+ for (const hunk of patch.hunks) {
2551
+ lines.push(`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`);
2552
+ lines.push(...hunk.lines);
2553
+ }
2554
+ return lines.join("\n");
2555
+ }
1701
2556
  /** Memoised machine lookups — `claude plugin list` costs a process spawn, so it runs once. */
1702
2557
  var Probes = class {
1703
2558
  onPathCache = /* @__PURE__ */ new Map();
@@ -1753,8 +2608,11 @@ var Probes = class {
1753
2608
  //#endregion
1754
2609
  //#region src/commands/setup/agents/executor.ts
1755
2610
  /** The one place `dryRun` is consulted: the same diff is either printed or committed. */
1756
- async function runPlan(plan, dryRun) {
1757
- await walk(await diff(plan), dryRun ? render : commit);
2611
+ async function runPlan(plan, dryRun, resolve$1) {
2612
+ const state = await loadState(plan.stateFile);
2613
+ const before = stable(state);
2614
+ await walk(await diff(plan, state), dryRun ? render : (change) => commit(change, state, resolve$1));
2615
+ if (!dryRun && stable(state) !== before) await saveState(plan.stateFile, state);
1758
2616
  }
1759
2617
  async function walk(sections, handle) {
1760
2618
  for (const { title, changes } of sections) {
@@ -1769,29 +2627,59 @@ function render(change) {
1769
2627
  case "pending":
1770
2628
  log.plan(phrase(change.action));
1771
2629
  for (const note of change.notes ?? []) log.info(note);
2630
+ return;
2631
+ case "conflict":
2632
+ log.warn(`conflict: ${change.label} — ${change.summary}`);
2633
+ log.info("will ask keep / use config / show diff (piped runs keep; --force uses config)");
1772
2634
  }
1773
2635
  }
1774
- async function commit(change) {
2636
+ async function commit(change, state, resolve$1) {
1775
2637
  switch (change.status) {
1776
- case "unchanged": return log.skip(`${change.label} (unchanged)`);
2638
+ case "unchanged":
2639
+ record(state, change.record);
2640
+ return log.skip(`${change.label} (unchanged)`);
1777
2641
  case "blocked": return log.fail(`${change.label} — ${change.reason}, leaving it alone`);
1778
2642
  case "pending": {
1779
2643
  const { ok, notes } = await perform(change.action);
1780
2644
  if (!ok) return log.fail(`${change.label}: ${notes.join(" ")}`);
2645
+ record(state, change.record);
1781
2646
  log.ok(change.label);
1782
2647
  for (const note of [...notes, ...change.notes ?? []]) log.info(note);
2648
+ return;
2649
+ }
2650
+ case "conflict": {
2651
+ const outcome = await resolve$1(change) === "apply" ? change.apply : change.keep;
2652
+ if (!outcome) return log.warn(`${change.label} — ${change.summary}; kept as-is (resolve interactively or with --force)`);
2653
+ const { ok, notes } = await perform(outcome.action);
2654
+ if (!ok) return log.fail(`${change.label}: ${notes.join(" ")}`);
2655
+ record(state, outcome.record);
2656
+ log.ok(change.label);
2657
+ for (const note of [...notes, ...outcome.notes ?? []]) log.info(note);
1783
2658
  }
1784
2659
  }
1785
2660
  }
2661
+ function record(state, entry) {
2662
+ if (!entry) return;
2663
+ if ("hash" in entry) state.files[entry.file] = entry.hash;
2664
+ else state.keys[entry.file] = {
2665
+ ...state.keys[entry.file],
2666
+ ...entry.keys
2667
+ };
2668
+ }
1786
2669
  async function perform(action) {
1787
2670
  switch (action.do) {
1788
2671
  case "write-file": {
2672
+ const notes = [];
2673
+ if (action.backupTo) {
2674
+ const bak = await backup(action.dest, action.backupTo);
2675
+ if (bak) notes.push(`backed up → ${bak}`);
2676
+ }
1789
2677
  const bytes = await readFile(action.src);
1790
2678
  await ensureDir(dirname(action.dest));
1791
2679
  await writeFile(action.dest, bytes, action.mode ? { mode: action.mode } : void 0);
1792
2680
  return {
1793
2681
  ok: true,
1794
- notes: []
2682
+ notes
1795
2683
  };
1796
2684
  }
1797
2685
  case "link": {
@@ -1848,16 +2736,72 @@ function phrase(action) {
1848
2736
  }
1849
2737
  }
1850
2738
 
2739
+ //#endregion
2740
+ //#region src/commands/setup/agents/resolve.ts
2741
+ var import_picocolors$3 = /* @__PURE__ */ __toESM(require_picocolors(), 1);
2742
+ /** `--force`: the config wins every conflict, exactly as if each prompt answered "use config". */
2743
+ const forceResolver = async () => "apply";
2744
+ /** No one to ask — keep what the machine has, dpkg's default for the same reason. */
2745
+ const keepResolver = async () => "keep";
2746
+ function defaultResolver() {
2747
+ return isInteractive() ? interactiveResolver() : keepResolver;
2748
+ }
2749
+ function interactiveResolver(ask = select) {
2750
+ let rest$1 = null;
2751
+ return async (conflict) => {
2752
+ if (rest$1) return rest$1;
2753
+ for (;;) switch (await ask(`${conflict.label} — ${conflict.summary}`, [
2754
+ {
2755
+ value: "keep",
2756
+ label: "Keep what this machine has",
2757
+ hint: "asks again next run"
2758
+ },
2759
+ {
2760
+ value: "apply",
2761
+ label: "Use the config's version",
2762
+ hint: "existing is backed up"
2763
+ },
2764
+ ...conflict.diffText ? [{
2765
+ value: "diff",
2766
+ label: "Show the diff first"
2767
+ }] : [],
2768
+ {
2769
+ value: "keep-all",
2770
+ label: "Keep — here and for every remaining conflict"
2771
+ },
2772
+ {
2773
+ value: "apply-all",
2774
+ label: "Use config — here and for every remaining conflict"
2775
+ }
2776
+ ])) {
2777
+ case "diff":
2778
+ printDiff(conflict.diffText);
2779
+ continue;
2780
+ case "apply": return "apply";
2781
+ case "apply-all": return rest$1 = "apply";
2782
+ case "keep-all":
2783
+ case null: return rest$1 = "keep";
2784
+ default: return "keep";
2785
+ }
2786
+ };
2787
+ }
2788
+ function printDiff(text) {
2789
+ for (const line of text.split("\n")) if (line.startsWith("+")) console.log(` ${import_picocolors$3.default.green(line)}`);
2790
+ else if (line.startsWith("-")) console.log(` ${import_picocolors$3.default.red(line)}`);
2791
+ else if (line.startsWith("@@")) console.log(` ${import_picocolors$3.default.cyan(line)}`);
2792
+ else console.log(` ${import_picocolors$3.default.dim(line)}`);
2793
+ }
2794
+
1851
2795
  //#endregion
1852
2796
  //#region src/commands/setup/agents/apply.ts
1853
2797
  /** An agent with no config directory is not on this machine — skip it, never create it. */
1854
2798
  function isInstalled(home, emitter) {
1855
2799
  return exists(join(home, emitter.configDir));
1856
2800
  }
1857
- async function applyAgents(ctx, ids, dryRun) {
2801
+ async function applyAgents(ctx, ids, dryRun, resolve$1 = defaultResolver()) {
1858
2802
  validateExtensions(ctx.config);
1859
2803
  logCoverage(ctx.config);
1860
- await runPlan(await buildStorePlan(ctx), dryRun);
2804
+ await runPlan(await buildStorePlan(ctx), dryRun, resolve$1);
1861
2805
  for (const id of ids) {
1862
2806
  const emitter = emitters[id];
1863
2807
  if (!emitter) continue;
@@ -1866,7 +2810,7 @@ async function applyAgents(ctx, ids, dryRun) {
1866
2810
  log.warn(`${id} not installed on this machine — skipping`);
1867
2811
  continue;
1868
2812
  }
1869
- await runPlan(await emitter.buildPlan(ctx), dryRun);
2813
+ await runPlan(await emitter.buildPlan(ctx), dryRun, resolve$1);
1870
2814
  }
1871
2815
  }
1872
2816
 
@@ -1881,10 +2825,14 @@ scripted runs apply to every configured agent.
1881
2825
 
1882
2826
  plan dry run — show every change, write nothing
1883
2827
 
2828
+ Anything on the machine that setup did not write is a conflict: interactively you choose
2829
+ keep / use config / see the diff; piped runs keep the machine's version.
2830
+
1884
2831
  Options:
1885
2832
  -n, --dry-run same as plan
1886
2833
  -a, --agent <id> target one agent (repeatable) — skips the prompt
1887
2834
  --all every configured agent — skips the prompt
2835
+ --force resolve every conflict in the config's favour, no prompts
1888
2836
  --home <dir> apply against a different home directory
1889
2837
  -h, --help show this help`;
1890
2838
  const agents = {
@@ -1908,6 +2856,10 @@ const agents = {
1908
2856
  type: "boolean",
1909
2857
  default: false
1910
2858
  },
2859
+ force: {
2860
+ type: "boolean",
2861
+ default: false
2862
+ },
1911
2863
  home: { type: "string" },
1912
2864
  help: {
1913
2865
  type: "boolean",
@@ -1945,7 +2897,7 @@ const agents = {
1945
2897
  home,
1946
2898
  repoRoot: packageRoot$1,
1947
2899
  config
1948
- }, selected, dryRun);
2900
+ }, selected, dryRun, values.force ? forceResolver : defaultResolver());
1949
2901
  console.log(dryRun ? `\n${import_picocolors$2.default.yellow("dry run complete — nothing written")}\n` : `\n${import_picocolors$2.default.green("done")}\n`);
1950
2902
  return 0;
1951
2903
  }
@@ -2009,7 +2961,7 @@ async function version() {
2009
2961
  }
2010
2962
  function usage() {
2011
2963
  console.log(`Usage: pakhale <command> [options]\n\nCommands:`);
2012
- for (const c of Object.values(commands)) console.log(` ${c.name.padEnd(10)} ${c.describe}`);
2964
+ for (const c$1 of Object.values(commands)) console.log(` ${c$1.name.padEnd(10)} ${c$1.describe}`);
2013
2965
  console.log(`\nOptions:\n -h, --help show this help\n -v, --version show version`);
2014
2966
  }
2015
2967
  if (!name || name === "--help" || name === "-h") {