@quikcommit/cli 9.0.0 → 11.0.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 (2) hide show
  1. package/dist/index.js +1469 -657
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -585,13 +585,13 @@ var require_identity = __commonJS({
585
585
  var require_visit = __commonJS({
586
586
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/visit.js"(exports2) {
587
587
  "use strict";
588
- var identity = require_identity();
588
+ var identity2 = require_identity();
589
589
  var BREAK = /* @__PURE__ */ Symbol("break visit");
590
590
  var SKIP = /* @__PURE__ */ Symbol("skip children");
591
591
  var REMOVE = /* @__PURE__ */ Symbol("remove node");
592
592
  function visit(node, visitor) {
593
593
  const visitor_ = initVisitor(visitor);
594
- if (identity.isDocument(node)) {
594
+ if (identity2.isDocument(node)) {
595
595
  const cd = visit_(null, node.contents, visitor_, Object.freeze([node]));
596
596
  if (cd === REMOVE)
597
597
  node.contents = null;
@@ -603,12 +603,12 @@ var require_visit = __commonJS({
603
603
  visit.REMOVE = REMOVE;
604
604
  function visit_(key, node, visitor, path) {
605
605
  const ctrl = callVisitor(key, node, visitor, path);
606
- if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
606
+ if (identity2.isNode(ctrl) || identity2.isPair(ctrl)) {
607
607
  replaceNode(key, path, ctrl);
608
608
  return visit_(key, ctrl, visitor, path);
609
609
  }
610
610
  if (typeof ctrl !== "symbol") {
611
- if (identity.isCollection(node)) {
611
+ if (identity2.isCollection(node)) {
612
612
  path = Object.freeze(path.concat(node));
613
613
  for (let i = 0; i < node.items.length; ++i) {
614
614
  const ci = visit_(i, node.items[i], visitor, path);
@@ -621,7 +621,7 @@ var require_visit = __commonJS({
621
621
  i -= 1;
622
622
  }
623
623
  }
624
- } else if (identity.isPair(node)) {
624
+ } else if (identity2.isPair(node)) {
625
625
  path = Object.freeze(path.concat(node));
626
626
  const ck = visit_("key", node.key, visitor, path);
627
627
  if (ck === BREAK)
@@ -639,7 +639,7 @@ var require_visit = __commonJS({
639
639
  }
640
640
  async function visitAsync(node, visitor) {
641
641
  const visitor_ = initVisitor(visitor);
642
- if (identity.isDocument(node)) {
642
+ if (identity2.isDocument(node)) {
643
643
  const cd = await visitAsync_(null, node.contents, visitor_, Object.freeze([node]));
644
644
  if (cd === REMOVE)
645
645
  node.contents = null;
@@ -651,12 +651,12 @@ var require_visit = __commonJS({
651
651
  visitAsync.REMOVE = REMOVE;
652
652
  async function visitAsync_(key, node, visitor, path) {
653
653
  const ctrl = await callVisitor(key, node, visitor, path);
654
- if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
654
+ if (identity2.isNode(ctrl) || identity2.isPair(ctrl)) {
655
655
  replaceNode(key, path, ctrl);
656
656
  return visitAsync_(key, ctrl, visitor, path);
657
657
  }
658
658
  if (typeof ctrl !== "symbol") {
659
- if (identity.isCollection(node)) {
659
+ if (identity2.isCollection(node)) {
660
660
  path = Object.freeze(path.concat(node));
661
661
  for (let i = 0; i < node.items.length; ++i) {
662
662
  const ci = await visitAsync_(i, node.items[i], visitor, path);
@@ -669,7 +669,7 @@ var require_visit = __commonJS({
669
669
  i -= 1;
670
670
  }
671
671
  }
672
- } else if (identity.isPair(node)) {
672
+ } else if (identity2.isPair(node)) {
673
673
  path = Object.freeze(path.concat(node));
674
674
  const ck = await visitAsync_("key", node.key, visitor, path);
675
675
  if (ck === BREAK)
@@ -706,31 +706,31 @@ var require_visit = __commonJS({
706
706
  function callVisitor(key, node, visitor, path) {
707
707
  if (typeof visitor === "function")
708
708
  return visitor(key, node, path);
709
- if (identity.isMap(node))
709
+ if (identity2.isMap(node))
710
710
  return visitor.Map?.(key, node, path);
711
- if (identity.isSeq(node))
711
+ if (identity2.isSeq(node))
712
712
  return visitor.Seq?.(key, node, path);
713
- if (identity.isPair(node))
713
+ if (identity2.isPair(node))
714
714
  return visitor.Pair?.(key, node, path);
715
- if (identity.isScalar(node))
715
+ if (identity2.isScalar(node))
716
716
  return visitor.Scalar?.(key, node, path);
717
- if (identity.isAlias(node))
717
+ if (identity2.isAlias(node))
718
718
  return visitor.Alias?.(key, node, path);
719
719
  return void 0;
720
720
  }
721
721
  function replaceNode(key, path, node) {
722
722
  const parent = path[path.length - 1];
723
- if (identity.isCollection(parent)) {
723
+ if (identity2.isCollection(parent)) {
724
724
  parent.items[key] = node;
725
- } else if (identity.isPair(parent)) {
725
+ } else if (identity2.isPair(parent)) {
726
726
  if (key === "key")
727
727
  parent.key = node;
728
728
  else
729
729
  parent.value = node;
730
- } else if (identity.isDocument(parent)) {
730
+ } else if (identity2.isDocument(parent)) {
731
731
  parent.contents = node;
732
732
  } else {
733
- const pt = identity.isAlias(parent) ? "alias" : "scalar";
733
+ const pt = identity2.isAlias(parent) ? "alias" : "scalar";
734
734
  throw new Error(`Cannot replace node with ${pt} parent`);
735
735
  }
736
736
  }
@@ -743,7 +743,7 @@ var require_visit = __commonJS({
743
743
  var require_directives = __commonJS({
744
744
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/doc/directives.js"(exports2) {
745
745
  "use strict";
746
- var identity = require_identity();
746
+ var identity2 = require_identity();
747
747
  var visit = require_visit();
748
748
  var escapeChars = {
749
749
  "!": "%21",
@@ -886,10 +886,10 @@ var require_directives = __commonJS({
886
886
  const lines = this.yaml.explicit ? [`%YAML ${this.yaml.version || "1.2"}`] : [];
887
887
  const tagEntries = Object.entries(this.tags);
888
888
  let tagNames;
889
- if (doc && tagEntries.length > 0 && identity.isNode(doc.contents)) {
889
+ if (doc && tagEntries.length > 0 && identity2.isNode(doc.contents)) {
890
890
  const tags = {};
891
891
  visit.visit(doc.contents, (_key, node) => {
892
- if (identity.isNode(node) && node.tag)
892
+ if (identity2.isNode(node) && node.tag)
893
893
  tags[node.tag] = true;
894
894
  });
895
895
  tagNames = Object.keys(tags);
@@ -914,7 +914,7 @@ var require_directives = __commonJS({
914
914
  var require_anchors = __commonJS({
915
915
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/doc/anchors.js"(exports2) {
916
916
  "use strict";
917
- var identity = require_identity();
917
+ var identity2 = require_identity();
918
918
  var visit = require_visit();
919
919
  function anchorIsValid(anchor) {
920
920
  if (/[\x00-\x19\s,[\]{}]/.test(anchor)) {
@@ -961,7 +961,7 @@ var require_anchors = __commonJS({
961
961
  setAnchors: () => {
962
962
  for (const source of aliasObjects) {
963
963
  const ref = sourceObjects.get(source);
964
- if (typeof ref === "object" && ref.anchor && (identity.isScalar(ref.node) || identity.isCollection(ref.node))) {
964
+ if (typeof ref === "object" && ref.anchor && (identity2.isScalar(ref.node) || identity2.isCollection(ref.node))) {
965
965
  ref.node.anchor = ref.anchor;
966
966
  } else {
967
967
  const error = new Error("Failed to resolve repeated object (this should not happen)");
@@ -1034,12 +1034,12 @@ var require_applyReviver = __commonJS({
1034
1034
  var require_toJS = __commonJS({
1035
1035
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/nodes/toJS.js"(exports2) {
1036
1036
  "use strict";
1037
- var identity = require_identity();
1037
+ var identity2 = require_identity();
1038
1038
  function toJS(value, arg, ctx) {
1039
1039
  if (Array.isArray(value))
1040
1040
  return value.map((v, i) => toJS(v, String(i), ctx));
1041
1041
  if (value && typeof value.toJSON === "function") {
1042
- if (!ctx || !identity.hasAnchor(value))
1042
+ if (!ctx || !identity2.hasAnchor(value))
1043
1043
  return value.toJSON(arg, ctx);
1044
1044
  const data = { aliasCount: 0, count: 1, res: void 0 };
1045
1045
  ctx.anchors.set(value, data);
@@ -1065,11 +1065,11 @@ var require_Node = __commonJS({
1065
1065
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/nodes/Node.js"(exports2) {
1066
1066
  "use strict";
1067
1067
  var applyReviver = require_applyReviver();
1068
- var identity = require_identity();
1068
+ var identity2 = require_identity();
1069
1069
  var toJS = require_toJS();
1070
1070
  var NodeBase = class {
1071
1071
  constructor(type) {
1072
- Object.defineProperty(this, identity.NODE_TYPE, { value: type });
1072
+ Object.defineProperty(this, identity2.NODE_TYPE, { value: type });
1073
1073
  }
1074
1074
  /** Create a copy of this node. */
1075
1075
  clone() {
@@ -1080,7 +1080,7 @@ var require_Node = __commonJS({
1080
1080
  }
1081
1081
  /** A plain JavaScript representation of this node. */
1082
1082
  toJS(doc, { mapAsMap, maxAliasCount, onAnchor, reviver } = {}) {
1083
- if (!identity.isDocument(doc))
1083
+ if (!identity2.isDocument(doc))
1084
1084
  throw new TypeError("A document argument is required");
1085
1085
  const ctx = {
1086
1086
  anchors: /* @__PURE__ */ new Map(),
@@ -1107,12 +1107,12 @@ var require_Alias = __commonJS({
1107
1107
  "use strict";
1108
1108
  var anchors = require_anchors();
1109
1109
  var visit = require_visit();
1110
- var identity = require_identity();
1110
+ var identity2 = require_identity();
1111
1111
  var Node = require_Node();
1112
1112
  var toJS = require_toJS();
1113
1113
  var Alias = class extends Node.NodeBase {
1114
1114
  constructor(source) {
1115
- super(identity.ALIAS);
1115
+ super(identity2.ALIAS);
1116
1116
  this.source = source;
1117
1117
  Object.defineProperty(this, "tag", {
1118
1118
  set() {
@@ -1134,7 +1134,7 @@ var require_Alias = __commonJS({
1134
1134
  nodes = [];
1135
1135
  visit.visit(doc, {
1136
1136
  Node: (_key, node) => {
1137
- if (identity.isAlias(node) || identity.hasAnchor(node))
1137
+ if (identity2.isAlias(node) || identity2.hasAnchor(node))
1138
1138
  nodes.push(node);
1139
1139
  }
1140
1140
  });
@@ -1194,11 +1194,11 @@ var require_Alias = __commonJS({
1194
1194
  }
1195
1195
  };
1196
1196
  function getAliasCount(doc, node, anchors2) {
1197
- if (identity.isAlias(node)) {
1197
+ if (identity2.isAlias(node)) {
1198
1198
  const source = node.resolve(doc);
1199
1199
  const anchor = anchors2 && source && anchors2.get(source);
1200
1200
  return anchor ? anchor.count * anchor.aliasCount : 0;
1201
- } else if (identity.isCollection(node)) {
1201
+ } else if (identity2.isCollection(node)) {
1202
1202
  let count = 0;
1203
1203
  for (const item of node.items) {
1204
1204
  const c = getAliasCount(doc, item, anchors2);
@@ -1206,7 +1206,7 @@ var require_Alias = __commonJS({
1206
1206
  count = c;
1207
1207
  }
1208
1208
  return count;
1209
- } else if (identity.isPair(node)) {
1209
+ } else if (identity2.isPair(node)) {
1210
1210
  const kc = getAliasCount(doc, node.key, anchors2);
1211
1211
  const vc = getAliasCount(doc, node.value, anchors2);
1212
1212
  return Math.max(kc, vc);
@@ -1221,13 +1221,13 @@ var require_Alias = __commonJS({
1221
1221
  var require_Scalar = __commonJS({
1222
1222
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/nodes/Scalar.js"(exports2) {
1223
1223
  "use strict";
1224
- var identity = require_identity();
1224
+ var identity2 = require_identity();
1225
1225
  var Node = require_Node();
1226
1226
  var toJS = require_toJS();
1227
1227
  var isScalarValue = (value) => !value || typeof value !== "function" && typeof value !== "object";
1228
1228
  var Scalar = class extends Node.NodeBase {
1229
1229
  constructor(value) {
1230
- super(identity.SCALAR);
1230
+ super(identity2.SCALAR);
1231
1231
  this.value = value;
1232
1232
  }
1233
1233
  toJSON(arg, ctx) {
@@ -1252,7 +1252,7 @@ var require_createNode = __commonJS({
1252
1252
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/doc/createNode.js"(exports2) {
1253
1253
  "use strict";
1254
1254
  var Alias = require_Alias();
1255
- var identity = require_identity();
1255
+ var identity2 = require_identity();
1256
1256
  var Scalar = require_Scalar();
1257
1257
  var defaultTagPrefix = "tag:yaml.org,2002:";
1258
1258
  function findTagObject(value, tagName, tags) {
@@ -1266,12 +1266,12 @@ var require_createNode = __commonJS({
1266
1266
  return tags.find((t) => t.identify?.(value) && !t.format);
1267
1267
  }
1268
1268
  function createNode(value, tagName, ctx) {
1269
- if (identity.isDocument(value))
1269
+ if (identity2.isDocument(value))
1270
1270
  value = value.contents;
1271
- if (identity.isNode(value))
1271
+ if (identity2.isNode(value))
1272
1272
  return value;
1273
- if (identity.isPair(value)) {
1274
- const map = ctx.schema[identity.MAP].createNode?.(ctx.schema, null, ctx);
1273
+ if (identity2.isPair(value)) {
1274
+ const map = ctx.schema[identity2.MAP].createNode?.(ctx.schema, null, ctx);
1275
1275
  map.items.push(value);
1276
1276
  return map;
1277
1277
  }
@@ -1303,7 +1303,7 @@ var require_createNode = __commonJS({
1303
1303
  ref.node = node2;
1304
1304
  return node2;
1305
1305
  }
1306
- tagObj = value instanceof Map ? schema[identity.MAP] : Symbol.iterator in Object(value) ? schema[identity.SEQ] : schema[identity.MAP];
1306
+ tagObj = value instanceof Map ? schema[identity2.MAP] : Symbol.iterator in Object(value) ? schema[identity2.SEQ] : schema[identity2.MAP];
1307
1307
  }
1308
1308
  if (onTagObj) {
1309
1309
  onTagObj(tagObj);
@@ -1327,7 +1327,7 @@ var require_Collection = __commonJS({
1327
1327
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/nodes/Collection.js"(exports2) {
1328
1328
  "use strict";
1329
1329
  var createNode = require_createNode();
1330
- var identity = require_identity();
1330
+ var identity2 = require_identity();
1331
1331
  var Node = require_Node();
1332
1332
  function collectionFromPath(schema, path, value) {
1333
1333
  let v = value;
@@ -1371,7 +1371,7 @@ var require_Collection = __commonJS({
1371
1371
  const copy = Object.create(Object.getPrototypeOf(this), Object.getOwnPropertyDescriptors(this));
1372
1372
  if (schema)
1373
1373
  copy.schema = schema;
1374
- copy.items = copy.items.map((it) => identity.isNode(it) || identity.isPair(it) ? it.clone(schema) : it);
1374
+ copy.items = copy.items.map((it) => identity2.isNode(it) || identity2.isPair(it) ? it.clone(schema) : it);
1375
1375
  if (this.range)
1376
1376
  copy.range = this.range.slice();
1377
1377
  return copy;
@@ -1387,7 +1387,7 @@ var require_Collection = __commonJS({
1387
1387
  else {
1388
1388
  const [key, ...rest] = path;
1389
1389
  const node = this.get(key, true);
1390
- if (identity.isCollection(node))
1390
+ if (identity2.isCollection(node))
1391
1391
  node.addIn(rest, value);
1392
1392
  else if (node === void 0 && this.schema)
1393
1393
  this.set(key, collectionFromPath(this.schema, rest, value));
@@ -1404,7 +1404,7 @@ var require_Collection = __commonJS({
1404
1404
  if (rest.length === 0)
1405
1405
  return this.delete(key);
1406
1406
  const node = this.get(key, true);
1407
- if (identity.isCollection(node))
1407
+ if (identity2.isCollection(node))
1408
1408
  return node.deleteIn(rest);
1409
1409
  else
1410
1410
  throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
@@ -1418,16 +1418,16 @@ var require_Collection = __commonJS({
1418
1418
  const [key, ...rest] = path;
1419
1419
  const node = this.get(key, true);
1420
1420
  if (rest.length === 0)
1421
- return !keepScalar && identity.isScalar(node) ? node.value : node;
1421
+ return !keepScalar && identity2.isScalar(node) ? node.value : node;
1422
1422
  else
1423
- return identity.isCollection(node) ? node.getIn(rest, keepScalar) : void 0;
1423
+ return identity2.isCollection(node) ? node.getIn(rest, keepScalar) : void 0;
1424
1424
  }
1425
1425
  hasAllNullValues(allowScalar) {
1426
1426
  return this.items.every((node) => {
1427
- if (!identity.isPair(node))
1427
+ if (!identity2.isPair(node))
1428
1428
  return false;
1429
1429
  const n = node.value;
1430
- return n == null || allowScalar && identity.isScalar(n) && n.value == null && !n.commentBefore && !n.comment && !n.tag;
1430
+ return n == null || allowScalar && identity2.isScalar(n) && n.value == null && !n.commentBefore && !n.comment && !n.tag;
1431
1431
  });
1432
1432
  }
1433
1433
  /**
@@ -1438,7 +1438,7 @@ var require_Collection = __commonJS({
1438
1438
  if (rest.length === 0)
1439
1439
  return this.has(key);
1440
1440
  const node = this.get(key, true);
1441
- return identity.isCollection(node) ? node.hasIn(rest) : false;
1441
+ return identity2.isCollection(node) ? node.hasIn(rest) : false;
1442
1442
  }
1443
1443
  /**
1444
1444
  * Sets a value in this collection. For `!!set`, `value` needs to be a
@@ -1450,7 +1450,7 @@ var require_Collection = __commonJS({
1450
1450
  this.set(key, value);
1451
1451
  } else {
1452
1452
  const node = this.get(key, true);
1453
- if (identity.isCollection(node))
1453
+ if (identity2.isCollection(node))
1454
1454
  node.setIn(rest, value);
1455
1455
  else if (node === void 0 && this.schema)
1456
1456
  this.set(key, collectionFromPath(this.schema, rest, value));
@@ -1906,7 +1906,7 @@ var require_stringify = __commonJS({
1906
1906
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/stringify/stringify.js"(exports2) {
1907
1907
  "use strict";
1908
1908
  var anchors = require_anchors();
1909
- var identity = require_identity();
1909
+ var identity2 = require_identity();
1910
1910
  var stringifyComment = require_stringifyComment();
1911
1911
  var stringifyString = require_stringifyString();
1912
1912
  function createStringifyContext(doc, options) {
@@ -1959,7 +1959,7 @@ var require_stringify = __commonJS({
1959
1959
  }
1960
1960
  let tagObj = void 0;
1961
1961
  let obj;
1962
- if (identity.isScalar(item)) {
1962
+ if (identity2.isScalar(item)) {
1963
1963
  obj = item.value;
1964
1964
  let match = tags.filter((t) => t.identify?.(obj));
1965
1965
  if (match.length > 1) {
@@ -1982,7 +1982,7 @@ var require_stringify = __commonJS({
1982
1982
  if (!doc.directives)
1983
1983
  return "";
1984
1984
  const props = [];
1985
- const anchor = (identity.isScalar(node) || identity.isCollection(node)) && node.anchor;
1985
+ const anchor = (identity2.isScalar(node) || identity2.isCollection(node)) && node.anchor;
1986
1986
  if (anchor && anchors.anchorIsValid(anchor)) {
1987
1987
  anchors$1.add(anchor);
1988
1988
  props.push(`&${anchor}`);
@@ -1993,9 +1993,9 @@ var require_stringify = __commonJS({
1993
1993
  return props.join(" ");
1994
1994
  }
1995
1995
  function stringify(item, ctx, onComment, onChompKeep) {
1996
- if (identity.isPair(item))
1996
+ if (identity2.isPair(item))
1997
1997
  return item.toString(ctx, onComment, onChompKeep);
1998
- if (identity.isAlias(item)) {
1998
+ if (identity2.isAlias(item)) {
1999
1999
  if (ctx.doc.directives)
2000
2000
  return item.toString(ctx);
2001
2001
  if (ctx.resolvedAliases?.has(item)) {
@@ -2009,15 +2009,15 @@ var require_stringify = __commonJS({
2009
2009
  }
2010
2010
  }
2011
2011
  let tagObj = void 0;
2012
- const node = identity.isNode(item) ? item : ctx.doc.createNode(item, { onTagObj: (o) => tagObj = o });
2012
+ const node = identity2.isNode(item) ? item : ctx.doc.createNode(item, { onTagObj: (o) => tagObj = o });
2013
2013
  tagObj ?? (tagObj = getTagObject(ctx.doc.schema.tags, node));
2014
2014
  const props = stringifyProps(node, tagObj, ctx);
2015
2015
  if (props.length > 0)
2016
2016
  ctx.indentAtStart = (ctx.indentAtStart ?? 0) + props.length + 1;
2017
- const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node, ctx, onComment, onChompKeep) : identity.isScalar(node) ? stringifyString.stringifyString(node, ctx, onComment, onChompKeep) : node.toString(ctx, onComment, onChompKeep);
2017
+ const str = typeof tagObj.stringify === "function" ? tagObj.stringify(node, ctx, onComment, onChompKeep) : identity2.isScalar(node) ? stringifyString.stringifyString(node, ctx, onComment, onChompKeep) : node.toString(ctx, onComment, onChompKeep);
2018
2018
  if (!props)
2019
2019
  return str;
2020
- return identity.isScalar(node) || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}
2020
+ return identity2.isScalar(node) || str[0] === "{" || str[0] === "[" ? `${props} ${str}` : `${props}
2021
2021
  ${ctx.indent}${str}`;
2022
2022
  }
2023
2023
  exports2.createStringifyContext = createStringifyContext;
@@ -2029,23 +2029,23 @@ ${ctx.indent}${str}`;
2029
2029
  var require_stringifyPair = __commonJS({
2030
2030
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyPair.js"(exports2) {
2031
2031
  "use strict";
2032
- var identity = require_identity();
2032
+ var identity2 = require_identity();
2033
2033
  var Scalar = require_Scalar();
2034
2034
  var stringify = require_stringify();
2035
2035
  var stringifyComment = require_stringifyComment();
2036
2036
  function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
2037
2037
  const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
2038
- let keyComment = identity.isNode(key) && key.comment || null;
2038
+ let keyComment = identity2.isNode(key) && key.comment || null;
2039
2039
  if (simpleKeys) {
2040
2040
  if (keyComment) {
2041
2041
  throw new Error("With simple keys, key nodes cannot have comments");
2042
2042
  }
2043
- if (identity.isCollection(key) || !identity.isNode(key) && typeof key === "object") {
2043
+ if (identity2.isCollection(key) || !identity2.isNode(key) && typeof key === "object") {
2044
2044
  const msg = "With simple keys, collection cannot be used as a key value";
2045
2045
  throw new Error(msg);
2046
2046
  }
2047
2047
  }
2048
- let explicitKey = !simpleKeys && (!key || keyComment && value == null && !ctx.inFlow || identity.isCollection(key) || (identity.isScalar(key) ? key.type === Scalar.Scalar.BLOCK_FOLDED || key.type === Scalar.Scalar.BLOCK_LITERAL : typeof key === "object"));
2048
+ let explicitKey = !simpleKeys && (!key || keyComment && value == null && !ctx.inFlow || identity2.isCollection(key) || (identity2.isScalar(key) ? key.type === Scalar.Scalar.BLOCK_FOLDED || key.type === Scalar.Scalar.BLOCK_LITERAL : typeof key === "object"));
2049
2049
  ctx = Object.assign({}, ctx, {
2050
2050
  allNullValues: false,
2051
2051
  implicitKey: !explicitKey && (simpleKeys || !allNullValues),
@@ -2086,7 +2086,7 @@ ${indent}:`;
2086
2086
  str += stringifyComment.lineComment(str, ctx.indent, commentString(keyComment));
2087
2087
  }
2088
2088
  let vsb, vcb, valueComment;
2089
- if (identity.isNode(value)) {
2089
+ if (identity2.isNode(value)) {
2090
2090
  vsb = !!value.spaceBefore;
2091
2091
  vcb = value.commentBefore;
2092
2092
  valueComment = value.comment;
@@ -2098,10 +2098,10 @@ ${indent}:`;
2098
2098
  value = doc.createNode(value);
2099
2099
  }
2100
2100
  ctx.implicitKey = false;
2101
- if (!explicitKey && !keyComment && identity.isScalar(value))
2101
+ if (!explicitKey && !keyComment && identity2.isScalar(value))
2102
2102
  ctx.indentAtStart = str.length + 1;
2103
2103
  chompKeep = false;
2104
- if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && identity.isSeq(value) && !value.flow && !value.tag && !value.anchor) {
2104
+ if (!indentSeq && indentStep.length >= 2 && !ctx.inFlow && !explicitKey && identity2.isSeq(value) && !value.flow && !value.tag && !value.anchor) {
2105
2105
  ctx.indent = ctx.indent.substring(2);
2106
2106
  }
2107
2107
  let valueCommentDone = false;
@@ -2121,7 +2121,7 @@ ${stringifyComment.indentComment(cs, ctx.indent)}`;
2121
2121
  ws += `
2122
2122
  ${ctx.indent}`;
2123
2123
  }
2124
- } else if (!explicitKey && identity.isCollection(value)) {
2124
+ } else if (!explicitKey && identity2.isCollection(value)) {
2125
2125
  const vs0 = valueStr[0];
2126
2126
  const nl0 = valueStr.indexOf("\n");
2127
2127
  const hasNewline = nl0 !== -1;
@@ -2184,7 +2184,7 @@ var require_log = __commonJS({
2184
2184
  var require_merge = __commonJS({
2185
2185
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/merge.js"(exports2) {
2186
2186
  "use strict";
2187
- var identity = require_identity();
2187
+ var identity2 = require_identity();
2188
2188
  var Scalar = require_Scalar();
2189
2189
  var MERGE_KEY = "<<";
2190
2190
  var merge = {
@@ -2197,10 +2197,10 @@ var require_merge = __commonJS({
2197
2197
  }),
2198
2198
  stringify: () => MERGE_KEY
2199
2199
  };
2200
- var isMergeKey = (ctx, key) => (merge.identify(key) || identity.isScalar(key) && (!key.type || key.type === Scalar.Scalar.PLAIN) && merge.identify(key.value)) && ctx?.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default);
2200
+ var isMergeKey = (ctx, key) => (merge.identify(key) || identity2.isScalar(key) && (!key.type || key.type === Scalar.Scalar.PLAIN) && merge.identify(key.value)) && ctx?.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default);
2201
2201
  function addMergeToJSMap(ctx, map, value) {
2202
2202
  const source = resolveAliasValue(ctx, value);
2203
- if (identity.isSeq(source))
2203
+ if (identity2.isSeq(source))
2204
2204
  for (const it of source.items)
2205
2205
  mergeValue(ctx, map, it);
2206
2206
  else if (Array.isArray(source))
@@ -2211,7 +2211,7 @@ var require_merge = __commonJS({
2211
2211
  }
2212
2212
  function mergeValue(ctx, map, value) {
2213
2213
  const source = resolveAliasValue(ctx, value);
2214
- if (!identity.isMap(source))
2214
+ if (!identity2.isMap(source))
2215
2215
  throw new Error("Merge sources must be maps or map aliases");
2216
2216
  const srcMap = source.toJSON(null, ctx, Map);
2217
2217
  for (const [key, value2] of srcMap) {
@@ -2232,7 +2232,7 @@ var require_merge = __commonJS({
2232
2232
  return map;
2233
2233
  }
2234
2234
  function resolveAliasValue(ctx, value) {
2235
- return ctx && identity.isAlias(value) ? value.resolve(ctx.doc, ctx) : value;
2235
+ return ctx && identity2.isAlias(value) ? value.resolve(ctx.doc, ctx) : value;
2236
2236
  }
2237
2237
  exports2.addMergeToJSMap = addMergeToJSMap;
2238
2238
  exports2.isMergeKey = isMergeKey;
@@ -2247,10 +2247,10 @@ var require_addPairToJSMap = __commonJS({
2247
2247
  var log = require_log();
2248
2248
  var merge = require_merge();
2249
2249
  var stringify = require_stringify();
2250
- var identity = require_identity();
2250
+ var identity2 = require_identity();
2251
2251
  var toJS = require_toJS();
2252
2252
  function addPairToJSMap(ctx, map, { key, value }) {
2253
- if (identity.isNode(key) && key.addToJSMap)
2253
+ if (identity2.isNode(key) && key.addToJSMap)
2254
2254
  key.addToJSMap(ctx, map, value);
2255
2255
  else if (merge.isMergeKey(ctx, key))
2256
2256
  merge.addMergeToJSMap(ctx, map, value);
@@ -2281,7 +2281,7 @@ var require_addPairToJSMap = __commonJS({
2281
2281
  return "";
2282
2282
  if (typeof jsKey !== "object")
2283
2283
  return String(jsKey);
2284
- if (identity.isNode(key) && ctx?.doc) {
2284
+ if (identity2.isNode(key) && ctx?.doc) {
2285
2285
  const strCtx = stringify.createStringifyContext(ctx.doc, {});
2286
2286
  strCtx.anchors = /* @__PURE__ */ new Set();
2287
2287
  for (const node of ctx.anchors.keys())
@@ -2311,7 +2311,7 @@ var require_Pair = __commonJS({
2311
2311
  var createNode = require_createNode();
2312
2312
  var stringifyPair = require_stringifyPair();
2313
2313
  var addPairToJSMap = require_addPairToJSMap();
2314
- var identity = require_identity();
2314
+ var identity2 = require_identity();
2315
2315
  function createPair(key, value, ctx) {
2316
2316
  const k = createNode.createNode(key, void 0, ctx);
2317
2317
  const v = createNode.createNode(value, void 0, ctx);
@@ -2319,15 +2319,15 @@ var require_Pair = __commonJS({
2319
2319
  }
2320
2320
  var Pair = class _Pair {
2321
2321
  constructor(key, value = null) {
2322
- Object.defineProperty(this, identity.NODE_TYPE, { value: identity.PAIR });
2322
+ Object.defineProperty(this, identity2.NODE_TYPE, { value: identity2.PAIR });
2323
2323
  this.key = key;
2324
2324
  this.value = value;
2325
2325
  }
2326
2326
  clone(schema) {
2327
2327
  let { key, value } = this;
2328
- if (identity.isNode(key))
2328
+ if (identity2.isNode(key))
2329
2329
  key = key.clone(schema);
2330
- if (identity.isNode(value))
2330
+ if (identity2.isNode(value))
2331
2331
  value = value.clone(schema);
2332
2332
  return new _Pair(key, value);
2333
2333
  }
@@ -2348,7 +2348,7 @@ var require_Pair = __commonJS({
2348
2348
  var require_stringifyCollection = __commonJS({
2349
2349
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyCollection.js"(exports2) {
2350
2350
  "use strict";
2351
- var identity = require_identity();
2351
+ var identity2 = require_identity();
2352
2352
  var stringify = require_stringify();
2353
2353
  var stringifyComment = require_stringifyComment();
2354
2354
  function stringifyCollection(collection, ctx, options) {
@@ -2364,14 +2364,14 @@ var require_stringifyCollection = __commonJS({
2364
2364
  for (let i = 0; i < items.length; ++i) {
2365
2365
  const item = items[i];
2366
2366
  let comment2 = null;
2367
- if (identity.isNode(item)) {
2367
+ if (identity2.isNode(item)) {
2368
2368
  if (!chompKeep && item.spaceBefore)
2369
2369
  lines.push("");
2370
2370
  addCommentBefore(ctx, lines, item.commentBefore, chompKeep);
2371
2371
  if (item.comment)
2372
2372
  comment2 = item.comment;
2373
- } else if (identity.isPair(item)) {
2374
- const ik = identity.isNode(item.key) ? item.key : null;
2373
+ } else if (identity2.isPair(item)) {
2374
+ const ik = identity2.isNode(item.key) ? item.key : null;
2375
2375
  if (ik) {
2376
2376
  if (!chompKeep && ik.spaceBefore)
2377
2377
  lines.push("");
@@ -2419,14 +2419,14 @@ ${indent}${line}` : "\n";
2419
2419
  for (let i = 0; i < items.length; ++i) {
2420
2420
  const item = items[i];
2421
2421
  let comment = null;
2422
- if (identity.isNode(item)) {
2422
+ if (identity2.isNode(item)) {
2423
2423
  if (item.spaceBefore)
2424
2424
  lines.push("");
2425
2425
  addCommentBefore(ctx, lines, item.commentBefore, false);
2426
2426
  if (item.comment)
2427
2427
  comment = item.comment;
2428
- } else if (identity.isPair(item)) {
2429
- const ik = identity.isNode(item.key) ? item.key : null;
2428
+ } else if (identity2.isPair(item)) {
2429
+ const ik = identity2.isNode(item.key) ? item.key : null;
2430
2430
  if (ik) {
2431
2431
  if (ik.spaceBefore)
2432
2432
  lines.push("");
@@ -2434,7 +2434,7 @@ ${indent}${line}` : "\n";
2434
2434
  if (ik.comment)
2435
2435
  reqNewline = true;
2436
2436
  }
2437
- const iv = identity.isNode(item.value) ? item.value : null;
2437
+ const iv = identity2.isNode(item.value) ? item.value : null;
2438
2438
  if (iv) {
2439
2439
  if (iv.comment)
2440
2440
  comment = iv.comment;
@@ -2502,16 +2502,16 @@ var require_YAMLMap = __commonJS({
2502
2502
  var stringifyCollection = require_stringifyCollection();
2503
2503
  var addPairToJSMap = require_addPairToJSMap();
2504
2504
  var Collection = require_Collection();
2505
- var identity = require_identity();
2505
+ var identity2 = require_identity();
2506
2506
  var Pair = require_Pair();
2507
2507
  var Scalar = require_Scalar();
2508
2508
  function findPair(items, key) {
2509
- const k = identity.isScalar(key) ? key.value : key;
2509
+ const k = identity2.isScalar(key) ? key.value : key;
2510
2510
  for (const it of items) {
2511
- if (identity.isPair(it)) {
2511
+ if (identity2.isPair(it)) {
2512
2512
  if (it.key === key || it.key === k)
2513
2513
  return it;
2514
- if (identity.isScalar(it.key) && it.key.value === k)
2514
+ if (identity2.isScalar(it.key) && it.key.value === k)
2515
2515
  return it;
2516
2516
  }
2517
2517
  }
@@ -2522,7 +2522,7 @@ var require_YAMLMap = __commonJS({
2522
2522
  return "tag:yaml.org,2002:map";
2523
2523
  }
2524
2524
  constructor(schema) {
2525
- super(identity.MAP, schema);
2525
+ super(identity2.MAP, schema);
2526
2526
  this.items = [];
2527
2527
  }
2528
2528
  /**
@@ -2560,7 +2560,7 @@ var require_YAMLMap = __commonJS({
2560
2560
  */
2561
2561
  add(pair, overwrite) {
2562
2562
  let _pair;
2563
- if (identity.isPair(pair))
2563
+ if (identity2.isPair(pair))
2564
2564
  _pair = pair;
2565
2565
  else if (!pair || typeof pair !== "object" || !("key" in pair)) {
2566
2566
  _pair = new Pair.Pair(pair, pair?.value);
@@ -2571,7 +2571,7 @@ var require_YAMLMap = __commonJS({
2571
2571
  if (prev) {
2572
2572
  if (!overwrite)
2573
2573
  throw new Error(`Key ${_pair.key} already set`);
2574
- if (identity.isScalar(prev.value) && Scalar.isScalarValue(_pair.value))
2574
+ if (identity2.isScalar(prev.value) && Scalar.isScalarValue(_pair.value))
2575
2575
  prev.value.value = _pair.value;
2576
2576
  else
2577
2577
  prev.value = _pair.value;
@@ -2595,7 +2595,7 @@ var require_YAMLMap = __commonJS({
2595
2595
  get(key, keepScalar) {
2596
2596
  const it = findPair(this.items, key);
2597
2597
  const node = it?.value;
2598
- return (!keepScalar && identity.isScalar(node) ? node.value : node) ?? void 0;
2598
+ return (!keepScalar && identity2.isScalar(node) ? node.value : node) ?? void 0;
2599
2599
  }
2600
2600
  has(key) {
2601
2601
  return !!findPair(this.items, key);
@@ -2620,7 +2620,7 @@ var require_YAMLMap = __commonJS({
2620
2620
  if (!ctx)
2621
2621
  return JSON.stringify(this);
2622
2622
  for (const item of this.items) {
2623
- if (!identity.isPair(item))
2623
+ if (!identity2.isPair(item))
2624
2624
  throw new Error(`Map items must all be pairs; found ${JSON.stringify(item)} instead`);
2625
2625
  }
2626
2626
  if (!ctx.allNullValues && this.hasAllNullValues(false))
@@ -2643,7 +2643,7 @@ var require_YAMLMap = __commonJS({
2643
2643
  var require_map = __commonJS({
2644
2644
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/schema/common/map.js"(exports2) {
2645
2645
  "use strict";
2646
- var identity = require_identity();
2646
+ var identity2 = require_identity();
2647
2647
  var YAMLMap = require_YAMLMap();
2648
2648
  var map = {
2649
2649
  collection: "map",
@@ -2651,7 +2651,7 @@ var require_map = __commonJS({
2651
2651
  nodeClass: YAMLMap.YAMLMap,
2652
2652
  tag: "tag:yaml.org,2002:map",
2653
2653
  resolve(map2, onError) {
2654
- if (!identity.isMap(map2))
2654
+ if (!identity2.isMap(map2))
2655
2655
  onError("Expected a mapping for this tag");
2656
2656
  return map2;
2657
2657
  },
@@ -2668,7 +2668,7 @@ var require_YAMLSeq = __commonJS({
2668
2668
  var createNode = require_createNode();
2669
2669
  var stringifyCollection = require_stringifyCollection();
2670
2670
  var Collection = require_Collection();
2671
- var identity = require_identity();
2671
+ var identity2 = require_identity();
2672
2672
  var Scalar = require_Scalar();
2673
2673
  var toJS = require_toJS();
2674
2674
  var YAMLSeq = class extends Collection.Collection {
@@ -2676,7 +2676,7 @@ var require_YAMLSeq = __commonJS({
2676
2676
  return "tag:yaml.org,2002:seq";
2677
2677
  }
2678
2678
  constructor(schema) {
2679
- super(identity.SEQ, schema);
2679
+ super(identity2.SEQ, schema);
2680
2680
  this.items = [];
2681
2681
  }
2682
2682
  add(value) {
@@ -2702,7 +2702,7 @@ var require_YAMLSeq = __commonJS({
2702
2702
  if (typeof idx !== "number")
2703
2703
  return void 0;
2704
2704
  const it = this.items[idx];
2705
- return !keepScalar && identity.isScalar(it) ? it.value : it;
2705
+ return !keepScalar && identity2.isScalar(it) ? it.value : it;
2706
2706
  }
2707
2707
  /**
2708
2708
  * Checks if the collection includes a value with the key `key`.
@@ -2726,7 +2726,7 @@ var require_YAMLSeq = __commonJS({
2726
2726
  if (typeof idx !== "number")
2727
2727
  throw new Error(`Expected a valid index, not ${key}.`);
2728
2728
  const prev = this.items[idx];
2729
- if (identity.isScalar(prev) && Scalar.isScalarValue(value))
2729
+ if (identity2.isScalar(prev) && Scalar.isScalarValue(value))
2730
2730
  prev.value = value;
2731
2731
  else
2732
2732
  this.items[idx] = value;
@@ -2768,7 +2768,7 @@ var require_YAMLSeq = __commonJS({
2768
2768
  }
2769
2769
  };
2770
2770
  function asItemIndex(key) {
2771
- let idx = identity.isScalar(key) ? key.value : key;
2771
+ let idx = identity2.isScalar(key) ? key.value : key;
2772
2772
  if (idx && typeof idx === "string")
2773
2773
  idx = Number(idx);
2774
2774
  return typeof idx === "number" && Number.isInteger(idx) && idx >= 0 ? idx : null;
@@ -2781,7 +2781,7 @@ var require_YAMLSeq = __commonJS({
2781
2781
  var require_seq = __commonJS({
2782
2782
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/schema/common/seq.js"(exports2) {
2783
2783
  "use strict";
2784
- var identity = require_identity();
2784
+ var identity2 = require_identity();
2785
2785
  var YAMLSeq = require_YAMLSeq();
2786
2786
  var seq = {
2787
2787
  collection: "seq",
@@ -2789,7 +2789,7 @@ var require_seq = __commonJS({
2789
2789
  nodeClass: YAMLSeq.YAMLSeq,
2790
2790
  tag: "tag:yaml.org,2002:seq",
2791
2791
  resolve(seq2, onError) {
2792
- if (!identity.isSeq(seq2))
2792
+ if (!identity2.isSeq(seq2))
2793
2793
  onError("Expected a sequence for this tag");
2794
2794
  return seq2;
2795
2795
  },
@@ -3143,17 +3143,17 @@ var require_binary = __commonJS({
3143
3143
  var require_pairs = __commonJS({
3144
3144
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/pairs.js"(exports2) {
3145
3145
  "use strict";
3146
- var identity = require_identity();
3146
+ var identity2 = require_identity();
3147
3147
  var Pair = require_Pair();
3148
3148
  var Scalar = require_Scalar();
3149
3149
  var YAMLSeq = require_YAMLSeq();
3150
3150
  function resolvePairs(seq, onError) {
3151
- if (identity.isSeq(seq)) {
3151
+ if (identity2.isSeq(seq)) {
3152
3152
  for (let i = 0; i < seq.items.length; ++i) {
3153
3153
  let item = seq.items[i];
3154
- if (identity.isPair(item))
3154
+ if (identity2.isPair(item))
3155
3155
  continue;
3156
- else if (identity.isMap(item)) {
3156
+ else if (identity2.isMap(item)) {
3157
3157
  if (item.items.length > 1)
3158
3158
  onError("Each pair must have its own sequence indicator");
3159
3159
  const pair = item.items[0] || new Pair.Pair(new Scalar.Scalar(null));
@@ -3167,7 +3167,7 @@ ${cn.comment}` : item.comment;
3167
3167
  }
3168
3168
  item = pair;
3169
3169
  }
3170
- seq.items[i] = identity.isPair(item) ? item : new Pair.Pair(item);
3170
+ seq.items[i] = identity2.isPair(item) ? item : new Pair.Pair(item);
3171
3171
  }
3172
3172
  } else
3173
3173
  onError("Expected a sequence for this tag");
@@ -3221,7 +3221,7 @@ ${cn.comment}` : item.comment;
3221
3221
  var require_omap = __commonJS({
3222
3222
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/omap.js"(exports2) {
3223
3223
  "use strict";
3224
- var identity = require_identity();
3224
+ var identity2 = require_identity();
3225
3225
  var toJS = require_toJS();
3226
3226
  var YAMLMap = require_YAMLMap();
3227
3227
  var YAMLSeq = require_YAMLSeq();
@@ -3248,7 +3248,7 @@ var require_omap = __commonJS({
3248
3248
  ctx.onCreate(map);
3249
3249
  for (const pair of this.items) {
3250
3250
  let key, value;
3251
- if (identity.isPair(pair)) {
3251
+ if (identity2.isPair(pair)) {
3252
3252
  key = toJS.toJS(pair.key, "", ctx);
3253
3253
  value = toJS.toJS(pair.value, key, ctx);
3254
3254
  } else {
@@ -3278,7 +3278,7 @@ var require_omap = __commonJS({
3278
3278
  const pairs$1 = pairs.resolvePairs(seq, onError);
3279
3279
  const seenKeys = [];
3280
3280
  for (const { key } of pairs$1.items) {
3281
- if (identity.isScalar(key)) {
3281
+ if (identity2.isScalar(key)) {
3282
3282
  if (seenKeys.includes(key.value)) {
3283
3283
  onError(`Ordered maps must not include duplicate keys: ${key.value}`);
3284
3284
  } else {
@@ -3459,7 +3459,7 @@ var require_int2 = __commonJS({
3459
3459
  var require_set = __commonJS({
3460
3460
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/schema/yaml-1.1/set.js"(exports2) {
3461
3461
  "use strict";
3462
- var identity = require_identity();
3462
+ var identity2 = require_identity();
3463
3463
  var Pair = require_Pair();
3464
3464
  var YAMLMap = require_YAMLMap();
3465
3465
  var YAMLSet = class _YAMLSet extends YAMLMap.YAMLMap {
@@ -3469,7 +3469,7 @@ var require_set = __commonJS({
3469
3469
  }
3470
3470
  add(key) {
3471
3471
  let pair;
3472
- if (identity.isPair(key))
3472
+ if (identity2.isPair(key))
3473
3473
  pair = key;
3474
3474
  else if (key && typeof key === "object" && "key" in key && "value" in key && key.value === null)
3475
3475
  pair = new Pair.Pair(key.key, null);
@@ -3485,7 +3485,7 @@ var require_set = __commonJS({
3485
3485
  */
3486
3486
  get(key, keepPair) {
3487
3487
  const pair = YAMLMap.findPair(this.items, key);
3488
- return !keepPair && identity.isPair(pair) ? identity.isScalar(pair.key) ? pair.key.value : pair.key : pair;
3488
+ return !keepPair && identity2.isPair(pair) ? identity2.isScalar(pair.key) ? pair.key.value : pair.key : pair;
3489
3489
  }
3490
3490
  set(key, value) {
3491
3491
  if (typeof value !== "boolean")
@@ -3529,7 +3529,7 @@ var require_set = __commonJS({
3529
3529
  tag: "tag:yaml.org,2002:set",
3530
3530
  createNode: (schema, iterable, ctx) => YAMLSet.from(schema, iterable, ctx),
3531
3531
  resolve(map, onError) {
3532
- if (identity.isMap(map)) {
3532
+ if (identity2.isMap(map)) {
3533
3533
  if (map.hasAllNullValues(true))
3534
3534
  return Object.assign(new YAMLSet(), map);
3535
3535
  else
@@ -3774,7 +3774,7 @@ var require_tags = __commonJS({
3774
3774
  var require_Schema = __commonJS({
3775
3775
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/schema/Schema.js"(exports2) {
3776
3776
  "use strict";
3777
- var identity = require_identity();
3777
+ var identity2 = require_identity();
3778
3778
  var map = require_map();
3779
3779
  var seq = require_seq();
3780
3780
  var string = require_string();
@@ -3787,9 +3787,9 @@ var require_Schema = __commonJS({
3787
3787
  this.knownTags = resolveKnownTags ? tags.coreKnownTags : {};
3788
3788
  this.tags = tags.getTags(customTags, this.name, merge);
3789
3789
  this.toStringOptions = toStringDefaults ?? null;
3790
- Object.defineProperty(this, identity.MAP, { value: map.map });
3791
- Object.defineProperty(this, identity.SCALAR, { value: string.string });
3792
- Object.defineProperty(this, identity.SEQ, { value: seq.seq });
3790
+ Object.defineProperty(this, identity2.MAP, { value: map.map });
3791
+ Object.defineProperty(this, identity2.SCALAR, { value: string.string });
3792
+ Object.defineProperty(this, identity2.SEQ, { value: seq.seq });
3793
3793
  this.sortMapEntries = typeof sortMapEntries === "function" ? sortMapEntries : sortMapEntries === true ? sortMapEntriesByKey : null;
3794
3794
  }
3795
3795
  clone() {
@@ -3806,7 +3806,7 @@ var require_Schema = __commonJS({
3806
3806
  var require_stringifyDocument = __commonJS({
3807
3807
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/stringify/stringifyDocument.js"(exports2) {
3808
3808
  "use strict";
3809
- var identity = require_identity();
3809
+ var identity2 = require_identity();
3810
3810
  var stringify = require_stringify();
3811
3811
  var stringifyComment = require_stringifyComment();
3812
3812
  function stringifyDocument(doc, options) {
@@ -3833,7 +3833,7 @@ var require_stringifyDocument = __commonJS({
3833
3833
  let chompKeep = false;
3834
3834
  let contentComment = null;
3835
3835
  if (doc.contents) {
3836
- if (identity.isNode(doc.contents)) {
3836
+ if (identity2.isNode(doc.contents)) {
3837
3837
  if (doc.contents.spaceBefore && hasDirectives)
3838
3838
  lines.push("");
3839
3839
  if (doc.contents.commentBefore) {
@@ -3888,7 +3888,7 @@ var require_Document = __commonJS({
3888
3888
  "use strict";
3889
3889
  var Alias = require_Alias();
3890
3890
  var Collection = require_Collection();
3891
- var identity = require_identity();
3891
+ var identity2 = require_identity();
3892
3892
  var Pair = require_Pair();
3893
3893
  var toJS = require_toJS();
3894
3894
  var Schema = require_Schema();
@@ -3903,7 +3903,7 @@ var require_Document = __commonJS({
3903
3903
  this.comment = null;
3904
3904
  this.errors = [];
3905
3905
  this.warnings = [];
3906
- Object.defineProperty(this, identity.NODE_TYPE, { value: identity.DOC });
3906
+ Object.defineProperty(this, identity2.NODE_TYPE, { value: identity2.DOC });
3907
3907
  let _replacer = null;
3908
3908
  if (typeof replacer === "function" || Array.isArray(replacer)) {
3909
3909
  _replacer = replacer;
@@ -3939,7 +3939,7 @@ var require_Document = __commonJS({
3939
3939
  */
3940
3940
  clone() {
3941
3941
  const copy = Object.create(_Document.prototype, {
3942
- [identity.NODE_TYPE]: { value: identity.DOC }
3942
+ [identity2.NODE_TYPE]: { value: identity2.DOC }
3943
3943
  });
3944
3944
  copy.commentBefore = this.commentBefore;
3945
3945
  copy.comment = this.comment;
@@ -3949,7 +3949,7 @@ var require_Document = __commonJS({
3949
3949
  if (this.directives)
3950
3950
  copy.directives = this.directives.clone();
3951
3951
  copy.schema = this.schema.clone();
3952
- copy.contents = identity.isNode(this.contents) ? this.contents.clone(copy.schema) : this.contents;
3952
+ copy.contents = identity2.isNode(this.contents) ? this.contents.clone(copy.schema) : this.contents;
3953
3953
  if (this.range)
3954
3954
  copy.range = this.range.slice();
3955
3955
  return copy;
@@ -4012,7 +4012,7 @@ var require_Document = __commonJS({
4012
4012
  sourceObjects
4013
4013
  };
4014
4014
  const node = createNode.createNode(value, tag, ctx);
4015
- if (flow && identity.isCollection(node))
4015
+ if (flow && identity2.isCollection(node))
4016
4016
  node.flow = true;
4017
4017
  setAnchors();
4018
4018
  return node;
@@ -4052,7 +4052,7 @@ var require_Document = __commonJS({
4052
4052
  * `true` (collections are always returned intact).
4053
4053
  */
4054
4054
  get(key, keepScalar) {
4055
- return identity.isCollection(this.contents) ? this.contents.get(key, keepScalar) : void 0;
4055
+ return identity2.isCollection(this.contents) ? this.contents.get(key, keepScalar) : void 0;
4056
4056
  }
4057
4057
  /**
4058
4058
  * Returns item at `path`, or `undefined` if not found. By default unwraps
@@ -4061,14 +4061,14 @@ var require_Document = __commonJS({
4061
4061
  */
4062
4062
  getIn(path, keepScalar) {
4063
4063
  if (Collection.isEmptyPath(path))
4064
- return !keepScalar && identity.isScalar(this.contents) ? this.contents.value : this.contents;
4065
- return identity.isCollection(this.contents) ? this.contents.getIn(path, keepScalar) : void 0;
4064
+ return !keepScalar && identity2.isScalar(this.contents) ? this.contents.value : this.contents;
4065
+ return identity2.isCollection(this.contents) ? this.contents.getIn(path, keepScalar) : void 0;
4066
4066
  }
4067
4067
  /**
4068
4068
  * Checks if the document includes a value with the key `key`.
4069
4069
  */
4070
4070
  has(key) {
4071
- return identity.isCollection(this.contents) ? this.contents.has(key) : false;
4071
+ return identity2.isCollection(this.contents) ? this.contents.has(key) : false;
4072
4072
  }
4073
4073
  /**
4074
4074
  * Checks if the document includes a value at `path`.
@@ -4076,7 +4076,7 @@ var require_Document = __commonJS({
4076
4076
  hasIn(path) {
4077
4077
  if (Collection.isEmptyPath(path))
4078
4078
  return this.contents !== void 0;
4079
- return identity.isCollection(this.contents) ? this.contents.hasIn(path) : false;
4079
+ return identity2.isCollection(this.contents) ? this.contents.hasIn(path) : false;
4080
4080
  }
4081
4081
  /**
4082
4082
  * Sets a value in this document. For `!!set`, `value` needs to be a
@@ -4183,7 +4183,7 @@ var require_Document = __commonJS({
4183
4183
  }
4184
4184
  };
4185
4185
  function assertCollection(contents) {
4186
- if (identity.isCollection(contents))
4186
+ if (identity2.isCollection(contents))
4187
4187
  return true;
4188
4188
  throw new Error("Expected a YAML collection as document contents");
4189
4189
  }
@@ -4454,12 +4454,12 @@ var require_util_flow_indent_check = __commonJS({
4454
4454
  var require_util_map_includes = __commonJS({
4455
4455
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/compose/util-map-includes.js"(exports2) {
4456
4456
  "use strict";
4457
- var identity = require_identity();
4457
+ var identity2 = require_identity();
4458
4458
  function mapIncludes(ctx, items, search) {
4459
4459
  const { uniqueKeys } = ctx.options;
4460
4460
  if (uniqueKeys === false)
4461
4461
  return false;
4462
- const isEqual = typeof uniqueKeys === "function" ? uniqueKeys : (a, b) => a === b || identity.isScalar(a) && identity.isScalar(b) && a.value === b.value;
4462
+ const isEqual = typeof uniqueKeys === "function" ? uniqueKeys : (a, b) => a === b || identity2.isScalar(a) && identity2.isScalar(b) && a.value === b.value;
4463
4463
  return items.some((pair) => isEqual(pair.key, search));
4464
4464
  }
4465
4465
  exports2.mapIncludes = mapIncludes;
@@ -4672,7 +4672,7 @@ var require_resolve_end = __commonJS({
4672
4672
  var require_resolve_flow_collection = __commonJS({
4673
4673
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/compose/resolve-flow-collection.js"(exports2) {
4674
4674
  "use strict";
4675
- var identity = require_identity();
4675
+ var identity2 = require_identity();
4676
4676
  var Pair = require_Pair();
4677
4677
  var YAMLMap = require_YAMLMap();
4678
4678
  var YAMLSeq = require_YAMLSeq();
@@ -4751,7 +4751,7 @@ var require_resolve_flow_collection = __commonJS({
4751
4751
  }
4752
4752
  if (prevItemComment) {
4753
4753
  let prev = coll.items[coll.items.length - 1];
4754
- if (identity.isPair(prev))
4754
+ if (identity2.isPair(prev))
4755
4755
  prev = prev.value ?? prev.key;
4756
4756
  if (prev.comment)
4757
4757
  prev.comment += "\n" + prevItemComment;
@@ -4866,7 +4866,7 @@ var require_resolve_flow_collection = __commonJS({
4866
4866
  var require_compose_collection = __commonJS({
4867
4867
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/compose/compose-collection.js"(exports2) {
4868
4868
  "use strict";
4869
- var identity = require_identity();
4869
+ var identity2 = require_identity();
4870
4870
  var Scalar = require_Scalar();
4871
4871
  var YAMLMap = require_YAMLMap();
4872
4872
  var YAMLSeq = require_YAMLSeq();
@@ -4916,7 +4916,7 @@ var require_compose_collection = __commonJS({
4916
4916
  }
4917
4917
  const coll = resolveCollection(CN, ctx, token, onError, tagName, tag);
4918
4918
  const res = tag.resolve?.(coll, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg), ctx.options) ?? coll;
4919
- const node = identity.isNode(res) ? res : new Scalar.Scalar(res);
4919
+ const node = identity2.isNode(res) ? res : new Scalar.Scalar(res);
4920
4920
  node.range = coll.range;
4921
4921
  node.tag = tagName;
4922
4922
  if (tag?.format)
@@ -5334,7 +5334,7 @@ var require_resolve_flow_scalar = __commonJS({
5334
5334
  var require_compose_scalar = __commonJS({
5335
5335
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/compose/compose-scalar.js"(exports2) {
5336
5336
  "use strict";
5337
- var identity = require_identity();
5337
+ var identity2 = require_identity();
5338
5338
  var Scalar = require_Scalar();
5339
5339
  var resolveBlockScalar = require_resolve_block_scalar();
5340
5340
  var resolveFlowScalar = require_resolve_flow_scalar();
@@ -5343,17 +5343,17 @@ var require_compose_scalar = __commonJS({
5343
5343
  const tagName = tagToken ? ctx.directives.tagName(tagToken.source, (msg) => onError(tagToken, "TAG_RESOLVE_FAILED", msg)) : null;
5344
5344
  let tag;
5345
5345
  if (ctx.options.stringKeys && ctx.atKey) {
5346
- tag = ctx.schema[identity.SCALAR];
5346
+ tag = ctx.schema[identity2.SCALAR];
5347
5347
  } else if (tagName)
5348
5348
  tag = findScalarTagByName(ctx.schema, value, tagName, tagToken, onError);
5349
5349
  else if (token.type === "scalar")
5350
5350
  tag = findScalarTagByTest(ctx, value, token, onError);
5351
5351
  else
5352
- tag = ctx.schema[identity.SCALAR];
5352
+ tag = ctx.schema[identity2.SCALAR];
5353
5353
  let scalar;
5354
5354
  try {
5355
5355
  const res = tag.resolve(value, (msg) => onError(tagToken ?? token, "TAG_RESOLVE_FAILED", msg), ctx.options);
5356
- scalar = identity.isScalar(res) ? res : new Scalar.Scalar(res);
5356
+ scalar = identity2.isScalar(res) ? res : new Scalar.Scalar(res);
5357
5357
  } catch (error) {
5358
5358
  const msg = error instanceof Error ? error.message : String(error);
5359
5359
  onError(tagToken ?? token, "TAG_RESOLVE_FAILED", msg);
@@ -5373,7 +5373,7 @@ var require_compose_scalar = __commonJS({
5373
5373
  }
5374
5374
  function findScalarTagByName(schema, value, tagName, tagToken, onError) {
5375
5375
  if (tagName === "!")
5376
- return schema[identity.SCALAR];
5376
+ return schema[identity2.SCALAR];
5377
5377
  const matchWithTest = [];
5378
5378
  for (const tag of schema.tags) {
5379
5379
  if (!tag.collection && tag.tag === tagName) {
@@ -5392,12 +5392,12 @@ var require_compose_scalar = __commonJS({
5392
5392
  return kt;
5393
5393
  }
5394
5394
  onError(tagToken, "TAG_RESOLVE_FAILED", `Unresolved tag: ${tagName}`, tagName !== "tag:yaml.org,2002:str");
5395
- return schema[identity.SCALAR];
5395
+ return schema[identity2.SCALAR];
5396
5396
  }
5397
5397
  function findScalarTagByTest({ atKey, directives, schema }, value, token, onError) {
5398
- const tag = schema.tags.find((tag2) => (tag2.default === true || atKey && tag2.default === "key") && tag2.test?.test(value)) || schema[identity.SCALAR];
5398
+ const tag = schema.tags.find((tag2) => (tag2.default === true || atKey && tag2.default === "key") && tag2.test?.test(value)) || schema[identity2.SCALAR];
5399
5399
  if (schema.compat) {
5400
- const compat = schema.compat.find((tag2) => tag2.default && tag2.test?.test(value)) ?? schema[identity.SCALAR];
5400
+ const compat = schema.compat.find((tag2) => tag2.default && tag2.test?.test(value)) ?? schema[identity2.SCALAR];
5401
5401
  if (tag.tag !== compat.tag) {
5402
5402
  const ts = directives.tagString(tag.tag);
5403
5403
  const cs = directives.tagString(compat.tag);
@@ -5446,7 +5446,7 @@ var require_compose_node = __commonJS({
5446
5446
  "../../node_modules/.pnpm/yaml@2.8.4/node_modules/yaml/dist/compose/compose-node.js"(exports2) {
5447
5447
  "use strict";
5448
5448
  var Alias = require_Alias();
5449
- var identity = require_identity();
5449
+ var identity2 = require_identity();
5450
5450
  var composeCollection = require_compose_collection();
5451
5451
  var composeScalar = require_compose_scalar();
5452
5452
  var resolveEnd = require_resolve_end();
@@ -5492,7 +5492,7 @@ var require_compose_node = __commonJS({
5492
5492
  node ?? (node = composeEmptyNode(ctx, token.offset, void 0, null, props, onError));
5493
5493
  if (anchor && node.anchor === "")
5494
5494
  onError(anchor, "BAD_ALIAS", "Anchor cannot be an empty string");
5495
- if (atKey && ctx.options.stringKeys && (!identity.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
5495
+ if (atKey && ctx.options.stringKeys && (!identity2.isScalar(node) || typeof node.value !== "string" || node.tag && node.tag !== "tag:yaml.org,2002:str")) {
5496
5496
  const msg = "With stringKeys, all keys must be strings";
5497
5497
  onError(tag ?? token, "NON_STRING_KEY", msg);
5498
5498
  }
@@ -5598,7 +5598,7 @@ var require_composer = __commonJS({
5598
5598
  var directives = require_directives();
5599
5599
  var Document = require_Document();
5600
5600
  var errors = require_errors();
5601
- var identity = require_identity();
5601
+ var identity2 = require_identity();
5602
5602
  var composeDoc = require_compose_doc();
5603
5603
  var resolveEnd = require_resolve_end();
5604
5604
  function getErrorPos(src) {
@@ -5660,9 +5660,9 @@ var require_composer = __commonJS({
5660
5660
  ${comment}` : comment;
5661
5661
  } else if (afterEmptyLine || doc.directives.docStart || !dc) {
5662
5662
  doc.commentBefore = comment;
5663
- } else if (identity.isCollection(dc) && !dc.flow && dc.items.length > 0) {
5663
+ } else if (identity2.isCollection(dc) && !dc.flow && dc.items.length > 0) {
5664
5664
  let it = dc.items[0];
5665
- if (identity.isPair(it))
5665
+ if (identity2.isPair(it))
5666
5666
  it = it.key;
5667
5667
  const cb = it.commentBefore;
5668
5668
  it.commentBefore = cb ? `${comment}
@@ -7691,7 +7691,7 @@ var require_public_api = __commonJS({
7691
7691
  var Document = require_Document();
7692
7692
  var errors = require_errors();
7693
7693
  var log = require_log();
7694
- var identity = require_identity();
7694
+ var identity2 = require_identity();
7695
7695
  var lineCounter = require_line_counter();
7696
7696
  var parser = require_parser();
7697
7697
  function parseOptions(options) {
@@ -7769,7 +7769,7 @@ var require_public_api = __commonJS({
7769
7769
  if (!keepUndefined)
7770
7770
  return void 0;
7771
7771
  }
7772
- if (identity.isDocument(value) && !_replacer)
7772
+ if (identity2.isDocument(value) && !_replacer)
7773
7773
  return value.toString(options);
7774
7774
  return new Document.Document(value, _replacer, options).toString(options);
7775
7775
  }
@@ -7789,7 +7789,7 @@ var require_dist = __commonJS({
7789
7789
  var Schema = require_Schema();
7790
7790
  var errors = require_errors();
7791
7791
  var Alias = require_Alias();
7792
- var identity = require_identity();
7792
+ var identity2 = require_identity();
7793
7793
  var Pair = require_Pair();
7794
7794
  var Scalar = require_Scalar();
7795
7795
  var YAMLMap = require_YAMLMap();
@@ -7807,14 +7807,14 @@ var require_dist = __commonJS({
7807
7807
  exports2.YAMLParseError = errors.YAMLParseError;
7808
7808
  exports2.YAMLWarning = errors.YAMLWarning;
7809
7809
  exports2.Alias = Alias.Alias;
7810
- exports2.isAlias = identity.isAlias;
7811
- exports2.isCollection = identity.isCollection;
7812
- exports2.isDocument = identity.isDocument;
7813
- exports2.isMap = identity.isMap;
7814
- exports2.isNode = identity.isNode;
7815
- exports2.isPair = identity.isPair;
7816
- exports2.isScalar = identity.isScalar;
7817
- exports2.isSeq = identity.isSeq;
7810
+ exports2.isAlias = identity2.isAlias;
7811
+ exports2.isCollection = identity2.isCollection;
7812
+ exports2.isDocument = identity2.isDocument;
7813
+ exports2.isMap = identity2.isMap;
7814
+ exports2.isNode = identity2.isNode;
7815
+ exports2.isPair = identity2.isPair;
7816
+ exports2.isScalar = identity2.isScalar;
7817
+ exports2.isSeq = identity2.isSeq;
7818
7818
  exports2.Pair = Pair.Pair;
7819
7819
  exports2.Scalar = Scalar.Scalar;
7820
7820
  exports2.YAMLMap = YAMLMap.YAMLMap;
@@ -7833,6 +7833,48 @@ var require_dist = __commonJS({
7833
7833
  });
7834
7834
 
7835
7835
  // src/git.ts
7836
+ var git_exports = {};
7837
+ __export(git_exports, {
7838
+ branchExists: () => branchExists,
7839
+ checkoutBranch: () => checkoutBranch,
7840
+ createAndCheckoutBranch: () => createAndCheckoutBranch,
7841
+ createBranch: () => createBranch,
7842
+ deleteBranch: () => deleteBranch,
7843
+ getAllChangedFiles: () => getAllChangedFiles,
7844
+ getBranchCommits: () => getBranchCommits,
7845
+ getChangedFilesSince: () => getChangedFilesSince,
7846
+ getCommitHash: () => getCommitHash,
7847
+ getCommitsAheadOfUpstream: () => getCommitsAheadOfUpstream,
7848
+ getCommitsSince: () => getCommitsSince,
7849
+ getCurrentBranch: () => getCurrentBranch,
7850
+ getDefaultBranch: () => getDefaultBranch,
7851
+ getDiffStat: () => getDiffStat,
7852
+ getFullDiff: () => getFullDiff,
7853
+ getGitRoot: () => getGitRoot,
7854
+ getHeadSha: () => getHeadSha,
7855
+ getLatestTag: () => getLatestTag,
7856
+ getOnlineLog: () => getOnlineLog,
7857
+ getPushStats: () => getPushStats,
7858
+ getRecentBranchCommits: () => getRecentBranchCommits,
7859
+ getShortStagedFiles: () => getShortStagedFiles,
7860
+ getStagedDiff: () => getStagedDiff,
7861
+ getStagedDiffShortstat: () => getStagedDiffShortstat,
7862
+ getStagedFileCount: () => getStagedFileCount,
7863
+ getStagedFiles: () => getStagedFiles,
7864
+ getUnstagedFiles: () => getUnstagedFiles,
7865
+ getUpstreamRef: () => getUpstreamRef,
7866
+ getWorkingTreeDiff: () => getWorkingTreeDiff,
7867
+ gitCommit: () => gitCommit,
7868
+ gitPush: () => gitPush,
7869
+ gitPushSetUpstream: () => gitPushSetUpstream,
7870
+ hasStagedChanges: () => hasStagedChanges,
7871
+ isGitRepo: () => isGitRepo,
7872
+ resetHard: () => resetHard,
7873
+ stageAll: () => stageAll,
7874
+ stashPop: () => stashPop,
7875
+ stashPushIfDirty: () => stashPushIfDirty,
7876
+ validateRef: () => validateRef
7877
+ });
7836
7878
  function validateRef(ref, name = "ref") {
7837
7879
  if (ref.startsWith("-")) {
7838
7880
  throw new Error(`Invalid git ref ${name}: starts with hyphen: "${ref}"`);
@@ -7879,6 +7921,26 @@ function getStagedFiles() {
7879
7921
  encoding: "utf-8"
7880
7922
  });
7881
7923
  }
7924
+ function getWorkingTreeDiff(excludes = []) {
7925
+ const args = ["diff", "HEAD"];
7926
+ if (excludes.length > 0) {
7927
+ args.push("--");
7928
+ args.push(".");
7929
+ for (const pattern of excludes) {
7930
+ args.push(`:(exclude)${pattern}`);
7931
+ }
7932
+ }
7933
+ return (0, import_child_process2.execFileSync)("git", args, {
7934
+ encoding: "utf-8",
7935
+ maxBuffer: 10 * 1024 * 1024
7936
+ });
7937
+ }
7938
+ function getAllChangedFiles() {
7939
+ const output = (0, import_child_process2.execFileSync)("git", ["status", "--porcelain"], {
7940
+ encoding: "utf-8"
7941
+ });
7942
+ return output.trim().split("\n").filter(Boolean).map((line) => line.slice(3)).join("\n");
7943
+ }
7882
7944
  function hasStagedChanges() {
7883
7945
  const output = (0, import_child_process2.execFileSync)("git", ["diff", "--cached", "--name-only"], {
7884
7946
  encoding: "utf-8"
@@ -7889,17 +7951,21 @@ function getUnstagedFiles() {
7889
7951
  const output = (0, import_child_process2.execFileSync)("git", ["status", "--porcelain"], {
7890
7952
  encoding: "utf-8"
7891
7953
  });
7892
- return output.trim().split("\n").filter(Boolean).filter((line) => !line.startsWith("??"));
7954
+ return output.trim().split("\n").filter(Boolean);
7893
7955
  }
7894
7956
  function stageAll() {
7895
- (0, import_child_process2.execFileSync)("git", ["add", "-u"], { stdio: "pipe" });
7957
+ (0, import_child_process2.execFileSync)("git", ["add", "-A"], { stdio: "pipe" });
7896
7958
  }
7897
7959
  function gitCommit(message) {
7898
7960
  const tmpDir = (0, import_fs2.mkdtempSync)((0, import_path2.join)((0, import_os3.tmpdir)(), "qc-"));
7899
7961
  const tmpFile = (0, import_path2.join)(tmpDir, "commit.txt");
7900
7962
  (0, import_fs2.writeFileSync)(tmpFile, message, { mode: 384 });
7901
7963
  try {
7902
- (0, import_child_process2.execFileSync)("git", ["commit", "-F", tmpFile], { stdio: "inherit" });
7964
+ (0, import_child_process2.execFileSync)("git", ["commit", "-F", tmpFile], { stdio: "pipe" });
7965
+ } catch (err) {
7966
+ const stderr = err?.stderr?.toString() ?? "";
7967
+ if (stderr) process.stderr.write(stderr);
7968
+ throw err;
7903
7969
  } finally {
7904
7970
  try {
7905
7971
  (0, import_fs2.unlinkSync)(tmpFile);
@@ -7909,7 +7975,13 @@ function gitCommit(message) {
7909
7975
  }
7910
7976
  }
7911
7977
  function gitPush() {
7912
- (0, import_child_process2.execFileSync)("git", ["push"], { stdio: "inherit" });
7978
+ try {
7979
+ (0, import_child_process2.execFileSync)("git", ["push"], { stdio: "pipe" });
7980
+ } catch (err) {
7981
+ const stderr = err?.stderr?.toString() ?? "";
7982
+ if (stderr) process.stderr.write(stderr);
7983
+ throw err;
7984
+ }
7913
7985
  }
7914
7986
  function getBranchCommits(base = "main") {
7915
7987
  validateRef(base, "base");
@@ -7979,6 +8051,12 @@ function getFullDiff(base = "main") {
7979
8051
  maxBuffer: 10 * 1024 * 1024
7980
8052
  });
7981
8053
  }
8054
+ function getStagedFileCount() {
8055
+ const output = (0, import_child_process2.execFileSync)("git", ["diff", "--cached", "--name-only"], {
8056
+ encoding: "utf-8"
8057
+ });
8058
+ return output.trim().split("\n").filter(Boolean).length;
8059
+ }
7982
8060
  function getStagedDiffShortstat() {
7983
8061
  try {
7984
8062
  const out = (0, import_child_process2.execFileSync)("git", ["diff", "--cached", "--shortstat"], {
@@ -8135,7 +8213,13 @@ function getHeadSha() {
8135
8213
  }
8136
8214
  function gitPushSetUpstream(branch) {
8137
8215
  validateRef(branch, "branch");
8138
- (0, import_child_process2.execFileSync)("git", ["push", "-u", "origin", branch], { stdio: "inherit" });
8216
+ try {
8217
+ (0, import_child_process2.execFileSync)("git", ["push", "-u", "origin", branch], { stdio: "pipe" });
8218
+ } catch (err) {
8219
+ const stderr = err?.stderr?.toString() ?? "";
8220
+ if (stderr) process.stderr.write(stderr);
8221
+ throw err;
8222
+ }
8139
8223
  }
8140
8224
  function deleteBranch(name) {
8141
8225
  validateRef(name, "name");
@@ -8658,86 +8742,357 @@ var init_monorepo = __esm({
8658
8742
  }
8659
8743
  });
8660
8744
 
8661
- // src/commands/changeset.ts
8662
- var changeset_exports = {};
8663
- __export(changeset_exports, {
8664
- changeset: () => changeset,
8665
- formatChangesetFile: () => formatChangesetFile,
8666
- generateSlug: () => generateSlug,
8667
- mapFilesToPackages: () => mapFilesToPackages
8745
+ // src/smart-diff.ts
8746
+ var smart_diff_exports = {};
8747
+ __export(smart_diff_exports, {
8748
+ classifyFile: () => classifyFile,
8749
+ preprocessDiff: () => preprocessDiff,
8750
+ preprocessDiffWithSizeBudget: () => preprocessDiffWithSizeBudget
8668
8751
  });
8669
- function generateSlug() {
8670
- const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
8671
- return `${pick(ADJECTIVES)}-${pick(ANIMALS)}-${pick(VERBS)}`;
8752
+ function sanitizeFilepath(path) {
8753
+ return path.replace(/[\x00-\x1F\x7F[\]`]/g, "_").slice(0, 200);
8672
8754
  }
8673
- function mapFilesToPackages(files, workspace) {
8674
- const dirToName = /* @__PURE__ */ new Map();
8755
+ function classifyFile(filepath) {
8756
+ const basename = filepath.split("/").pop() ?? filepath;
8757
+ if (LOCK_FILES.has(basename)) return "lock";
8758
+ if (filepath.endsWith(".map")) return "sourcemap";
8759
+ if (VENDORED_PREFIXES.some((p) => filepath.startsWith(p))) return "vendored";
8760
+ if (GENERATED_PATTERNS.some((p) => p.test(filepath))) return "generated";
8761
+ return "code";
8762
+ }
8763
+ function parseDiffIntoFiles(diff) {
8764
+ const files = [];
8765
+ const parts = diff.split(/^(diff --git .+)$/m);
8766
+ for (let i = 1; i < parts.length; i += 2) {
8767
+ const header = parts[i];
8768
+ const content = parts[i + 1] ?? "";
8769
+ const match = header.match(/diff --git a\/(.+?) b\/(.+)/);
8770
+ const filepath = match?.[2] ?? "unknown";
8771
+ const lines = content.split("\n");
8772
+ let additions = 0;
8773
+ let deletions = 0;
8774
+ for (const line of lines) {
8775
+ if (line.startsWith("+") && !line.startsWith("+++")) additions++;
8776
+ else if (line.startsWith("-") && !line.startsWith("---")) deletions++;
8777
+ }
8778
+ files.push({ filepath, content: header + content, additions, deletions });
8779
+ }
8780
+ return files;
8781
+ }
8782
+ function isMinified(content) {
8783
+ const lines = content.split("\n").filter(
8784
+ (l) => (l.startsWith("+") || l.startsWith("-")) && !l.startsWith("+++") && !l.startsWith("---")
8785
+ );
8786
+ if (lines.length === 0) return false;
8787
+ return lines.some((l) => l.length > 500);
8788
+ }
8789
+ function preprocessDiff(diff) {
8790
+ const files = parseDiffIntoFiles(diff);
8791
+ if (files.length === 0) return { processedDiff: diff, summarized: [], aggressivelySummarized: [], tokensSaved: 0 };
8792
+ const kept = [];
8793
+ const summarized = [];
8794
+ let tokensSaved = 0;
8675
8795
  for (const file of files) {
8676
- const dirName = getPackageForFile(file, workspace);
8677
- if (!dirName || dirToName.has(dirName)) continue;
8678
- for (const pattern of workspace.packages) {
8679
- const hasGlob = /\*/.test(pattern);
8680
- const dir = pattern.replace(/\/?\*\*?$/, "").replace(/\/$/, "");
8681
- const pkgJsonPath = hasGlob ? (0, import_path7.join)(workspace.root, dir, dirName, "package.json") : (0, import_path7.join)(workspace.root, pattern.replace(/\/$/, ""), "package.json");
8682
- try {
8683
- const pkg = JSON.parse((0, import_fs7.readFileSync)(pkgJsonPath, "utf-8"));
8684
- dirToName.set(dirName, pkg.name ?? dirName);
8796
+ const classification = classifyFile(file.filepath);
8797
+ switch (classification) {
8798
+ case "sourcemap":
8799
+ tokensSaved += estimateTokens(file.content);
8800
+ summarized.push(file.filepath);
8801
+ break;
8802
+ case "lock":
8803
+ tokensSaved += estimateTokens(file.content);
8804
+ kept.push(`[lock file updated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions} lines)]
8805
+ `);
8806
+ summarized.push(file.filepath);
8807
+ break;
8808
+ case "generated":
8809
+ tokensSaved += estimateTokens(file.content);
8810
+ kept.push(`[generated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions})]
8811
+ `);
8812
+ summarized.push(file.filepath);
8813
+ break;
8814
+ case "vendored":
8815
+ tokensSaved += estimateTokens(file.content);
8816
+ kept.push(`[vendored: ${sanitizeFilepath(file.filepath)} updated]
8817
+ `);
8818
+ summarized.push(file.filepath);
8819
+ break;
8820
+ case "code":
8821
+ if (isMinified(file.content)) {
8822
+ tokensSaved += estimateTokens(file.content);
8823
+ const sizeKB = Math.round(file.content.length / 1024);
8824
+ kept.push(`[minified asset: ${sanitizeFilepath(file.filepath)} (${sizeKB} KB)]
8825
+ `);
8826
+ summarized.push(file.filepath);
8827
+ } else {
8828
+ kept.push(file.content);
8829
+ }
8685
8830
  break;
8686
- } catch {
8687
- }
8688
- }
8689
- if (!dirToName.has(dirName)) {
8690
- dirToName.set(dirName, dirName);
8691
8831
  }
8692
8832
  }
8693
- return dirToName;
8833
+ return {
8834
+ processedDiff: kept.join(""),
8835
+ summarized,
8836
+ aggressivelySummarized: [],
8837
+ tokensSaved
8838
+ };
8694
8839
  }
8695
- function formatChangesetFile(packages, summary) {
8696
- const frontmatter = packages.map((p) => `"${p.name}": ${p.bump}`).join("\n");
8697
- return `---
8698
- ${frontmatter}
8699
- ---
8700
-
8701
- ${summary}
8840
+ function buildFileSummary(file) {
8841
+ const sizeKB = Math.round(file.content.length / 1024);
8842
+ return `[modified: ${sanitizeFilepath(file.filepath)} \u2014 +${file.additions} \u2212${file.deletions} lines, ~${sizeKB}KB]
8702
8843
  `;
8703
8844
  }
8704
- async function prompt(rl, question) {
8705
- return new Promise((resolve) => rl.question(question, resolve));
8706
- }
8707
- async function changeset(options) {
8708
- const base = options.base ?? "main";
8709
- const apiKey = getApiKey();
8710
- if (!apiKey) {
8711
- console.error("Error: Not authenticated. Run `qc login` first.");
8712
- process.exit(1);
8845
+ function preprocessDiffWithSizeBudget(diff, maxBytes = 5 * 1024 * 1024) {
8846
+ const files = parseDiffIntoFiles(diff);
8847
+ if (files.length === 0) {
8848
+ return { processedDiff: diff, summarized: [], aggressivelySummarized: [], tokensSaved: 0 };
8713
8849
  }
8714
- const { detectWorkspace: detectWorkspace2 } = await Promise.resolve().then(() => (init_monorepo(), monorepo_exports));
8715
- const workspace = detectWorkspace2();
8716
- if (!workspace) {
8717
- console.error(
8718
- "No workspace packages found. Is this a pnpm monorepo?"
8719
- );
8720
- process.exit(1);
8850
+ const entries = [];
8851
+ const summarized = [];
8852
+ let tokensSaved = 0;
8853
+ for (const file of files) {
8854
+ const classification = classifyFile(file.filepath);
8855
+ switch (classification) {
8856
+ case "sourcemap":
8857
+ tokensSaved += estimateTokens(file.content);
8858
+ summarized.push(file.filepath);
8859
+ entries.push({ file, isNoise: true, summaryLine: null });
8860
+ break;
8861
+ case "lock":
8862
+ tokensSaved += estimateTokens(file.content);
8863
+ summarized.push(file.filepath);
8864
+ entries.push({
8865
+ file,
8866
+ isNoise: true,
8867
+ summaryLine: `[lock file updated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions} lines)]
8868
+ `
8869
+ });
8870
+ break;
8871
+ case "generated":
8872
+ tokensSaved += estimateTokens(file.content);
8873
+ summarized.push(file.filepath);
8874
+ entries.push({
8875
+ file,
8876
+ isNoise: true,
8877
+ summaryLine: `[generated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions})]
8878
+ `
8879
+ });
8880
+ break;
8881
+ case "vendored":
8882
+ tokensSaved += estimateTokens(file.content);
8883
+ summarized.push(file.filepath);
8884
+ entries.push({
8885
+ file,
8886
+ isNoise: true,
8887
+ summaryLine: `[vendored: ${sanitizeFilepath(file.filepath)} updated]
8888
+ `
8889
+ });
8890
+ break;
8891
+ case "code":
8892
+ if (isMinified(file.content)) {
8893
+ tokensSaved += estimateTokens(file.content);
8894
+ const sizeKB = Math.round(file.content.length / 1024);
8895
+ summarized.push(file.filepath);
8896
+ entries.push({
8897
+ file,
8898
+ isNoise: true,
8899
+ summaryLine: `[minified asset: ${sanitizeFilepath(file.filepath)} (${sizeKB} KB)]
8900
+ `
8901
+ });
8902
+ } else {
8903
+ entries.push({ file, isNoise: false, summaryLine: null });
8904
+ }
8905
+ break;
8906
+ }
8721
8907
  }
8722
- const changedFiles = getChangedFilesSince(base);
8723
- if (changedFiles.length === 0) {
8724
- console.error(`No changes detected vs ${base}.`);
8725
- process.exit(1);
8908
+ const aggressiveMap = /* @__PURE__ */ new Map();
8909
+ function buildOutput() {
8910
+ const parts = [];
8911
+ for (const entry of entries) {
8912
+ if (entry.isNoise) {
8913
+ if (entry.summaryLine !== null) parts.push(entry.summaryLine);
8914
+ } else if (aggressiveMap.has(entry.file.filepath)) {
8915
+ parts.push(aggressiveMap.get(entry.file.filepath));
8916
+ } else {
8917
+ parts.push(entry.file.content);
8918
+ }
8919
+ }
8920
+ return parts.join("");
8726
8921
  }
8727
- const packageMap = mapFilesToPackages(changedFiles, workspace);
8728
- const packageNames = Array.from(packageMap.values());
8729
- if (packageNames.length === 0) {
8730
- console.error("No workspace packages detected in changed files.");
8731
- process.exit(1);
8922
+ const codeEntries = entries.filter((e) => !e.isNoise);
8923
+ let output = buildOutput();
8924
+ if (output.length <= maxBytes) {
8925
+ return {
8926
+ processedDiff: output,
8927
+ summarized,
8928
+ aggressivelySummarized: [],
8929
+ tokensSaved
8930
+ };
8732
8931
  }
8733
- const commits = getOnlineLog(base);
8734
- const diff = getFullDiff(base);
8735
- const commitCount = commits.split("\n").filter(Boolean).length;
8736
- console.error(
8737
- `Analyzing changes vs ${base}... ${commitCount} commit(s), ${packageNames.length} package(s) changed`
8738
- );
8739
- const client = new ApiClient({ apiKey });
8740
- let result;
8932
+ const TIER1_THRESHOLD = 5 * 1024;
8933
+ for (const entry of codeEntries) {
8934
+ if (entry.file.content.length > TIER1_THRESHOLD && !aggressiveMap.has(entry.file.filepath)) {
8935
+ tokensSaved += estimateTokens(entry.file.content);
8936
+ aggressiveMap.set(entry.file.filepath, buildFileSummary(entry.file));
8937
+ }
8938
+ }
8939
+ output = buildOutput();
8940
+ if (output.length <= maxBytes) {
8941
+ return {
8942
+ processedDiff: output,
8943
+ summarized,
8944
+ aggressivelySummarized: [...aggressiveMap.keys()],
8945
+ tokensSaved
8946
+ };
8947
+ }
8948
+ const TIER2_THRESHOLD = 2 * 1024;
8949
+ for (const entry of codeEntries) {
8950
+ if (entry.file.content.length > TIER2_THRESHOLD && !aggressiveMap.has(entry.file.filepath)) {
8951
+ tokensSaved += estimateTokens(entry.file.content);
8952
+ aggressiveMap.set(entry.file.filepath, buildFileSummary(entry.file));
8953
+ }
8954
+ }
8955
+ output = buildOutput();
8956
+ if (output.length <= maxBytes) {
8957
+ return {
8958
+ processedDiff: output,
8959
+ summarized,
8960
+ aggressivelySummarized: [...aggressiveMap.keys()],
8961
+ tokensSaved
8962
+ };
8963
+ }
8964
+ for (const entry of codeEntries) {
8965
+ if (!aggressiveMap.has(entry.file.filepath)) {
8966
+ tokensSaved += estimateTokens(entry.file.content);
8967
+ aggressiveMap.set(entry.file.filepath, buildFileSummary(entry.file));
8968
+ }
8969
+ }
8970
+ return {
8971
+ processedDiff: buildOutput(),
8972
+ summarized,
8973
+ aggressivelySummarized: [...aggressiveMap.keys()],
8974
+ tokensSaved
8975
+ };
8976
+ }
8977
+ var LOCK_FILES, GENERATED_PATTERNS, VENDORED_PREFIXES;
8978
+ var init_smart_diff = __esm({
8979
+ "src/smart-diff.ts"() {
8980
+ "use strict";
8981
+ init_dist();
8982
+ LOCK_FILES = /* @__PURE__ */ new Set([
8983
+ "pnpm-lock.yaml",
8984
+ "package-lock.json",
8985
+ "yarn.lock",
8986
+ "Cargo.lock",
8987
+ "Gemfile.lock",
8988
+ "poetry.lock",
8989
+ "composer.lock",
8990
+ "bun.lockb",
8991
+ "shrinkwrap.json"
8992
+ ]);
8993
+ GENERATED_PATTERNS = [
8994
+ /\.generated\.\w+$/,
8995
+ /\.g\.dart$/,
8996
+ /\.pb\.go$/,
8997
+ /\.pb\.ts$/,
8998
+ /(^|\/)\.prisma\/client\//,
8999
+ /\/generated\//
9000
+ ];
9001
+ VENDORED_PREFIXES = ["vendor/", "third_party/", "node_modules/"];
9002
+ }
9003
+ });
9004
+
9005
+ // src/commands/changeset.ts
9006
+ var changeset_exports = {};
9007
+ __export(changeset_exports, {
9008
+ changeset: () => changeset,
9009
+ formatChangesetFile: () => formatChangesetFile,
9010
+ generateSlug: () => generateSlug,
9011
+ mapFilesToPackages: () => mapFilesToPackages
9012
+ });
9013
+ function generateSlug() {
9014
+ const pick = (arr) => arr[Math.floor(Math.random() * arr.length)];
9015
+ return `${pick(ADJECTIVES)}-${pick(ANIMALS)}-${pick(VERBS)}`;
9016
+ }
9017
+ function mapFilesToPackages(files, workspace) {
9018
+ const dirToName = /* @__PURE__ */ new Map();
9019
+ for (const file of files) {
9020
+ const dirName = getPackageForFile(file, workspace);
9021
+ if (!dirName || dirToName.has(dirName)) continue;
9022
+ for (const pattern of workspace.packages) {
9023
+ const hasGlob = /\*/.test(pattern);
9024
+ const dir = pattern.replace(/\/?\*\*?$/, "").replace(/\/$/, "");
9025
+ const pkgJsonPath = hasGlob ? (0, import_path7.join)(workspace.root, dir, dirName, "package.json") : (0, import_path7.join)(workspace.root, pattern.replace(/\/$/, ""), "package.json");
9026
+ try {
9027
+ const pkg = JSON.parse((0, import_fs7.readFileSync)(pkgJsonPath, "utf-8"));
9028
+ dirToName.set(dirName, pkg.name ?? dirName);
9029
+ break;
9030
+ } catch {
9031
+ }
9032
+ }
9033
+ if (!dirToName.has(dirName)) {
9034
+ dirToName.set(dirName, dirName);
9035
+ }
9036
+ }
9037
+ return dirToName;
9038
+ }
9039
+ function formatChangesetFile(packages, summary) {
9040
+ const frontmatter = packages.map((p) => `"${p.name}": ${p.bump}`).join("\n");
9041
+ return `---
9042
+ ${frontmatter}
9043
+ ---
9044
+
9045
+ ${summary}
9046
+ `;
9047
+ }
9048
+ async function prompt(rl, question) {
9049
+ return new Promise((resolve) => rl.question(question, resolve));
9050
+ }
9051
+ async function changeset(options) {
9052
+ const base = options.base ?? "main";
9053
+ const apiKey = getApiKey();
9054
+ if (!apiKey) {
9055
+ console.error("Error: Not authenticated. Run `qc login` first.");
9056
+ process.exit(1);
9057
+ }
9058
+ const { detectWorkspace: detectWorkspace2 } = await Promise.resolve().then(() => (init_monorepo(), monorepo_exports));
9059
+ const workspace = detectWorkspace2();
9060
+ if (!workspace) {
9061
+ console.error(
9062
+ "No workspace packages found. Is this a pnpm monorepo?"
9063
+ );
9064
+ process.exit(1);
9065
+ }
9066
+ const changedFiles = getChangedFilesSince(base);
9067
+ if (changedFiles.length === 0) {
9068
+ console.error(`No commits with file changes detected on this branch vs ${base}.`);
9069
+ console.error(`Tip: \`qc changeset\` requires committed changes (not just staged files).`);
9070
+ console.error(` Commit first with \`qc\`, then run \`qc changeset\`.`);
9071
+ process.exit(1);
9072
+ }
9073
+ const packageMap = mapFilesToPackages(changedFiles, workspace);
9074
+ const packageNames = Array.from(packageMap.values());
9075
+ if (packageNames.length === 0) {
9076
+ console.error("No workspace packages detected in changed files.");
9077
+ process.exit(1);
9078
+ }
9079
+ const commits = getOnlineLog(base);
9080
+ const commitCount = commits.split("\n").filter(Boolean).length;
9081
+ const { preprocessDiffWithSizeBudget: preprocessDiffWithSizeBudget2 } = await Promise.resolve().then(() => (init_smart_diff(), smart_diff_exports));
9082
+ const { getDiffStat: getDiffStat2, getFullDiff: getFullDiff2 } = await Promise.resolve().then(() => (init_git(), git_exports));
9083
+ const diffStat = getDiffStat2(base);
9084
+ const rawDiff = getFullDiff2(base);
9085
+ const { processedDiff } = preprocessDiffWithSizeBudget2(rawDiff, 6e4);
9086
+ const diff = `DIFF STAT:
9087
+ ${diffStat}
9088
+
9089
+ DETAILED DIFF (may be summarized for large changes):
9090
+ ${processedDiff}`;
9091
+ console.error(
9092
+ `Analyzing changes vs ${base}... ${commitCount} commit(s), ${packageNames.length} package(s) changed`
9093
+ );
9094
+ const client = new ApiClient({ apiKey });
9095
+ let result;
8741
9096
  const msg = (e) => e instanceof Error ? e.message : String(e);
8742
9097
  const isTransient = (m) => /invalid json|no changeset|unexpected response|ai worker|timeout|502|503|504/i.test(m);
8743
9098
  let attempts = 0;
@@ -9226,6 +9581,193 @@ var require_picocolors = __commonJS({
9226
9581
  }
9227
9582
  });
9228
9583
 
9584
+ // src/ui-theme.ts
9585
+ function overlayTypeColors(base, custom) {
9586
+ if (!custom || Object.keys(custom).length === 0) return { ...base };
9587
+ const next = { ...base };
9588
+ const pmap = import_picocolors.default;
9589
+ for (const [key, raw] of Object.entries(custom)) {
9590
+ const name = typeof raw === "string" ? raw.trim().toLowerCase() : "";
9591
+ if (!name) continue;
9592
+ const fn = pmap[name];
9593
+ if (typeof fn === "function") {
9594
+ next[key] = fn;
9595
+ }
9596
+ }
9597
+ return next;
9598
+ }
9599
+ function buildVibrant() {
9600
+ return {
9601
+ step: import_picocolors.default.dim,
9602
+ success: import_picocolors.default.greenBright,
9603
+ error: import_picocolors.default.redBright,
9604
+ dim: import_picocolors.default.dim,
9605
+ bullet: import_picocolors.default.greenBright,
9606
+ inlineCode: import_picocolors.default.magentaBright,
9607
+ scope: (s) => import_picocolors.default.bold(import_picocolors.default.yellow(s)),
9608
+ strong: import_picocolors.default.bold,
9609
+ additions: import_picocolors.default.greenBright,
9610
+ deletions: import_picocolors.default.redBright,
9611
+ branchName: (s) => import_picocolors.default.bold(import_picocolors.default.magenta(s)),
9612
+ commitHash: import_picocolors.default.dim,
9613
+ boxBorder: import_picocolors.default.dim,
9614
+ boxBorderAccent: import_picocolors.default.cyanBright,
9615
+ spinner: {
9616
+ aiGenerate: import_picocolors.default.cyanBright,
9617
+ branchGen: import_picocolors.default.cyanBright,
9618
+ gitOp: import_picocolors.default.blueBright,
9619
+ localProvider: import_picocolors.default.magentaBright,
9620
+ smartDiff: import_picocolors.default.dim
9621
+ },
9622
+ type: {
9623
+ feat: (s) => import_picocolors.default.bold(import_picocolors.default.cyanBright(s)),
9624
+ fix: (s) => import_picocolors.default.bold(import_picocolors.default.redBright(s)),
9625
+ perf: (s) => import_picocolors.default.bold(import_picocolors.default.magentaBright(s)),
9626
+ refactor: (s) => import_picocolors.default.bold(import_picocolors.default.yellow(s)),
9627
+ docs: (s) => import_picocolors.default.bold(import_picocolors.default.blue(s)),
9628
+ test: (s) => import_picocolors.default.bold(import_picocolors.default.green(s)),
9629
+ chore: (s) => import_picocolors.default.dim(import_picocolors.default.bold(import_picocolors.default.white(s))),
9630
+ ci: (s) => import_picocolors.default.dim(import_picocolors.default.bold(import_picocolors.default.cyan(s))),
9631
+ style: (s) => import_picocolors.default.dim(import_picocolors.default.bold(import_picocolors.default.magenta(s)))
9632
+ }
9633
+ };
9634
+ }
9635
+ function buildMuted() {
9636
+ return {
9637
+ step: import_picocolors.default.dim,
9638
+ success: import_picocolors.default.green,
9639
+ error: import_picocolors.default.red,
9640
+ dim: import_picocolors.default.dim,
9641
+ bullet: import_picocolors.default.green,
9642
+ inlineCode: import_picocolors.default.magenta,
9643
+ scope: (s) => import_picocolors.default.bold(import_picocolors.default.yellow(s)),
9644
+ strong: import_picocolors.default.bold,
9645
+ additions: import_picocolors.default.green,
9646
+ deletions: import_picocolors.default.red,
9647
+ branchName: (s) => import_picocolors.default.bold(import_picocolors.default.magenta(s)),
9648
+ commitHash: import_picocolors.default.dim,
9649
+ boxBorder: import_picocolors.default.dim,
9650
+ boxBorderAccent: import_picocolors.default.cyan,
9651
+ spinner: {
9652
+ aiGenerate: import_picocolors.default.cyan,
9653
+ branchGen: import_picocolors.default.cyan,
9654
+ gitOp: import_picocolors.default.blue,
9655
+ localProvider: import_picocolors.default.magenta,
9656
+ smartDiff: import_picocolors.default.dim
9657
+ },
9658
+ type: {
9659
+ feat: (s) => import_picocolors.default.bold(import_picocolors.default.cyan(s)),
9660
+ fix: (s) => import_picocolors.default.bold(import_picocolors.default.red(s)),
9661
+ perf: (s) => import_picocolors.default.bold(import_picocolors.default.magenta(s)),
9662
+ refactor: (s) => import_picocolors.default.bold(import_picocolors.default.yellow(s)),
9663
+ docs: (s) => import_picocolors.default.bold(import_picocolors.default.blue(s)),
9664
+ test: (s) => import_picocolors.default.bold(import_picocolors.default.green(s)),
9665
+ chore: (s) => import_picocolors.default.dim(import_picocolors.default.bold(import_picocolors.default.white(s))),
9666
+ ci: (s) => import_picocolors.default.dim(import_picocolors.default.bold(import_picocolors.default.cyan(s))),
9667
+ style: (s) => import_picocolors.default.dim(import_picocolors.default.bold(import_picocolors.default.magenta(s)))
9668
+ }
9669
+ };
9670
+ }
9671
+ function buildMono() {
9672
+ const bold = import_picocolors.default.bold;
9673
+ const dim = import_picocolors.default.dim;
9674
+ return {
9675
+ step: dim,
9676
+ success: bold,
9677
+ error: bold,
9678
+ dim,
9679
+ bullet: bold,
9680
+ inlineCode: bold,
9681
+ scope: bold,
9682
+ strong: bold,
9683
+ additions: bold,
9684
+ deletions: bold,
9685
+ branchName: bold,
9686
+ commitHash: dim,
9687
+ boxBorder: dim,
9688
+ boxBorderAccent: bold,
9689
+ spinner: {
9690
+ aiGenerate: identity,
9691
+ branchGen: identity,
9692
+ gitOp: identity,
9693
+ localProvider: identity,
9694
+ smartDiff: dim
9695
+ },
9696
+ type: {
9697
+ feat: bold,
9698
+ fix: bold,
9699
+ perf: bold,
9700
+ refactor: bold,
9701
+ docs: bold,
9702
+ test: bold,
9703
+ chore: dim,
9704
+ ci: dim,
9705
+ style: dim
9706
+ }
9707
+ };
9708
+ }
9709
+ function applyAdaptive(theme, bg) {
9710
+ if (bg !== "light") return theme;
9711
+ return {
9712
+ ...theme,
9713
+ boxBorder: import_picocolors.default.dim,
9714
+ boxBorderAccent: import_picocolors.default.blue,
9715
+ type: {
9716
+ ...theme.type,
9717
+ feat: (s) => theme.strong(import_picocolors.default.cyan(s)),
9718
+ fix: (s) => theme.strong(import_picocolors.default.red(s)),
9719
+ perf: (s) => theme.strong(import_picocolors.default.magenta(s))
9720
+ }
9721
+ };
9722
+ }
9723
+ function getTheme(name, adaptive) {
9724
+ let base;
9725
+ if (name === "muted") base = buildMuted();
9726
+ else if (name === "mono") base = buildMono();
9727
+ else base = buildVibrant();
9728
+ if (!adaptive) return base;
9729
+ return applyAdaptive(base, detectTerminalBackground());
9730
+ }
9731
+ function detectTerminalBackground() {
9732
+ const raw = process.env.COLORFGBG;
9733
+ if (!raw) return "unknown";
9734
+ const parts = raw.split(";").map((p) => p.trim());
9735
+ if (parts.length < 2) return "unknown";
9736
+ const last = parts[parts.length - 1];
9737
+ const n = parseInt(last, 10);
9738
+ if (!Number.isFinite(n)) return "unknown";
9739
+ if (n >= 232 && n <= 255) return n >= 244 ? "light" : "dark";
9740
+ if (n >= 16 && n <= 231) {
9741
+ const i = n - 16;
9742
+ const r = Math.floor(i / 36) / 5;
9743
+ const g = Math.floor(i % 36 / 6) / 5;
9744
+ const b = i % 6 / 5;
9745
+ const luminance = 0.299 * r + 0.587 * g + 0.114 * b;
9746
+ return luminance >= 0.55 ? "light" : "dark";
9747
+ }
9748
+ if (n >= 8 && n <= 15) return "light";
9749
+ if (n >= 0 && n <= 7) return "dark";
9750
+ return "unknown";
9751
+ }
9752
+ function resolveTheme(opts) {
9753
+ if (opts.noColor) return getTheme("mono", false);
9754
+ const baseName = opts.name ?? "vibrant";
9755
+ const adaptive = opts.adaptive ?? true;
9756
+ let theme = getTheme(baseName, adaptive);
9757
+ if (opts.typeColors && Object.keys(opts.typeColors).length > 0) {
9758
+ theme = { ...theme, type: overlayTypeColors(theme.type, opts.typeColors) };
9759
+ }
9760
+ return theme;
9761
+ }
9762
+ var import_picocolors, identity;
9763
+ var init_ui_theme = __esm({
9764
+ "src/ui-theme.ts"() {
9765
+ "use strict";
9766
+ import_picocolors = __toESM(require_picocolors());
9767
+ identity = (s) => s;
9768
+ }
9769
+ });
9770
+
9229
9771
  // src/ui.ts
9230
9772
  function hasCliNoColor() {
9231
9773
  try {
@@ -9239,16 +9781,21 @@ function getTerminalWidth() {
9239
9781
  }
9240
9782
  function createUI(options) {
9241
9783
  const isColor = options.isTTY && !options.noColor;
9242
- const wrap = (fn) => (s) => isColor ? fn(s) : s;
9784
+ const theme = resolveTheme({
9785
+ name: options.themeName,
9786
+ adaptive: options.adaptive,
9787
+ noColor: !isColor,
9788
+ typeColors: options.typeColors
9789
+ });
9243
9790
  const format = {
9244
- step: (msg) => `${isColor ? import_picocolors.default.dim("\u203A") : "\u203A"} ${isColor ? import_picocolors.default.dim(msg) : msg}`,
9245
- success: (msg) => `${isColor ? import_picocolors.default.green("\u2713") : "\u2713"} ${msg}`,
9246
- error: (msg) => `${isColor ? import_picocolors.default.red("\u2717") : "\u2717"} ${msg}`,
9247
- dim: wrap(import_picocolors.default.dim),
9248
- bold: wrap(import_picocolors.default.bold),
9249
- commitType: wrap(import_picocolors.default.cyan),
9250
- commitScope: wrap(import_picocolors.default.yellow),
9251
- accent: wrap(import_picocolors.default.magenta)
9791
+ step: (msg) => isColor ? `${theme.step("\u203A")} ${theme.dim(msg)}` : `\u203A ${msg}`,
9792
+ success: (msg) => isColor ? `${theme.success("\u2713")} ${msg}` : `\u2713 ${msg}`,
9793
+ error: (msg) => isColor ? `${theme.error("\u2717")} ${msg}` : `\u2717 ${msg}`,
9794
+ dim: (msg) => isColor ? theme.dim(msg) : msg,
9795
+ bold: (msg) => isColor ? theme.strong(msg) : msg,
9796
+ commitType: (t) => isColor ? (theme.type[t] ?? theme.type.feat ?? ((s) => s))(t) : t,
9797
+ commitScope: (scope) => isColor ? theme.scope(scope) : scope,
9798
+ accent: (msg) => isColor ? theme.inlineCode(msg) : msg
9252
9799
  };
9253
9800
  function createSpinner(message, write = (s) => process.stderr.write(s)) {
9254
9801
  let frame = 0;
@@ -9259,7 +9806,7 @@ function createUI(options) {
9259
9806
  if (!options.isTTY) return;
9260
9807
  interval = setInterval(() => {
9261
9808
  const f = SPINNER_FRAMES2[frame++ % SPINNER_FRAMES2.length];
9262
- write(`\r${format.step(message)} ${isColor ? import_picocolors.default.cyan(f) : f}`);
9809
+ write(`\r${format.step(message)} ${isColor ? theme.spinner.aiGenerate(f) : f}`);
9263
9810
  }, 80);
9264
9811
  },
9265
9812
  stop(finalMessage) {
@@ -9282,22 +9829,27 @@ function createUI(options) {
9282
9829
  error: (msg) => process.stderr.write(format.error(msg) + "\n"),
9283
9830
  dim: (msg) => process.stderr.write(format.dim(msg) + "\n")
9284
9831
  };
9285
- return { isColor, format, spinner: createSpinner, log };
9832
+ return { isColor, format, spinner: createSpinner, log, theme };
9286
9833
  }
9287
9834
  function getUI() {
9288
9835
  if (!_defaultUI) {
9836
+ const cfg = getConfig();
9289
9837
  _defaultUI = createUI({
9290
9838
  isTTY: !!process.stderr.isTTY,
9291
- noColor: !!process.env.NO_COLOR || hasCliNoColor()
9839
+ noColor: !!process.env.NO_COLOR || hasCliNoColor(),
9840
+ themeName: cfg.ui?.theme,
9841
+ adaptive: cfg.ui?.adaptive !== false,
9842
+ typeColors: cfg.ui?.type_colors
9292
9843
  });
9293
9844
  }
9294
9845
  return _defaultUI;
9295
9846
  }
9296
- var import_picocolors, SPINNER_FRAMES2, _defaultUI, ui;
9847
+ var SPINNER_FRAMES2, _defaultUI, ui;
9297
9848
  var init_ui = __esm({
9298
9849
  "src/ui.ts"() {
9299
9850
  "use strict";
9300
- import_picocolors = __toESM(require_picocolors());
9851
+ init_config();
9852
+ init_ui_theme();
9301
9853
  SPINNER_FRAMES2 = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
9302
9854
  ui = new Proxy({}, {
9303
9855
  get(_target, prop) {
@@ -9307,7 +9859,10 @@ var init_ui = __esm({
9307
9859
  }
9308
9860
  });
9309
9861
 
9310
- // src/ui-rich.ts
9862
+ // src/ui-layout.ts
9863
+ function stripAnsi(s) {
9864
+ return s.replace(/\x1b\[[0-9;]*m/g, "");
9865
+ }
9311
9866
  function splitCommitForBox(message) {
9312
9867
  const firstLine = message.split("\n")[0] ?? "";
9313
9868
  const m = firstLine.match(HEADER_RX);
@@ -9319,91 +9874,174 @@ function splitCommitForBox(message) {
9319
9874
  subject: m[4] ?? ""
9320
9875
  };
9321
9876
  }
9322
- function renderFileTree(files, maxFiles) {
9877
+ function colorizePath(filepath, isColor) {
9878
+ if (!isColor) return filepath;
9879
+ const slashIdx = filepath.lastIndexOf("/");
9880
+ const dir = slashIdx >= 0 ? filepath.slice(0, slashIdx + 1) : "";
9881
+ const name = slashIdx >= 0 ? filepath.slice(slashIdx + 1) : filepath;
9882
+ const dotIdx = name.lastIndexOf(".");
9883
+ const ext = dotIdx > 0 ? name.slice(dotIdx) : "";
9884
+ const colorize = EXTENSION_COLORS[ext];
9885
+ const coloredName = colorize ? colorize(name) : name;
9886
+ return (dir ? import_picocolors2.default.dim(dir) : "") + coloredName;
9887
+ }
9888
+ function renderFileTree(files, maxFiles, opts = {}) {
9323
9889
  if (files.length === 0) return "";
9890
+ const isColor = opts.isColor ?? false;
9324
9891
  const lines = [];
9325
9892
  const display = files.slice(0, maxFiles);
9326
- const overflow = Math.max(0, files.length - maxFiles);
9893
+ const overflow = files.length - maxFiles;
9327
9894
  for (let i = 0; i < display.length; i++) {
9328
- const isLast = i === display.length - 1 && overflow === 0;
9895
+ const isLast = i === display.length - 1 && overflow <= 0;
9329
9896
  const connector = isLast ? "\u2514\u2500" : "\u251C\u2500";
9330
- lines.push(` ${connector} ${display[i]}`);
9897
+ const colored = colorizePath(display[i] ?? "", isColor);
9898
+ const connectorRendered = isColor ? import_picocolors2.default.dim(connector) : connector;
9899
+ lines.push(` ${connectorRendered} ${colored}`);
9331
9900
  }
9332
9901
  if (overflow > 0) {
9333
- lines.push(` \u2514\u2500 +${overflow} more files`);
9902
+ const connector = isColor ? import_picocolors2.default.dim("\u2514\u2500") : "\u2514\u2500";
9903
+ const more = isColor ? import_picocolors2.default.dim(`+${overflow} more files`) : `+${overflow} more files`;
9904
+ lines.push(` ${connector} ${more}`);
9334
9905
  }
9335
9906
  return lines.join("\n");
9336
9907
  }
9908
+ function renderStatsLine(stats, isColor, theme) {
9909
+ if (stats.files === 0 && stats.additions === 0 && stats.deletions === 0) return "";
9910
+ const dim = theme?.dim ?? import_picocolors2.default.dim;
9911
+ const addFn = theme?.additions ?? ((s) => import_picocolors2.default.green(s));
9912
+ const delFn = theme?.deletions ?? ((s) => import_picocolors2.default.red(s));
9913
+ const filesText = isColor ? dim(`${stats.files} files`) : `${stats.files} files`;
9914
+ const additions = isColor ? addFn(`+${stats.additions}`) : `+${stats.additions}`;
9915
+ const deletions = isColor ? delFn(`\u2212${stats.deletions}`) : `\u2212${stats.deletions}`;
9916
+ const sep = isColor ? dim(" \xB7 ") : " \xB7 ";
9917
+ let text = `${filesText}${sep}${additions} ${deletions}`;
9918
+ if (stats.tokens !== void 0) {
9919
+ const tokens = isColor ? dim(`${stats.tokens} tokens`) : `${stats.tokens} tokens`;
9920
+ text += `${sep}${tokens}`;
9921
+ }
9922
+ return ` ${text}`;
9923
+ }
9337
9924
  function wrapLine(text, width) {
9338
- if (text.length <= width) return [text];
9925
+ if (stripAnsi(text).length <= width) return [text];
9339
9926
  const result = [];
9340
9927
  let remaining = text;
9341
- while (remaining.length > width) {
9342
- let breakAt = remaining.lastIndexOf(" ", width);
9343
- if (breakAt < width / 2) breakAt = width;
9928
+ while (stripAnsi(remaining).length > width) {
9929
+ let visibleCount = 0;
9930
+ let rawIdx = 0;
9931
+ let lastSpaceRaw = -1;
9932
+ const len = remaining.length;
9933
+ while (rawIdx < len && visibleCount < width) {
9934
+ if (remaining[rawIdx] === "\x1B") {
9935
+ while (rawIdx < len && remaining[rawIdx] !== "m") rawIdx++;
9936
+ if (rawIdx < len) rawIdx++;
9937
+ continue;
9938
+ }
9939
+ if (remaining[rawIdx] === " ") lastSpaceRaw = rawIdx;
9940
+ visibleCount++;
9941
+ rawIdx++;
9942
+ }
9943
+ const breakAt = lastSpaceRaw > 0 && lastSpaceRaw > width / 2 ? lastSpaceRaw : rawIdx;
9344
9944
  result.push(remaining.slice(0, breakAt));
9345
9945
  remaining = remaining.slice(breakAt).trimStart();
9346
9946
  }
9347
9947
  if (remaining) result.push(remaining);
9348
9948
  return result;
9349
9949
  }
9350
- function stripAnsi(s) {
9351
- return s.replace(/\x1b\[[0-9;]*m/g, "");
9950
+ function isImportantCommit(header, body) {
9951
+ if (/BREAKING CHANGE/i.test(body)) return true;
9952
+ if (/^[a-z]+(\([^)]+\))?!:/i.test(header)) return true;
9953
+ return false;
9954
+ }
9955
+ function styleBoxTopRow(box, horizRepeat, isColor, theme) {
9956
+ if (!isColor) return box.topLeft + box.horizontal.repeat(horizRepeat) + box.topRight;
9957
+ const edge = theme?.boxBorder ?? import_picocolors2.default.dim;
9958
+ const corner = theme?.boxBorderAccent ?? edge;
9959
+ return corner(box.topLeft) + edge(box.horizontal.repeat(horizRepeat)) + corner(box.topRight);
9352
9960
  }
9353
- function boxedLine(content, innerWidth, isColor) {
9961
+ function styleBoxBottomRow(box, horizRepeat, isColor, theme) {
9962
+ if (!isColor) return box.bottomLeft + box.horizontal.repeat(horizRepeat) + box.bottomRight;
9963
+ const edge = theme?.boxBorder ?? import_picocolors2.default.dim;
9964
+ const corner = theme?.boxBorderAccent ?? edge;
9965
+ return corner(box.bottomLeft) + edge(box.horizontal.repeat(horizRepeat)) + corner(box.bottomRight);
9966
+ }
9967
+ function boxedLine(vertical, content, innerWidth, isColor, theme) {
9354
9968
  const visibleLen = stripAnsi(content).length;
9355
9969
  const padding = " ".repeat(Math.max(0, innerWidth - visibleLen));
9356
- const border = isColor ? import_picocolors2.default.dim("\u2502") : "\u2502";
9970
+ const border = isColor ? (theme?.boxBorder ?? import_picocolors2.default.dim)(vertical) : vertical;
9357
9971
  return ` ${border} ${content}${padding} ${border}`;
9358
9972
  }
9973
+ function buildHeaderPrefixAndSubject(parsed, headerFirstLine, isColor, theme) {
9974
+ if (!parsed.type) {
9975
+ return { prefix: "", subjectText: headerFirstLine };
9976
+ }
9977
+ const bangPlain = parsed.breaking ? "!" : "";
9978
+ if (parsed.scope) {
9979
+ const prefixPlain2 = `${parsed.type}(${parsed.scope})${bangPlain}: `;
9980
+ if (!isColor) {
9981
+ return { prefix: prefixPlain2, subjectText: parsed.subject };
9982
+ }
9983
+ const typeCell2 = theme ? theme.type[parsed.type] ?? theme.type.feat ?? ((s) => s) : (s) => import_picocolors2.default.bold(import_picocolors2.default.cyan(s));
9984
+ const scopeCell = theme ? theme.scope : (s) => import_picocolors2.default.bold(import_picocolors2.default.yellow(s));
9985
+ const bangCell2 = theme ? parsed.breaking ? theme.error("!") : "" : parsed.breaking ? import_picocolors2.default.bold(import_picocolors2.default.red("!")) : "";
9986
+ const prefixStyled2 = `${typeCell2(parsed.type)}(${scopeCell(parsed.scope)})${bangCell2}: `;
9987
+ return { prefix: prefixStyled2, subjectText: parsed.subject };
9988
+ }
9989
+ const prefixPlain = `${parsed.type}${bangPlain}: `;
9990
+ if (!isColor) {
9991
+ return { prefix: prefixPlain, subjectText: parsed.subject };
9992
+ }
9993
+ const typeCell = theme ? theme.type[parsed.type] ?? theme.type.feat ?? ((s) => s) : (s) => import_picocolors2.default.bold(import_picocolors2.default.cyan(s));
9994
+ const bangCell = theme ? parsed.breaking ? theme.error("!") : "" : parsed.breaking ? import_picocolors2.default.bold(import_picocolors2.default.red("!")) : "";
9995
+ const prefixStyled = `${typeCell(parsed.type)}${bangCell}: `;
9996
+ return { prefix: prefixStyled, subjectText: parsed.subject };
9997
+ }
9359
9998
  function renderBoxedCommit(header, body, opts) {
9360
- if (opts.width < MIN_BOX_WIDTH) {
9999
+ const requestedStyle = opts.style ?? "gradient";
10000
+ const promoted = opts.autoEmphasis !== false && requestedStyle !== "none" && isImportantCommit(header.split("\n")[0] ?? header, body);
10001
+ const style = promoted ? "double" : requestedStyle;
10002
+ if (style === "none" || opts.width < MIN_BOX_WIDTH) {
9361
10003
  const lines2 = [header.split("\n")[0] ?? header];
9362
10004
  if (body) lines2.push("", body);
9363
10005
  return lines2.join("\n");
9364
10006
  }
9365
- const innerWidth = opts.width - 8;
10007
+ const chars = BOX_CHARS[style];
10008
+ const innerWidth = opts.width - 6;
9366
10009
  const horiz = opts.width - 2;
9367
- const top = " " + (opts.isColor ? import_picocolors2.default.dim("\u256D" + "\u2500".repeat(horiz) + "\u256E") : "\u256D" + "\u2500".repeat(horiz) + "\u256E");
9368
- const bottom = " " + (opts.isColor ? import_picocolors2.default.dim("\u2570" + "\u2500".repeat(horiz) + "\u256F") : "\u2570" + "\u2500".repeat(horiz) + "\u256F");
10010
+ const firstLineHeader = header.split("\n")[0] ?? header;
9369
10011
  const parsed = splitCommitForBox(header);
9370
- let firstLineStyled;
9371
- if (parsed.type && parsed.scope) {
9372
- const bare = `${parsed.type}(${parsed.scope})${parsed.breaking ? "!" : ""}: ${parsed.subject}`;
9373
- firstLineStyled = opts.isColor ? `${import_picocolors2.default.bold(import_picocolors2.default.cyan(parsed.type))}(${import_picocolors2.default.bold(import_picocolors2.default.yellow(parsed.scope))})${parsed.breaking ? import_picocolors2.default.bold(import_picocolors2.default.red("!")) : ""}: ${parsed.subject}` : bare;
9374
- } else if (parsed.type) {
9375
- const bare = `${parsed.type}${parsed.breaking ? "!" : ""}: ${parsed.subject}`;
9376
- firstLineStyled = opts.isColor ? `${import_picocolors2.default.bold(import_picocolors2.default.cyan(parsed.type))}${parsed.breaking ? import_picocolors2.default.bold(import_picocolors2.default.red("!")) : ""}: ${parsed.subject}` : bare;
9377
- } else {
9378
- firstLineStyled = header.split("\n")[0] ?? header;
9379
- }
10012
+ const { prefix: headerPrefix, subjectText } = buildHeaderPrefixAndSubject(
10013
+ parsed,
10014
+ firstLineHeader,
10015
+ opts.isColor,
10016
+ opts.theme
10017
+ );
10018
+ const prefixLen = stripAnsi(headerPrefix).length;
10019
+ const subjectLines = wrapLine(subjectText, Math.max(1, innerWidth - prefixLen));
10020
+ const styledTop = styleBoxTopRow(chars, horiz, opts.isColor, opts.theme);
10021
+ const styledBottom = styleBoxBottomRow(chars, horiz, opts.isColor, opts.theme);
9380
10022
  const lines = [];
9381
- const headerParts = wrapLine(firstLineStyled, innerWidth);
9382
- for (let i = 0; i < headerParts.length; i++) {
9383
- const indent = i === 0 ? "" : " ";
9384
- lines.push(boxedLine(indent + (headerParts[i] ?? ""), innerWidth, opts.isColor));
10023
+ lines.push(" " + styledTop);
10024
+ lines.push(boxedLine(chars.vertical, headerPrefix + (subjectLines[0] ?? ""), innerWidth, opts.isColor, opts.theme));
10025
+ for (let i = 1; i < subjectLines.length; i++) {
10026
+ lines.push(boxedLine(chars.vertical, " " + (subjectLines[i] ?? ""), innerWidth, opts.isColor, opts.theme));
9385
10027
  }
9386
10028
  if (body) {
9387
- lines.push(boxedLine("", innerWidth, opts.isColor));
10029
+ lines.push(boxedLine(chars.vertical, "", innerWidth, opts.isColor, opts.theme));
9388
10030
  for (const bline of body.split("\n")) {
9389
10031
  const trimmed = bline.trim();
9390
10032
  if (!trimmed) continue;
9391
- const rendered = trimmed.replace(/^[-*]\s+/, opts.isColor ? `${import_picocolors2.default.green("\u2022")} ` : "\u2022 ");
10033
+ const bulletChar = opts.isColor ? (opts.theme?.bullet ?? import_picocolors2.default.green)("\u2022") : "\u2022";
10034
+ const rendered = trimmed.replace(/^[-*]\s+/, `${bulletChar} `);
9392
10035
  const wrapped = wrapLine(rendered, innerWidth);
9393
10036
  for (let i = 0; i < wrapped.length; i++) {
9394
- lines.push(boxedLine((i === 0 ? "" : " ") + (wrapped[i] ?? ""), innerWidth, opts.isColor));
10037
+ lines.push(
10038
+ boxedLine(chars.vertical, (i === 0 ? "" : " ") + (wrapped[i] ?? ""), innerWidth, opts.isColor, opts.theme)
10039
+ );
9395
10040
  }
9396
10041
  }
9397
10042
  }
9398
- return [top, ...lines, bottom].join("\n");
9399
- }
9400
- function renderStatsLine(stats, isColor) {
9401
- const parts = [];
9402
- parts.push(`${stats.files} files`);
9403
- parts.push(`+${stats.additions} \u2212${stats.deletions}`);
9404
- if (stats.tokens !== void 0) parts.push(`${stats.tokens} tokens`);
9405
- const text = parts.join(" \xB7 ");
9406
- return isColor ? ` ${import_picocolors2.default.dim(text)}` : ` ${text}`;
10043
+ lines.push(" " + styledBottom);
10044
+ return lines.join("\n");
9407
10045
  }
9408
10046
  function shouldUseRichOutput(opts) {
9409
10047
  if (!opts.isTTY) return false;
@@ -9412,14 +10050,162 @@ function shouldUseRichOutput(opts) {
9412
10050
  if (opts.width < MIN_BOX_WIDTH) return false;
9413
10051
  return true;
9414
10052
  }
9415
- var import_picocolors2, HEADER_RX, MIN_BOX_WIDTH;
9416
- var init_ui_rich = __esm({
9417
- "src/ui-rich.ts"() {
10053
+ var import_picocolors2, HEADER_RX, EXTENSION_COLORS, MIN_BOX_WIDTH, BOX_CHARS;
10054
+ var init_ui_layout = __esm({
10055
+ "src/ui-layout.ts"() {
9418
10056
  "use strict";
9419
10057
  import_picocolors2 = __toESM(require_picocolors());
9420
- init_ui();
9421
10058
  HEADER_RX = /^([a-z]+)(?:\(([^)]+)\))?(!)?:\s*(.*)$/;
10059
+ EXTENSION_COLORS = {
10060
+ ".ts": import_picocolors2.default.cyan,
10061
+ ".mts": import_picocolors2.default.cyan,
10062
+ ".tsx": import_picocolors2.default.cyanBright,
10063
+ ".js": import_picocolors2.default.yellow,
10064
+ ".mjs": import_picocolors2.default.yellow,
10065
+ ".cjs": import_picocolors2.default.yellow,
10066
+ ".jsx": import_picocolors2.default.yellowBright,
10067
+ ".py": import_picocolors2.default.blue,
10068
+ ".rs": import_picocolors2.default.red,
10069
+ ".go": import_picocolors2.default.cyanBright,
10070
+ ".css": import_picocolors2.default.magenta,
10071
+ ".scss": import_picocolors2.default.magenta,
10072
+ ".sass": import_picocolors2.default.magenta,
10073
+ ".html": import_picocolors2.default.redBright,
10074
+ ".md": import_picocolors2.default.green,
10075
+ ".json": (s) => import_picocolors2.default.dim(import_picocolors2.default.cyan(s)),
10076
+ ".yaml": (s) => import_picocolors2.default.dim(import_picocolors2.default.cyan(s)),
10077
+ ".yml": (s) => import_picocolors2.default.dim(import_picocolors2.default.cyan(s)),
10078
+ ".toml": (s) => import_picocolors2.default.dim(import_picocolors2.default.cyan(s)),
10079
+ ".lock": import_picocolors2.default.dim
10080
+ };
9422
10081
  MIN_BOX_WIDTH = 60;
10082
+ BOX_CHARS = {
10083
+ rounded: {
10084
+ topLeft: "\u256D",
10085
+ topRight: "\u256E",
10086
+ bottomLeft: "\u2570",
10087
+ bottomRight: "\u256F",
10088
+ horizontal: "\u2500",
10089
+ vertical: "\u2502"
10090
+ },
10091
+ gradient: {
10092
+ topLeft: "\u256D",
10093
+ topRight: "\u256E",
10094
+ bottomLeft: "\u2570",
10095
+ bottomRight: "\u256F",
10096
+ horizontal: "\u2500",
10097
+ vertical: "\u2502"
10098
+ },
10099
+ double: {
10100
+ topLeft: "\u2554",
10101
+ topRight: "\u2557",
10102
+ bottomLeft: "\u255A",
10103
+ bottomRight: "\u255D",
10104
+ horizontal: "\u2550",
10105
+ vertical: "\u2551"
10106
+ }
10107
+ };
10108
+ }
10109
+ });
10110
+
10111
+ // src/ui-rich.ts
10112
+ function buildUIContext(ui2, config2, args) {
10113
+ return {
10114
+ theme: ui2.theme,
10115
+ animate: args.noAnimate ? "none" : config2.ui?.animate ?? "tasteful",
10116
+ isTTY: !!process.stderr.isTTY,
10117
+ isColor: ui2.isColor,
10118
+ asciiFallback: !ui2.isColor,
10119
+ uniform: config2.ui?.spinner === "uniform"
10120
+ };
10121
+ }
10122
+ function createStageSpinner(opts) {
10123
+ const origCfg = STAGE_CONFIG[opts.stage];
10124
+ const cfg = opts.uniform ? {
10125
+ frames: STAGE_CONFIG.aiGenerate.frames,
10126
+ intervalMs: STAGE_CONFIG.aiGenerate.intervalMs,
10127
+ themeKey: origCfg.themeKey
10128
+ } : origCfg;
10129
+ const intervalMs = Math.max(16, Math.round(cfg.intervalMs * (opts.animate === "full" ? 0.55 : 1)));
10130
+ const frames = !opts.isColor && opts.asciiFallback ? ASCII_FRAMES : cfg.frames;
10131
+ const colorize = opts.isColor && opts.animate !== "none" ? opts.theme.spinner[cfg.themeKey] : (s) => s;
10132
+ const dim = opts.theme.dim;
10133
+ const write = opts.write ?? ((s) => process.stderr.write(s));
10134
+ let frame = 0;
10135
+ let interval = null;
10136
+ return {
10137
+ start() {
10138
+ if (interval) return;
10139
+ if (!opts.isTTY) return;
10140
+ if (opts.animate === "none") return;
10141
+ interval = setInterval(() => {
10142
+ const f = frames[frame++ % frames.length];
10143
+ write(`\r${dim("\u203A")} ${dim(opts.message)} ${colorize(f)}`);
10144
+ }, intervalMs);
10145
+ },
10146
+ stop(finalMessage) {
10147
+ if (interval) {
10148
+ clearInterval(interval);
10149
+ interval = null;
10150
+ }
10151
+ if (opts.isTTY) {
10152
+ write("\r\x1B[2K");
10153
+ }
10154
+ if (finalMessage) {
10155
+ write(finalMessage + "\n");
10156
+ }
10157
+ }
10158
+ };
10159
+ }
10160
+ async function flashSuccess(opts) {
10161
+ const write = opts.write ?? ((s) => process.stderr.write(s));
10162
+ const animate = opts.animate !== "none" && opts.isTTY;
10163
+ const rawFallback = opts.settledMessage ?? opts.theme.success(opts.message);
10164
+ const fallbackLine = animate ? rawFallback : stripAnsi(rawFallback);
10165
+ if (!animate) {
10166
+ write(fallbackLine + "\n");
10167
+ return;
10168
+ }
10169
+ write(opts.theme.success(opts.message));
10170
+ await new Promise((r) => setTimeout(r, opts.flashMs ?? 200));
10171
+ write("\r\x1B[2K");
10172
+ write((opts.settledMessage ?? opts.message) + "\n");
10173
+ }
10174
+ var STAGE_CONFIG, ASCII_FRAMES;
10175
+ var init_ui_rich = __esm({
10176
+ "src/ui-rich.ts"() {
10177
+ "use strict";
10178
+ init_ui();
10179
+ init_ui_layout();
10180
+ init_ui_layout();
10181
+ STAGE_CONFIG = {
10182
+ aiGenerate: {
10183
+ frames: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
10184
+ intervalMs: 80,
10185
+ themeKey: "aiGenerate"
10186
+ },
10187
+ branchGen: {
10188
+ frames: ["\u25F0", "\u25F3", "\u25F2", "\u25F1"],
10189
+ intervalMs: 85,
10190
+ themeKey: "branchGen"
10191
+ },
10192
+ localProvider: {
10193
+ frames: ["\u25D0", "\u25D3", "\u25D1", "\u25D2"],
10194
+ intervalMs: 100,
10195
+ themeKey: "localProvider"
10196
+ },
10197
+ gitOp: {
10198
+ frames: ["\u2190", "\u2196", "\u2191", "\u2197", "\u2192", "\u2198", "\u2193", "\u2199"],
10199
+ intervalMs: 90,
10200
+ themeKey: "gitOp"
10201
+ },
10202
+ smartDiff: {
10203
+ frames: ["\u258F", "\u258E", "\u258D", "\u258C", "\u258B", "\u258A", "\u2589", "\u258A", "\u258B", "\u258C", "\u258D", "\u258E"],
10204
+ intervalMs: 70,
10205
+ themeKey: "smartDiff"
10206
+ }
10207
+ };
10208
+ ASCII_FRAMES = ["|", "/", "-", "\\"];
9423
10209
  }
9424
10210
  });
9425
10211
 
@@ -9466,326 +10252,128 @@ function formatVerboseCommitDiagnostics(diagnostics, roundTripMs) {
9466
10252
  }
9467
10253
  async function interactiveRefineMessage(initial, opts) {
9468
10254
  if (opts.skip) return { action: "accept", message: initial };
9469
- const rl = import_promises.default.createInterface({ input: process.stdin, output: process.stderr });
9470
- try {
9471
- process.stderr.write(`
9472
- ${initial}
9473
-
9474
- `);
9475
- const choice = (await rl.question("Keep? [Y/n/e]: ")).trim().toLowerCase();
9476
- if (choice === "n") {
9477
- return { action: "abort" };
9478
- }
9479
- if (choice === "e") {
9480
- process.stderr.write("Enter new message (end with a line containing only .):\n");
9481
- const lines = [];
9482
- while (true) {
9483
- const line = await rl.question("");
9484
- if (line === ".") break;
9485
- lines.push(line);
9486
- }
9487
- const edited = lines.join("\n").trim();
9488
- return { action: "edit", message: edited.length > 0 ? edited : initial };
9489
- }
9490
- return { action: "accept", message: initial };
9491
- } finally {
9492
- rl.close();
9493
- }
9494
- }
9495
- async function promptYesNo(question, defaultYes = true) {
9496
- const rl = import_promises.default.createInterface({ input: process.stdin, output: process.stderr });
9497
- const suffix = defaultYes ? "[Y/n]" : "[y/N]";
9498
- try {
9499
- const answer = (await rl.question(`${question} ${suffix} `)).trim().toLowerCase();
9500
- if (answer === "n" || answer === "no") return false;
9501
- if (answer === "y" || answer === "yes") return true;
9502
- return defaultYes;
9503
- } finally {
9504
- rl.close();
9505
- }
9506
- }
9507
- async function confirmCommit(prompt2, opts) {
9508
- if (opts.skip) return { action: "commit" };
9509
- const rl = import_promises.default.createInterface({ input: process.stdin, output: process.stderr });
9510
- try {
9511
- const ans = (await rl.question(prompt2)).trim().toLowerCase();
9512
- if (ans !== "y" && ans !== "yes") {
9513
- return { action: "abort" };
9514
- }
9515
- return { action: "commit" };
9516
- } finally {
9517
- rl.close();
9518
- }
9519
- }
9520
- function shouldSkipTTYInteraction(hookMode) {
9521
- return hookMode === true || process.stdin.isTTY !== true;
9522
- }
9523
- function logVerboseDiagnostics(dim, verbose, quiet, diagnostics, roundTripMs) {
9524
- if (!verbose || quiet) return;
9525
- process.stderr.write(
9526
- `
9527
- ${formatVerboseCommitDiagnostics(diagnostics, roundTripMs)}
9528
- `
9529
- );
9530
- dim("(verbose diagnostics on stderr)");
9531
- }
9532
- function isDisplayOpts(opts) {
9533
- return typeof opts === "object" && opts !== null && "log" in opts;
9534
- }
9535
- function createSilentLog() {
9536
- return {
9537
- step: () => {
9538
- },
9539
- success: () => {
9540
- },
9541
- error: (msg) => console.error(msg),
9542
- dim: () => {
9543
- }
9544
- };
9545
- }
9546
- function displayCommitMessage(message, opts) {
9547
- const display = isDisplayOpts(opts) ? opts : { log: opts };
9548
- const log = display.log;
9549
- const { subject, body } = splitCommitMessageForDisplay(message);
9550
- const tw = getTerminalWidth();
9551
- const useRich = shouldUseRichOutput({
9552
- isTTY: display.isTTY ?? !!process.stderr.isTTY,
9553
- noColor: display.isColor === false,
9554
- width: tw,
9555
- style: display.style ?? "rich"
9556
- });
9557
- if (useRich) {
9558
- const tree = display.stagedFiles && display.stagedFiles.length > 0 ? renderFileTree(display.stagedFiles, 8) : "";
9559
- if (tree) {
9560
- process.stderr.write(tree + "\n");
9561
- }
9562
- const boxed = renderBoxedCommit(subject, body, {
9563
- width: Math.min(Math.max(tw - 4, 60), 80),
9564
- isColor: !!display.isColor
9565
- });
9566
- process.stderr.write(boxed + "\n");
9567
- if (display.stats) {
9568
- process.stderr.write(renderStatsLine(display.stats, !!display.isColor) + "\n");
9569
- }
9570
- return;
9571
- }
9572
- log.success(subject);
9573
- if (body) {
9574
- for (const line of body.split("\n")) {
9575
- log.dim(` ${line}`);
9576
- }
9577
- process.stderr.write("\n");
9578
- }
9579
- }
9580
- var import_promises;
9581
- var init_commit_helpers = __esm({
9582
- "src/commit-helpers.ts"() {
9583
- "use strict";
9584
- import_promises = __toESM(require("node:readline/promises"));
9585
- init_ui_rich();
9586
- }
9587
- });
9588
-
9589
- // src/smart-diff.ts
9590
- function sanitizeFilepath(path) {
9591
- return path.replace(/[\x00-\x1F\x7F[\]`]/g, "_").slice(0, 200);
9592
- }
9593
- function classifyFile(filepath) {
9594
- const basename = filepath.split("/").pop() ?? filepath;
9595
- if (LOCK_FILES.has(basename)) return "lock";
9596
- if (filepath.endsWith(".map")) return "sourcemap";
9597
- if (VENDORED_PREFIXES.some((p) => filepath.startsWith(p))) return "vendored";
9598
- if (GENERATED_PATTERNS.some((p) => p.test(filepath))) return "generated";
9599
- return "code";
9600
- }
9601
- function parseDiffIntoFiles(diff) {
9602
- const files = [];
9603
- const parts = diff.split(/^(diff --git .+)$/m);
9604
- for (let i = 1; i < parts.length; i += 2) {
9605
- const header = parts[i];
9606
- const content = parts[i + 1] ?? "";
9607
- const match = header.match(/diff --git a\/(.+?) b\/(.+)/);
9608
- const filepath = match?.[2] ?? "unknown";
9609
- const lines = content.split("\n");
9610
- let additions = 0;
9611
- let deletions = 0;
9612
- for (const line of lines) {
9613
- if (line.startsWith("+") && !line.startsWith("+++")) additions++;
9614
- else if (line.startsWith("-") && !line.startsWith("---")) deletions++;
9615
- }
9616
- files.push({ filepath, content: header + content, additions, deletions });
9617
- }
9618
- return files;
9619
- }
9620
- function isMinified(content) {
9621
- const lines = content.split("\n").filter(
9622
- (l) => (l.startsWith("+") || l.startsWith("-")) && !l.startsWith("+++") && !l.startsWith("---")
9623
- );
9624
- if (lines.length === 0) return false;
9625
- return lines.some((l) => l.length > 500);
9626
- }
9627
- function buildFileSummary(file) {
9628
- const sizeKB = Math.round(file.content.length / 1024);
9629
- return `[modified: ${sanitizeFilepath(file.filepath)} \u2014 +${file.additions} \u2212${file.deletions} lines, ~${sizeKB}KB]
9630
- `;
9631
- }
9632
- function preprocessDiffWithSizeBudget(diff, maxBytes = 5 * 1024 * 1024) {
9633
- const files = parseDiffIntoFiles(diff);
9634
- if (files.length === 0) {
9635
- return { processedDiff: diff, summarized: [], aggressivelySummarized: [], tokensSaved: 0 };
9636
- }
9637
- const entries = [];
9638
- const summarized = [];
9639
- let tokensSaved = 0;
9640
- for (const file of files) {
9641
- const classification = classifyFile(file.filepath);
9642
- switch (classification) {
9643
- case "sourcemap":
9644
- tokensSaved += estimateTokens(file.content);
9645
- summarized.push(file.filepath);
9646
- entries.push({ file, isNoise: true, summaryLine: null });
9647
- break;
9648
- case "lock":
9649
- tokensSaved += estimateTokens(file.content);
9650
- summarized.push(file.filepath);
9651
- entries.push({
9652
- file,
9653
- isNoise: true,
9654
- summaryLine: `[lock file updated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions} lines)]
9655
- `
9656
- });
9657
- break;
9658
- case "generated":
9659
- tokensSaved += estimateTokens(file.content);
9660
- summarized.push(file.filepath);
9661
- entries.push({
9662
- file,
9663
- isNoise: true,
9664
- summaryLine: `[generated: ${sanitizeFilepath(file.filepath)} (+${file.additions} \u2212${file.deletions})]
9665
- `
9666
- });
9667
- break;
9668
- case "vendored":
9669
- tokensSaved += estimateTokens(file.content);
9670
- summarized.push(file.filepath);
9671
- entries.push({
9672
- file,
9673
- isNoise: true,
9674
- summaryLine: `[vendored: ${sanitizeFilepath(file.filepath)} updated]
9675
- `
9676
- });
9677
- break;
9678
- case "code":
9679
- if (isMinified(file.content)) {
9680
- tokensSaved += estimateTokens(file.content);
9681
- const sizeKB = Math.round(file.content.length / 1024);
9682
- summarized.push(file.filepath);
9683
- entries.push({
9684
- file,
9685
- isNoise: true,
9686
- summaryLine: `[minified asset: ${sanitizeFilepath(file.filepath)} (${sizeKB} KB)]
9687
- `
9688
- });
9689
- } else {
9690
- entries.push({ file, isNoise: false, summaryLine: null });
9691
- }
9692
- break;
9693
- }
9694
- }
9695
- const aggressiveMap = /* @__PURE__ */ new Map();
9696
- function buildOutput() {
9697
- const parts = [];
9698
- for (const entry of entries) {
9699
- if (entry.isNoise) {
9700
- if (entry.summaryLine !== null) parts.push(entry.summaryLine);
9701
- } else if (aggressiveMap.has(entry.file.filepath)) {
9702
- parts.push(aggressiveMap.get(entry.file.filepath));
9703
- } else {
9704
- parts.push(entry.file.content);
10255
+ const rl = import_promises.default.createInterface({ input: process.stdin, output: process.stderr });
10256
+ try {
10257
+ process.stderr.write(`
10258
+ ${initial}
10259
+
10260
+ `);
10261
+ const choice = (await rl.question("Keep? [Y/n/e]: ")).trim().toLowerCase();
10262
+ if (choice === "n") {
10263
+ return { action: "abort" };
10264
+ }
10265
+ if (choice === "e") {
10266
+ process.stderr.write("Enter new message (end with a line containing only .):\n");
10267
+ const lines = [];
10268
+ while (true) {
10269
+ const line = await rl.question("");
10270
+ if (line === ".") break;
10271
+ lines.push(line);
9705
10272
  }
10273
+ const edited = lines.join("\n").trim();
10274
+ return { action: "edit", message: edited.length > 0 ? edited : initial };
9706
10275
  }
9707
- return parts.join("");
10276
+ return { action: "accept", message: initial };
10277
+ } finally {
10278
+ rl.close();
9708
10279
  }
9709
- const codeEntries = entries.filter((e) => !e.isNoise);
9710
- let output = buildOutput();
9711
- if (output.length <= maxBytes) {
9712
- return {
9713
- processedDiff: output,
9714
- summarized,
9715
- aggressivelySummarized: [],
9716
- tokensSaved
9717
- };
10280
+ }
10281
+ async function promptYesNo(question, defaultYes = true) {
10282
+ const rl = import_promises.default.createInterface({ input: process.stdin, output: process.stderr });
10283
+ const suffix = defaultYes ? "[Y/n]" : "[y/N]";
10284
+ try {
10285
+ const answer = (await rl.question(`${question} ${suffix} `)).trim().toLowerCase();
10286
+ if (answer === "n" || answer === "no") return false;
10287
+ if (answer === "y" || answer === "yes") return true;
10288
+ return defaultYes;
10289
+ } finally {
10290
+ rl.close();
9718
10291
  }
9719
- const TIER1_THRESHOLD = 5 * 1024;
9720
- for (const entry of codeEntries) {
9721
- if (entry.file.content.length > TIER1_THRESHOLD && !aggressiveMap.has(entry.file.filepath)) {
9722
- tokensSaved += estimateTokens(entry.file.content);
9723
- aggressiveMap.set(entry.file.filepath, buildFileSummary(entry.file));
10292
+ }
10293
+ async function confirmCommit(prompt2, opts) {
10294
+ if (opts.skip) return { action: "commit" };
10295
+ const rl = import_promises.default.createInterface({ input: process.stdin, output: process.stderr });
10296
+ try {
10297
+ const ans = (await rl.question(prompt2)).trim().toLowerCase();
10298
+ if (ans !== "y" && ans !== "yes") {
10299
+ return { action: "abort" };
9724
10300
  }
10301
+ return { action: "commit" };
10302
+ } finally {
10303
+ rl.close();
9725
10304
  }
9726
- output = buildOutput();
9727
- if (output.length <= maxBytes) {
9728
- return {
9729
- processedDiff: output,
9730
- summarized,
9731
- aggressivelySummarized: [...aggressiveMap.keys()],
9732
- tokensSaved
9733
- };
9734
- }
9735
- const TIER2_THRESHOLD = 2 * 1024;
9736
- for (const entry of codeEntries) {
9737
- if (entry.file.content.length > TIER2_THRESHOLD && !aggressiveMap.has(entry.file.filepath)) {
9738
- tokensSaved += estimateTokens(entry.file.content);
9739
- aggressiveMap.set(entry.file.filepath, buildFileSummary(entry.file));
10305
+ }
10306
+ function shouldSkipTTYInteraction(hookMode) {
10307
+ return hookMode === true || process.stdin.isTTY !== true;
10308
+ }
10309
+ function logVerboseDiagnostics(dim, verbose, quiet, diagnostics, roundTripMs) {
10310
+ if (!verbose || quiet) return;
10311
+ process.stderr.write(
10312
+ `
10313
+ ${formatVerboseCommitDiagnostics(diagnostics, roundTripMs)}
10314
+ `
10315
+ );
10316
+ dim("(verbose diagnostics on stderr)");
10317
+ }
10318
+ function isDisplayOpts(opts) {
10319
+ return typeof opts === "object" && opts !== null && "log" in opts;
10320
+ }
10321
+ function createSilentLog() {
10322
+ return {
10323
+ step: () => {
10324
+ },
10325
+ success: () => {
10326
+ },
10327
+ error: (msg) => console.error(msg),
10328
+ dim: () => {
9740
10329
  }
10330
+ };
10331
+ }
10332
+ function displayCommitMessage(message, opts) {
10333
+ const display = isDisplayOpts(opts) ? opts : { log: opts, isTTY: false };
10334
+ const log = display.log;
10335
+ const { subject, body } = splitCommitMessageForDisplay(message);
10336
+ const tw = getTerminalWidth();
10337
+ const useRich = shouldUseRichOutput({
10338
+ isTTY: display.isTTY ?? !!process.stderr.isTTY,
10339
+ noColor: display.isColor === false,
10340
+ width: tw,
10341
+ style: display.style ?? "rich"
10342
+ });
10343
+ if (useRich) {
10344
+ const theme = display.theme ?? getUI().theme;
10345
+ const tree = display.stagedFiles && display.stagedFiles.length > 0 ? renderFileTree(display.stagedFiles, 3, { isColor: !!display.isColor }) : "";
10346
+ if (tree) {
10347
+ process.stderr.write(tree + "\n");
10348
+ }
10349
+ const boxed = renderBoxedCommit(subject, body, {
10350
+ width: display.boxWidth ?? Math.min(getTerminalWidth() - 4, 80),
10351
+ isColor: !!display.isColor,
10352
+ style: display.boxStyle ?? "gradient",
10353
+ autoEmphasis: display.autoEmphasis ?? true,
10354
+ theme
10355
+ });
10356
+ process.stderr.write(boxed + "\n");
10357
+ if (display.stats) {
10358
+ process.stderr.write(renderStatsLine(display.stats, !!display.isColor, theme) + "\n");
10359
+ }
10360
+ return;
9741
10361
  }
9742
- output = buildOutput();
9743
- if (output.length <= maxBytes) {
9744
- return {
9745
- processedDiff: output,
9746
- summarized,
9747
- aggressivelySummarized: [...aggressiveMap.keys()],
9748
- tokensSaved
9749
- };
9750
- }
9751
- for (const entry of codeEntries) {
9752
- if (!aggressiveMap.has(entry.file.filepath)) {
9753
- tokensSaved += estimateTokens(entry.file.content);
9754
- aggressiveMap.set(entry.file.filepath, buildFileSummary(entry.file));
10362
+ log.success(subject);
10363
+ if (body) {
10364
+ for (const line of body.split("\n")) {
10365
+ log.dim(` ${line}`);
9755
10366
  }
10367
+ process.stderr.write("\n");
9756
10368
  }
9757
- return {
9758
- processedDiff: buildOutput(),
9759
- summarized,
9760
- aggressivelySummarized: [...aggressiveMap.keys()],
9761
- tokensSaved
9762
- };
9763
10369
  }
9764
- var LOCK_FILES, GENERATED_PATTERNS, VENDORED_PREFIXES;
9765
- var init_smart_diff = __esm({
9766
- "src/smart-diff.ts"() {
10370
+ var import_promises;
10371
+ var init_commit_helpers = __esm({
10372
+ "src/commit-helpers.ts"() {
9767
10373
  "use strict";
9768
- init_dist();
9769
- LOCK_FILES = /* @__PURE__ */ new Set([
9770
- "pnpm-lock.yaml",
9771
- "package-lock.json",
9772
- "yarn.lock",
9773
- "Cargo.lock",
9774
- "Gemfile.lock",
9775
- "poetry.lock",
9776
- "composer.lock",
9777
- "bun.lockb",
9778
- "shrinkwrap.json"
9779
- ]);
9780
- GENERATED_PATTERNS = [
9781
- /\.generated\.\w+$/,
9782
- /\.g\.dart$/,
9783
- /\.pb\.go$/,
9784
- /\.pb\.ts$/,
9785
- /(^|\/)\.prisma\/client\//,
9786
- /\/generated\//
9787
- ];
9788
- VENDORED_PREFIXES = ["vendor/", "third_party/", "node_modules/"];
10374
+ import_promises = __toESM(require("node:readline/promises"));
10375
+ init_ui();
10376
+ init_ui_rich();
9789
10377
  }
9790
10378
  });
9791
10379
 
@@ -9986,6 +10574,8 @@ async function runLocalCommit(args) {
9986
10574
  }
9987
10575
  const config2 = getConfig();
9988
10576
  const excludes = [...config2.excludes ?? [], ...args.exclude];
10577
+ const uiCtx = buildUIContext(ui2, config2, args);
10578
+ const boxStyle = args.boxStyleOverride ?? config2.ui?.box?.style ?? "gradient";
9989
10579
  let diff = getStagedDiff(excludes);
9990
10580
  const changes = getStagedFiles();
9991
10581
  if (!args.noSmartDiff) {
@@ -10043,7 +10633,11 @@ async function runLocalCommit(args) {
10043
10633
  "Cloudflare provider requires api_url. Run: qc config set api_url https://your-worker.workers.dev"
10044
10634
  );
10045
10635
  }
10046
- const spinner = ui2.spinner(`generating commit (${modelDisplay} via ${local.provider})...`);
10636
+ const spinner = createStageSpinner({
10637
+ stage: "localProvider",
10638
+ message: `generating commit (${modelDisplay} via ${local.provider})...`,
10639
+ ...uiCtx
10640
+ });
10047
10641
  if (!silent) spinner.start();
10048
10642
  const t0 = Date.now();
10049
10643
  let res;
@@ -10094,6 +10688,10 @@ async function runLocalCommit(args) {
10094
10688
  isTTY: !!process.stderr.isTTY,
10095
10689
  style: "rich",
10096
10690
  stagedFiles: stagedPaths,
10691
+ boxStyle,
10692
+ autoEmphasis: config2.ui?.box?.auto_emphasis ?? true,
10693
+ theme: ui2.theme,
10694
+ boxWidth: typeof config2.ui?.box?.width === "number" ? config2.ui.box.width : void 0,
10097
10695
  stats: {
10098
10696
  files: stagedPaths.length,
10099
10697
  additions: short.additions,
@@ -10112,8 +10710,41 @@ async function runLocalCommit(args) {
10112
10710
  }
10113
10711
  }
10114
10712
  gitCommit(message);
10713
+ const branch = getCurrentBranch();
10714
+ const hash = getCommitHash();
10715
+ if (!silent) {
10716
+ await flashSuccess({
10717
+ message: `\u2713 committed ${branch} \xB7 ${hash}`,
10718
+ settledMessage: `${ui2.theme.success("\u2713 committed")}${ui2.theme.dim(` ${branch} \xB7 ${hash}`)}`,
10719
+ theme: ui2.theme,
10720
+ animate: uiCtx.animate,
10721
+ isTTY: uiCtx.isTTY
10722
+ });
10723
+ }
10115
10724
  if (args.push) {
10725
+ const pushStats = getPushStats();
10726
+ log.step(`pushing to origin/${branch}...`);
10116
10727
  gitPush();
10728
+ if (!silent) {
10729
+ if (pushStats) {
10730
+ await flashSuccess({
10731
+ message: `\u2713 pushed ${pushStats.commits} commit(s) \xB7 ${pushStats.stat}`,
10732
+ settledMessage: `${ui2.theme.success("\u2713 pushed")}${ui2.theme.dim(
10733
+ ` ${pushStats.commits} commit(s) \xB7 ${pushStats.stat}`
10734
+ )}`,
10735
+ theme: ui2.theme,
10736
+ animate: uiCtx.animate,
10737
+ isTTY: uiCtx.isTTY
10738
+ });
10739
+ } else {
10740
+ await flashSuccess({
10741
+ message: "\u2713 pushed",
10742
+ theme: ui2.theme,
10743
+ animate: uiCtx.animate,
10744
+ isTTY: uiCtx.isTTY
10745
+ });
10746
+ }
10747
+ }
10117
10748
  }
10118
10749
  }
10119
10750
  async function generateLocalBranchName(opts) {
@@ -10228,7 +10859,13 @@ async function runLocalBranch(opts) {
10228
10859
  }
10229
10860
  const ui2 = getUI();
10230
10861
  const log = ui2.log;
10231
- const spinner = ui2.spinner(`generating branch name (${opts.model ?? local.model} via ${local.provider})...`);
10862
+ const config2 = getConfig();
10863
+ const branchUiCtx = buildUIContext(ui2, config2, { noAnimate: opts.noAnimate });
10864
+ const spinner = createStageSpinner({
10865
+ stage: "branchGen",
10866
+ message: `generating branch name (${opts.model ?? local.model} via ${local.provider})...`,
10867
+ ...branchUiCtx
10868
+ });
10232
10869
  if (process.stderr.isTTY) spinner.start();
10233
10870
  let final;
10234
10871
  try {
@@ -10278,6 +10915,7 @@ var init_local = __esm({
10278
10915
  init_ui();
10279
10916
  init_commit_helpers();
10280
10917
  init_branch_name();
10918
+ init_ui_rich();
10281
10919
  CONFIG_PATH2 = (0, import_path8.join)((0, import_os4.homedir)(), CONFIG_DIR);
10282
10920
  PROVIDER_URLS = {
10283
10921
  ollama: "http://localhost:11434",
@@ -10312,12 +10950,14 @@ function finalizeGeneratedBranchName(raw) {
10312
10950
  async function runBranch(opts) {
10313
10951
  const ui2 = getUI();
10314
10952
  const log = ui2.log;
10953
+ const config2 = getConfig();
10954
+ const animate = opts.noAnimate ? "none" : config2.ui?.animate ?? "tasteful";
10955
+ const uniformSpinner = config2.ui?.spinner === "uniform";
10315
10956
  if (!isGitRepo()) {
10316
10957
  log.error("Not a git repository.");
10317
10958
  process.exit(1);
10318
10959
  }
10319
10960
  const baseRef = opts.from ?? "HEAD";
10320
- const config2 = getConfig();
10321
10961
  const model = opts.model ?? config2.model;
10322
10962
  const genRules = branchGenerationRules(config2);
10323
10963
  if (opts.rescue) {
@@ -10346,7 +10986,16 @@ async function runBranch(opts) {
10346
10986
  const recent = getRecentBranchCommits(state.commitsAhead);
10347
10987
  const apiKey2 = opts.apiKey ?? getApiKey();
10348
10988
  if (apiKey2) {
10349
- const spinner2 = ui2.spinner(`generating branch name (${model ?? "default"})...`);
10989
+ const spinner2 = createStageSpinner({
10990
+ stage: "branchGen",
10991
+ message: `generating branch name (${model ?? "default"})...`,
10992
+ theme: ui2.theme,
10993
+ animate,
10994
+ isTTY: !!process.stderr.isTTY,
10995
+ isColor: ui2.isColor,
10996
+ asciiFallback: !ui2.isColor,
10997
+ uniform: uniformSpinner
10998
+ });
10350
10999
  if (process.stderr.isTTY) spinner2.start();
10351
11000
  try {
10352
11001
  const client = new ApiClient({ apiKey: apiKey2 });
@@ -10375,7 +11024,16 @@ async function runBranch(opts) {
10375
11024
  "Not authenticated. Run `qc login` first, or configure a local provider for `--rescue`."
10376
11025
  );
10377
11026
  }
10378
- const spinner2 = ui2.spinner(`generating branch name (${model ?? "default"} via local)...`);
11027
+ const spinner2 = createStageSpinner({
11028
+ stage: "branchGen",
11029
+ message: `generating branch name (${model ?? "default"} via local)...`,
11030
+ theme: ui2.theme,
11031
+ animate,
11032
+ isTTY: !!process.stderr.isTTY,
11033
+ isColor: ui2.isColor,
11034
+ asciiFallback: !ui2.isColor,
11035
+ uniform: uniformSpinner
11036
+ });
10379
11037
  if (process.stderr.isTTY) spinner2.start();
10380
11038
  try {
10381
11039
  try {
@@ -10472,13 +11130,23 @@ async function runBranch(opts) {
10472
11130
  noSwitch: opts.noSwitch,
10473
11131
  push: opts.push,
10474
11132
  baseRef,
10475
- rules: genRules
11133
+ rules: genRules,
11134
+ noAnimate: opts.noAnimate
10476
11135
  });
10477
11136
  return;
10478
11137
  }
10479
11138
  throw new Error("Not authenticated. Run `qc login` first, or provide --message.");
10480
11139
  }
10481
- const spinner = ui2.spinner(`generating branch name (${model ?? "default"})...`);
11140
+ const spinner = createStageSpinner({
11141
+ stage: "branchGen",
11142
+ message: `generating branch name (${model ?? "default"})...`,
11143
+ theme: ui2.theme,
11144
+ animate,
11145
+ isTTY: !!process.stderr.isTTY,
11146
+ isColor: ui2.isColor,
11147
+ asciiFallback: !ui2.isColor,
11148
+ uniform: uniformSpinner
11149
+ });
10482
11150
  if (process.stderr.isTTY) spinner.start();
10483
11151
  let result;
10484
11152
  try {
@@ -10516,6 +11184,7 @@ var init_branch2 = __esm({
10516
11184
  init_branch_name();
10517
11185
  init_commit_helpers();
10518
11186
  init_ui();
11187
+ init_ui_rich();
10519
11188
  }
10520
11189
  });
10521
11190
 
@@ -10896,8 +11565,16 @@ async function runBranchGuard(args, log) {
10896
11565
  if (action === "continue") {
10897
11566
  return { action: "continue" };
10898
11567
  }
10899
- const stagedDiff = state.mode === "uncommitted" ? getStagedDiff(args.excludes ?? []) : "";
10900
- const stagedChanges = state.mode === "uncommitted" ? getStagedFiles() : "";
11568
+ let stagedDiff = "";
11569
+ let stagedChanges = "";
11570
+ if (state.mode === "uncommitted") {
11571
+ stagedDiff = getStagedDiff(args.excludes ?? []);
11572
+ stagedChanges = getStagedFiles();
11573
+ if (!stagedDiff.trim()) {
11574
+ stagedDiff = getWorkingTreeDiff(args.excludes ?? []);
11575
+ stagedChanges = getAllChangedFiles();
11576
+ }
11577
+ }
10901
11578
  const recentCommits = state.mode === "rescue" ? getRecentBranchCommits(state.commitsAhead) : void 0;
10902
11579
  const branchRules = args.branchRules ?? (config2.branch?.generation?.types && config2.branch.generation.types.length > 0 ? { types: [...config2.branch.generation.types] } : void 0);
10903
11580
  const apiKey = args.apiKey;
@@ -10913,7 +11590,12 @@ async function runBranchGuard(args, log) {
10913
11590
  }
10914
11591
  generateLocalBranchNameFn = generateLocalBranchName2;
10915
11592
  }
10916
- const spinner = ui2.spinner(`generating branch name...`);
11593
+ const guardUiCtx = buildUIContext(ui2, config2, args);
11594
+ const spinner = createStageSpinner({
11595
+ stage: "branchGen",
11596
+ message: "generating branch name...",
11597
+ ...guardUiCtx
11598
+ });
10917
11599
  if (process.stderr.isTTY) spinner.start();
10918
11600
  let rawName;
10919
11601
  let usedFallback = false;
@@ -10990,10 +11672,22 @@ async function runBranchGuard(args, log) {
10990
11672
  async function promptProtectedAction(mode) {
10991
11673
  const rl = import_promises2.default.createInterface({ input: process.stdin, output: process.stderr });
10992
11674
  try {
10993
- const question = mode === "rescue" ? "Move commits to a new branch? [B/c/a] " : "Create a new branch first? [B/c/a] ";
10994
- const answer = (await rl.question(question)).trim().toLowerCase();
10995
- if (answer === "" || answer === "b" || answer === "y") return "branch";
10996
- if (answer === "c") return "continue";
11675
+ const continueLabel = mode === "rescue" ? "commit on this branch anyway (do not move existing commits)" : "commit on this branch anyway (not recommended)";
11676
+ const branchLabel = mode === "rescue" ? "create a new branch and move your existing commits to it" : "create a new branch first, then commit your staged changes there";
11677
+ process.stderr.write(
11678
+ `
11679
+ What would you like to do?
11680
+ (b)ranch ${branchLabel} \u2190 default
11681
+ (c)ommit ${continueLabel}
11682
+ (a)bort cancel without committing
11683
+ `
11684
+ );
11685
+ const answer = (await rl.question("> ")).trim().toLowerCase();
11686
+ if (answer === "" || answer === "b" || answer === "branch" || answer === "y") return "branch";
11687
+ if (answer === "c" || answer === "commit") return "continue";
11688
+ if (answer === "a" || answer === "abort" || answer === "n") return "abort";
11689
+ process.stderr.write(`(unrecognized response "${answer}" \u2014 aborting)
11690
+ `);
10997
11691
  return "abort";
10998
11692
  } finally {
10999
11693
  rl.close();
@@ -11011,6 +11705,7 @@ var init_branch_guard = __esm({
11011
11705
  init_branch_name();
11012
11706
  init_ui();
11013
11707
  init_commit_helpers();
11708
+ init_ui_rich();
11014
11709
  }
11015
11710
  });
11016
11711
 
@@ -11037,7 +11732,8 @@ async function runCommit(args) {
11037
11732
  hookMode: !!args.hookMode,
11038
11733
  apiKey: apiKeyFlag ?? getApiKey() ?? void 0,
11039
11734
  model: args.model,
11040
- excludes
11735
+ excludes,
11736
+ noAnimate: args.noAnimate
11041
11737
  },
11042
11738
  log
11043
11739
  );
@@ -11051,15 +11747,13 @@ async function runCommit(args) {
11051
11747
  void _exhaustive;
11052
11748
  if (all || config2.autoStage) {
11053
11749
  stageAll();
11054
- const { files, total } = getShortStagedFiles();
11055
- const fileList = total > 3 ? `${files.join(", ")}, +${total - 3} more` : files.join(", ");
11750
+ const total = getStagedFileCount();
11056
11751
  log.step(`staging working tree (${total} file(s))...`);
11057
- if (fileList) log.dim(` ${fileList}`);
11058
11752
  }
11059
11753
  if (!hasStagedChanges()) {
11060
11754
  const unstaged = getUnstagedFiles();
11061
11755
  if (unstaged.length > 0) {
11062
- log.error("No staged changes. Use `qc -a` to stage tracked files, or `git add` manually.");
11756
+ log.error("No staged changes. Use `qc -a` to stage all files (modified + untracked), or `git add` manually.");
11063
11757
  } else {
11064
11758
  log.error("No changes to commit.");
11065
11759
  }
@@ -11120,7 +11814,13 @@ async function runCommit(args) {
11120
11814
  const skipInteractive = silent || args.quiet || shouldSkipTTYInteraction(args.hookMode);
11121
11815
  const skipConfirm = args.dryRun || messageOnly || silent || args.quiet || shouldSkipTTYInteraction(args.hookMode);
11122
11816
  const modelDisplay = model ?? "default";
11123
- const spinner = ui2.spinner(`generating commit (${modelDisplay})...`);
11817
+ const uiCtx = buildUIContext(ui2, config2, args);
11818
+ const boxStyle = args.boxStyleOverride ?? config2.ui?.box?.style ?? "gradient";
11819
+ const spinner = createStageSpinner({
11820
+ stage: "aiGenerate",
11821
+ message: `generating commit (${modelDisplay})...`,
11822
+ ...uiCtx
11823
+ });
11124
11824
  if (!silent) spinner.start();
11125
11825
  const t0 = Date.now();
11126
11826
  let generatedMessage;
@@ -11164,6 +11864,10 @@ async function runCommit(args) {
11164
11864
  isTTY: !!process.stderr.isTTY,
11165
11865
  style: "rich",
11166
11866
  stagedFiles: stagedPaths,
11867
+ boxStyle,
11868
+ autoEmphasis: config2.ui?.box?.auto_emphasis ?? true,
11869
+ theme: ui2.theme,
11870
+ boxWidth: typeof config2.ui?.box?.width === "number" ? config2.ui.box.width : void 0,
11167
11871
  stats: {
11168
11872
  files: stagedPaths.length,
11169
11873
  additions: short.additions,
@@ -11183,15 +11887,38 @@ async function runCommit(args) {
11183
11887
  gitCommit(message);
11184
11888
  const hash = getCommitHash();
11185
11889
  const branch = getCurrentBranch();
11186
- log.step(`[${branch} ${hash}] committed`);
11890
+ if (!silent) {
11891
+ await flashSuccess({
11892
+ message: `\u2713 committed ${branch} \xB7 ${hash}`,
11893
+ settledMessage: `${ui2.theme.success("\u2713 committed")}${ui2.theme.dim(` ${branch} \xB7 ${hash}`)}`,
11894
+ theme: ui2.theme,
11895
+ animate: uiCtx.animate,
11896
+ isTTY: !!process.stderr.isTTY
11897
+ });
11898
+ }
11187
11899
  if (push) {
11900
+ const pushStats = getPushStats();
11188
11901
  log.step(`pushing to origin/${branch}...`);
11189
11902
  gitPush();
11190
- const stats = getPushStats();
11191
- if (stats) {
11192
- log.success(`pushed ${stats.commits} commit(s) \xB7 ${stats.stat}`);
11193
- } else {
11194
- log.success("pushed");
11903
+ if (!silent) {
11904
+ if (pushStats) {
11905
+ await flashSuccess({
11906
+ message: `\u2713 pushed ${pushStats.commits} commit(s) \xB7 ${pushStats.stat}`,
11907
+ settledMessage: `${ui2.theme.success("\u2713 pushed")}${ui2.theme.dim(
11908
+ ` ${pushStats.commits} commit(s) \xB7 ${pushStats.stat}`
11909
+ )}`,
11910
+ theme: ui2.theme,
11911
+ animate: uiCtx.animate,
11912
+ isTTY: !!process.stderr.isTTY
11913
+ });
11914
+ } else {
11915
+ await flashSuccess({
11916
+ message: "\u2713 pushed",
11917
+ theme: ui2.theme,
11918
+ animate: uiCtx.animate,
11919
+ isTTY: !!process.stderr.isTTY
11920
+ });
11921
+ }
11195
11922
  }
11196
11923
  }
11197
11924
  }
@@ -11207,6 +11934,7 @@ var init_commit = __esm({
11207
11934
  init_smart_diff();
11208
11935
  init_commit_helpers();
11209
11936
  init_branch_guard();
11937
+ init_ui_rich();
11210
11938
  }
11211
11939
  });
11212
11940
 
@@ -11223,8 +11951,8 @@ Usage:
11223
11951
  qc Generate commit message and commit (default)
11224
11952
  qc pr Generate PR description from branch commits
11225
11953
  qc changelog Generate changelog from commits since last tag
11226
- qc changeset Automate pnpm changeset with AI
11227
- qc branch Generate branch name + create branch (use --message for description)
11954
+ qc changeset Generate changesets from branch commits (pnpm monorepo)
11955
+ qc branch Generate and create a named branch from changes
11228
11956
  qc init Install prepare-commit-msg hook
11229
11957
  qc login Sign in via browser
11230
11958
  qc logout Clear local credentials
@@ -11232,11 +11960,13 @@ Usage:
11232
11960
  qc team Team management (info, rules, invite)
11233
11961
  qc config Show/set config
11234
11962
 
11235
- Flags:
11963
+ Run \`qc <command> -h\` for command-specific help.
11964
+
11965
+ Commit flags:
11236
11966
  -p, --push Commit and push
11237
- -a, --all Stage all tracked changes first
11967
+ -a, --all Stage all files (modified + untracked) first
11238
11968
  -m, --message-only Print message only (stdout, no commit)
11239
- -v, --verbose Show diagnostics (model, token estimates, rules) + API round-trip ms on stderr
11969
+ -v, --verbose Show diagnostics (model, tokens, latency)
11240
11970
  -q, --quiet Minimal output
11241
11971
  -n, --dry-run Show message without committing
11242
11972
  -i, --interactive Interactive refinement mode
@@ -11247,28 +11977,15 @@ Flags:
11247
11977
  -t, --type <type> Force commit type
11248
11978
  -S, --scope <scope> Force scope
11249
11979
  -e, --exclude <pat> Exclude files from diff (repeatable)
11250
-
11251
11980
  --no-context Skip commit history context
11252
11981
  --no-smart-diff Skip smart diff preprocessing
11253
11982
  --no-color Disable colors
11983
+ --no-animate Disable spinner animation and success flash
11984
+ --style <name> Box style: rounded | gradient | double | none
11254
11985
  --model <id> Use specific model
11255
- --base <branch> Base branch for pr/changeset (default: main)
11256
- --create Create PR with gh CLI (qc pr --create)
11257
- --from <ref> Start ref for changelog / base ref for qc branch
11258
- --to <ref> End ref for changelog
11259
- --write Write changelog to CHANGELOG.md
11260
11986
  --hook-mode Silent mode for git hooks
11261
-
11262
- Branch flags (qc branch):
11263
- --message <text> Generate from a description (no diff needed)
11264
- --from-commits Generate from recent commits instead of diff
11265
- --rescue Move commits off current protected branch (see docs)
11266
- --no-switch Create branch but don't checkout
11267
- --from <ref> Create branch from this ref (default: HEAD)
11268
-
11269
- Commit guard flags:
11270
- --allow-protected Bypass protected-branch guard for this run
11271
- --auto-branch Auto-create branch with generated name (no prompt)
11987
+ --allow-protected Bypass protected-branch guard
11988
+ --auto-branch Auto-create branch (no prompt) when on protected branch
11272
11989
 
11273
11990
  Compose short flags: qc -ap (stage all + push), qc -apv (+ verbose)
11274
11991
 
@@ -11281,6 +11998,81 @@ Examples:
11281
11998
  qc -e "*.lock" # exclude lock files
11282
11999
  qc -t fix -S auth # force type and scope
11283
12000
  `;
12001
+ var HELP_PR = `qc pr \u2014 Generate a PR description from branch commits
12002
+
12003
+ Usage:
12004
+ qc pr Generate PR description and print to stdout
12005
+ qc pr --create Generate and open a PR via \`gh\` CLI
12006
+
12007
+ Flags:
12008
+ --base <branch> Base branch to compare against (default: main)
12009
+ --create Create the PR with \`gh pr create\` (requires gh CLI)
12010
+ --model <id> Use specific model
12011
+
12012
+ Examples:
12013
+ qc pr # print PR description
12014
+ qc pr --create # create the PR directly
12015
+ qc pr --base develop # compare against develop
12016
+ `;
12017
+ var HELP_CHANGELOG = `qc changelog \u2014 Generate a changelog from commits since last tag
12018
+
12019
+ Usage:
12020
+ qc changelog Print changelog entry to stdout
12021
+ qc changelog --write Prepend to CHANGELOG.md
12022
+
12023
+ Flags:
12024
+ --from <ref> Start ref (default: latest tag)
12025
+ --to <ref> End ref (default: HEAD)
12026
+ --write Write/prepend to CHANGELOG.md
12027
+ --version <ver> Version label for header (default: derived from --to)
12028
+ --model <id> Use specific model
12029
+
12030
+ Examples:
12031
+ qc changelog # print changelog since last tag
12032
+ qc changelog --write # prepend to CHANGELOG.md
12033
+ qc changelog --from v1.0.0 # since a specific tag
12034
+ `;
12035
+ var HELP_CHANGESET = `qc changeset \u2014 Generate pnpm changesets from branch commits
12036
+
12037
+ Usage:
12038
+ qc changeset Analyze commits on current branch vs base, generate .changeset/ file
12039
+
12040
+ Requires: commits ahead of base branch (not just staged files).
12041
+ Tip: commit your changes first with \`qc\`, then run \`qc changeset\`.
12042
+
12043
+ Flags:
12044
+ --base <branch> Base branch to compare against (default: main)
12045
+ --model <id> Use specific model
12046
+
12047
+ Examples:
12048
+ qc changeset # changeset from commits vs main
12049
+ qc changeset --base develop # compare against develop
12050
+ `;
12051
+ var HELP_BRANCH = `qc branch \u2014 Generate and create a branch with an AI-generated name
12052
+
12053
+ Usage:
12054
+ qc branch Name from staged/unstaged diff
12055
+ qc branch <name> Use explicit name (skip AI)
12056
+ qc branch --message "..." Name from a description (no diff needed)
12057
+ qc branch --from-commits Name from recent commit history
12058
+ qc branch --rescue Move commits off a protected branch
12059
+
12060
+ Flags:
12061
+ --message <text> Generate name from a description
12062
+ --from-commits Use commit log instead of diff for naming
12063
+ --rescue Move existing commits off protected branch to new branch
12064
+ --no-switch Create branch but don't checkout
12065
+ --from <ref> Base from this ref (default: HEAD)
12066
+ -p, --push Push immediately and set upstream
12067
+ -n, --dry-run Show generated name without creating
12068
+
12069
+ Examples:
12070
+ qc branch # name from current changes
12071
+ qc branch -m "add oauth login" # name from description
12072
+ qc branch feat/my-feature # explicit name
12073
+ qc branch --rescue # move commits off main
12074
+ qc branch -np # dry-run (show name only)
12075
+ `;
11284
12076
  var SHORT_FLAGS = {
11285
12077
  p: "push",
11286
12078
  a: "all",
@@ -11343,6 +12135,7 @@ function parseArgs(args) {
11343
12135
  result[key] = val;
11344
12136
  }
11345
12137
  } else if (ch === "h") {
12138
+ if (result.command !== "commit") result.helpFor = result.command;
11346
12139
  result.command = "help";
11347
12140
  } else {
11348
12141
  throw new Error(`Unknown flag: -${ch}`);
@@ -11371,12 +12164,14 @@ function parseArgs(args) {
11371
12164
  continue;
11372
12165
  }
11373
12166
  if (ch === "h") {
12167
+ if (result.command !== "commit") result.helpFor = result.command;
11374
12168
  result.command = "help";
11375
12169
  continue;
11376
12170
  }
11377
12171
  throw new Error(`Unknown flag: -${ch}`);
11378
12172
  }
11379
12173
  if (arg === "--help") {
12174
+ if (result.command !== "commit") result.helpFor = result.command;
11380
12175
  result.command = "help";
11381
12176
  } else if (arg === "--all") {
11382
12177
  result.all = true;
@@ -11455,6 +12250,16 @@ function parseArgs(args) {
11455
12250
  const ex = args[++i];
11456
12251
  if (ex) result.exclude.push(ex);
11457
12252
  } else if (arg === "--no-color") {
12253
+ } else if (arg === "--no-animate") {
12254
+ result.noAnimate = true;
12255
+ } else if (arg === "--style" && i + 1 < args.length) {
12256
+ const v = args[++i];
12257
+ if (v !== "rounded" && v !== "gradient" && v !== "double" && v !== "none") {
12258
+ throw new Error(
12259
+ `Invalid --style value: ${v}. Must be: rounded | gradient | double | none.`
12260
+ );
12261
+ }
12262
+ result.boxStyleOverride = v;
11458
12263
  } else if (arg === "login") {
11459
12264
  result.command = "login";
11460
12265
  subcommandSeen = true;
@@ -11514,7 +12319,13 @@ async function main() {
11514
12319
  }
11515
12320
  const { command, apiKey } = values;
11516
12321
  if (command === "help") {
11517
- console.log(HELP);
12322
+ const subHelp = {
12323
+ pr: HELP_PR,
12324
+ changelog: HELP_CHANGELOG,
12325
+ changeset: HELP_CHANGESET,
12326
+ branch: HELP_BRANCH
12327
+ };
12328
+ console.log(values.helpFor && subHelp[values.helpFor] ? subHelp[values.helpFor] : HELP);
11518
12329
  return;
11519
12330
  }
11520
12331
  if (values.setProvider) {
@@ -11600,7 +12411,8 @@ async function main() {
11600
12411
  push: values.push,
11601
12412
  from: values.from,
11602
12413
  model: values.model,
11603
- apiKey: values.apiKey
12414
+ apiKey: values.apiKey,
12415
+ noAnimate: values.noAnimate
11604
12416
  });
11605
12417
  return;
11606
12418
  }