@amdahl/cli 0.4.1 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +63 -2
  2. package/dist/amdahl.js +789 -348
  3. package/package.json +1 -1
package/dist/amdahl.js CHANGED
@@ -18,9 +18,9 @@ var __commonJS = (cb, mod) => function __require2() {
18
18
  };
19
19
  var __copyProps = (to, from, except, desc) => {
20
20
  if (from && typeof from === "object" || typeof from === "function") {
21
- for (let key of __getOwnPropNames(from))
22
- if (!__hasOwnProp.call(to, key) && key !== except)
23
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
21
+ for (let key2 of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key2) && key2 !== except)
23
+ __defProp(to, key2, { get: () => from[key2], enumerable: !(desc = __getOwnPropDesc(from, key2)) || desc.enumerable });
24
24
  }
25
25
  return to;
26
26
  };
@@ -110,11 +110,11 @@ var require_visit = __commonJS({
110
110
  visit.BREAK = BREAK;
111
111
  visit.SKIP = SKIP;
112
112
  visit.REMOVE = REMOVE;
113
- function visit_(key, node, visitor, path) {
114
- const ctrl = callVisitor(key, node, visitor, path);
113
+ function visit_(key2, node, visitor, path) {
114
+ const ctrl = callVisitor(key2, node, visitor, path);
115
115
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
116
- replaceNode(key, path, ctrl);
117
- return visit_(key, ctrl, visitor, path);
116
+ replaceNode(key2, path, ctrl);
117
+ return visit_(key2, ctrl, visitor, path);
118
118
  }
119
119
  if (typeof ctrl !== "symbol") {
120
120
  if (identity.isCollection(node)) {
@@ -158,11 +158,11 @@ var require_visit = __commonJS({
158
158
  visitAsync.BREAK = BREAK;
159
159
  visitAsync.SKIP = SKIP;
160
160
  visitAsync.REMOVE = REMOVE;
161
- async function visitAsync_(key, node, visitor, path) {
162
- const ctrl = await callVisitor(key, node, visitor, path);
161
+ async function visitAsync_(key2, node, visitor, path) {
162
+ const ctrl = await callVisitor(key2, node, visitor, path);
163
163
  if (identity.isNode(ctrl) || identity.isPair(ctrl)) {
164
- replaceNode(key, path, ctrl);
165
- return visitAsync_(key, ctrl, visitor, path);
164
+ replaceNode(key2, path, ctrl);
165
+ return visitAsync_(key2, ctrl, visitor, path);
166
166
  }
167
167
  if (typeof ctrl !== "symbol") {
168
168
  if (identity.isCollection(node)) {
@@ -212,27 +212,27 @@ var require_visit = __commonJS({
212
212
  }
213
213
  return visitor;
214
214
  }
215
- function callVisitor(key, node, visitor, path) {
215
+ function callVisitor(key2, node, visitor, path) {
216
216
  if (typeof visitor === "function")
217
- return visitor(key, node, path);
217
+ return visitor(key2, node, path);
218
218
  if (identity.isMap(node))
219
- return visitor.Map?.(key, node, path);
219
+ return visitor.Map?.(key2, node, path);
220
220
  if (identity.isSeq(node))
221
- return visitor.Seq?.(key, node, path);
221
+ return visitor.Seq?.(key2, node, path);
222
222
  if (identity.isPair(node))
223
- return visitor.Pair?.(key, node, path);
223
+ return visitor.Pair?.(key2, node, path);
224
224
  if (identity.isScalar(node))
225
- return visitor.Scalar?.(key, node, path);
225
+ return visitor.Scalar?.(key2, node, path);
226
226
  if (identity.isAlias(node))
227
- return visitor.Alias?.(key, node, path);
227
+ return visitor.Alias?.(key2, node, path);
228
228
  return void 0;
229
229
  }
230
- function replaceNode(key, path, node) {
230
+ function replaceNode(key2, path, node) {
231
231
  const parent = path[path.length - 1];
232
232
  if (identity.isCollection(parent)) {
233
- parent.items[key] = node;
233
+ parent.items[key2] = node;
234
234
  } else if (identity.isPair(parent)) {
235
- if (key === "key")
235
+ if (key2 === "key")
236
236
  parent.key = node;
237
237
  else
238
238
  parent.value = node;
@@ -307,8 +307,8 @@ var require_directives = __commonJS({
307
307
  this.atNextDocument = false;
308
308
  }
309
309
  const parts = line.trim().split(/[ \t]+/);
310
- const name = parts.shift();
311
- switch (name) {
310
+ const name2 = parts.shift();
311
+ switch (name2) {
312
312
  case "%TAG": {
313
313
  if (parts.length !== 2) {
314
314
  onError(0, "%TAG directive should contain exactly two parts");
@@ -336,7 +336,7 @@ var require_directives = __commonJS({
336
336
  }
337
337
  }
338
338
  default:
339
- onError(0, `Unknown directive ${name}`, true);
339
+ onError(0, `Unknown directive ${name2}`, true);
340
340
  return false;
341
341
  }
342
342
  }
@@ -445,9 +445,9 @@ var require_anchors = __commonJS({
445
445
  }
446
446
  function findNewAnchor(prefix2, exclude) {
447
447
  for (let i = 1; true; ++i) {
448
- const name = `${prefix2}${i}`;
449
- if (!exclude.has(name))
450
- return name;
448
+ const name2 = `${prefix2}${i}`;
449
+ if (!exclude.has(name2))
450
+ return name2;
451
451
  }
452
452
  }
453
453
  function createNodeAnchors(doc, prefix2) {
@@ -493,7 +493,7 @@ var require_anchors = __commonJS({
493
493
  var require_applyReviver = __commonJS({
494
494
  "node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/doc/applyReviver.js"(exports) {
495
495
  "use strict";
496
- function applyReviver(reviver, obj, key, val) {
496
+ function applyReviver(reviver, obj, key2, val) {
497
497
  if (val && typeof val === "object") {
498
498
  if (Array.isArray(val)) {
499
499
  for (let i = 0, len = val.length; i < len; ++i) {
@@ -533,7 +533,7 @@ var require_applyReviver = __commonJS({
533
533
  }
534
534
  }
535
535
  }
536
- return reviver.call(obj, key, val);
536
+ return reviver.call(obj, key2, val);
537
537
  }
538
538
  exports.applyReviver = applyReviver;
539
539
  }
@@ -896,14 +896,14 @@ var require_Collection = __commonJS({
896
896
  if (isEmptyPath(path))
897
897
  this.add(value);
898
898
  else {
899
- const [key, ...rest] = path;
900
- const node = this.get(key, true);
899
+ const [key2, ...rest] = path;
900
+ const node = this.get(key2, true);
901
901
  if (identity.isCollection(node))
902
902
  node.addIn(rest, value);
903
903
  else if (node === void 0 && this.schema)
904
- this.set(key, collectionFromPath(this.schema, rest, value));
904
+ this.set(key2, collectionFromPath(this.schema, rest, value));
905
905
  else
906
- throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
906
+ throw new Error(`Expected YAML collection at ${key2}. Remaining path: ${rest}`);
907
907
  }
908
908
  }
909
909
  /**
@@ -911,14 +911,14 @@ var require_Collection = __commonJS({
911
911
  * @returns `true` if the item was found and removed.
912
912
  */
913
913
  deleteIn(path) {
914
- const [key, ...rest] = path;
914
+ const [key2, ...rest] = path;
915
915
  if (rest.length === 0)
916
- return this.delete(key);
917
- const node = this.get(key, true);
916
+ return this.delete(key2);
917
+ const node = this.get(key2, true);
918
918
  if (identity.isCollection(node))
919
919
  return node.deleteIn(rest);
920
920
  else
921
- throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
921
+ throw new Error(`Expected YAML collection at ${key2}. Remaining path: ${rest}`);
922
922
  }
923
923
  /**
924
924
  * Returns item at `key`, or `undefined` if not found. By default unwraps
@@ -926,8 +926,8 @@ var require_Collection = __commonJS({
926
926
  * `true` (collections are always returned intact).
927
927
  */
928
928
  getIn(path, keepScalar) {
929
- const [key, ...rest] = path;
930
- const node = this.get(key, true);
929
+ const [key2, ...rest] = path;
930
+ const node = this.get(key2, true);
931
931
  if (rest.length === 0)
932
932
  return !keepScalar && identity.isScalar(node) ? node.value : node;
933
933
  else
@@ -945,10 +945,10 @@ var require_Collection = __commonJS({
945
945
  * Checks if the collection includes a value with the key `key`.
946
946
  */
947
947
  hasIn(path) {
948
- const [key, ...rest] = path;
948
+ const [key2, ...rest] = path;
949
949
  if (rest.length === 0)
950
- return this.has(key);
951
- const node = this.get(key, true);
950
+ return this.has(key2);
951
+ const node = this.get(key2, true);
952
952
  return identity.isCollection(node) ? node.hasIn(rest) : false;
953
953
  }
954
954
  /**
@@ -956,17 +956,17 @@ var require_Collection = __commonJS({
956
956
  * boolean to add/remove the item from the set.
957
957
  */
958
958
  setIn(path, value) {
959
- const [key, ...rest] = path;
959
+ const [key2, ...rest] = path;
960
960
  if (rest.length === 0) {
961
- this.set(key, value);
961
+ this.set(key2, value);
962
962
  } else {
963
- const node = this.get(key, true);
963
+ const node = this.get(key2, true);
964
964
  if (identity.isCollection(node))
965
965
  node.setIn(rest, value);
966
966
  else if (node === void 0 && this.schema)
967
- this.set(key, collectionFromPath(this.schema, rest, value));
967
+ this.set(key2, collectionFromPath(this.schema, rest, value));
968
968
  else
969
- throw new Error(`Expected YAML collection at ${key}. Remaining path: ${rest}`);
969
+ throw new Error(`Expected YAML collection at ${key2}. Remaining path: ${rest}`);
970
970
  }
971
971
  }
972
972
  };
@@ -1484,8 +1484,8 @@ var require_stringify = __commonJS({
1484
1484
  tagObj = tags.find((t) => t.nodeClass && obj instanceof t.nodeClass);
1485
1485
  }
1486
1486
  if (!tagObj) {
1487
- const name = obj?.constructor?.name ?? (obj === null ? "null" : typeof obj);
1488
- throw new Error(`Tag not resolved for ${name} value`);
1487
+ const name2 = obj?.constructor?.name ?? (obj === null ? "null" : typeof obj);
1488
+ throw new Error(`Tag not resolved for ${name2} value`);
1489
1489
  }
1490
1490
  return tagObj;
1491
1491
  }
@@ -1544,19 +1544,19 @@ var require_stringifyPair = __commonJS({
1544
1544
  var Scalar = require_Scalar();
1545
1545
  var stringify = require_stringify();
1546
1546
  var stringifyComment = require_stringifyComment();
1547
- function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1547
+ function stringifyPair({ key: key2, value }, ctx, onComment, onChompKeep) {
1548
1548
  const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
1549
- let keyComment = identity.isNode(key) && key.comment || null;
1549
+ let keyComment = identity.isNode(key2) && key2.comment || null;
1550
1550
  if (simpleKeys) {
1551
1551
  if (keyComment) {
1552
1552
  throw new Error("With simple keys, key nodes cannot have comments");
1553
1553
  }
1554
- if (identity.isCollection(key) || !identity.isNode(key) && typeof key === "object") {
1554
+ if (identity.isCollection(key2) || !identity.isNode(key2) && typeof key2 === "object") {
1555
1555
  const msg = "With simple keys, collection cannot be used as a key value";
1556
1556
  throw new Error(msg);
1557
1557
  }
1558
1558
  }
1559
- 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"));
1559
+ let explicitKey = !simpleKeys && (!key2 || keyComment && value == null && !ctx.inFlow || identity.isCollection(key2) || (identity.isScalar(key2) ? key2.type === Scalar.Scalar.BLOCK_FOLDED || key2.type === Scalar.Scalar.BLOCK_LITERAL : typeof key2 === "object"));
1560
1560
  ctx = Object.assign({}, ctx, {
1561
1561
  allNullValues: false,
1562
1562
  implicitKey: !explicitKey && (simpleKeys || !allNullValues),
@@ -1564,7 +1564,7 @@ var require_stringifyPair = __commonJS({
1564
1564
  });
1565
1565
  let keyCommentDone = false;
1566
1566
  let chompKeep = false;
1567
- let str2 = stringify.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
1567
+ let str2 = stringify.stringify(key2, ctx, () => keyCommentDone = true, () => chompKeep = true);
1568
1568
  if (!explicitKey && !ctx.inFlow && str2.length > 1024) {
1569
1569
  if (simpleKeys)
1570
1570
  throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
@@ -1708,7 +1708,7 @@ var require_merge = __commonJS({
1708
1708
  }),
1709
1709
  stringify: () => MERGE_KEY
1710
1710
  };
1711
- 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);
1711
+ var isMergeKey = (ctx, key2) => (merge.identify(key2) || identity.isScalar(key2) && (!key2.type || key2.type === Scalar.Scalar.PLAIN) && merge.identify(key2.value)) && ctx?.doc.schema.tags.some((tag) => tag.tag === merge.tag && tag.default);
1712
1712
  function addMergeToJSMap(ctx, map, value) {
1713
1713
  const source = resolveAliasValue(ctx, value);
1714
1714
  if (identity.isSeq(source))
@@ -1725,14 +1725,14 @@ var require_merge = __commonJS({
1725
1725
  if (!identity.isMap(source))
1726
1726
  throw new Error("Merge sources must be maps or map aliases");
1727
1727
  const srcMap = source.toJSON(null, ctx, Map);
1728
- for (const [key, value2] of srcMap) {
1728
+ for (const [key2, value2] of srcMap) {
1729
1729
  if (map instanceof Map) {
1730
- if (!map.has(key))
1731
- map.set(key, value2);
1730
+ if (!map.has(key2))
1731
+ map.set(key2, value2);
1732
1732
  } else if (map instanceof Set) {
1733
- map.add(key);
1734
- } else if (!Object.prototype.hasOwnProperty.call(map, key)) {
1735
- Object.defineProperty(map, key, {
1733
+ map.add(key2);
1734
+ } else if (!Object.prototype.hasOwnProperty.call(map, key2)) {
1735
+ Object.defineProperty(map, key2, {
1736
1736
  value: value2,
1737
1737
  writable: true,
1738
1738
  enumerable: true,
@@ -1760,19 +1760,19 @@ var require_addPairToJSMap = __commonJS({
1760
1760
  var stringify = require_stringify();
1761
1761
  var identity = require_identity();
1762
1762
  var toJS = require_toJS();
1763
- function addPairToJSMap(ctx, map, { key, value }) {
1764
- if (identity.isNode(key) && key.addToJSMap)
1765
- key.addToJSMap(ctx, map, value);
1766
- else if (merge.isMergeKey(ctx, key))
1763
+ function addPairToJSMap(ctx, map, { key: key2, value }) {
1764
+ if (identity.isNode(key2) && key2.addToJSMap)
1765
+ key2.addToJSMap(ctx, map, value);
1766
+ else if (merge.isMergeKey(ctx, key2))
1767
1767
  merge.addMergeToJSMap(ctx, map, value);
1768
1768
  else {
1769
- const jsKey = toJS.toJS(key, "", ctx);
1769
+ const jsKey = toJS.toJS(key2, "", ctx);
1770
1770
  if (map instanceof Map) {
1771
1771
  map.set(jsKey, toJS.toJS(value, jsKey, ctx));
1772
1772
  } else if (map instanceof Set) {
1773
1773
  map.add(jsKey);
1774
1774
  } else {
1775
- const stringKey = stringifyKey(key, jsKey, ctx);
1775
+ const stringKey = stringifyKey(key2, jsKey, ctx);
1776
1776
  const jsValue = toJS.toJS(value, stringKey, ctx);
1777
1777
  if (stringKey in map)
1778
1778
  Object.defineProperty(map, stringKey, {
@@ -1787,19 +1787,19 @@ var require_addPairToJSMap = __commonJS({
1787
1787
  }
1788
1788
  return map;
1789
1789
  }
1790
- function stringifyKey(key, jsKey, ctx) {
1790
+ function stringifyKey(key2, jsKey, ctx) {
1791
1791
  if (jsKey === null)
1792
1792
  return "";
1793
1793
  if (typeof jsKey !== "object")
1794
1794
  return String(jsKey);
1795
- if (identity.isNode(key) && ctx?.doc) {
1795
+ if (identity.isNode(key2) && ctx?.doc) {
1796
1796
  const strCtx = stringify.createStringifyContext(ctx.doc, {});
1797
1797
  strCtx.anchors = /* @__PURE__ */ new Set();
1798
1798
  for (const node of ctx.anchors.keys())
1799
1799
  strCtx.anchors.add(node.anchor);
1800
1800
  strCtx.inFlow = true;
1801
1801
  strCtx.inStringifyKey = true;
1802
- const strKey = key.toString(strCtx);
1802
+ const strKey = key2.toString(strCtx);
1803
1803
  if (!ctx.mapKeyWarned) {
1804
1804
  let jsonStr = JSON.stringify(strKey);
1805
1805
  if (jsonStr.length > 40)
@@ -1823,24 +1823,24 @@ var require_Pair = __commonJS({
1823
1823
  var stringifyPair = require_stringifyPair();
1824
1824
  var addPairToJSMap = require_addPairToJSMap();
1825
1825
  var identity = require_identity();
1826
- function createPair(key, value, ctx) {
1827
- const k = createNode.createNode(key, void 0, ctx);
1826
+ function createPair(key2, value, ctx) {
1827
+ const k = createNode.createNode(key2, void 0, ctx);
1828
1828
  const v = createNode.createNode(value, void 0, ctx);
1829
1829
  return new Pair(k, v);
1830
1830
  }
1831
1831
  var Pair = class _Pair {
1832
- constructor(key, value = null) {
1832
+ constructor(key2, value = null) {
1833
1833
  Object.defineProperty(this, identity.NODE_TYPE, { value: identity.PAIR });
1834
- this.key = key;
1834
+ this.key = key2;
1835
1835
  this.value = value;
1836
1836
  }
1837
1837
  clone(schema) {
1838
- let { key, value } = this;
1839
- if (identity.isNode(key))
1840
- key = key.clone(schema);
1838
+ let { key: key2, value } = this;
1839
+ if (identity.isNode(key2))
1840
+ key2 = key2.clone(schema);
1841
1841
  if (identity.isNode(value))
1842
1842
  value = value.clone(schema);
1843
- return new _Pair(key, value);
1843
+ return new _Pair(key2, value);
1844
1844
  }
1845
1845
  toJSON(_, ctx) {
1846
1846
  const pair = ctx?.mapAsMap ? /* @__PURE__ */ new Map() : {};
@@ -2016,11 +2016,11 @@ var require_YAMLMap = __commonJS({
2016
2016
  var identity = require_identity();
2017
2017
  var Pair = require_Pair();
2018
2018
  var Scalar = require_Scalar();
2019
- function findPair(items, key) {
2020
- const k = identity.isScalar(key) ? key.value : key;
2019
+ function findPair(items, key2) {
2020
+ const k = identity.isScalar(key2) ? key2.value : key2;
2021
2021
  for (const it of items) {
2022
2022
  if (identity.isPair(it)) {
2023
- if (it.key === key || it.key === k)
2023
+ if (it.key === key2 || it.key === k)
2024
2024
  return it;
2025
2025
  if (identity.isScalar(it.key) && it.key.value === k)
2026
2026
  return it;
@@ -2043,20 +2043,20 @@ var require_YAMLMap = __commonJS({
2043
2043
  static from(schema, obj, ctx) {
2044
2044
  const { keepUndefined, replacer } = ctx;
2045
2045
  const map = new this(schema);
2046
- const add = (key, value) => {
2046
+ const add = (key2, value) => {
2047
2047
  if (typeof replacer === "function")
2048
- value = replacer.call(obj, key, value);
2049
- else if (Array.isArray(replacer) && !replacer.includes(key))
2048
+ value = replacer.call(obj, key2, value);
2049
+ else if (Array.isArray(replacer) && !replacer.includes(key2))
2050
2050
  return;
2051
2051
  if (value !== void 0 || keepUndefined)
2052
- map.items.push(Pair.createPair(key, value, ctx));
2052
+ map.items.push(Pair.createPair(key2, value, ctx));
2053
2053
  };
2054
2054
  if (obj instanceof Map) {
2055
- for (const [key, value] of obj)
2056
- add(key, value);
2055
+ for (const [key2, value] of obj)
2056
+ add(key2, value);
2057
2057
  } else if (obj && typeof obj === "object") {
2058
- for (const key of Object.keys(obj))
2059
- add(key, obj[key]);
2058
+ for (const key2 of Object.keys(obj))
2059
+ add(key2, obj[key2]);
2060
2060
  }
2061
2061
  if (typeof schema.sortMapEntries === "function") {
2062
2062
  map.items.sort(schema.sortMapEntries);
@@ -2096,23 +2096,23 @@ var require_YAMLMap = __commonJS({
2096
2096
  this.items.push(_pair);
2097
2097
  }
2098
2098
  }
2099
- delete(key) {
2100
- const it = findPair(this.items, key);
2099
+ delete(key2) {
2100
+ const it = findPair(this.items, key2);
2101
2101
  if (!it)
2102
2102
  return false;
2103
2103
  const del = this.items.splice(this.items.indexOf(it), 1);
2104
2104
  return del.length > 0;
2105
2105
  }
2106
- get(key, keepScalar) {
2107
- const it = findPair(this.items, key);
2106
+ get(key2, keepScalar) {
2107
+ const it = findPair(this.items, key2);
2108
2108
  const node = it?.value;
2109
2109
  return (!keepScalar && identity.isScalar(node) ? node.value : node) ?? void 0;
2110
2110
  }
2111
- has(key) {
2112
- return !!findPair(this.items, key);
2111
+ has(key2) {
2112
+ return !!findPair(this.items, key2);
2113
2113
  }
2114
- set(key, value) {
2115
- this.add(new Pair.Pair(key, value), true);
2114
+ set(key2, value) {
2115
+ this.add(new Pair.Pair(key2, value), true);
2116
2116
  }
2117
2117
  /**
2118
2118
  * @param ctx - Conversion context, originally set in Document#toJS()
@@ -2201,15 +2201,15 @@ var require_YAMLSeq = __commonJS({
2201
2201
  *
2202
2202
  * @returns `true` if the item was found and removed.
2203
2203
  */
2204
- delete(key) {
2205
- const idx = asItemIndex(key);
2204
+ delete(key2) {
2205
+ const idx = asItemIndex(key2);
2206
2206
  if (typeof idx !== "number")
2207
2207
  return false;
2208
2208
  const del = this.items.splice(idx, 1);
2209
2209
  return del.length > 0;
2210
2210
  }
2211
- get(key, keepScalar) {
2212
- const idx = asItemIndex(key);
2211
+ get(key2, keepScalar) {
2212
+ const idx = asItemIndex(key2);
2213
2213
  if (typeof idx !== "number")
2214
2214
  return void 0;
2215
2215
  const it = this.items[idx];
@@ -2221,8 +2221,8 @@ var require_YAMLSeq = __commonJS({
2221
2221
  * `key` must contain a representation of an integer for this to succeed.
2222
2222
  * It may be wrapped in a `Scalar`.
2223
2223
  */
2224
- has(key) {
2225
- const idx = asItemIndex(key);
2224
+ has(key2) {
2225
+ const idx = asItemIndex(key2);
2226
2226
  return typeof idx === "number" && idx < this.items.length;
2227
2227
  }
2228
2228
  /**
@@ -2232,10 +2232,10 @@ var require_YAMLSeq = __commonJS({
2232
2232
  * If `key` does not contain a representation of an integer, this will throw.
2233
2233
  * It may be wrapped in a `Scalar`.
2234
2234
  */
2235
- set(key, value) {
2236
- const idx = asItemIndex(key);
2235
+ set(key2, value) {
2236
+ const idx = asItemIndex(key2);
2237
2237
  if (typeof idx !== "number")
2238
- throw new Error(`Expected a valid index, not ${key}.`);
2238
+ throw new Error(`Expected a valid index, not ${key2}.`);
2239
2239
  const prev = this.items[idx];
2240
2240
  if (identity.isScalar(prev) && Scalar.isScalarValue(value))
2241
2241
  prev.value = value;
@@ -2269,8 +2269,8 @@ var require_YAMLSeq = __commonJS({
2269
2269
  let i = 0;
2270
2270
  for (let it of obj) {
2271
2271
  if (typeof replacer === "function") {
2272
- const key = obj instanceof Set ? it : String(i++);
2273
- it = replacer.call(obj, key, it);
2272
+ const key2 = obj instanceof Set ? it : String(i++);
2273
+ it = replacer.call(obj, key2, it);
2274
2274
  }
2275
2275
  seq.items.push(createNode.createNode(it, void 0, ctx));
2276
2276
  }
@@ -2278,8 +2278,8 @@ var require_YAMLSeq = __commonJS({
2278
2278
  return seq;
2279
2279
  }
2280
2280
  };
2281
- function asItemIndex(key) {
2282
- let idx = identity.isScalar(key) ? key.value : key;
2281
+ function asItemIndex(key2) {
2282
+ let idx = identity.isScalar(key2) ? key2.value : key2;
2283
2283
  if (idx && typeof idx === "string")
2284
2284
  idx = Number(idx);
2285
2285
  return typeof idx === "number" && Number.isInteger(idx) && idx >= 0 ? idx : null;
@@ -2693,25 +2693,25 @@ ${cn.comment}` : item.comment;
2693
2693
  for (let it of iterable) {
2694
2694
  if (typeof replacer === "function")
2695
2695
  it = replacer.call(iterable, String(i++), it);
2696
- let key, value;
2696
+ let key2, value;
2697
2697
  if (Array.isArray(it)) {
2698
2698
  if (it.length === 2) {
2699
- key = it[0];
2699
+ key2 = it[0];
2700
2700
  value = it[1];
2701
2701
  } else
2702
2702
  throw new TypeError(`Expected [key, value] tuple: ${it}`);
2703
2703
  } else if (it && it instanceof Object) {
2704
2704
  const keys = Object.keys(it);
2705
2705
  if (keys.length === 1) {
2706
- key = keys[0];
2707
- value = it[key];
2706
+ key2 = keys[0];
2707
+ value = it[key2];
2708
2708
  } else {
2709
2709
  throw new TypeError(`Expected tuple with one key, not ${keys.length} keys`);
2710
2710
  }
2711
2711
  } else {
2712
- key = it;
2712
+ key2 = it;
2713
2713
  }
2714
- pairs2.items.push(Pair.createPair(key, value, ctx));
2714
+ pairs2.items.push(Pair.createPair(key2, value, ctx));
2715
2715
  }
2716
2716
  return pairs2;
2717
2717
  }
@@ -2758,16 +2758,16 @@ var require_omap = __commonJS({
2758
2758
  if (ctx?.onCreate)
2759
2759
  ctx.onCreate(map);
2760
2760
  for (const pair of this.items) {
2761
- let key, value;
2761
+ let key2, value;
2762
2762
  if (identity.isPair(pair)) {
2763
- key = toJS.toJS(pair.key, "", ctx);
2764
- value = toJS.toJS(pair.value, key, ctx);
2763
+ key2 = toJS.toJS(pair.key, "", ctx);
2764
+ value = toJS.toJS(pair.value, key2, ctx);
2765
2765
  } else {
2766
- key = toJS.toJS(pair, "", ctx);
2766
+ key2 = toJS.toJS(pair, "", ctx);
2767
2767
  }
2768
- if (map.has(key))
2768
+ if (map.has(key2))
2769
2769
  throw new Error("Ordered maps must not include duplicate keys");
2770
- map.set(key, value);
2770
+ map.set(key2, value);
2771
2771
  }
2772
2772
  return map;
2773
2773
  }
@@ -2788,12 +2788,12 @@ var require_omap = __commonJS({
2788
2788
  resolve(seq, onError) {
2789
2789
  const pairs$1 = pairs.resolvePairs(seq, onError);
2790
2790
  const seenKeys = [];
2791
- for (const { key } of pairs$1.items) {
2792
- if (identity.isScalar(key)) {
2793
- if (seenKeys.includes(key.value)) {
2794
- onError(`Ordered maps must not include duplicate keys: ${key.value}`);
2791
+ for (const { key: key2 } of pairs$1.items) {
2792
+ if (identity.isScalar(key2)) {
2793
+ if (seenKeys.includes(key2.value)) {
2794
+ onError(`Ordered maps must not include duplicate keys: ${key2.value}`);
2795
2795
  } else {
2796
- seenKeys.push(key.value);
2796
+ seenKeys.push(key2.value);
2797
2797
  }
2798
2798
  }
2799
2799
  }
@@ -2978,14 +2978,14 @@ var require_set = __commonJS({
2978
2978
  super(schema);
2979
2979
  this.tag = _YAMLSet.tag;
2980
2980
  }
2981
- add(key) {
2981
+ add(key2) {
2982
2982
  let pair;
2983
- if (identity.isPair(key))
2984
- pair = key;
2985
- else if (key && typeof key === "object" && "key" in key && "value" in key && key.value === null)
2986
- pair = new Pair.Pair(key.key, null);
2983
+ if (identity.isPair(key2))
2984
+ pair = key2;
2985
+ else if (key2 && typeof key2 === "object" && "key" in key2 && "value" in key2 && key2.value === null)
2986
+ pair = new Pair.Pair(key2.key, null);
2987
2987
  else
2988
- pair = new Pair.Pair(key, null);
2988
+ pair = new Pair.Pair(key2, null);
2989
2989
  const prev = YAMLMap.findPair(this.items, pair.key);
2990
2990
  if (!prev)
2991
2991
  this.items.push(pair);
@@ -2994,18 +2994,18 @@ var require_set = __commonJS({
2994
2994
  * If `keepPair` is `true`, returns the Pair matching `key`.
2995
2995
  * Otherwise, returns the value of that Pair's key.
2996
2996
  */
2997
- get(key, keepPair) {
2998
- const pair = YAMLMap.findPair(this.items, key);
2997
+ get(key2, keepPair) {
2998
+ const pair = YAMLMap.findPair(this.items, key2);
2999
2999
  return !keepPair && identity.isPair(pair) ? identity.isScalar(pair.key) ? pair.key.value : pair.key : pair;
3000
3000
  }
3001
- set(key, value) {
3001
+ set(key2, value) {
3002
3002
  if (typeof value !== "boolean")
3003
3003
  throw new Error(`Expected boolean value for set(key, value) in a YAML set, not ${typeof value}`);
3004
- const prev = YAMLMap.findPair(this.items, key);
3004
+ const prev = YAMLMap.findPair(this.items, key2);
3005
3005
  if (prev && !value) {
3006
3006
  this.items.splice(this.items.indexOf(prev), 1);
3007
3007
  } else if (!prev && value) {
3008
- this.items.push(new Pair.Pair(key));
3008
+ this.items.push(new Pair.Pair(key2));
3009
3009
  }
3010
3010
  }
3011
3011
  toJSON(_, ctx) {
@@ -3252,7 +3252,7 @@ var require_tags = __commonJS({
3252
3252
  if (Array.isArray(customTags))
3253
3253
  tags = [];
3254
3254
  else {
3255
- const keys = Array.from(schemas.keys()).filter((key) => key !== "yaml11").map((key) => JSON.stringify(key)).join(", ");
3255
+ const keys = Array.from(schemas.keys()).filter((key2) => key2 !== "yaml11").map((key2) => JSON.stringify(key2)).join(", ");
3256
3256
  throw new Error(`Unknown schema "${schemaName}"; use one of ${keys} or define customTags array`);
3257
3257
  }
3258
3258
  }
@@ -3268,7 +3268,7 @@ var require_tags = __commonJS({
3268
3268
  const tagObj = typeof tag === "string" ? tagsByName[tag] : tag;
3269
3269
  if (!tagObj) {
3270
3270
  const tagName = JSON.stringify(tag);
3271
- const keys = Object.keys(tagsByName).map((key) => JSON.stringify(key)).join(", ");
3271
+ const keys = Object.keys(tagsByName).map((key2) => JSON.stringify(key2)).join(", ");
3272
3272
  throw new Error(`Unknown custom tag ${tagName}; use one of ${keys}`);
3273
3273
  }
3274
3274
  if (!tags2.includes(tagObj))
@@ -3484,11 +3484,11 @@ var require_Document = __commonJS({
3484
3484
  * `name` will be used as a prefix for a new unique anchor.
3485
3485
  * If `name` is undefined, the generated anchor will use 'a' as a prefix.
3486
3486
  */
3487
- createAlias(node, name) {
3487
+ createAlias(node, name2) {
3488
3488
  if (!node.anchor) {
3489
3489
  const prev = anchors.anchorNames(this);
3490
3490
  node.anchor = // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
3491
- !name || prev.has(name) ? anchors.findNewAnchor(name || "a", prev) : name;
3491
+ !name2 || prev.has(name2) ? anchors.findNewAnchor(name2 || "a", prev) : name2;
3492
3492
  }
3493
3493
  return new Alias.Alias(node.anchor);
3494
3494
  }
@@ -3532,8 +3532,8 @@ var require_Document = __commonJS({
3532
3532
  * Convert a key and a value into a `Pair` using the current schema,
3533
3533
  * recursively wrapping all values as `Scalar` or `Collection` nodes.
3534
3534
  */
3535
- createPair(key, value, options = {}) {
3536
- const k = this.createNode(key, null, options);
3535
+ createPair(key2, value, options = {}) {
3536
+ const k = this.createNode(key2, null, options);
3537
3537
  const v = this.createNode(value, null, options);
3538
3538
  return new Pair.Pair(k, v);
3539
3539
  }
@@ -3541,8 +3541,8 @@ var require_Document = __commonJS({
3541
3541
  * Removes a value from the document.
3542
3542
  * @returns `true` if the item was found and removed.
3543
3543
  */
3544
- delete(key) {
3545
- return assertCollection(this.contents) ? this.contents.delete(key) : false;
3544
+ delete(key2) {
3545
+ return assertCollection(this.contents) ? this.contents.delete(key2) : false;
3546
3546
  }
3547
3547
  /**
3548
3548
  * Removes a value from the document.
@@ -3562,8 +3562,8 @@ var require_Document = __commonJS({
3562
3562
  * scalar values from their surrounding node; to disable set `keepScalar` to
3563
3563
  * `true` (collections are always returned intact).
3564
3564
  */
3565
- get(key, keepScalar) {
3566
- return identity.isCollection(this.contents) ? this.contents.get(key, keepScalar) : void 0;
3565
+ get(key2, keepScalar) {
3566
+ return identity.isCollection(this.contents) ? this.contents.get(key2, keepScalar) : void 0;
3567
3567
  }
3568
3568
  /**
3569
3569
  * Returns item at `path`, or `undefined` if not found. By default unwraps
@@ -3578,8 +3578,8 @@ var require_Document = __commonJS({
3578
3578
  /**
3579
3579
  * Checks if the document includes a value with the key `key`.
3580
3580
  */
3581
- has(key) {
3582
- return identity.isCollection(this.contents) ? this.contents.has(key) : false;
3581
+ has(key2) {
3582
+ return identity.isCollection(this.contents) ? this.contents.has(key2) : false;
3583
3583
  }
3584
3584
  /**
3585
3585
  * Checks if the document includes a value at `path`.
@@ -3593,11 +3593,11 @@ var require_Document = __commonJS({
3593
3593
  * Sets a value in this document. For `!!set`, `value` needs to be a
3594
3594
  * boolean to add/remove the item from the set.
3595
3595
  */
3596
- set(key, value) {
3596
+ set(key2, value) {
3597
3597
  if (this.contents == null) {
3598
- this.contents = Collection.collectionFromPath(this.schema, [key], value);
3598
+ this.contents = Collection.collectionFromPath(this.schema, [key2], value);
3599
3599
  } else if (assertCollection(this.contents)) {
3600
- this.contents.set(key, value);
3600
+ this.contents.set(key2, value);
3601
3601
  }
3602
3602
  }
3603
3603
  /**
@@ -3707,9 +3707,9 @@ var require_errors = __commonJS({
3707
3707
  "node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/errors.js"(exports) {
3708
3708
  "use strict";
3709
3709
  var YAMLError = class extends Error {
3710
- constructor(name, pos, code, message2) {
3710
+ constructor(name2, pos, code, message2) {
3711
3711
  super();
3712
- this.name = name;
3712
+ this.name = name2;
3713
3713
  this.code = code;
3714
3714
  this.message = message2;
3715
3715
  this.pos = pos;
@@ -3905,24 +3905,24 @@ var require_resolve_props = __commonJS({
3905
3905
  var require_util_contains_newline = __commonJS({
3906
3906
  "node_modules/.pnpm/yaml@2.9.1/node_modules/yaml/dist/compose/util-contains-newline.js"(exports) {
3907
3907
  "use strict";
3908
- function containsNewline(key) {
3909
- if (!key)
3908
+ function containsNewline(key2) {
3909
+ if (!key2)
3910
3910
  return null;
3911
- switch (key.type) {
3911
+ switch (key2.type) {
3912
3912
  case "alias":
3913
3913
  case "scalar":
3914
3914
  case "double-quoted-scalar":
3915
3915
  case "single-quoted-scalar":
3916
- if (key.source.includes("\n"))
3916
+ if (key2.source.includes("\n"))
3917
3917
  return true;
3918
- if (key.end) {
3919
- for (const st of key.end)
3918
+ if (key2.end) {
3919
+ for (const st of key2.end)
3920
3920
  if (st.type === "newline")
3921
3921
  return true;
3922
3922
  }
3923
3923
  return false;
3924
3924
  case "flow-collection":
3925
- for (const it of key.items) {
3925
+ for (const it of key2.items) {
3926
3926
  for (const st of it.start)
3927
3927
  if (st.type === "newline")
3928
3928
  return true;
@@ -3996,10 +3996,10 @@ var require_resolve_block_map = __commonJS({
3996
3996
  let offset = bm.offset;
3997
3997
  let commentEnd = null;
3998
3998
  for (const collItem of bm.items) {
3999
- const { start, key, sep: sep2, value } = collItem;
3999
+ const { start, key: key2, sep: sep2, value } = collItem;
4000
4000
  const keyProps = resolveProps.resolveProps(start, {
4001
4001
  indicator: "explicit-key-ind",
4002
- next: key ?? sep2?.[0],
4002
+ next: key2 ?? sep2?.[0],
4003
4003
  offset,
4004
4004
  onError,
4005
4005
  parentIndent: bm.indent,
@@ -4007,10 +4007,10 @@ var require_resolve_block_map = __commonJS({
4007
4007
  });
4008
4008
  const implicitKey = !keyProps.found;
4009
4009
  if (implicitKey) {
4010
- if (key) {
4011
- if (key.type === "block-seq")
4010
+ if (key2) {
4011
+ if (key2.type === "block-seq")
4012
4012
  onError(offset, "BLOCK_AS_IMPLICIT_KEY", "A block sequence may not be used as an implicit map key");
4013
- else if ("indent" in key && key.indent !== bm.indent)
4013
+ else if ("indent" in key2 && key2.indent !== bm.indent)
4014
4014
  onError(offset, "BAD_INDENT", startColMsg);
4015
4015
  }
4016
4016
  if (!keyProps.anchor && !keyProps.tag && !sep2) {
@@ -4023,17 +4023,17 @@ var require_resolve_block_map = __commonJS({
4023
4023
  }
4024
4024
  continue;
4025
4025
  }
4026
- if (keyProps.newlineAfterProp || utilContainsNewline.containsNewline(key)) {
4027
- onError(key ?? start[start.length - 1], "MULTILINE_IMPLICIT_KEY", "Implicit keys need to be on a single line");
4026
+ if (keyProps.newlineAfterProp || utilContainsNewline.containsNewline(key2)) {
4027
+ onError(key2 ?? start[start.length - 1], "MULTILINE_IMPLICIT_KEY", "Implicit keys need to be on a single line");
4028
4028
  }
4029
4029
  } else if (keyProps.found?.indent !== bm.indent) {
4030
4030
  onError(offset, "BAD_INDENT", startColMsg);
4031
4031
  }
4032
4032
  ctx.atKey = true;
4033
4033
  const keyStart = keyProps.end;
4034
- const keyNode = key ? composeNode(ctx, key, keyProps, onError) : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
4034
+ const keyNode = key2 ? composeNode(ctx, key2, keyProps, onError) : composeEmptyNode(ctx, keyStart, start, null, keyProps, onError);
4035
4035
  if (ctx.schema.compat)
4036
- utilFlowIndentCheck.flowIndentCheck(bm.indent, key, onError);
4036
+ utilFlowIndentCheck.flowIndentCheck(bm.indent, key2, onError);
4037
4037
  ctx.atKey = false;
4038
4038
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
4039
4039
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
@@ -4043,7 +4043,7 @@ var require_resolve_block_map = __commonJS({
4043
4043
  offset: keyNode.range[2],
4044
4044
  onError,
4045
4045
  parentIndent: bm.indent,
4046
- startOnNewline: !key || key.type === "block-scalar"
4046
+ startOnNewline: !key2 || key2.type === "block-scalar"
4047
4047
  });
4048
4048
  offset = valueProps.end;
4049
4049
  if (valueProps.found) {
@@ -4207,11 +4207,11 @@ var require_resolve_flow_collection = __commonJS({
4207
4207
  let offset = fc.offset + fc.start.source.length;
4208
4208
  for (let i = 0; i < fc.items.length; ++i) {
4209
4209
  const collItem = fc.items[i];
4210
- const { start, key, sep: sep2, value } = collItem;
4210
+ const { start, key: key2, sep: sep2, value } = collItem;
4211
4211
  const props = resolveProps.resolveProps(start, {
4212
4212
  flow: fcName,
4213
4213
  indicator: "explicit-key-ind",
4214
- next: key ?? sep2?.[0],
4214
+ next: key2 ?? sep2?.[0],
4215
4215
  offset,
4216
4216
  onError,
4217
4217
  parentIndent: fc.indent,
@@ -4232,9 +4232,9 @@ var require_resolve_flow_collection = __commonJS({
4232
4232
  offset = props.end;
4233
4233
  continue;
4234
4234
  }
4235
- if (!isMap && ctx.options.strict && utilContainsNewline.containsNewline(key))
4235
+ if (!isMap && ctx.options.strict && utilContainsNewline.containsNewline(key2))
4236
4236
  onError(
4237
- key,
4237
+ key2,
4238
4238
  // checked by containsNewline()
4239
4239
  "MULTILINE_IMPLICIT_KEY",
4240
4240
  "Implicit keys of flow sequence pairs need to be on a single line"
@@ -4281,8 +4281,8 @@ var require_resolve_flow_collection = __commonJS({
4281
4281
  } else {
4282
4282
  ctx.atKey = true;
4283
4283
  const keyStart = props.end;
4284
- const keyNode = key ? composeNode(ctx, key, props, onError) : composeEmptyNode(ctx, keyStart, start, null, props, onError);
4285
- if (isBlock(key))
4284
+ const keyNode = key2 ? composeNode(ctx, key2, props, onError) : composeEmptyNode(ctx, keyStart, start, null, props, onError);
4285
+ if (isBlock(key2))
4286
4286
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
4287
4287
  ctx.atKey = false;
4288
4288
  const valueProps = resolveProps.resolveProps(sep2 ?? [], {
@@ -4349,8 +4349,8 @@ var require_resolve_flow_collection = __commonJS({
4349
4349
  if (ce?.source === expectedEnd)
4350
4350
  cePos = ce.offset + ce.source.length;
4351
4351
  else {
4352
- const name = fcName[0].toUpperCase() + fcName.substring(1);
4353
- const msg = atRoot ? `${name} must end with a ${expectedEnd}` : `${name} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
4352
+ const name2 = fcName[0].toUpperCase() + fcName.substring(1);
4353
+ const msg = atRoot ? `${name2} must end with a ${expectedEnd}` : `${name2} in block collection must be sufficiently indented and end with a ${expectedEnd}`;
4354
4354
  onError(offset, atRoot ? "MISSING_CHAR" : "BAD_INDENT", msg);
4355
4355
  if (ce && ce.source.length !== 1)
4356
4356
  ee.unshift(ce);
@@ -5432,9 +5432,9 @@ var require_cst_scalar = __commonJS({
5432
5432
  ];
5433
5433
  if (!addEndtoBlockProps(props, "end" in token ? token.end : void 0))
5434
5434
  props.push({ type: "newline", offset: -1, indent, source: "\n" });
5435
- for (const key of Object.keys(token))
5436
- if (key !== "type" && key !== "offset")
5437
- delete token[key];
5435
+ for (const key2 of Object.keys(token))
5436
+ if (key2 !== "type" && key2 !== "offset")
5437
+ delete token[key2];
5438
5438
  Object.assign(token, { type: "block-scalar", indent, props, source: body });
5439
5439
  }
5440
5440
  }
@@ -5482,9 +5482,9 @@ var require_cst_scalar = __commonJS({
5482
5482
  default: {
5483
5483
  const indent = "indent" in token ? token.indent : -1;
5484
5484
  const end = "end" in token && Array.isArray(token.end) ? token.end.filter((st) => st.type === "space" || st.type === "comment" || st.type === "newline") : [];
5485
- for (const key of Object.keys(token))
5486
- if (key !== "type" && key !== "offset")
5487
- delete token[key];
5485
+ for (const key2 of Object.keys(token))
5486
+ if (key2 !== "type" && key2 !== "offset")
5487
+ delete token[key2];
5488
5488
  Object.assign(token, { type, indent, source, end });
5489
5489
  }
5490
5490
  }
@@ -5539,12 +5539,12 @@ var require_cst_stringify = __commonJS({
5539
5539
  }
5540
5540
  }
5541
5541
  }
5542
- function stringifyItem({ start, key, sep: sep2, value }) {
5542
+ function stringifyItem({ start, key: key2, sep: sep2, value }) {
5543
5543
  let res = "";
5544
5544
  for (const st of start)
5545
5545
  res += st.source;
5546
- if (key)
5547
- res += stringifyToken(key);
5546
+ if (key2)
5547
+ res += stringifyToken(key2);
5548
5548
  if (sep2)
5549
5549
  for (const st of sep2)
5550
5550
  res += st.source;
@@ -6876,7 +6876,7 @@ var require_parser = __commonJS({
6876
6876
  });
6877
6877
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
6878
6878
  const start2 = getFirstKeyStartProps(it.start);
6879
- const key = it.key;
6879
+ const key2 = it.key;
6880
6880
  const sep2 = it.sep;
6881
6881
  sep2.push(this.sourceToken);
6882
6882
  delete it.key;
@@ -6885,7 +6885,7 @@ var require_parser = __commonJS({
6885
6885
  type: "block-map",
6886
6886
  offset: this.offset,
6887
6887
  indent: this.indent,
6888
- items: [{ start: start2, key, sep: sep2 }]
6888
+ items: [{ start: start2, key: key2, sep: sep2 }]
6889
6889
  });
6890
6890
  } else if (start.length > 0) {
6891
6891
  it.sep = it.sep.concat(start, this.sourceToken);
@@ -7396,9 +7396,9 @@ function runMenu(input, output, head, rows, onKey) {
7396
7396
  let headLines = 0;
7397
7397
  let drawn = 0;
7398
7398
  const frame = () => {
7399
- const cols = width();
7400
- const lines = [...rows(), ...fitHint(hint, cols)];
7401
- drawn = lines.reduce((n, line) => n + screenLines(line, cols), 0);
7399
+ const cols2 = width();
7400
+ const lines = [...rows(), ...fitHint(hint, cols2)];
7401
+ drawn = lines.reduce((n, line) => n + screenLines(line, cols2), 0);
7402
7402
  return lines.map((line) => `${CLEAR_LINE}\r${line}
7403
7403
  `).join("");
7404
7404
  };
@@ -7426,12 +7426,12 @@ ${SHOW_CURSOR}`);
7426
7426
  reject(outcome.error);
7427
7427
  }
7428
7428
  };
7429
- const onKeypress = (text3, key) => {
7430
- const name = key?.name ?? text3;
7431
- if (key?.ctrl && (name === "c" || name === "d") || name === "escape" || name === "q" && !key?.ctrl) {
7429
+ const onKeypress = (text3, key2) => {
7430
+ const name2 = key2?.name ?? text3;
7431
+ if (key2?.ctrl && (name2 === "c" || name2 === "d") || name2 === "escape" || name2 === "q" && !key2?.ctrl) {
7432
7432
  return finish({ error: new PromptCancelled() });
7433
7433
  }
7434
- const result = onKey(text3, name);
7434
+ const result = onKey(text3, name2);
7435
7435
  if (result === "redraw") output.write(`\r${up(drawn)}${CLEAR_DOWN}${frame()}`);
7436
7436
  else if (result) finish(result);
7437
7437
  };
@@ -7440,9 +7440,9 @@ ${SHOW_CURSOR}`);
7440
7440
  try {
7441
7441
  emitKeypressEvents(input);
7442
7442
  input.setRawMode?.(true);
7443
- const cols = width();
7444
- const top = [question, ...note ? note.split("\n").flatMap((line) => wrapWords(line, cols)) : []];
7445
- headLines = top.reduce((n, line) => n + screenLines(line, cols), 0);
7443
+ const cols2 = width();
7444
+ const top = [question, ...note ? note.split("\n").flatMap((line) => wrapWords(line, cols2)) : []];
7445
+ headLines = top.reduce((n, line) => n + screenLines(line, cols2), 0);
7446
7446
  output.write(`${HIDE_CURSOR}${top.map((line) => `${line}
7447
7447
  `).join("")}${frame()}`);
7448
7448
  input.on("keypress", onKeypress);
@@ -7477,9 +7477,9 @@ function wrapWords(text3, columns) {
7477
7477
  function marker(options) {
7478
7478
  return options.color ? options.trueColor ? "\x1B[1;38;2;253;75;3m" : "\x1B[1;38;5;202m" : "\x1B[1m";
7479
7479
  }
7480
- function move(current, count2, text3, name) {
7481
- if (name === "up" || name === "k") return (current - 1 + count2) % count2;
7482
- if (name === "down" || name === "j") return (current + 1) % count2;
7480
+ function move(current, count2, text3, name2) {
7481
+ if (name2 === "up" || name2 === "k") return (current - 1 + count2) % count2;
7482
+ if (name2 === "down" || name2 === "j") return (current + 1) % count2;
7483
7483
  if (text3 && /^[1-9]$/.test(text3) && Number(text3) <= count2) return Number(text3) - 1;
7484
7484
  return null;
7485
7485
  }
@@ -7487,9 +7487,9 @@ function selectMenu(input, output, question, choices, options = {}) {
7487
7487
  let current = Math.min(Math.max(options.initial ?? 0, 0), choices.length - 1);
7488
7488
  const on = marker(options);
7489
7489
  const rows = () => choices.map((c, i) => i === current ? `${on}> ${c}${OFF}` : ` ${c}`);
7490
- return runMenu(input, output, { question, hint: HINT, columns: options.columns }, rows, (text3, name) => {
7491
- if (name === "return" || name === "enter") return { pick: current, summary: choices[current] ?? "" };
7492
- const next = move(current, choices.length, text3, name);
7490
+ return runMenu(input, output, { question, hint: HINT, columns: options.columns }, rows, (text3, name2) => {
7491
+ if (name2 === "return" || name2 === "enter") return { pick: current, summary: choices[current] ?? "" };
7492
+ const next = move(current, choices.length, text3, name2);
7493
7493
  if (next === null || next === current) return null;
7494
7494
  current = next;
7495
7495
  return "redraw";
@@ -7503,22 +7503,22 @@ function multiSelectMenu(input, output, question, choices, options = {}) {
7503
7503
  const pad2 = Math.max(...choices.map((c) => c.length));
7504
7504
  const label = (i) => {
7505
7505
  const tag = options.tags?.[i];
7506
- const name = choices[i] ?? "";
7507
- if (!tag) return name;
7508
- const cols = options.columns?.() ?? Infinity;
7506
+ const name2 = choices[i] ?? "";
7507
+ if (!tag) return name2;
7508
+ const cols2 = options.columns?.() ?? Infinity;
7509
7509
  const grey = options.color ? `${GREY}${tag}${GREY_OFF}` : tag;
7510
- if (6 + pad2 + 3 + tag.length <= cols) return `${name.padEnd(pad2)} ${grey}`;
7511
- if (6 + name.length + 1 + tag.length <= cols) return `${name} ${grey}`;
7512
- return name;
7510
+ if (6 + pad2 + 3 + tag.length <= cols2) return `${name2.padEnd(pad2)} ${grey}`;
7511
+ if (6 + name2.length + 1 + tag.length <= cols2) return `${name2} ${grey}`;
7512
+ return name2;
7513
7513
  };
7514
7514
  const rows = () => choices.map((_, i) => `${i === current ? pointer : " "} [${ticked[i] ? "x" : " "}] ${label(i)}`);
7515
7515
  const head = { question, note: options.note, hint: options.hint ?? MULTI_HINT, columns: options.columns };
7516
- return runMenu(input, output, head, rows, (text3, name) => {
7517
- if (name === "return" || name === "enter") {
7516
+ return runMenu(input, output, head, rows, (text3, name2) => {
7517
+ if (name2 === "return" || name2 === "enter") {
7518
7518
  const picks = choices.flatMap((_, i) => ticked[i] ? [i] : []);
7519
7519
  return { pick: picks, summary: picks.map((i) => choices[i]).join(", ") || "none" };
7520
7520
  }
7521
- if (name === "space") {
7521
+ if (name2 === "space") {
7522
7522
  ticked[current] = !ticked[current];
7523
7523
  return "redraw";
7524
7524
  }
@@ -7527,7 +7527,7 @@ function multiSelectMenu(input, output, question, choices, options = {}) {
7527
7527
  ticked[current] = !ticked[current];
7528
7528
  return "redraw";
7529
7529
  }
7530
- const next = move(current, choices.length, text3, name);
7530
+ const next = move(current, choices.length, text3, name2);
7531
7531
  if (next === null || next === current) return null;
7532
7532
  current = next;
7533
7533
  return "redraw";
@@ -7553,9 +7553,9 @@ function listenForEnter(input, onEnter, onCancel) {
7553
7553
  stop();
7554
7554
  onCancel();
7555
7555
  };
7556
- const onKeypress = (_text, key) => {
7557
- if (key?.ctrl && key.name === "c") cancel();
7558
- else if (key?.name === "return" || key?.name === "enter") onEnter();
7556
+ const onKeypress = (_text, key2) => {
7557
+ if (key2?.ctrl && key2.name === "c") cancel();
7558
+ else if (key2?.name === "return" || key2?.name === "enter") onEnter();
7559
7559
  };
7560
7560
  try {
7561
7561
  emitKeypressEvents(input);
@@ -7593,10 +7593,10 @@ function readPaste(input, output, question) {
7593
7593
  else reject(outcome.error);
7594
7594
  };
7595
7595
  const done = () => finish({ text: lines.join("\n").trim() });
7596
- const onKeypress = (_text, key) => {
7597
- if (key?.name === "paste-start") pasting = true;
7598
- else if (key?.name === "paste-end") pasting = false;
7599
- else if (settle && key?.name !== "return" && key?.name !== "enter") {
7596
+ const onKeypress = (_text, key2) => {
7597
+ if (key2?.name === "paste-start") pasting = true;
7598
+ else if (key2?.name === "paste-end") pasting = false;
7599
+ else if (settle && key2?.name !== "return" && key2?.name !== "enter") {
7600
7600
  clearTimeout(settle);
7601
7601
  settle = void 0;
7602
7602
  }
@@ -7868,7 +7868,8 @@ var COMMAND_OPTIONS = {
7868
7868
  list: { type: "string" },
7869
7869
  batch: { type: "string" },
7870
7870
  "no-wait": { type: "boolean" },
7871
- force: { type: "boolean" }
7871
+ force: { type: "boolean" },
7872
+ for: { type: "string" }
7872
7873
  },
7873
7874
  search: { research: { type: "boolean" }, limit: { type: "string" } },
7874
7875
  connections: { all: { type: "boolean" } },
@@ -7946,7 +7947,7 @@ function parseCommandLine(argv) {
7946
7947
  return { command: null, args: [], flags: strictParse(argv, { ...GLOBAL_OPTIONS, ...SETUP_OPTIONS }).values };
7947
7948
  }
7948
7949
  let words = 1;
7949
- let name = first2;
7950
+ let name2 = first2;
7950
7951
  if (TWO_WORD.has(first2)) {
7951
7952
  const second = positionals[1];
7952
7953
  if (first2 === "skills" && second !== "add") {
@@ -7957,14 +7958,14 @@ function parseCommandLine(argv) {
7957
7958
  );
7958
7959
  }
7959
7960
  if (second === void 0) throw usageError(`\`amdahl ${first2}\` needs a subcommand.`);
7960
- name = `${first2} ${second}`;
7961
+ name2 = `${first2} ${second}`;
7961
7962
  words = 2;
7962
7963
  }
7963
- name = ALIASES[name] ?? name;
7964
- const spec = COMMAND_OPTIONS[name];
7964
+ name2 = ALIASES[name2] ?? name2;
7965
+ const spec = COMMAND_OPTIONS[name2];
7965
7966
  if (!spec) throw usageError(`Unknown command \`${positionals.slice(0, words).join(" ")}\`.`, `Run \`${amdahlCommand("--help")}\` to see the commands.`);
7966
7967
  const strict = strictParse(argv, { ...GLOBAL_OPTIONS, ...spec });
7967
- return { command: name, args: strict.positionals.slice(words), flags: strict.values };
7968
+ return { command: name2, args: strict.positionals.slice(words), flags: strict.values };
7968
7969
  }
7969
7970
  function strictParse(argv, options) {
7970
7971
  try {
@@ -8006,6 +8007,10 @@ What you can do:
8006
8007
  amdahl optimize --list drafts.csv
8007
8008
  Rewrite a whole list in one batch; results go
8008
8009
  to drafts.optimized.csv
8010
+ amdahl optimize --list drafts.csv --for lemlist
8011
+ Also write drafts-lemlist.csv, a file your
8012
+ sequencer imports, and say how (Instantly,
8013
+ Smartlead, lemlist, HeyReach, Apollo and more)
8009
8014
  amdahl search "<question>" Ask about your customers, calls and deals
8010
8015
  amdahl connect hubspot Add a CRM or call recorder in the console
8011
8016
  (amdahl connections lists what is connected)
@@ -8032,13 +8037,20 @@ Commands:
8032
8037
  --json prints {ok, file, result}: the message is .result.message
8033
8038
  and the run id is .result.run_id.
8034
8039
  optimize --list <file.csv|file.jsonl> [--no-wait] [--batch <id>] [--force]
8035
- [the optimize flags above, for every message]
8040
+ [--for <tool>] [the optimize flags above, for every message]
8036
8041
  A CSV needs a message column, and may have item_id, channel,
8037
8042
  evidence, on_unsupported, facts and rules. Any other column is
8038
8043
  copied to the results as it is. --batch <id> picks up a batch
8039
8044
  queued earlier, with the same list. --force replaces an existing
8040
8045
  results file. In the results CSV, a cell that starts with =, +, -
8041
8046
  or @ (a phone number, say) gets a ' in front: it is no formula.
8047
+ --for <tool> a CSV list only: also write the messages Amdahl wrote
8048
+ as a CSV that tool imports (<list>-<tool>.csv), and say
8049
+ how to import it. Tools: instantly, smartlead, lemlist,
8050
+ heyreach, reply_io, apollo, outreach, salesloft,
8051
+ hubspot, lgm, woodpecker, other (any tool that imports
8052
+ a CSV). lemlist, reply_io and other take both channels,
8053
+ so add --channel email|linkedin.
8042
8054
  search "<question>" [--research] [--limit <n>]
8043
8055
  --research ask for a research job: a deeper, cited answer (needs
8044
8056
  a Customer agent key, amdahl keys create --preset
@@ -8104,7 +8116,7 @@ Global options:
8104
8116
  `;
8105
8117
 
8106
8118
  // src/version.ts
8107
- var VERSION = "0.4.1";
8119
+ var VERSION = "0.4.2";
8108
8120
 
8109
8121
  // src/api.ts
8110
8122
  var CLIENT_HEADER = {
@@ -8180,20 +8192,20 @@ function parseErrorBody(errorBody, statusCode) {
8180
8192
  }
8181
8193
  var PLATFORM = "/api/platform/v1";
8182
8194
  var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
8183
- function assertUuid(name, value) {
8195
+ function assertUuid(name2, value) {
8184
8196
  if (typeof value !== "string" || value.length === 0) {
8185
8197
  throw new Error(
8186
- `mcpKeys client: ${name} must be a non-empty string (got ${typeof value === "string" ? "empty string" : String(value)})`
8198
+ `mcpKeys client: ${name2} must be a non-empty string (got ${typeof value === "string" ? "empty string" : String(value)})`
8187
8199
  );
8188
8200
  }
8189
8201
  const lowered = value.toLowerCase();
8190
8202
  if (lowered === "undefined" || lowered === "null") {
8191
8203
  throw new Error(
8192
- `mcpKeys client: ${name} is the literal string '${value}'. Fix the caller rather than relaxing this guard.`
8204
+ `mcpKeys client: ${name2} is the literal string '${value}'. Fix the caller rather than relaxing this guard.`
8193
8205
  );
8194
8206
  }
8195
8207
  if (!UUID_RE.test(value)) {
8196
- throw new Error(`mcpKeys client: ${name} must be a UUID (got '${value}')`);
8208
+ throw new Error(`mcpKeys client: ${name2} must be a UUID (got '${value}')`);
8197
8209
  }
8198
8210
  }
8199
8211
  function createAmdahlClient(config) {
@@ -9014,9 +9026,9 @@ async function browserSignIn(ctx) {
9014
9026
  const client = apiClient(ctx, { source: "profile", token: secrets.access_token });
9015
9027
  const me = await call(() => client.cli.whoami());
9016
9028
  const ws = me.workspace ?? { id: me.business_id, name: me.business_id, slug: me.business_id };
9017
- const name = explicitProfile ?? (PROFILE_NAME.test(ws.slug) ? ws.slug : "default");
9018
- await ctx.secrets().set(keychainAccount(ctx.apiUrl, name), secrets);
9019
- ctx.config.profiles[name] = {
9029
+ const name2 = explicitProfile ?? (PROFILE_NAME.test(ws.slug) ? ws.slug : "default");
9030
+ await ctx.secrets().set(keychainAccount(ctx.apiUrl, name2), secrets);
9031
+ ctx.config.profiles[name2] = {
9020
9032
  api_url: ctx.apiUrl,
9021
9033
  user_id: me.user_id,
9022
9034
  email: me.email ?? null,
@@ -9024,11 +9036,11 @@ async function browserSignIn(ctx) {
9024
9036
  scopes: me.scopes,
9025
9037
  created_at: new Date(io.now()).toISOString()
9026
9038
  };
9027
- ctx.config.default_profile = name;
9039
+ ctx.config.default_profile = name2;
9028
9040
  ctx.saveConfig();
9029
- ctx.profileName = name;
9030
- ctx.profile = ctx.config.profiles[name] ?? null;
9031
- return { profile: name, me, workspace: ws };
9041
+ ctx.profileName = name2;
9042
+ ctx.profile = ctx.config.profiles[name2] ?? null;
9043
+ return { profile: name2, me, workspace: ws };
9032
9044
  } finally {
9033
9045
  stopKeys();
9034
9046
  loopback.close();
@@ -9067,10 +9079,10 @@ async function logout(ctx) {
9067
9079
  }
9068
9080
  const notRevoked = [];
9069
9081
  const store = ctx.secrets();
9070
- for (const name of names) {
9071
- const profile = config.profiles[name];
9082
+ for (const name2 of names) {
9083
+ const profile = config.profiles[name2];
9072
9084
  if (!profile) continue;
9073
- const account = keychainAccount(profile.api_url, name);
9085
+ const account = keychainAccount(profile.api_url, name2);
9074
9086
  const secrets = await store.get(account);
9075
9087
  if (secrets) {
9076
9088
  let ok = false;
@@ -9082,10 +9094,10 @@ async function logout(ctx) {
9082
9094
  } catch {
9083
9095
  ok = false;
9084
9096
  }
9085
- if (!ok) notRevoked.push(name);
9097
+ if (!ok) notRevoked.push(name2);
9086
9098
  }
9087
9099
  await store.delete(account);
9088
- delete config.profiles[name];
9100
+ delete config.profiles[name2];
9089
9101
  }
9090
9102
  if (config.default_profile && !config.profiles[config.default_profile]) {
9091
9103
  config.default_profile = Object.keys(config.profiles)[0] ?? null;
@@ -9143,7 +9155,7 @@ async function authToken(ctx) {
9143
9155
  // src/ci.ts
9144
9156
  var isSet = (value) => Boolean(value) && value !== "false" && value !== "0";
9145
9157
  function ciVariable(env) {
9146
- const named = ["CI", "JENKINS_URL", "TF_BUILD", "CODEBUILD_BUILD_ID", "TEAMCITY_VERSION", "GITHUB_ACTIONS", "GITLAB_CI", "BUILDKITE", "CIRCLECI"].find((name) => isSet(env[name]));
9158
+ const named = ["CI", "JENKINS_URL", "TF_BUILD", "CODEBUILD_BUILD_ID", "TEAMCITY_VERSION", "GITHUB_ACTIONS", "GITLAB_CI", "BUILDKITE", "CIRCLECI"].find((name2) => isSet(env[name2]));
9147
9159
  if (named) return named;
9148
9160
  return isSet(env.BUILD_NUMBER) && isSet(env.JENKINS_HOME) ? "BUILD_NUMBER with JENKINS_HOME" : null;
9149
9161
  }
@@ -9156,10 +9168,10 @@ import { dirname as dirname2, join as join4, relative, sep } from "path";
9156
9168
  import { randomBytes as randomBytes2 } from "crypto";
9157
9169
  import { chmodSync as chmodSync3, lstatSync, mkdirSync as mkdirSync2, mkdtempSync, readdirSync, readFileSync as readFileSync3, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "fs";
9158
9170
  import { dirname, join as join3 } from "path";
9159
- function skillDirs(targets, name) {
9171
+ function skillDirs(targets, name2) {
9160
9172
  const dirs = [];
9161
- if (targets.claude) dirs.push(join3(targets.base, ".claude", "skills", name));
9162
- if (targets.agents) dirs.push(join3(targets.base, ".agents", "skills", name));
9173
+ if (targets.claude) dirs.push(join3(targets.base, ".claude", "skills", name2));
9174
+ if (targets.agents) dirs.push(join3(targets.base, ".agents", "skills", name2));
9163
9175
  return dirs;
9164
9176
  }
9165
9177
  var message = (err) => err instanceof Error ? err.message : String(err);
@@ -9253,24 +9265,24 @@ function planInstall(dirs, payload) {
9253
9265
  return { path, action: current === null ? "wrote" : current.equals(payload.body) ? "unchanged" : "replaced" };
9254
9266
  });
9255
9267
  }
9256
- function refuseClashes(plan, name, force) {
9268
+ function refuseClashes(plan, name2, force) {
9257
9269
  const clashes = plan.filter((p) => p.action === "replaced").map((p) => p.path);
9258
9270
  if (clashes.length > 0 && !force) {
9259
9271
  throw new CliError(
9260
9272
  "skill_exists",
9261
- `A different ${name} skill is already at ${clashes.join(" and ")}.`,
9273
+ `A different ${name2} skill is already at ${clashes.join(" and ")}.`,
9262
9274
  EXIT.general,
9263
9275
  "Nothing was written. Run again with --force to replace it."
9264
9276
  );
9265
9277
  }
9266
9278
  }
9267
- function stage(target, name, archive, staged) {
9279
+ function stage(target, name2, archive, staged) {
9268
9280
  const s = { target, temp: "" };
9269
9281
  staged.push(s);
9270
9282
  refuseLinks(target);
9271
9283
  s.createdParent = mkdirSync2(dirname(target), { recursive: true }) ?? void 0;
9272
9284
  refuseLinks(target);
9273
- s.temp = mkdtempSync(join3(dirname(target), `.${name}.amdahl-tmp-`));
9285
+ s.temp = mkdtempSync(join3(dirname(target), `.${name2}.amdahl-tmp-`));
9274
9286
  chmodSync3(s.temp, 493);
9275
9287
  for (const dir of archive.dirs) mkdirSync2(join3(s.temp, dir));
9276
9288
  for (const file of archive.files) writeFileSync2(join3(s.temp, file.path), file.bytes, { flag: "wx", mode: file.mode });
@@ -9290,14 +9302,14 @@ function rollBack(staged) {
9290
9302
  if (s.createdParent) rmSync2(s.createdParent, { recursive: true, force: true });
9291
9303
  }
9292
9304
  }
9293
- function writeFolders(plan, name, archive) {
9305
+ function writeFolders(plan, name2, archive) {
9294
9306
  const staged = [];
9295
9307
  let current = "";
9296
9308
  try {
9297
9309
  for (const p of plan) {
9298
9310
  if (p.action === "unchanged") continue;
9299
9311
  current = p.path;
9300
- stage(p.path, name, archive, staged);
9312
+ stage(p.path, name2, archive, staged);
9301
9313
  }
9302
9314
  for (const s of staged) {
9303
9315
  current = s.target;
@@ -9334,8 +9346,8 @@ function writeFiles(plan, body) {
9334
9346
  written.push(p.path);
9335
9347
  }
9336
9348
  }
9337
- function writeInstall(io, plan, name, payload) {
9338
- io.uninterruptible(() => payload.type === "archive" ? writeFolders(plan, name, payload.archive) : writeFiles(plan, payload.body));
9349
+ function writeInstall(io, plan, name2, payload) {
9350
+ io.uninterruptible(() => payload.type === "archive" ? writeFolders(plan, name2, payload.archive) : writeFiles(plan, payload.body));
9339
9351
  }
9340
9352
 
9341
9353
  // src/commands/skills-guide.ts
@@ -9566,8 +9578,8 @@ function catalogEntries(body) {
9566
9578
  }));
9567
9579
  }
9568
9580
  function findConnector(entries, wanted) {
9569
- const key = wanted.toLowerCase().replace(/[\s-]+/g, "_");
9570
- return entries.find((e) => e.type.toLowerCase() === key || e.name.toLowerCase().replace(/[\s-]+/g, "_") === key);
9581
+ const key2 = wanted.toLowerCase().replace(/[\s-]+/g, "_");
9582
+ return entries.find((e) => e.type.toLowerCase() === key2 || e.name.toLowerCase().replace(/[\s-]+/g, "_") === key2);
9571
9583
  }
9572
9584
  async function connect(ctx, args) {
9573
9585
  if (args.length > 1) throw usageError("Name one connector at a time.", `Usage: ${amdahlCommand("connect [<connector>] [--no-browser]")}`);
@@ -9635,11 +9647,11 @@ function connectionRow(c) {
9635
9647
  const connector = record(c.connector);
9636
9648
  const type = field(connector?.name) || field(c.connector_type);
9637
9649
  const label = field(c.name);
9638
- const name = label && label !== type ? `${type} (${label})` : type || label;
9650
+ const name2 = label && label !== type ? `${type} (${label})` : type || label;
9639
9651
  const health = healthOf(c);
9640
9652
  const synced = day(c.last_synced_at);
9641
9653
  return {
9642
- name: clip(name, 32),
9654
+ name: clip(name2, 32),
9643
9655
  kind: field(connector?.category),
9644
9656
  health: HEALTH[health] ?? health,
9645
9657
  synced: synced ? `synced ${synced}` : "never synced"
@@ -9661,7 +9673,7 @@ ${connectLine()}`);
9661
9673
  return EXIT.ok;
9662
9674
  }
9663
9675
  const rows = list2.map(connectionRow);
9664
- const width = (key) => Math.max(...rows.map((r) => [...r[key]].length));
9676
+ const width = (key2) => Math.max(...rows.map((r) => [...r[key2]].length));
9665
9677
  const [w1, w2, w3] = [width("name"), width("kind"), width("health")];
9666
9678
  const pad2 = (s, w) => s + " ".repeat(Math.max(0, w - [...s].length));
9667
9679
  const lines = rows.map((r) => `${pad2(r.name, w1)} ${pad2(r.kind, w2)} ${pad2(r.health, w3)} ${r.synced}`.trimEnd());
@@ -9794,13 +9806,13 @@ async function sent(ctx, args) {
9794
9806
  throw usageError("--sent-at must be a time with a time zone, for example 2026-11-12T09:30:00Z.");
9795
9807
  }
9796
9808
  const item = { run_id: id, provider, channel, sent_as: sentAs, sent_at: sentAt };
9797
- for (const [flag, [key, max]] of Object.entries(PROVIDER_IDS)) {
9809
+ for (const [flag, [key2, max]] of Object.entries(PROVIDER_IDS)) {
9798
9810
  const value = text(flag, str(flags[flag]), max);
9799
9811
  if (value === void 0) continue;
9800
9812
  if (EMAIL_WHOLE_VALUE.test(value.trim()) || LINKEDIN_PROFILE.test(value.trim())) {
9801
9813
  throw usageError(`--${flag} is the provider's own id, not an email address or a LinkedIn profile URL.`, "Amdahl stores a person only as a hash: give the address with --recipient.");
9802
9814
  }
9803
- item[key] = value;
9815
+ item[key2] = value;
9804
9816
  }
9805
9817
  const sendId = typeof item.provider_send_id === "string" ? item.provider_send_id : void 0;
9806
9818
  if (provider === "gmail" && sendId !== void 0 && !BRACKETED_MESSAGE_ID.test(sendId.trim())) {
@@ -10246,9 +10258,9 @@ async function waitForDecision(ctx, client, req) {
10246
10258
  }
10247
10259
  }
10248
10260
  async function keysCreate(ctx) {
10249
- const name = str(ctx.flags.name)?.trim();
10250
- if (!name) throw usageError("--name is required.", `Example: ${amdahlCommand('keys create --name "CI pipeline"')}`);
10251
- if (name.length > 80) throw usageError("--name must be at most 80 characters.");
10261
+ const name2 = str(ctx.flags.name)?.trim();
10262
+ if (!name2) throw usageError("--name is required.", `Example: ${amdahlCommand('keys create --name "CI pipeline"')}`);
10263
+ if (name2.length > 80) throw usageError("--name must be at most 80 characters.");
10252
10264
  const preset = str(ctx.flags.preset) ?? "read-only";
10253
10265
  const bundle = PRESET_BUNDLES[preset];
10254
10266
  if (!bundle) throw usageError(`--preset must be one of: ${Object.keys(PRESET_BUNDLES).join(", ")}.`);
@@ -10257,22 +10269,22 @@ async function keysCreate(ctx) {
10257
10269
  if (!days) throw usageError(`--expires must be one of: ${Object.keys(EXPIRES_DAYS).join(", ")}.`);
10258
10270
  const credential = await requireOAuthCredential(ctx);
10259
10271
  const client = apiClient(ctx, credential);
10260
- const key = generateKey();
10272
+ const key2 = generateKey();
10261
10273
  const req = await call(
10262
10274
  () => client.cli.createKeyRequest({
10263
10275
  action: "create",
10264
- name,
10276
+ name: name2,
10265
10277
  bundle_name: bundle,
10266
10278
  expires_in_days: days,
10267
- key_hash: key.hash,
10268
- key_prefix: key.prefix,
10279
+ key_hash: key2.hash,
10280
+ key_prefix: key2.prefix,
10269
10281
  device_name: ctx.io.hostname.slice(0, 120)
10270
10282
  })
10271
10283
  );
10272
- announce(ctx, req, `create the key "${name}"`);
10284
+ announce(ctx, req, `create the key "${name2}"`);
10273
10285
  const state = await waitForDecision(ctx, client, req);
10274
10286
  const minted = state.key;
10275
- if (!minted || minted.key_prefix !== key.prefix) {
10287
+ if (!minted || minted.key_prefix !== key2.prefix) {
10276
10288
  throw new CliError(
10277
10289
  "key_mismatch",
10278
10290
  "The approved key does not match the one this terminal generated. Nothing was printed.",
@@ -10281,7 +10293,7 @@ async function keysCreate(ctx) {
10281
10293
  );
10282
10294
  }
10283
10295
  ctx.out.info(`Key created: ${minted.name} (${minted.key_prefix}...). Copy it now: it is shown once and stored nowhere.`);
10284
- ctx.out.result({ ok: true, secret: key.secret, key: minted }, key.secret);
10296
+ ctx.out.result({ ok: true, secret: key2.secret, key: minted }, key2.secret);
10285
10297
  return EXIT.ok;
10286
10298
  }
10287
10299
  async function workspaceId(ctx, client, fromProfile) {
@@ -10363,7 +10375,354 @@ function sentLines(runId2, lead = "Sent it?") {
10363
10375
 
10364
10376
  // src/commands/batch.ts
10365
10377
  import { existsSync as existsSync5, writeFileSync as writeFileSync4 } from "fs";
10366
- import { basename as basename2, dirname as dirname4, extname, join as join7 } from "path";
10378
+ import { basename as basename3, dirname as dirname4, extname, join as join7 } from "path";
10379
+
10380
+ // src/send-to.ts
10381
+ import { basename as basename2 } from "path";
10382
+ var SEND_TO_IDS = ["instantly", "smartlead", "lemlist", "heyreach", "reply_io", "apollo", "outreach", "salesloft", "hubspot", "lgm", "woodpecker", "other"];
10383
+ var braces = (column) => `{{${column}}}`;
10384
+ var name = (column) => column;
10385
+ var single = (column) => `{${column}}`;
10386
+ var PASTE = "Paste into your step";
10387
+ var MENU = "Add them from the variable menu in your step";
10388
+ var cols = (channel, to) => channel === "email" ? `amdahl_subject and amdahl_message ${to}` : `amdahl_message ${to}`;
10389
+ var key = (channel, email, linkedin) => channel === "linkedin" ? linkedin : email;
10390
+ var SEND_TO_PRESETS = [
10391
+ {
10392
+ id: "instantly",
10393
+ label: "Instantly",
10394
+ channels: ["email"],
10395
+ headers: { company: "company_name" },
10396
+ where: "In your campaign, open Leads and choose Upload CSV.",
10397
+ match: (c) => `Map email to Email, and ${cols(c, "to custom variables")}.`,
10398
+ insert: PASTE,
10399
+ variable: braces
10400
+ },
10401
+ {
10402
+ id: "smartlead",
10403
+ label: "Smartlead",
10404
+ channels: ["email"],
10405
+ headers: { company: "company_name" },
10406
+ where: "Engage > Campaigns > your campaign > Import Leads > Import CSV.",
10407
+ match: (c) => `Map email to Email, and ${cols(c, "to custom variables")}.`,
10408
+ insert: PASTE,
10409
+ variable: braces
10410
+ },
10411
+ {
10412
+ id: "lemlist",
10413
+ label: "lemlist",
10414
+ channels: ["email", "linkedin"],
10415
+ headers: { first_name: "firstName", last_name: "lastName", company: "companyName", linkedin_url: "linkedinUrl" },
10416
+ where: "In your campaign, open Leads list > Import new leads > CSV.",
10417
+ match: (c) => `${key(c, "email", "linkedinUrl")} and the name columns map on their own. ${cols(c, "become custom variables")}.`,
10418
+ insert: PASTE,
10419
+ maxValue: 2e3,
10420
+ variable: braces
10421
+ },
10422
+ {
10423
+ id: "heyreach",
10424
+ label: "HeyReach",
10425
+ channels: ["linkedin"],
10426
+ needsNames: true,
10427
+ where: "Leads > Add Leads > Import from CSV.",
10428
+ match: () => "Map linkedin_url to the profile URL. Add a custom variable from amdahl_message.",
10429
+ insert: "Add amdahl_message from the Add variable menu, or paste",
10430
+ note: "Set a fallback message on the step: HeyReach sends it when a lead has no value. Its docs do not show the brace syntax, so use the Add variable menu if the pasted text does not turn orange.",
10431
+ variable: single
10432
+ },
10433
+ {
10434
+ id: "reply_io",
10435
+ label: "Reply.io",
10436
+ channels: ["email", "linkedin"],
10437
+ where: "Add contacts > Import from a CSV file.",
10438
+ match: (c) => `Map ${key(c, "email to Email", "linkedin_url to LinkedIn")}. Create a custom field for ${c === "email" ? "each of amdahl_subject and amdahl_message" : "amdahl_message"}.`,
10439
+ insert: PASTE,
10440
+ variable: braces
10441
+ },
10442
+ {
10443
+ id: "apollo",
10444
+ label: "Apollo",
10445
+ channels: ["email"],
10446
+ where: "Import a CSV of contacts.",
10447
+ match: () => "Map email to Email. Create a custom contact field for amdahl_subject and one for amdahl_message, then map to them.",
10448
+ insert: MENU,
10449
+ variable: name
10450
+ },
10451
+ {
10452
+ id: "outreach",
10453
+ label: "Outreach",
10454
+ channels: ["email"],
10455
+ where: "Actions > Bulk Create > Prospects.",
10456
+ match: () => "Map email to Email, amdahl_subject to Custom 1 and amdahl_message to Custom 2.",
10457
+ insert: PASTE,
10458
+ variable: (column) => column === "amdahl_subject" ? "{{custom1}}" : "{{custom2}}"
10459
+ },
10460
+ {
10461
+ id: "salesloft",
10462
+ label: "Salesloft",
10463
+ channels: ["email"],
10464
+ where: "People > Create People > Import from CSV.",
10465
+ match: () => "Map email to Email Address. An admin first adds a person field for amdahl_subject and one for amdahl_message, then you map to them.",
10466
+ insert: MENU,
10467
+ variable: name
10468
+ },
10469
+ {
10470
+ id: "hubspot",
10471
+ label: "HubSpot",
10472
+ channels: ["email"],
10473
+ where: "Contacts > Import, then upload the CSV.",
10474
+ match: () => "Map email to Email. Choose Create new property for amdahl_subject and for amdahl_message.",
10475
+ insert: "Add them with Personalize in your sequence email",
10476
+ note: "HubSpot sequences can drop line breaks from a multi-line property, so check one email before you enroll.",
10477
+ variable: name
10478
+ },
10479
+ {
10480
+ id: "lgm",
10481
+ label: "La Growth Machine",
10482
+ channels: ["linkedin"],
10483
+ where: "Leads > Import leads > Import CSV.",
10484
+ match: () => "Map linkedin_url to the profile URL. Import amdahl_message as a custom attribute.",
10485
+ insert: "Add it from the variable menu in your step",
10486
+ note: "La Growth Machine does not document the exact form of a custom attribute, so copy it from its menu.",
10487
+ variable: name
10488
+ },
10489
+ {
10490
+ id: "woodpecker",
10491
+ label: "Woodpecker",
10492
+ channels: ["email"],
10493
+ where: "In your campaign, choose Add prospects > Import.",
10494
+ match: () => "Map email to Email, amdahl_subject to Snippet 1 and amdahl_message to Snippet 2.",
10495
+ insert: "Add them with the {{ }} button in your step",
10496
+ variable: (column) => column === "amdahl_subject" ? "Snippet 1" : "Snippet 2"
10497
+ },
10498
+ {
10499
+ id: "other",
10500
+ label: "Other (any tool)",
10501
+ channels: ["email", "linkedin"],
10502
+ where: "Use the CSV import for leads in your tool.",
10503
+ match: (c) => `${key(c, "Map email to your email field", "Map linkedin_url to your profile URL field")}, and ${cols(c, "to custom fields")}.`,
10504
+ insert: "Paste into your step (most tools use this form)",
10505
+ variable: braces
10506
+ }
10507
+ ];
10508
+ function presetFor(value) {
10509
+ const id = value.trim().toLowerCase().replace(/-/g, "_");
10510
+ return SEND_TO_PRESETS.find((p) => p.id === id);
10511
+ }
10512
+ var subjectColumn = "amdahl_subject";
10513
+ var messageColumn = "amdahl_message";
10514
+ var LEAD_FIELDS = [
10515
+ { key: "email", names: ["email", "email_address", "work_email", "e_mail", "contact_email", "person_email", "business_email"] },
10516
+ { key: "first", names: ["first_name", "firstname", "first", "given_name", "contact_first_name"] },
10517
+ { key: "last", names: ["last_name", "lastname", "last", "surname", "family_name", "contact_last_name"] },
10518
+ { key: "name", names: ["name", "full_name", "contact_name", "person_name", "contact"] },
10519
+ { key: "company", names: ["company", "company_name", "account", "account_name", "organization", "organisation", "organization_name"] },
10520
+ { key: "linkedin", names: ["linkedin", "linkedin_url", "linkedin_profile", "person_linkedin_url", "li_url", "linkedin_profile_url"] }
10521
+ ];
10522
+ var norm = (h) => h.replace(/^\uFEFF/, "").trim().toLowerCase().replace(/[^\p{L}\p{N}]+/gu, "_").replace(/^_+|_+$/g, "");
10523
+ function autoMap(headers) {
10524
+ const n = headers.map(norm);
10525
+ const map = {};
10526
+ for (const f of LEAD_FIELDS) map[f.key] = n.findIndex((h) => f.names.includes(h));
10527
+ return map;
10528
+ }
10529
+ function leadOf(cells, map) {
10530
+ const cell3 = (k) => map[k] >= 0 ? (cells[map[k]] ?? "").trim() : "";
10531
+ const first2 = cell3("first");
10532
+ return { cells, email: cell3("email"), name: cell3("name") || [first2, cell3("last")].filter(Boolean).join(" "), company: cell3("company"), linkedin: cell3("linkedin") };
10533
+ }
10534
+ function stripUnverifiedMarkers(text3) {
10535
+ const open2 = "<unverified>";
10536
+ const close = "</unverified>";
10537
+ if (!text3.includes(open2) && !text3.includes(close)) return text3;
10538
+ return text3.replace(/<unverified>([\s\S]*?)<\/unverified>/g, "$1").split(open2).join("").split(close).join("");
10539
+ }
10540
+ function splitSubject(text3) {
10541
+ const m = text3.match(/^\s*subject\s*:\s*(.*)\r?\n/i);
10542
+ if (!m) return { subject: null, body: text3.trim() };
10543
+ return { subject: m[1]?.trim() || null, body: text3.slice(m[0].length).trim() };
10544
+ }
10545
+ function writtenOf(item) {
10546
+ const result = item?.result && typeof item.result === "object" && !Array.isArray(item.result) ? item.result : null;
10547
+ if (item?.status === "failed" || result?.ok === false) return { kind: "failed" };
10548
+ if (!item || item.status !== "done" || !result) return { kind: "unwritten" };
10549
+ if (result.outcome === "needs_input") return { kind: "needs_input" };
10550
+ if (typeof result.message !== "string") return { kind: "unwritten" };
10551
+ const { subject, body } = splitSubject(stripUnverifiedMarkers(result.message));
10552
+ return { kind: "written", subject: subject ?? "", body };
10553
+ }
10554
+ function cell(value) {
10555
+ return /[",\n\r]/.test(value) ? `"${value.replace(/"/g, '""')}"` : value;
10556
+ }
10557
+ var AMDAHL_INPUT_COLUMNS = ["message", "channel", "evidence", "on_unsupported", "facts", "rules", "item_id"];
10558
+ var SUBJECT_HEADERS = ["subject", "subject_line", "email_subject", "subjectline", "betreff", "objet", "sujet", "asunto", "oggetto", "onderwerp"];
10559
+ var CHANNEL_HEADERS = ["channel", "type", "medium"];
10560
+ var ADDRESS = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
10561
+ var isDraftHeader = (h) => ["message", "draft", "email_copy"].includes(h) || /(^|_)body(_html|_text)?$/.test(h);
10562
+ function draftColumn(headers, rows) {
10563
+ const n = headers.map(norm);
10564
+ const subjectCol = n.findIndex((h) => SUBJECT_HEADERS.includes(h));
10565
+ const channelCol = n.findIndex((h) => CHANNEL_HEADERS.includes(h));
10566
+ const onlyAddresses = (c) => {
10567
+ const cells = rows.map((r) => (r[c] ?? "").trim()).filter(Boolean);
10568
+ return cells.length > 0 && cells.every((v) => ADDRESS.test(v));
10569
+ };
10570
+ return n.findIndex((h, i) => isDraftHeader(h) && i !== subjectCol && i !== channelCol && !onlyAddresses(i));
10571
+ }
10572
+ function snakeHeader(header) {
10573
+ return header.normalize("NFKD").replace(/[\u0300-\u036f]/g, "").toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "");
10574
+ }
10575
+ function sendToFileName(listPath, preset) {
10576
+ const list2 = basename2(listPath).replace(/\.(csv|tsv|txt)$/i, "");
10577
+ const base = snakeHeader(list2).replace(/_/g, "-") || "leads";
10578
+ return `${base}-${preset.id.replace(/_/g, "-")}.csv`;
10579
+ }
10580
+ function namesOf(lead, map) {
10581
+ const at = (field3) => map[field3] >= 0 ? (lead.cells[map[field3]] ?? "").trim() : "";
10582
+ const parts = lead.name.split(/\s+/).filter(Boolean);
10583
+ return { first: at("first") || parts[0] || "", last: at("last") || (map.last >= 0 ? "" : parts.slice(1).join(" ")) };
10584
+ }
10585
+ function hasContact(lead, map, channel, preset) {
10586
+ if (channel === "email") return Boolean(lead.email);
10587
+ if (!lead.linkedin) return false;
10588
+ if (!preset.needsNames) return true;
10589
+ const { first: first2, last } = namesOf(lead, map);
10590
+ return Boolean(first2 && last);
10591
+ }
10592
+ function identityColumns(map, preset) {
10593
+ const used = /* @__PURE__ */ new Set();
10594
+ const columns = [];
10595
+ const head = (k) => preset.headers?.[k] ?? k;
10596
+ const take = (...fields) => fields.forEach((f) => map[f] >= 0 && used.add(map[f]));
10597
+ if (map.email >= 0) {
10598
+ take("email");
10599
+ columns.push({ name: "email", value: (_, l) => l.email });
10600
+ }
10601
+ if (map.name >= 0 || map.first >= 0) {
10602
+ take("first", "last");
10603
+ columns.push({ name: head("first_name"), value: (_, l) => namesOf(l, map).first });
10604
+ columns.push({ name: head("last_name"), value: (_, l) => namesOf(l, map).last });
10605
+ }
10606
+ if (map.company >= 0) {
10607
+ take("company");
10608
+ columns.push({ name: head("company"), value: (_, l) => l.company });
10609
+ }
10610
+ if (map.linkedin >= 0) {
10611
+ take("linkedin");
10612
+ columns.push({ name: head("linkedin_url"), value: (_, l) => l.linkedin });
10613
+ }
10614
+ return { columns, used };
10615
+ }
10616
+ function otherColumns(headers, used, taken, draft) {
10617
+ const out = [];
10618
+ headers.forEach((header, i) => {
10619
+ if (used.has(i) || i === draft) return;
10620
+ const base = snakeHeader(header) || `column_${i + 1}`;
10621
+ if (AMDAHL_INPUT_COLUMNS.includes(base)) return;
10622
+ let columnName = base;
10623
+ for (let n = 2; taken.has(columnName); n += 1) columnName = `${base}_${n}`;
10624
+ taken.add(columnName);
10625
+ out.push({ name: columnName, value: (_, l) => l.cells[i] ?? "" });
10626
+ });
10627
+ return out;
10628
+ }
10629
+ function buildSendToFile({ path, headers: raw, rows, channel, preset }) {
10630
+ const headers = raw.map((h) => h.replace(/^\uFEFF/, "").trim());
10631
+ const map = autoMap(headers);
10632
+ const leftOut = { failed: 0, unwritten: 0, needsInput: 0, noContact: 0 };
10633
+ const ready = [];
10634
+ for (const row of rows) {
10635
+ const lead = leadOf(row.cells, map);
10636
+ const written = row.written;
10637
+ if (written.kind === "failed") leftOut.failed += 1;
10638
+ else if (written.kind === "unwritten") leftOut.unwritten += 1;
10639
+ else if (written.kind === "needs_input") leftOut.needsInput += 1;
10640
+ else if (!hasContact(lead, map, channel, preset)) leftOut.noContact += 1;
10641
+ else ready.push({ written, lead });
10642
+ }
10643
+ const identity = identityColumns(map, preset);
10644
+ const taken = /* @__PURE__ */ new Set([...identity.columns.map((c) => c.name), subjectColumn, messageColumn]);
10645
+ const columns = [
10646
+ ...identity.columns,
10647
+ ...channel === "email" ? [{ name: subjectColumn, value: (w) => w.subject }] : [],
10648
+ { name: messageColumn, value: (w) => w.body },
10649
+ ...otherColumns(headers, identity.used, taken, draftColumn(headers, rows.map((r) => r.cells)))
10650
+ ];
10651
+ const lines = ready.map(({ written, lead }) => columns.map((c) => cell(c.value(written, lead).replace(/\r\n?/g, "\n"))).join(","));
10652
+ const overLimit = preset.maxValue ? ready.filter(({ written }) => written.body.length > (preset.maxValue ?? 0)).length : 0;
10653
+ return {
10654
+ name: sendToFileName(path, preset),
10655
+ csv: [columns.map((c) => c.name).join(","), ...lines].join("\r\n"),
10656
+ ready: ready.length,
10657
+ leftOut,
10658
+ overLimit
10659
+ };
10660
+ }
10661
+ function leftOutLine(left, channel, preset) {
10662
+ const total = left.failed + left.unwritten + left.needsInput + left.noContact;
10663
+ if (total === 0) return null;
10664
+ const missing = channel === "email" ? "email" : preset.needsNames ? "LinkedIn URL or full name" : "LinkedIn URL";
10665
+ const parts = [
10666
+ left.failed ? `${left.failed} failed` : null,
10667
+ left.unwritten ? `${left.unwritten} not written yet` : null,
10668
+ left.needsInput ? `${left.needsInput} needed input` : null,
10669
+ left.noContact ? `${left.noContact} with no ${missing}` : null
10670
+ ].filter((p) => p !== null);
10671
+ return `${total} left out: ${parts.join(", ")}.`;
10672
+ }
10673
+ function guideLines(preset, channel) {
10674
+ const email = channel === "email";
10675
+ const variables = [...email ? [`Subject ${preset.variable(subjectColumn)}`] : [], `${email ? "Body" : "Message"} ${preset.variable(messageColumn)}`];
10676
+ return [`Import: ${preset.where}`, preset.match(channel), `${preset.insert}: ${variables.join(", ")}`];
10677
+ }
10678
+ function readyLine(ready, preset) {
10679
+ return `${ready} ${ready === 1 ? "message" : "messages"} ready ${preset.id === "other" ? "to import" : `for ${preset.label}`}`;
10680
+ }
10681
+ function overLimitLine(over, preset) {
10682
+ return `${over} ${over === 1 ? "message is" : "messages are"} over ${preset.label}'s ${(preset.maxValue ?? 0).toLocaleString("en-US")} character limit for a variable.`;
10683
+ }
10684
+ var NO_FILE = ["gmail", "outlook"];
10685
+ function toolFor(value) {
10686
+ const preset = presetFor(value);
10687
+ if (preset) return preset;
10688
+ const lower = value.trim().toLowerCase();
10689
+ if (NO_FILE.includes(lower)) {
10690
+ throw usageError(`${lower === "gmail" ? "Gmail" : "Outlook"} sends from a mailbox, so it has no import file.`, "Use --for other for any tool that imports a CSV.");
10691
+ }
10692
+ throw usageError(`--for must be one of: ${SEND_TO_IDS.join(", ")}.`, "Use other for a tool that is not listed.");
10693
+ }
10694
+ function planSendTo(preset, list2, flagChannel) {
10695
+ if (list2.kind !== "csv" || !list2.header) {
10696
+ throw usageError("--for needs a CSV list: the import file keeps your list's columns.", `${list2.path} is not a CSV. Make one, or leave --for out.`);
10697
+ }
10698
+ const valid = (c) => c === "email" || c === "linkedin";
10699
+ const own = new Set(list2.items.map((i) => i.channel).filter(valid));
10700
+ if (valid(flagChannel)) own.add(flagChannel);
10701
+ if (own.size > 1) {
10702
+ throw usageError("--for writes one channel at a time, and this list has both email and LinkedIn rows.", `Split ${list2.path} by channel, and run each part with --for.`);
10703
+ }
10704
+ const only = preset.channels.length === 1 ? preset.channels[0] : void 0;
10705
+ const channel = [...own][0] ?? only;
10706
+ if (!channel) {
10707
+ throw usageError(`${preset.label} takes email and LinkedIn lists, so --for needs to know which this is.`, "Add --channel email or --channel linkedin.");
10708
+ }
10709
+ if (!preset.channels.includes(channel)) {
10710
+ throw usageError(`${preset.label} takes ${preset.channels[0] === "email" ? "email" : "LinkedIn"} lists only, and this one is ${channel === "email" ? "email" : "LinkedIn"}.`, "Pick a tool for this channel, or use --for other.");
10711
+ }
10712
+ const map = autoMap(list2.header);
10713
+ if (channel === "email" && map.email < 0) {
10714
+ throw usageError(`${list2.path} has no email column.`, "Name the column email, email_address or work_email, so the tool can import it.");
10715
+ }
10716
+ if (channel === "linkedin" && map.linkedin < 0) {
10717
+ throw usageError(`${list2.path} has no LinkedIn URL column.`, "Name the column linkedin_url, linkedin or linkedin_profile, so the tool can import it.");
10718
+ }
10719
+ if (channel === "linkedin" && preset.needsNames && map.name < 0 && !(map.first >= 0 && map.last >= 0)) {
10720
+ throw usageError(`${preset.label} needs a first and a last name for each lead, and ${list2.path} has no name columns.`, "Add first_name and last_name columns, or one name column.");
10721
+ }
10722
+ return { preset, channel };
10723
+ }
10724
+
10725
+ // src/commands/batch.ts
10367
10726
  var PLATFORM4 = "/api/platform/v1";
10368
10727
  var BATCH_WAIT_MS = 15e3;
10369
10728
  var PAGE = 100;
@@ -10378,52 +10737,52 @@ function parseCsv(text3) {
10378
10737
  const rows = [];
10379
10738
  const lines = [];
10380
10739
  let row = [];
10381
- let cell2 = "";
10740
+ let cell3 = "";
10382
10741
  let quoted = false;
10383
10742
  let line = 1;
10384
10743
  let rowLine = 1;
10385
10744
  let touched = false;
10386
10745
  const src = text3.replace(/^\uFEFF/, "");
10387
10746
  const endRow = () => {
10388
- row.push(cell2);
10389
- if (touched || row.length > 1 || cell2 !== "") {
10747
+ row.push(cell3);
10748
+ if (touched || row.length > 1 || cell3 !== "") {
10390
10749
  rows.push(row);
10391
10750
  lines.push(rowLine);
10392
10751
  }
10393
10752
  row = [];
10394
- cell2 = "";
10753
+ cell3 = "";
10395
10754
  touched = false;
10396
10755
  };
10397
10756
  for (let i = 0; i < src.length; i++) {
10398
10757
  const c = src[i];
10399
10758
  if (quoted) {
10400
10759
  if (c === '"' && src[i + 1] === '"') {
10401
- cell2 += '"';
10760
+ cell3 += '"';
10402
10761
  i++;
10403
10762
  } else if (c === '"') quoted = false;
10404
10763
  else if (c === "\r" && src[i + 1] === "\n") continue;
10405
10764
  else {
10406
10765
  if (c === "\n") line++;
10407
- cell2 += c;
10766
+ cell3 += c;
10408
10767
  }
10409
10768
  continue;
10410
10769
  }
10411
- if (c === '"' && cell2 === "") {
10770
+ if (c === '"' && cell3 === "") {
10412
10771
  quoted = true;
10413
10772
  touched = true;
10414
10773
  } else if (c === ",") {
10415
- row.push(cell2);
10416
- cell2 = "";
10774
+ row.push(cell3);
10775
+ cell3 = "";
10417
10776
  touched = true;
10418
10777
  } else if (c === "\n" || c === "\r") {
10419
10778
  if (c === "\r" && src[i + 1] === "\n") i++;
10420
10779
  endRow();
10421
10780
  line++;
10422
10781
  rowLine = line;
10423
- } else cell2 += c;
10782
+ } else cell3 += c;
10424
10783
  }
10425
10784
  if (quoted) throw usageError(`A quoted CSV field that starts on line ${rowLine} never ends.`);
10426
- if (cell2 !== "" || row.length > 0 || touched) endRow();
10785
+ if (cell3 !== "" || row.length > 0 || touched) endRow();
10427
10786
  return { rows, lines };
10428
10787
  }
10429
10788
  function csvCell(value) {
@@ -10432,8 +10791,8 @@ function csvCell(value) {
10432
10791
  function toCsv(rows) {
10433
10792
  return rows.map((r) => r.map(csvCell).join(",")).join("\n") + "\n";
10434
10793
  }
10435
- function perLine(cell2) {
10436
- return cell2.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
10794
+ function perLine(cell3) {
10795
+ return cell3.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
10437
10796
  }
10438
10797
  function csvList(path, text3) {
10439
10798
  const { rows, lines } = parseCsv(text3);
@@ -10455,11 +10814,11 @@ function csvList(path, text3) {
10455
10814
  }
10456
10815
  const item = {};
10457
10816
  const context = {};
10458
- names.forEach((name, j) => {
10817
+ names.forEach((name2, j) => {
10459
10818
  const value = row[j] ?? "";
10460
- if (!CSV_COLUMNS.includes(name) || !value.trim()) return;
10461
- if (name === "facts" || name === "rules") context[name] = perLine(value);
10462
- else item[name] = name === "message" ? value : value.trim();
10819
+ if (!CSV_COLUMNS.includes(name2) || !value.trim()) return;
10820
+ if (name2 === "facts" || name2 === "rules") context[name2] = perLine(value);
10821
+ else item[name2] = name2 === "message" ? value : name2 === "channel" ? value.trim().toLowerCase() : value.trim();
10463
10822
  });
10464
10823
  if (Object.keys(context).length > 0) item.context = context;
10465
10824
  return item;
@@ -10494,13 +10853,13 @@ function readList(path) {
10494
10853
  }
10495
10854
  function resultsPath(path, kind) {
10496
10855
  const ext = extname(path);
10497
- const stem = basename2(path, ext);
10856
+ const stem = basename3(path, ext);
10498
10857
  return join7(dirname4(path), `${stem}.optimized.${kind === "csv" ? "csv" : "jsonl"}`);
10499
10858
  }
10500
10859
  function withDefaults(items, defaults) {
10501
10860
  return items.map((item) => {
10502
10861
  const merged = { ...item };
10503
- for (const [key, value] of Object.entries(defaults)) if (merged[key] === void 0) merged[key] = value;
10862
+ for (const [key2, value] of Object.entries(defaults)) if (merged[key2] === void 0) merged[key2] = value;
10504
10863
  const shared = record(defaults.context);
10505
10864
  const own = record(item.context);
10506
10865
  if (shared && own) merged.context = { ...shared, ...own };
@@ -10566,14 +10925,14 @@ async function allItems(ctx, credential, id) {
10566
10925
  } while (cursor);
10567
10926
  return { batch, items };
10568
10927
  }
10569
- function neutralise(cell2) {
10570
- return /^[=+\-@\t\r]/.test(cell2) ? `'${cell2}` : cell2;
10928
+ function neutralise(cell3) {
10929
+ return /^[=+\-@\t\r]/.test(cell3) ? `'${cell3}` : cell3;
10571
10930
  }
10572
10931
  var RESULT_COLUMNS = ["optimized_message", "status", "summary", "run_id", "error"];
10573
10932
  function resultColumnNames(header) {
10574
10933
  const taken = new Set(header.map((h) => h.trim().toLowerCase()));
10575
- return RESULT_COLUMNS.map((name) => {
10576
- let candidate = name;
10934
+ return RESULT_COLUMNS.map((name2) => {
10935
+ let candidate = name2;
10577
10936
  while (taken.has(candidate)) candidate = `amdahl_${candidate}`;
10578
10937
  taken.add(candidate);
10579
10938
  return candidate;
@@ -10593,18 +10952,67 @@ function resultsFile(list2, id, cwd) {
10593
10952
  function assertFree(path, force) {
10594
10953
  if (!force && existsSync5(path)) throw usageError(`${path} already exists.`, "Move it, or add --force to replace it.");
10595
10954
  }
10596
- function writeResults(list2, id, items, cwd, force, contexts) {
10955
+ function writeNew(path, text3, force, pickUp) {
10956
+ try {
10957
+ writeFileSync4(path, text3, { flag: force ? "w" : "wx" });
10958
+ } catch (err) {
10959
+ if (err?.code === "EEXIST") {
10960
+ throw usageError(`${path} already exists.`, `Move it, or add --force to replace it. The batch is done, and you can read it again: ${pickUp}`);
10961
+ }
10962
+ throw err;
10963
+ }
10964
+ }
10965
+ function writeResults(list2, id, items, cwd, force, contexts, pickUp) {
10597
10966
  const byIndex = new Map(items.map((i) => [i.index, i]));
10598
10967
  const path = resultsFile(list2, id, cwd);
10599
- const flag = force ? "w" : "wx";
10600
10968
  if (list2?.kind === "csv" && list2.header && list2.rows) {
10601
10969
  const rows = [[...list2.header, ...resultColumnNames(list2.header)], ...list2.rows.map((row, i) => [...row, ...resultCells(byIndex.get(i), contexts[i])])];
10602
- writeFileSync4(path, toCsv(rows.map((row) => row.map(neutralise))), { flag });
10970
+ writeNew(path, toCsv(rows.map((row) => row.map(neutralise))), force, pickUp);
10603
10971
  return path;
10604
10972
  }
10605
- writeFileSync4(path, items.map((i) => JSON.stringify(i)).join("\n") + "\n", { flag });
10973
+ writeNew(path, items.map((i) => JSON.stringify(i)).join("\n") + "\n", force, pickUp);
10606
10974
  return path;
10607
10975
  }
10976
+ function writeSendTo(plan, list2, items, force, pickUp) {
10977
+ const byIndex = new Map(items.map((i) => [i.index, i]));
10978
+ const built = buildSendToFile({
10979
+ path: list2.path,
10980
+ headers: list2.header ?? [],
10981
+ rows: (list2.rows ?? []).map((cells, i) => ({ cells, written: writtenOf(byIndex.get(i)) })),
10982
+ channel: plan.channel,
10983
+ preset: plan.preset
10984
+ });
10985
+ if (built.ready === 0) return { built, path: null };
10986
+ const path = join7(dirname4(list2.path), built.name);
10987
+ writeNew(path, built.csv, force, pickUp);
10988
+ return { built, path };
10989
+ }
10990
+ function sendToJson(plan, sent2) {
10991
+ const { leftOut, ready, overLimit } = sent2.built;
10992
+ return {
10993
+ tool: plan.preset.id,
10994
+ channel: plan.channel,
10995
+ file: sent2.path,
10996
+ ready,
10997
+ left_out: { failed: leftOut.failed, not_written: leftOut.unwritten, needs_input: leftOut.needsInput, no_contact: leftOut.noContact },
10998
+ over_limit: overLimit
10999
+ };
11000
+ }
11001
+ function printSendTo(ctx, plan, sent2) {
11002
+ const { out } = ctx;
11003
+ const { preset, channel } = plan;
11004
+ const left = leftOutLine(sent2.built.leftOut, channel, preset);
11005
+ if (!sent2.path) {
11006
+ out.info(`Nothing to send to ${preset.label}.${left ? ` ${left}` : ""}`);
11007
+ return;
11008
+ }
11009
+ out.result({}, `Import file${preset.id === "other" ? "" : ` for ${preset.label}`}: ${sent2.path}`);
11010
+ out.info(`${readyLine(sent2.built.ready, preset)}.${left ? ` ${left}` : ""}`);
11011
+ const steps = guideLines(preset, channel).map((line, i) => `${i + 1}. ${line}`);
11012
+ const notes = [preset.note, sent2.built.overLimit > 0 ? overLimitLine(sent2.built.overLimit, preset) : void 0].filter((n) => Boolean(n));
11013
+ out.info(wrap(steps.join("\n"), COLUMNS, " ").join("\n"));
11014
+ for (const note of notes) out.info(wrap(note, COLUMNS).join("\n"));
11015
+ }
10608
11016
  function withLine(err, list2) {
10609
11017
  if (!(err instanceof CliError)) return err;
10610
11018
  const index = /\$\.items\[(\d+)\]/.exec(err.message)?.[1];
@@ -10612,7 +11020,8 @@ function withLine(err, list2) {
10612
11020
  if (line === void 0) return err;
10613
11021
  return new CliError(err.code, err.message, err.exit, `items[${index}] is line ${line} of ${list2.path}.`, err.detail, err.data);
10614
11022
  }
10615
- async function optimizeList(ctx, defaults) {
11023
+ async function optimizeList(ctx, requested) {
11024
+ let defaults = requested;
10616
11025
  const { out, flags } = ctx;
10617
11026
  const listPath = str(flags.list);
10618
11027
  const resume = str(flags.batch);
@@ -10623,7 +11032,15 @@ async function optimizeList(ctx, defaults) {
10623
11032
  if (resume && !BATCH_ID.test(resume)) {
10624
11033
  throw usageError("--batch needs a batch id: a UUID like the one `amdahl optimize --list` printed.");
10625
11034
  }
11035
+ const forFlag = str(flags.for);
11036
+ if (typeof flags.for === "string" && !forFlag) throw usageError("--for needs a tool.", `One of: ${SEND_TO_IDS.join(", ")}.`);
11037
+ if (forFlag && !listPath) throw usageError("--for needs the list: add --list <file.csv>.");
11038
+ const preset = forFlag ? toolFor(forFlag) : null;
10626
11039
  const list2 = listPath ? readList(listPath) : null;
11040
+ const plan = preset && list2 ? planSendTo(preset, list2, typeof defaults.channel === "string" ? defaults.channel : void 0) : null;
11041
+ if (plan) defaults = { ...defaults, channel: defaults.channel ?? plan.channel };
11042
+ const forPart = plan ? ` --for ${plan.preset.id}${plan.preset.channels.length > 1 ? ` --channel ${plan.channel}` : ""}` : "";
11043
+ const pickUpFor = (batchId) => amdahlCommand(`optimize ${listPath ? `--list ${shellWord(listPath, ctx.io.platform)} ` : ""}--batch ${batchId}${forPart}`);
10627
11044
  if (list2?.ignored?.length) {
10628
11045
  const shown = list2.ignored.slice(0, 6).join(", ");
10629
11046
  const more = list2.ignored.length > 6 ? ` and ${list2.ignored.length - 6} more` : "";
@@ -10634,6 +11051,7 @@ async function optimizeList(ctx, defaults) {
10634
11051
  }
10635
11052
  const force = flags.force === true;
10636
11053
  if (!out.json && flags["no-wait"] !== true) assertFree(resultsFile(list2, resume ?? "", ctx.io.cwd), force);
11054
+ if (plan && list2 && flags["no-wait"] !== true) assertFree(join7(dirname4(list2.path), sendToFileName(list2.path, plan.preset)), force);
10637
11055
  const credential = await resolveCredential(ctx);
10638
11056
  let id = resume ?? "";
10639
11057
  let first2 = null;
@@ -10657,7 +11075,7 @@ async function optimizeList(ctx, defaults) {
10657
11075
  }
10658
11076
  id = field(first2.batch_id);
10659
11077
  if (!id) throw new CliError("no_batch_id", "Amdahl accepted the list but sent no batch id.", EXIT.general);
10660
- const pickUp = amdahlCommand(`optimize --list ${shellWord(listPath ?? "", ctx.io.platform)} --batch ${id}`);
11078
+ const pickUp = pickUpFor(id);
10661
11079
  if (flags["no-wait"] === true) {
10662
11080
  out.result({ ...first2, ok: true }, `Queued ${count(list2.items.length, "message")} as batch ${id}.
10663
11081
  Get the results: ${pickUp}`);
@@ -10672,17 +11090,21 @@ Get the results: ${pickUp}`);
10672
11090
  const { batch, items } = await allItems(ctx, credential, id);
10673
11091
  const failed = items.filter((i) => i.status === "failed" || record(i.result)?.ok === false).length;
10674
11092
  if (out.json) {
10675
- out.result({ ...batch, ok: failed === 0, items, next_cursor: null });
10676
- return failed === 0 ? EXIT.ok : EXIT.general;
11093
+ const sent3 = plan && list2 ? writeSendTo(plan, list2, items, force, pickUpFor(id)) : null;
11094
+ const ok = failed === 0 && (!sent3 || sent3.built.ready > 0);
11095
+ out.result({ ...batch, ok, items, next_cursor: null, ...plan && sent3 ? { send_to: sendToJson(plan, sent3) } : {} });
11096
+ return ok ? EXIT.ok : EXIT.general;
10677
11097
  }
10678
11098
  const contexts = list2 ? withDefaults(list2.items, defaults).map((item) => item.context) : [];
10679
- const path = writeResults(list2, id, items, ctx.io.cwd, force, contexts);
11099
+ const path = writeResults(list2, id, items, ctx.io.cwd, force, contexts, pickUpFor(id));
10680
11100
  const done = items.length - failed;
10681
11101
  out.info(`${done} of ${count(items.length, "message")} optimized${failed ? `, ${failed} failed` : ""}.`);
10682
11102
  out.result({}, `Results: ${path}`);
11103
+ const sent2 = plan && list2 ? writeSendTo(plan, list2, items, force, pickUpFor(id)) : null;
11104
+ if (plan && sent2) printSendTo(ctx, plan, sent2);
10683
11105
  const runId2 = items.map((i) => field(record(i.result)?.run_id)).find(Boolean);
10684
11106
  for (const line of sentLines(runId2, "Sent one?")) out.info(line);
10685
- return failed === 0 ? EXIT.ok : EXIT.general;
11107
+ return failed === 0 && (!sent2 || sent2.built.ready > 0) ? EXIT.ok : EXIT.general;
10686
11108
  }
10687
11109
 
10688
11110
  // src/commands/optimize.ts
@@ -10943,6 +11365,7 @@ async function optimize(ctx, args) {
10943
11365
  }
10944
11366
  if (ctx.flags["no-wait"] === true) throw usageError("--no-wait goes with --list <file>.");
10945
11367
  if (ctx.flags.force === true) throw usageError("--force goes with --list <file>.");
11368
+ if (ctx.flags.for !== void 0) throw usageError("--for goes with --list <file.csv>.");
10946
11369
  let files = args;
10947
11370
  if (files.length === 0) {
10948
11371
  if (atTerminal(ctx)) return optimizePasted(ctx);
@@ -10994,7 +11417,7 @@ var SYNTHESIZED_ID = "answer-text";
10994
11417
  var MAX_TABLE_ROWS = 25;
10995
11418
  var MAX_CELL_LINES = 4;
10996
11419
  var MIN_COLUMN = 6;
10997
- function cell(value) {
11420
+ function cell2(value) {
10998
11421
  if (typeof value === "number") return String(value);
10999
11422
  return typeof value === "string" ? field(value).replace(/\s+/g, " ") : "";
11000
11423
  }
@@ -11070,8 +11493,8 @@ function dataTable(block) {
11070
11493
  const columns = records(block.columns).filter((c) => field(c.key));
11071
11494
  const data = records(block.data);
11072
11495
  if (columns.length === 0 || data.length === 0) return [];
11073
- const labels = columns.map((c) => cell(c.label) || cell(c.key));
11074
- return asciiTable(labels, data.map((row) => columns.map((c) => cell(row[field(c.key)]))));
11496
+ const labels = columns.map((c) => cell2(c.label) || cell2(c.key));
11497
+ return asciiTable(labels, data.map((row) => columns.map((c) => cell2(row[field(c.key)]))));
11075
11498
  }
11076
11499
  function prose(markdown) {
11077
11500
  return plainMarkdown(paragraphs(markdown).replace(/<\s*unverified\s*>([^<]*)<\s*\/\s*unverified\s*>/gi, "$1 (unverified)"));
@@ -11095,7 +11518,7 @@ function renderBlock(block, answer) {
11095
11518
  const data = record(block.data);
11096
11519
  const value = data?.value ?? block.value;
11097
11520
  const delta = field(data?.delta ?? block.delta);
11098
- const shown = value === void 0 ? "" : cell(value);
11521
+ const shown = value === void 0 ? "" : cell2(value);
11099
11522
  return wrap(`${field(block.label)}: ${shown}${delta ? ` (${delta})` : ""}`);
11100
11523
  }
11101
11524
  case "citation": {
@@ -11144,8 +11567,8 @@ var TEXT_FIELDS = ["content_preview", "text", "quote", "snippet", "excerpt", "co
11144
11567
  var WHO_FIELDS = ["speaker", "speaker_name", "account_name", "company_name", "owner_name", "deal_stage_label", "speaker_type"];
11145
11568
  var AMOUNT_FIELDS = ["deal_amount", "amount"];
11146
11569
  function first(row, names) {
11147
- for (const name of names) {
11148
- const value = row[name];
11570
+ for (const name2 of names) {
11571
+ const value = row[name2];
11149
11572
  if (typeof value === "string" && value.trim()) return field(value);
11150
11573
  if (typeof value === "number") return String(value);
11151
11574
  }
@@ -11324,12 +11747,12 @@ var TRY_IN = {
11324
11747
  };
11325
11748
  var CODEX_TRY = `Run codex, paste an email and say: ${ASK}`;
11326
11749
  var CODEX_LOGIN = "codex mcp login amdahl";
11327
- function toolScreen(name, already) {
11750
+ function toolScreen(name2, already) {
11328
11751
  return [
11329
- already ? `\u2713 ${name} already has Amdahl.` : `\u2713 Added Amdahl to ${name}.`,
11330
- `One step left, in ${name}:`,
11331
- ` 1. ${SIGN_IN[name] ?? ""}`,
11332
- ` 2. ${TRY_IN[name] ?? ""}`
11752
+ already ? `\u2713 ${name2} already has Amdahl.` : `\u2713 Added Amdahl to ${name2}.`,
11753
+ `One step left, in ${name2}:`,
11754
+ ` 1. ${SIGN_IN[name2] ?? ""}`,
11755
+ ` 2. ${TRY_IN[name2] ?? ""}`
11333
11756
  ];
11334
11757
  }
11335
11758
  function whatNextLines() {
@@ -11616,8 +12039,8 @@ async function tryHere(ctx, say, lead) {
11616
12039
  say(`\u2713 Signed in \xB7 ${printable(signedIn.workspace.name)}`);
11617
12040
  if (verbose) say(` ${signedInLine(ctx, signedIn)}`);
11618
12041
  } else {
11619
- const name = who.source === "flag" ? "--api-key" : who.source.slice("env:".length);
11620
- out.info(`Amdahl rejected the key in ${name}, so a message can't be tried here. Fix it, or unset it and run \`${amdahlCommand("login")}\`.`);
12042
+ const name2 = who.source === "flag" ? "--api-key" : who.source.slice("env:".length);
12043
+ out.info(`Amdahl rejected the key in ${name2}, so a message can't be tried here. Fix it, or unset it and run \`${amdahlCommand("login")}\`.`);
11621
12044
  return EXIT.unauthenticated;
11622
12045
  }
11623
12046
  return optimizePasted(ctx);
@@ -11747,9 +12170,9 @@ function readTar(tar) {
11747
12170
  if (header.toString("latin1", 257, 263) !== "ustar\0" || header.toString("latin1", 263, 265) !== "00") {
11748
12171
  throw new ArchiveError("its tar is not ustar");
11749
12172
  }
11750
- const name = field2(header, 0, 100);
12173
+ const name2 = field2(header, 0, 100);
11751
12174
  const prefix2 = field2(header, 345, 155);
11752
- let path = prefix2 ? `${prefix2}/${name}` : name;
12175
+ let path = prefix2 ? `${prefix2}/${name2}` : name2;
11753
12176
  const type = String.fromCharCode(header[156]);
11754
12177
  const size = octal(header, 124, 12);
11755
12178
  const mode = octal(header, 100, 8);
@@ -11761,22 +12184,22 @@ function readTar(tar) {
11761
12184
  }
11762
12185
  if (isDir && path.endsWith("/")) path = path.slice(0, -1);
11763
12186
  checkPath(path);
11764
- const key = path.toLowerCase();
11765
- const parts = key.split("/");
12187
+ const key2 = path.toLowerCase();
12188
+ const parts = key2.split("/");
11766
12189
  for (let i = 1; i < parts.length; i += 1) {
11767
12190
  const parent = parts.slice(0, i).join("/");
11768
12191
  const kind = seen.get(parent);
11769
12192
  if (kind === "file") throw new ArchiveError(`it puts ${JSON.stringify(path)} inside a file`);
11770
12193
  if (!kind) seen.set(parent, "implied");
11771
12194
  }
11772
- const before = seen.get(key);
12195
+ const before = seen.get(key2);
11773
12196
  if (before === "file" || before === "dir" || before === "implied" && !isDir) {
11774
12197
  throw new ArchiveError(`it lists ${JSON.stringify(path)} twice`);
11775
12198
  }
11776
12199
  const start = at + BLOCK;
11777
12200
  if (isDir) {
11778
12201
  if (size !== 0) throw new ArchiveError(`its folder ${JSON.stringify(path)} has a size`);
11779
- seen.set(key, "dir");
12202
+ seen.set(key2, "dir");
11780
12203
  dirs.push(path);
11781
12204
  } else {
11782
12205
  if (!FILE_MODES.has(mode & 4095)) {
@@ -11786,7 +12209,7 @@ function readTar(tar) {
11786
12209
  unpacked += size;
11787
12210
  if (unpacked > MAX_UNPACKED_BYTES) throw new ArchiveError(`its files come to more than ${MAX_UNPACKED_BYTES / 1024 / 1024} MB`, true);
11788
12211
  if (start + size > tar.length) throw new ArchiveError(`its tar is cut short inside ${JSON.stringify(path)}`);
11789
- seen.set(key, "file");
12212
+ seen.set(key2, "file");
11790
12213
  files.push({ path, bytes: Buffer.from(tar.subarray(start, start + size)), mode: mode & 4095 });
11791
12214
  }
11792
12215
  at = start + Math.ceil(size / BLOCK) * BLOCK;
@@ -11851,8 +12274,8 @@ function canAsk(ctx) {
11851
12274
  async function confirmWarning(ctx, ref, site, warning) {
11852
12275
  const { out } = ctx;
11853
12276
  const host = new URL(site).host;
11854
- const name = `${ref.publisher}/${ref.skill}`;
11855
- const head = warning.result === "fail" ? `${name} failed ${host}'s security review.` : `${host}'s security review flagged ${name}.`;
12277
+ const name2 = `${ref.publisher}/${ref.skill}`;
12278
+ const head = warning.result === "fail" ? `${name2} failed ${host}'s security review.` : `${host}'s security review flagged ${name2}.`;
11856
12279
  out.info([out.bold(`Warning: ${head}`), ` ${warning.text}`, ` See what was flagged: ${skillPage(site, ref)}`].join("\n"));
11857
12280
  if (ctx.flags["accept-warning"] === true) {
11858
12281
  out.info("Installing it anyway, because of --accept-warning.");
@@ -11861,7 +12284,7 @@ async function confirmWarning(ctx, ref, site, warning) {
11861
12284
  if (!canAsk(ctx)) {
11862
12285
  throw new CliError(
11863
12286
  "skill_flagged",
11864
- `Did not install ${name}, because the security review flagged it. Nothing was written.`,
12287
+ `Did not install ${name2}, because the security review flagged it. Nothing was written.`,
11865
12288
  EXIT.flagged,
11866
12289
  "Show this warning to the person you are working for. Once they agree, run the same command again with --accept-warning.",
11867
12290
  void 0,
@@ -12052,10 +12475,10 @@ function checkSkillMd(body, what, ref) {
12052
12475
  } catch (err) {
12053
12476
  throw bad(`its front matter could not be read (${printable(err instanceof Error ? err.message : String(err))})`);
12054
12477
  }
12055
- const { name, description, version, metadata } = meta && typeof meta === "object" && !Array.isArray(meta) ? meta : {};
12056
- if (typeof name !== "string") throw bad("its front matter has no string name");
12478
+ const { name: name2, description, version, metadata } = meta && typeof meta === "object" && !Array.isArray(meta) ? meta : {};
12479
+ if (typeof name2 !== "string") throw bad("its front matter has no string name");
12057
12480
  if (typeof description !== "string" || description.trim() === "") throw bad("its front matter has no string description");
12058
- if (name !== ref.skill) throw bad(`its front matter names it "${printable(name)}", but the index lists ${ref.skill}`);
12481
+ if (name2 !== ref.skill) throw bad(`its front matter names it "${printable(name2)}", but the index lists ${ref.skill}`);
12059
12482
  const nested = metadata && typeof metadata === "object" ? metadata.version : void 0;
12060
12483
  const v = printable(typeof version === "string" ? version : typeof nested === "string" ? nested : "");
12061
12484
  return { description, ...v ? { version: v } : {} };
@@ -12226,8 +12649,8 @@ async function status(ctx) {
12226
12649
  }
12227
12650
  async function workspaceList(ctx) {
12228
12651
  const { config } = ctx;
12229
- const profiles = Object.entries(config.profiles).map(([name, p]) => ({
12230
- name,
12652
+ const profiles = Object.entries(config.profiles).map(([name2, p]) => ({
12653
+ name: name2,
12231
12654
  workspace: p.workspace,
12232
12655
  email: p.email,
12233
12656
  api_url: p.api_url
@@ -12239,14 +12662,14 @@ async function workspaceList(ctx) {
12239
12662
  return EXIT.ok;
12240
12663
  }
12241
12664
  async function workspaceUse(ctx, args) {
12242
- const name = args[0];
12243
- if (!name || args.length > 1) throw usageError("Usage: amdahl workspace use <profile>");
12244
- if (!ctx.config.profiles[name]) {
12245
- throw usageError(`No profile named "${name}".`, `Run \`${amdahlCommand("workspace list")}\` to see your profiles.`);
12665
+ const name2 = args[0];
12666
+ if (!name2 || args.length > 1) throw usageError("Usage: amdahl workspace use <profile>");
12667
+ if (!ctx.config.profiles[name2]) {
12668
+ throw usageError(`No profile named "${name2}".`, `Run \`${amdahlCommand("workspace list")}\` to see your profiles.`);
12246
12669
  }
12247
- ctx.config.default_profile = name;
12670
+ ctx.config.default_profile = name2;
12248
12671
  ctx.saveConfig();
12249
- ctx.out.result({ ok: true, default: name }, `Default profile: ${name}`);
12672
+ ctx.out.result({ ok: true, default: name2 }, `Default profile: ${name2}`);
12250
12673
  return EXIT.ok;
12251
12674
  }
12252
12675
 
@@ -12302,6 +12725,7 @@ With --json it prints the server's setup status as one object.
12302
12725
  [--evidence off|workspace] [--on-unsupported flag|remove]
12303
12726
  [--tries] [--context <file.json>]
12304
12727
  amdahl optimize --list <file.csv|file.jsonl> [--no-wait] [--force]
12728
+ amdahl optimize --list <file.csv> --for <tool> [--channel email|linkedin]
12305
12729
  amdahl optimize --batch <id> [--list <file>] [--force]
12306
12730
 
12307
12731
  Rewrite an outbound email or LinkedIn message. Each file is one message; "-"
@@ -12323,12 +12747,29 @@ reads standard input. With no file, at a terminal, paste the message.
12323
12747
  --no-wait With --list: queue the batch and print its id.
12324
12748
  --batch <id> Pick up a batch queued earlier. With --list, the
12325
12749
  same list; the results go next to it.
12750
+ --for <tool> With a CSV --list: also write the messages Amdahl
12751
+ wrote as a CSV that tool imports, next to the
12752
+ list (drafts.csv for lemlist gets
12753
+ drafts-lemlist.csv), then print how to import it.
12754
+ Tools: instantly, smartlead, lemlist, heyreach,
12755
+ reply_io, apollo, outreach, salesloft, hubspot,
12756
+ lgm, woodpecker, or other (any tool that imports
12757
+ a CSV).
12326
12758
  --force Replace a results file that already exists.
12327
12759
 
12328
12760
  In the results CSV, a cell that starts with =, +, - or @ gets a ' in front, so
12329
12761
  a spreadsheet does not run it as a formula. That includes a phone number such
12330
12762
  as +1 555 0100 or a negative number you copied through. Delete the ' to use it.
12331
12763
 
12764
+ The --for file holds only the leads Amdahl wrote, with your columns after
12765
+ Amdahl's, except the column the message came from and the ones Amdahl reads
12766
+ (message, channel, evidence, on_unsupported, facts, rules, item_id). Your tool
12767
+ imports a value as it is, so no cell gets the ' guard (the results file keeps
12768
+ it). A lead that failed, needed input or has no email (no LinkedIn URL for
12769
+ LinkedIn) is left out, and counted. A tool that takes one channel needs no
12770
+ --channel; lemlist, reply_io and other take both, so add --channel. With
12771
+ --json, .send_to has the file and the counts.
12772
+
12332
12773
  Output: the rewrite goes to stdout. What Amdahl did, and the run id, go to
12333
12774
  stderr. With --json it prints {"ok", "file", "result"}: the rewritten message
12334
12775
  is .result.message and the run id is .result.run_id. Several files give an
@@ -12491,12 +12932,12 @@ var GROUPS = {
12491
12932
  var ALIASES2 = { "auth login": "login", "auth logout": "logout", "auth status": "whoami" };
12492
12933
  var HELP_COMMANDS = Object.keys(HELP);
12493
12934
  function commandHelp(words) {
12494
- const key = ALIASES2[words.join(" ")] ?? words.join(" ");
12495
- const text3 = HELP[key];
12935
+ const key2 = ALIASES2[words.join(" ")] ?? words.join(" ");
12936
+ const text3 = HELP[key2];
12496
12937
  if (text3) return text3;
12497
12938
  const group = words.length === 1 ? GROUPS[words[0] ?? ""] : void 0;
12498
12939
  if (!group) return null;
12499
- const lines = group.map((name) => ` ${amdahlCommand(name)}`);
12940
+ const lines = group.map((name2) => ` ${amdahlCommand(name2)}`);
12500
12941
  return `Usage: amdahl ${words[0]} <command>
12501
12942
 
12502
12943
  Commands: