@callstack/apex 0.3.2 → 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 +71 -45
  2. package/dist/cli.js +884 -601
  3. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -48,13 +48,13 @@ function createScanner(text, ignoreTrivia = false) {
48
48
  if (text.charCodeAt(pos) === 48) pos++;
49
49
  else {
50
50
  pos++;
51
- while (pos < text.length && isDigit(text.charCodeAt(pos))) pos++;
51
+ while (pos < text.length && isDigit$1(text.charCodeAt(pos))) pos++;
52
52
  }
53
53
  if (pos < text.length && text.charCodeAt(pos) === 46) {
54
54
  pos++;
55
- if (pos < text.length && isDigit(text.charCodeAt(pos))) {
55
+ if (pos < text.length && isDigit$1(text.charCodeAt(pos))) {
56
56
  pos++;
57
- while (pos < text.length && isDigit(text.charCodeAt(pos))) pos++;
57
+ while (pos < text.length && isDigit$1(text.charCodeAt(pos))) pos++;
58
58
  } else {
59
59
  scanError = 3;
60
60
  return text.substring(start, pos);
@@ -64,9 +64,9 @@ function createScanner(text, ignoreTrivia = false) {
64
64
  if (pos < text.length && (text.charCodeAt(pos) === 69 || text.charCodeAt(pos) === 101)) {
65
65
  pos++;
66
66
  if (pos < text.length && text.charCodeAt(pos) === 43 || text.charCodeAt(pos) === 45) pos++;
67
- if (pos < text.length && isDigit(text.charCodeAt(pos))) {
67
+ if (pos < text.length && isDigit$1(text.charCodeAt(pos))) {
68
68
  pos++;
69
- while (pos < text.length && isDigit(text.charCodeAt(pos))) pos++;
69
+ while (pos < text.length && isDigit$1(text.charCodeAt(pos))) pos++;
70
70
  end = pos;
71
71
  } else scanError = 3;
72
72
  }
@@ -234,7 +234,7 @@ function createScanner(text, ignoreTrivia = false) {
234
234
  case 45:
235
235
  value += String.fromCharCode(code);
236
236
  pos++;
237
- if (pos === len || !isDigit(text.charCodeAt(pos))) return token = 16;
237
+ if (pos === len || !isDigit$1(text.charCodeAt(pos))) return token = 16;
238
238
  case 48:
239
239
  case 49:
240
240
  case 50:
@@ -306,7 +306,7 @@ function isWhiteSpace(ch) {
306
306
  function isLineBreak(ch) {
307
307
  return ch === 10 || ch === 13;
308
308
  }
309
- function isDigit(ch) {
309
+ function isDigit$1(ch) {
310
310
  return ch >= 48 && ch <= 57;
311
311
  }
312
312
  var CharacterCodes;
@@ -1275,11 +1275,11 @@ function applyEdits(text, edits) {
1275
1275
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1276
1276
  */
1277
1277
  function getLineColFromPtr(string, ptr) {
1278
- let lines = string.slice(0, ptr).split(/\r\n|\n|\r/g);
1278
+ let lines = string.slice(0, ptr).split(/\r?\n/);
1279
1279
  return [lines.length, lines.pop().length + 1];
1280
1280
  }
1281
1281
  function makeCodeBlock(string, line, column) {
1282
- let lines = string.split(/\r\n|\n|\r/g);
1282
+ let lines = string.split(/\r?\n/);
1283
1283
  let codeblock = "";
1284
1284
  let numberLen = (Math.log10(line + 1) | 0) + 1;
1285
1285
  for (let i = line - 1; i <= line + 1; i++) {
@@ -1296,7 +1296,7 @@ function makeCodeBlock(string, line, column) {
1296
1296
  }
1297
1297
  return codeblock;
1298
1298
  }
1299
- var TomlError = class extends Error {
1299
+ var TomlError = class TomlError extends Error {
1300
1300
  line;
1301
1301
  column;
1302
1302
  codeblock;
@@ -1308,10 +1308,17 @@ var TomlError = class extends Error {
1308
1308
  this.column = column;
1309
1309
  this.codeblock = codeblock;
1310
1310
  }
1311
+ /** @internal */
1312
+ static x(message, ctx, ptr) {
1313
+ throw new TomlError(message, {
1314
+ toml: ctx.s,
1315
+ ptr: ptr ?? ctx.p
1316
+ });
1317
+ }
1311
1318
  };
1312
1319
 
1313
1320
  //#endregion
1314
- //#region node_modules/smol-toml/dist/util.js
1321
+ //#region node_modules/smol-toml/dist/primitive.js
1315
1322
  /*!
1316
1323
  * Copyright (c) Squirrel Chat et al., All rights reserved.
1317
1324
  * SPDX-License-Identifier: BSD-3-Clause
@@ -1339,64 +1346,76 @@ var TomlError = class extends Error {
1339
1346
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1340
1347
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1341
1348
  */
1342
- function isEscaped(str, ptr) {
1343
- let i = 0;
1344
- while (str[ptr - ++i] === "\\");
1345
- return --i && i % 2;
1346
- }
1347
- function indexOfNewline(str, start = 0, end = str.length) {
1348
- let idx = str.indexOf("\n", start);
1349
- if (str[idx - 1] === "\r") idx--;
1350
- return idx <= end ? idx : -1;
1351
- }
1352
- function skipComment(str, ptr) {
1353
- for (let i = ptr; i < str.length; i++) {
1354
- let c = str[i];
1355
- if (c === "\n") return i;
1356
- if (c === "\r" && str[i + 1] === "\n") return i + 1;
1357
- if (c < " " && c !== " " || c === "") throw new TomlError("control characters are not allowed in comments", {
1358
- toml: str,
1359
- ptr
1360
- });
1349
+ /** @internal */
1350
+ function parseString(ctx) {
1351
+ let startPtr = ctx.p;
1352
+ let c = ctx.s.charCodeAt(ctx.p++);
1353
+ let first = c;
1354
+ let isLiteral = c === 39;
1355
+ let isMultiline = c === ctx.s.charCodeAt(ctx.p) && c === ctx.s.charCodeAt(ctx.p + 1);
1356
+ if (isMultiline) {
1357
+ if ((c = ctx.s.charCodeAt(ctx.p += 2)) === 10) ctx.p++;
1358
+ else if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) ctx.p += 2;
1361
1359
  }
1362
- return str.length;
1363
- }
1364
- function skipVoid(str, ptr, banNewLines, banComments) {
1365
- let c;
1366
- while ((c = str[ptr]) === " " || c === " " || !banNewLines && (c === "\n" || c === "\r" && str[ptr + 1] === "\n")) ptr++;
1367
- return banComments || c !== "#" ? ptr : skipVoid(str, skipComment(str, ptr), banNewLines);
1368
- }
1369
- function skipUntil(str, ptr, sep, end, banNewLines = false) {
1370
- if (!end) {
1371
- ptr = indexOfNewline(str, ptr);
1372
- return ptr < 0 ? str.length : ptr;
1373
- }
1374
- for (let i = ptr; i < str.length; i++) {
1375
- let c = str[i];
1376
- if (c === "#") i = indexOfNewline(str, i);
1377
- else if (c === sep) return i + 1;
1378
- else if (c === end || banNewLines && (c === "\n" || c === "\r" && str[i + 1] === "\n")) return i;
1379
- }
1380
- throw new TomlError("cannot find end of structure", {
1381
- toml: str,
1382
- ptr
1383
- });
1384
- }
1385
- function getStringEnd(str, seek) {
1386
- let first = str[seek];
1387
- let target = first === str[seek + 1] && str[seek + 1] === str[seek + 2] ? str.slice(seek, seek + 3) : first;
1388
- seek += target.length - 1;
1389
- do
1390
- seek = str.indexOf(target, ++seek);
1391
- while (seek > -1 && first !== "'" && isEscaped(str, seek));
1392
- if (seek > -1) {
1393
- seek += target.length;
1394
- if (target.length > 1) {
1395
- if (str[seek] === first) seek++;
1396
- if (str[seek] === first) seek++;
1360
+ let parsed = "";
1361
+ let sliceStart = ctx.p;
1362
+ let state = 0;
1363
+ for (; ctx.p < ctx.s.length; ctx.p++) {
1364
+ c = ctx.s.charCodeAt(ctx.p);
1365
+ if (isMultiline && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10)) state = state && 3;
1366
+ else if (c < 32 && c !== 9 || c === 127) TomlError.x("control characters are not allowed in strings", ctx);
1367
+ else if ((!state || state === 3) && c === first && (!isMultiline || ctx.s.charCodeAt(ctx.p + 1) === first && ctx.s.charCodeAt(ctx.p + 2) === first)) {
1368
+ if (isMultiline) {
1369
+ if (ctx.s.charCodeAt(ctx.p + 3) === first) ctx.p++;
1370
+ if (ctx.s.charCodeAt(ctx.p + 3) === first) ctx.p++;
1371
+ }
1372
+ if (!state) {
1373
+ let s = ctx.s.slice(sliceStart, ctx.p);
1374
+ parsed = parsed ? parsed + s : s;
1375
+ }
1376
+ ctx.p += isMultiline ? 3 : 1;
1377
+ return parsed;
1378
+ } else if (!state) {
1379
+ if (!isLiteral && c === 92) {
1380
+ parsed += ctx.s.slice(sliceStart, sliceStart = ctx.p);
1381
+ state = 1;
1382
+ }
1383
+ } else if (state === 1) {
1384
+ if (c === 120 || c === 117 || c === 85) {
1385
+ let errPtr = ctx.p++ - 1;
1386
+ let value = 0;
1387
+ let len = c === 120 ? 2 : c === 117 ? 4 : 8;
1388
+ for (let j = 0; j < len; j++, ctx.p++) {
1389
+ let hex = ctx.s.charCodeAt(ctx.p);
1390
+ let digit = hex >= 48 && hex <= 57 ? hex - 48 : hex >= 65 && hex <= 70 ? hex - 65 + 10 : hex >= 97 && hex <= 102 ? hex - 97 + 10 : -1;
1391
+ if (digit < 0) TomlError.x("invalid non-hex character in unicode escape", ctx);
1392
+ value = value << 4 | digit;
1393
+ }
1394
+ if (value < 0 || value > 1114111 || value >= 55296 && value <= 57343) TomlError.x("invalid unicode escape", ctx, errPtr);
1395
+ parsed += String.fromCodePoint(value);
1396
+ sliceStart = ctx.p--;
1397
+ state = 0;
1398
+ } else if (isMultiline && (c === 32 || c === 9)) state = 2;
1399
+ else {
1400
+ if (c === 98) parsed += "\b";
1401
+ else if (c === 116) parsed += " ";
1402
+ else if (c === 110) parsed += "\n";
1403
+ else if (c === 102) parsed += "\f";
1404
+ else if (c === 114) parsed += "\r";
1405
+ else if (c === 101) parsed += "\x1B";
1406
+ else if (c === 34) parsed += "\"";
1407
+ else if (c === 92) parsed += "\\";
1408
+ else TomlError.x("unrecognised escape sequence", ctx);
1409
+ sliceStart = ctx.p + 1;
1410
+ state = 0;
1411
+ }
1412
+ } else if (c !== 32 && c !== 9) {
1413
+ if (state === 2) TomlError.x("invalid escape: only line-ending whitespace may be escaped", ctx, sliceStart);
1414
+ state = !isLiteral && c === 92 ? 1 : 0;
1415
+ sliceStart = ctx.p;
1397
1416
  }
1398
1417
  }
1399
- return seek;
1418
+ TomlError.x("unfinished string", ctx, startPtr);
1400
1419
  }
1401
1420
 
1402
1421
  //#endregion
@@ -1428,31 +1447,48 @@ function getStringEnd(str, seek) {
1428
1447
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1429
1448
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1430
1449
  */
1431
- let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[T ]?(?:(\d{2}):\d{2}:\d{2}(?:\.\d+)?)?(Z|[-+]\d{2}:\d{2})?$/i;
1450
+ let DATE_TIME_RE = /^(\d{4}-\d{2}-\d{2})?[Tt ]?(?:(\d{2}):\d{2}(?::\d{2}(?:\.\d+)?)?)?(Z|z|[-+]\d{2}:\d{2})?$/i;
1432
1451
  var TomlDate = class TomlDate extends Date {
1433
1452
  #hasDate = false;
1434
1453
  #hasTime = false;
1435
1454
  #offset = null;
1436
- constructor(date) {
1455
+ constructor(date, fasttype, unsafeDelim) {
1437
1456
  let hasDate = true;
1438
1457
  let hasTime = true;
1439
1458
  let offset = "Z";
1459
+ let c;
1440
1460
  if (typeof date === "string") {
1441
- let match = date.match(DATE_TIME_RE);
1442
- if (match) {
1443
- if (!match[1]) {
1444
- hasDate = false;
1445
- date = `0000-01-01T${date}`;
1446
- }
1447
- hasTime = !!match[2];
1448
- hasTime && date[10] === " " && (date = date.replace(" ", "T"));
1449
- if (match[2] && +match[2] > 23) date = "";
1450
- else {
1451
- offset = match[3] || null;
1452
- date = date.toUpperCase();
1453
- if (!offset && hasTime) date += "Z";
1454
- }
1455
- } else date = "";
1461
+ if (fasttype) prep: {
1462
+ if (fasttype < 3) {
1463
+ if (+date.slice(11, 13) > 23) {
1464
+ date = "";
1465
+ break prep;
1466
+ }
1467
+ if (fasttype === 2) {
1468
+ offset = null;
1469
+ date += "Z";
1470
+ } else if ((c = date.charCodeAt(date.length - 1)) !== 90 && c !== 122) offset = date.slice(date.length - 6);
1471
+ if (unsafeDelim) date = date.slice(0, 10) + "T" + date.slice(11);
1472
+ } else if (fasttype === 4) date = +date.slice(0, 2) > 23 ? "" : `0000-01-01T${date}Z`;
1473
+ hasDate = fasttype !== 4;
1474
+ hasTime = fasttype !== 3;
1475
+ }
1476
+ else {
1477
+ let match = date.match(DATE_TIME_RE);
1478
+ if (match) {
1479
+ if (!match[1]) {
1480
+ hasDate = false;
1481
+ date = `0000-01-01T${date}`;
1482
+ }
1483
+ hasTime = !!match[2];
1484
+ hasTime && date[10] === " " && (date = date.replace(" ", "T"));
1485
+ if (match[2] && +match[2] > 23) date = "";
1486
+ else {
1487
+ offset = match[3] || null;
1488
+ if (!offset && hasTime) date += "Z";
1489
+ }
1490
+ } else date = "";
1491
+ }
1456
1492
  }
1457
1493
  super(date);
1458
1494
  if (!isNaN(this.getTime())) {
@@ -1481,7 +1517,7 @@ var TomlDate = class TomlDate extends Date {
1481
1517
  if (this.isDate()) return iso.slice(0, 10);
1482
1518
  if (this.isTime()) return iso.slice(11, 23);
1483
1519
  if (this.#offset === null) return iso.slice(0, -1);
1484
- if (this.#offset === "Z") return iso;
1520
+ if (this.#offset === "Z" || this.#offset === "z") return iso;
1485
1521
  let offset = +this.#offset.slice(1, 3) * 60 + +this.#offset.slice(4, 6);
1486
1522
  offset = this.#offset[0] === "-" ? offset : -offset;
1487
1523
  return (/* @__PURE__ */ new Date(this.getTime() - offset * 6e4)).toISOString().slice(0, -1) + this.#offset;
@@ -1511,7 +1547,7 @@ var TomlDate = class TomlDate extends Date {
1511
1547
  };
1512
1548
 
1513
1549
  //#endregion
1514
- //#region node_modules/smol-toml/dist/primitive.js
1550
+ //#region node_modules/smol-toml/dist/extract.js
1515
1551
  /*!
1516
1552
  * Copyright (c) Squirrel Chat et al., All rights reserved.
1517
1553
  * SPDX-License-Identifier: BSD-3-Clause
@@ -1539,117 +1575,147 @@ var TomlDate = class TomlDate extends Date {
1539
1575
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1540
1576
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1541
1577
  */
1542
- let INT_REGEX = /^((0x[0-9a-fA-F](_?[0-9a-fA-F])*)|(([+-]|0[ob])?\d(_?\d)*))$/;
1543
- let FLOAT_REGEX = /^[+-]?\d(_?\d)*(\.\d(_?\d)*)?([eE][+-]?\d(_?\d)*)?$/;
1544
- let LEADING_ZERO = /^[+-]?0[0-9_]/;
1545
- let ESCAPE_REGEX = /^[0-9a-f]{4,8}$/i;
1546
- let ESC_MAP = {
1547
- b: "\b",
1548
- t: " ",
1549
- n: "\n",
1550
- f: "\f",
1551
- r: "\r",
1552
- "\"": "\"",
1553
- "\\": "\\"
1554
- };
1555
- function parseString(str, ptr = 0, endPtr = str.length) {
1556
- let isLiteral = str[ptr] === "'";
1557
- let isMultiline = str[ptr++] === str[ptr] && str[ptr] === str[ptr + 1];
1558
- if (isMultiline) {
1559
- endPtr -= 2;
1560
- if (str[ptr += 2] === "\r") ptr++;
1561
- if (str[ptr] === "\n") ptr++;
1578
+ function isDigit(char, base = 10) {
1579
+ return base === 16 ? char > 47 && char < 58 || char > 64 && char < 71 || char > 96 && char < 103 : char > 47 && char < 48 + base;
1580
+ }
1581
+ function isEndOfValue(char, delim) {
1582
+ return char === 32 || char === 9 || char === 10 || char === 13 || delim && (char === delim || char === 44) || char === 35;
1583
+ }
1584
+ /** @internal */
1585
+ function extractValue(ctx, end) {
1586
+ let errPtr = ctx.p;
1587
+ let c = ctx.s.charCodeAt(ctx.p);
1588
+ if (c === 91 || c === 123) {
1589
+ ctx.d-- || TomlError.x("document contains excessively nested structures. aborting.", ctx);
1590
+ let value = c === 91 ? parseArray(ctx) : parseInlineTable(ctx);
1591
+ ctx.d++;
1592
+ return value;
1562
1593
  }
1563
- let tmp = 0;
1564
- let isEscape;
1565
- let parsed = "";
1566
- let sliceStart = ptr;
1567
- while (ptr < endPtr - 1) {
1568
- let c = str[ptr++];
1569
- if (c === "\n" || c === "\r" && str[ptr] === "\n") {
1570
- if (!isMultiline) throw new TomlError("newlines are not allowed in strings", {
1571
- toml: str,
1572
- ptr: ptr - 1
1573
- });
1574
- } else if (c < " " && c !== " " || c === "") throw new TomlError("control characters are not allowed in strings", {
1575
- toml: str,
1576
- ptr: ptr - 1
1577
- });
1578
- if (isEscape) {
1579
- isEscape = false;
1580
- if (c === "u" || c === "U") {
1581
- let code = str.slice(ptr, ptr += c === "u" ? 4 : 8);
1582
- if (!ESCAPE_REGEX.test(code)) throw new TomlError("invalid unicode escape", {
1583
- toml: str,
1584
- ptr: tmp
1585
- });
1586
- try {
1587
- parsed += String.fromCodePoint(parseInt(code, 16));
1588
- } catch {
1589
- throw new TomlError("invalid unicode escape", {
1590
- toml: str,
1591
- ptr: tmp
1592
- });
1593
- }
1594
- } else if (isMultiline && (c === "\n" || c === " " || c === " " || c === "\r")) {
1595
- ptr = skipVoid(str, ptr - 1, true);
1596
- if (str[ptr] !== "\n" && str[ptr] !== "\r") throw new TomlError("invalid escape: only line-ending whitespace may be escaped", {
1597
- toml: str,
1598
- ptr: tmp
1599
- });
1600
- ptr = skipVoid(str, ptr);
1601
- } else if (c in ESC_MAP) parsed += ESC_MAP[c];
1602
- else throw new TomlError("unrecognized escape sequence", {
1603
- toml: str,
1604
- ptr: tmp
1605
- });
1606
- sliceStart = ptr;
1607
- } else if (!isLiteral && c === "\\") {
1608
- tmp = ptr - 1;
1609
- isEscape = true;
1610
- parsed += str.slice(sliceStart, tmp);
1594
+ if (c === 34 || c === 39) return parseString(ctx);
1595
+ if (c === 116) {
1596
+ if (ctx.s.charCodeAt(++ctx.p) !== 114 || ctx.s.charCodeAt(++ctx.p) !== 117 || ctx.s.charCodeAt(++ctx.p) !== 101) TomlError.x("invalid value", ctx, errPtr);
1597
+ return ctx.p++, true;
1598
+ }
1599
+ if (c === 102) {
1600
+ if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 108 || ctx.s.charCodeAt(++ctx.p) !== 115 || ctx.s.charCodeAt(++ctx.p) !== 101) TomlError.x("invalid value", ctx, errPtr);
1601
+ return ctx.p++, false;
1602
+ }
1603
+ if (c === 43 || c === 45) return parseNumber(ctx, ctx.p, ctx.s.charCodeAt(++ctx.p), 44 - c, end);
1604
+ if (ctx.s.charCodeAt(ctx.p + 4) === 45 && ctx.s.charCodeAt(ctx.p + 7) === 45) return parseDate(ctx, c, end);
1605
+ if (ctx.s.charCodeAt(ctx.p + 2) === 58) return parseTime(ctx, c, end);
1606
+ return parseNumber(ctx, ctx.p, c, 0, end);
1607
+ }
1608
+ function parseNumber(ctx, startPtr, startChr, sign, endChr) {
1609
+ let c = startChr;
1610
+ let state = 0;
1611
+ let hasUnderscores = false;
1612
+ if (c === 105) {
1613
+ if (ctx.s.charCodeAt(++ctx.p) !== 110 || ctx.s.charCodeAt(++ctx.p) !== 102) TomlError.x("invalid value", ctx, startPtr);
1614
+ return ctx.p++, (sign || 1) / 0;
1615
+ }
1616
+ if (c === 110) {
1617
+ if (ctx.s.charCodeAt(++ctx.p) !== 97 || ctx.s.charCodeAt(++ctx.p) !== 110) TomlError.x("invalid value", ctx, startPtr);
1618
+ return ctx.p++, NaN;
1619
+ }
1620
+ if (c === 48) {
1621
+ if (++ctx.p >= ctx.s.length || isEndOfValue(c = ctx.s.charCodeAt(ctx.p), endChr)) return ctx.bi === true ? 0n : 0;
1622
+ if (!sign) {
1623
+ if (c === 120) return parseIntegerBaseN(ctx, startPtr, 16, endChr);
1624
+ else if (c === 98) return parseIntegerBaseN(ctx, startPtr, 2, endChr);
1625
+ else if (c === 111) return parseIntegerBaseN(ctx, startPtr, 8, endChr);
1611
1626
  }
1627
+ if (c === 46) state = 2;
1628
+ else if (c === 101 || c === 69) state = 4;
1629
+ else TomlError.x("illegal leading zero", ctx, startPtr);
1630
+ } else if (!isDigit(c)) TomlError.x("invalid value", ctx, startPtr);
1631
+ while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) {
1632
+ if (!state) state = 1;
1633
+ if (c === 95) {
1634
+ if (!(state & 1)) TomlError.x("illegal underscore", ctx);
1635
+ state += 11;
1636
+ hasUnderscores = true;
1637
+ } else if (state === 1 && c === 46) state = 2;
1638
+ else if ((state === 1 || state === 3) && (c === 101 || c === 69)) state = 4;
1639
+ else if (state === 4 && (c === 43 || c === 45)) state = 6;
1640
+ else if (!isDigit(c)) TomlError.x(`illegal character in numeric literal`, ctx);
1641
+ else if (state > 9) state -= 11;
1642
+ else if (!(state & 1)) state++;
1643
+ }
1644
+ if (!state) {
1645
+ let val = (startChr - 48) * (sign || 1);
1646
+ return ctx.bi === true ? BigInt(val) : val;
1647
+ }
1648
+ if (!(state & 1)) TomlError.x("unfinished numeric value", ctx, startPtr);
1649
+ let str = ctx.s.slice(startPtr, ctx.p);
1650
+ if (hasUnderscores) str = str.replaceAll("_", "");
1651
+ return state > 1 ? parseFloat(str) : parseInteger(ctx, str, 10, startPtr);
1652
+ }
1653
+ function parseIntegerBaseN(ctx, startPtr, base, endChr) {
1654
+ let c, underscore = 1;
1655
+ while (++ctx.p < ctx.s.length && (c = ctx.s.charCodeAt(ctx.p), !isEndOfValue(c, endChr))) if (c === 95) {
1656
+ if (underscore & 1) TomlError.x("illegal underscore", ctx);
1657
+ underscore = 3;
1658
+ } else if (!isDigit(c, base)) TomlError.x(`illegal character in numeric literal`, ctx);
1659
+ else if (underscore & 1) underscore--;
1660
+ if (underscore & 1) TomlError.x("unfinished numeric value", ctx);
1661
+ let str = ctx.s.slice(startPtr + 2, ctx.p);
1662
+ if (underscore) str = str.replaceAll("_", "");
1663
+ return parseInteger(ctx, str, base, startPtr);
1664
+ }
1665
+ function parseInteger(ctx, str, base, startPtr) {
1666
+ if (ctx.bi !== true) int: {
1667
+ let val = parseInt(str, base);
1668
+ if (!Number.isSafeInteger(val)) {
1669
+ if (ctx.bi) break int;
1670
+ TomlError.x("integer value cannot be represented losslessly", ctx, startPtr);
1671
+ }
1672
+ return val;
1673
+ }
1674
+ return base === 10 ? BigInt(str) : BigInt((base === 2 ? "0b" : base === 8 ? "0o" : "0x") + str);
1675
+ }
1676
+ function parseDate(ctx, c, endChr) {
1677
+ let startPtr = ctx.p++, unsafeSeparator;
1678
+ if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++)) || !isDigit(ctx.s.charCodeAt(ctx.p++))) return parseNumber(ctx, ctx.p = startPtr, c, 0, endChr);
1679
+ ctx.p += 5;
1680
+ if (!isDigit(ctx.s.charCodeAt(ctx.p++))) TomlError.x("invalid date-time: date part is malformed", ctx, startPtr);
1681
+ if (ctx.p >= ctx.s.length || ((c = ctx.s.charCodeAt(ctx.p)) !== 32 || (unsafeSeparator = true, !isDigit(ctx.s.charCodeAt(ctx.p + 1)))) && c !== 84 && c !== 116) return readDate(ctx, ctx.s.slice(startPtr, ctx.p), 3, false, startPtr);
1682
+ if (ctx.s.charCodeAt(ctx.p += 3) !== 58) TomlError.x("invalid date-time: time part is malformed", ctx, startPtr);
1683
+ if (ctx.s.charCodeAt(ctx.p += 3) === 58) ctx.p += 3;
1684
+ if (ctx.s.charCodeAt(ctx.p) === 46) while (isDigit(ctx.s.charCodeAt(++ctx.p)));
1685
+ if (c = ctx.s.charCodeAt(ctx.p)) {
1686
+ if (c === 90 || c === 122) return readDate(ctx, ctx.s.slice(startPtr, ++ctx.p), 1, unsafeSeparator, startPtr, "[+00:00]");
1687
+ if (c === 43 || c === 45) return readDate(ctx, ctx.s.slice(startPtr, ctx.p += 6), 1, unsafeSeparator, startPtr, !ctx.ld && "[" + ctx.s.slice(ctx.p - 6, ctx.p) + "]");
1688
+ }
1689
+ return readDate(ctx, ctx.s.slice(startPtr, ctx.p), 2, unsafeSeparator, startPtr);
1690
+ }
1691
+ function parseTime(ctx, c, endChr) {
1692
+ let start = ctx.p;
1693
+ if (!isDigit(c) || !isDigit(ctx.s.charCodeAt(++ctx.p))) return parseNumber(ctx, --ctx.p, c, 0, endChr);
1694
+ if (ctx.s.charCodeAt(ctx.p += 4) === 58) ctx.p += 3;
1695
+ if (ctx.s.charCodeAt(ctx.p) === 46) while (isDigit(ctx.s.charCodeAt(++ctx.p)));
1696
+ return readDate(ctx, ctx.s.slice(start, ctx.p), 4, false, start);
1697
+ }
1698
+ function readDate(ctx, str, type, unsafeDelim, errPtr, temporalSuffix) {
1699
+ if (ctx.ld) {
1700
+ let date = new TomlDate(str, type, unsafeDelim);
1701
+ if (!date.isValid()) TomlError.x("invalid date", ctx, errPtr);
1702
+ return date;
1612
1703
  }
1613
- return parsed + str.slice(sliceStart, endPtr - 1);
1614
- }
1615
- function parseValue(value, toml, ptr, integersAsBigInt) {
1616
- if (value === "true") return true;
1617
- if (value === "false") return false;
1618
- if (value === "-inf") return -Infinity;
1619
- if (value === "inf" || value === "+inf") return Infinity;
1620
- if (value === "nan" || value === "+nan" || value === "-nan") return NaN;
1621
- if (value === "-0") return integersAsBigInt ? 0n : 0;
1622
- let isInt = INT_REGEX.test(value);
1623
- if (isInt || FLOAT_REGEX.test(value)) {
1624
- if (LEADING_ZERO.test(value)) throw new TomlError("leading zeroes are not allowed", {
1625
- toml,
1626
- ptr
1627
- });
1628
- value = value.replace(/_/g, "");
1629
- let numeric = +value;
1630
- if (isNaN(numeric)) throw new TomlError("invalid number", {
1631
- toml,
1632
- ptr
1633
- });
1634
- if (isInt) {
1635
- if ((isInt = !Number.isSafeInteger(numeric)) && !integersAsBigInt) throw new TomlError("integer value cannot be represented losslessly", {
1636
- toml,
1637
- ptr
1638
- });
1639
- if (isInt || integersAsBigInt === true) numeric = BigInt(value);
1704
+ try {
1705
+ if (temporalSuffix) str += temporalSuffix;
1706
+ switch (type) {
1707
+ case 1: return Temporal.ZonedDateTime.from(str);
1708
+ case 2: return Temporal.PlainDateTime.from(str);
1709
+ case 3: return Temporal.PlainDate.from(str);
1710
+ case 4: return Temporal.PlainTime.from(str);
1640
1711
  }
1641
- return numeric;
1712
+ } catch (e) {
1713
+ TomlError.x(e instanceof Error ? e.message : "" + e, ctx, errPtr);
1642
1714
  }
1643
- const date = new TomlDate(value);
1644
- if (!date.isValid()) throw new TomlError("invalid value", {
1645
- toml,
1646
- ptr
1647
- });
1648
- return date;
1649
1715
  }
1650
1716
 
1651
1717
  //#endregion
1652
- //#region node_modules/smol-toml/dist/extract.js
1718
+ //#region node_modules/smol-toml/dist/util.js
1653
1719
  /*!
1654
1720
  * Copyright (c) Squirrel Chat et al., All rights reserved.
1655
1721
  * SPDX-License-Identifier: BSD-3-Clause
@@ -1677,66 +1743,26 @@ function parseValue(value, toml, ptr, integersAsBigInt) {
1677
1743
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1678
1744
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1679
1745
  */
1680
- function sliceAndTrimEndOf(str, startPtr, endPtr, allowNewLines) {
1681
- let value = str.slice(startPtr, endPtr);
1682
- let commentIdx = value.indexOf("#");
1683
- if (commentIdx > -1) {
1684
- skipComment(str, commentIdx);
1685
- value = value.slice(0, commentIdx);
1686
- }
1687
- let trimmed = value.trimEnd();
1688
- if (!allowNewLines) {
1689
- let newlineIdx = value.indexOf("\n", trimmed.length);
1690
- if (newlineIdx > -1) throw new TomlError("newlines are not allowed in inline tables", {
1691
- toml: str,
1692
- ptr: startPtr + newlineIdx
1693
- });
1694
- }
1695
- return [trimmed, commentIdx];
1696
- }
1697
- function extractValue(str, ptr, end, depth, integersAsBigInt) {
1698
- if (depth === 0) throw new TomlError("document contains excessively nested structures. aborting.", {
1699
- toml: str,
1700
- ptr
1701
- });
1702
- let c = str[ptr];
1703
- if (c === "[" || c === "{") {
1704
- let [value, endPtr] = c === "[" ? parseArray(str, ptr, depth, integersAsBigInt) : parseInlineTable(str, ptr, depth, integersAsBigInt);
1705
- let newPtr = end ? skipUntil(str, endPtr, ",", end) : endPtr;
1706
- if (endPtr - newPtr && end === "}") {
1707
- let nextNewLine = indexOfNewline(str, endPtr, newPtr);
1708
- if (nextNewLine > -1) throw new TomlError("newlines are not allowed in inline tables", {
1709
- toml: str,
1710
- ptr: nextNewLine
1711
- });
1712
- }
1713
- return [value, newPtr];
1714
- }
1715
- let endPtr;
1716
- if (c === "\"" || c === "'") {
1717
- endPtr = getStringEnd(str, ptr);
1718
- let parsed = parseString(str, ptr, endPtr);
1719
- if (end) {
1720
- endPtr = skipVoid(str, endPtr, end !== "]");
1721
- if (str[endPtr] && str[endPtr] !== "," && str[endPtr] !== end && str[endPtr] !== "\n" && str[endPtr] !== "\r") throw new TomlError("unexpected character encountered", {
1722
- toml: str,
1723
- ptr: endPtr
1724
- });
1725
- endPtr += +(str[endPtr] === ",");
1746
+ /** @internal */
1747
+ function skipComment(ctx) {
1748
+ for (; ctx.p < ctx.s.length; ctx.p++) {
1749
+ let c = ctx.s.charCodeAt(ctx.p);
1750
+ if (c === 10) break;
1751
+ if (c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10) {
1752
+ ctx.p++;
1753
+ break;
1726
1754
  }
1727
- return [parsed, endPtr];
1755
+ if (c < 32 && c !== 9 || c === 127) TomlError.x("control characters are not allowed in comments", ctx);
1728
1756
  }
1729
- endPtr = skipUntil(str, ptr, ",", end);
1730
- let slice = sliceAndTrimEndOf(str, ptr, endPtr - +(str[endPtr - 1] === ","), end === "]");
1731
- if (!slice[0]) throw new TomlError("incomplete key-value declaration: no value specified", {
1732
- toml: str,
1733
- ptr
1734
- });
1735
- if (end && slice[1] > -1) {
1736
- endPtr = skipVoid(str, ptr + slice[1]);
1737
- endPtr += +(str[endPtr] === ",");
1757
+ }
1758
+ /** @internal */
1759
+ function skipVoid(ctx, banNewLines, banComments) {
1760
+ let c;
1761
+ while (ctx.p < ctx.s.length) {
1762
+ while (ctx.p < ctx.s.length && ((c = ctx.s.charCodeAt(ctx.p)) === 32 || c === 9 || !banNewLines && (c === 10 || c === 13 && ctx.s.charCodeAt(ctx.p + 1) === 10))) ctx.p++;
1763
+ if (banComments || c !== 35) break;
1764
+ skipComment(ctx);
1738
1765
  }
1739
- return [parseValue(slice[0], str, ptr, integersAsBigInt), endPtr];
1740
1766
  }
1741
1767
 
1742
1768
  //#endregion
@@ -1768,132 +1794,99 @@ function extractValue(str, ptr, end, depth, integersAsBigInt) {
1768
1794
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1769
1795
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1770
1796
  */
1771
- let KEY_PART_RE = /^[a-zA-Z0-9-_]+[ \t]*$/;
1772
- function parseKey(str, ptr, end = "=") {
1773
- let dot = ptr - 1;
1797
+ /** @internal */
1798
+ function parseKey(ctx, end = 61) {
1799
+ let startPtr;
1800
+ let state = 0;
1774
1801
  let parsed = [];
1775
- let endPtr = str.indexOf(end, ptr);
1776
- if (endPtr < 0) throw new TomlError("incomplete key-value: cannot find end of key", {
1777
- toml: str,
1778
- ptr
1779
- });
1780
- do {
1781
- let c = str[ptr = ++dot];
1782
- if (c !== " " && c !== " ") {
1783
- if (c === "\"" || c === "'") {
1784
- if (c === str[ptr + 1] && c === str[ptr + 2]) throw new TomlError("multiline strings are not allowed in keys", {
1785
- toml: str,
1786
- ptr
1787
- });
1788
- let eos = getStringEnd(str, ptr);
1789
- if (eos < 0) throw new TomlError("unfinished string encountered", {
1790
- toml: str,
1791
- ptr
1792
- });
1793
- dot = str.indexOf(".", eos);
1794
- let strEnd = str.slice(eos, dot < 0 || dot > endPtr ? endPtr : dot);
1795
- let newLine = indexOfNewline(strEnd);
1796
- if (newLine > -1) throw new TomlError("newlines are not allowed in keys", {
1797
- toml: str,
1798
- ptr: ptr + dot + newLine
1799
- });
1800
- if (strEnd.trimStart()) throw new TomlError("found extra tokens after the string part", {
1801
- toml: str,
1802
- ptr: eos
1803
- });
1804
- if (endPtr < eos) {
1805
- endPtr = str.indexOf(end, eos);
1806
- if (endPtr < 0) throw new TomlError("incomplete key-value: cannot find end of key", {
1807
- toml: str,
1808
- ptr
1809
- });
1810
- }
1811
- parsed.push(parseString(str, ptr, eos));
1812
- } else {
1813
- dot = str.indexOf(".", ptr);
1814
- let part = str.slice(ptr, dot < 0 || dot > endPtr ? endPtr : dot);
1815
- if (!KEY_PART_RE.test(part)) throw new TomlError("only letter, numbers, dashes and underscores are allowed in keys", {
1816
- toml: str,
1817
- ptr
1818
- });
1819
- parsed.push(part.trimEnd());
1802
+ let sliceStart;
1803
+ let c = ctx.s.charCodeAt(startPtr = ctx.p);
1804
+ do
1805
+ if (c === end) {
1806
+ if (!state) TomlError.x("unexpected end of key", ctx);
1807
+ if (state === 1) parsed.push(ctx.s.slice(sliceStart, ctx.p));
1808
+ return ctx.p++, parsed;
1809
+ } else if (c === 46) {
1810
+ if (!state) TomlError.x("illegal empty bare key", ctx);
1811
+ if (state === 1) parsed.push(ctx.s.slice(sliceStart, ctx.p));
1812
+ state = 0;
1813
+ } else if (!state && (c === 34 || c === 39)) {
1814
+ if (c === ctx.s.charCodeAt(ctx.p + 1) && c === ctx.s.charCodeAt(ctx.p + 2)) TomlError.x("illegal quoted key: multiline strings are not allowed", ctx);
1815
+ parsed.push(parseString(ctx));
1816
+ state = 2;
1817
+ ctx.p--;
1818
+ } else if (c === 32 || c === 9) {
1819
+ if (state === 1) {
1820
+ parsed.push(ctx.s.slice(sliceStart, ctx.p));
1821
+ state = 2;
1820
1822
  }
1823
+ } else if (state === 2 || c < 48 && c !== 45 || c > 57 && c < 65 || c > 90 && c < 97 && c !== 95 || c > 122) TomlError.x("illegal character in key", ctx);
1824
+ else if (!state) {
1825
+ state = 1;
1826
+ sliceStart = ctx.p;
1821
1827
  }
1822
- } while (dot + 1 && dot < endPtr);
1823
- return [parsed, skipVoid(str, endPtr + 1, true, true)];
1828
+ while (c = ctx.s.charCodeAt(++ctx.p));
1829
+ TomlError.x("incomplete key-value: cannot find end of key", ctx, startPtr);
1824
1830
  }
1825
- function parseInlineTable(str, ptr, depth, integersAsBigInt) {
1826
- let res = {};
1831
+ /** @internal */
1832
+ function parseInlineTable(ctx) {
1833
+ let startPtr = ctx.p++;
1834
+ let res = Object.create(null);
1827
1835
  let seen = /* @__PURE__ */ new Set();
1828
1836
  let c;
1829
- let comma = 0;
1830
- ptr++;
1831
- while ((c = str[ptr++]) !== "}" && c) {
1832
- let err = {
1833
- toml: str,
1834
- ptr: ptr - 1
1835
- };
1836
- if (c === "\n") throw new TomlError("newlines are not allowed in inline tables", err);
1837
- else if (c === "#") throw new TomlError("inline tables cannot contain comments", err);
1838
- else if (c === ",") throw new TomlError("expected key-value, found comma", err);
1839
- else if (c !== " " && c !== " ") {
1840
- let k;
1841
- let t = res;
1842
- let hasOwn = false;
1843
- let [key, keyEndPtr] = parseKey(str, ptr - 1);
1844
- for (let i = 0; i < key.length; i++) {
1845
- if (i) t = hasOwn ? t[k] : t[k] = {};
1846
- k = key[i];
1847
- if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) throw new TomlError("trying to redefine an already defined value", {
1848
- toml: str,
1849
- ptr
1850
- });
1851
- if (!hasOwn && k === "__proto__") Object.defineProperty(t, k, {
1852
- enumerable: true,
1853
- configurable: true,
1854
- writable: true
1855
- });
1837
+ while (ctx.p < ctx.s.length) {
1838
+ skipVoid(ctx);
1839
+ if ((c = ctx.s.charCodeAt(ctx.p)) === 125) {
1840
+ ctx.p++;
1841
+ return res;
1842
+ }
1843
+ let k;
1844
+ let t = res;
1845
+ let hasOwn = false;
1846
+ let errPtr = ctx.p;
1847
+ let key = parseKey(ctx);
1848
+ for (let i = 0; i < key.length; i++) {
1849
+ if (i) t = hasOwn ? t[k] : t[k] = Object.create(null);
1850
+ k = key[i];
1851
+ if ((hasOwn = Object.hasOwn(t, k)) && (typeof t[k] !== "object" || seen.has(t[k]))) TomlError.x("trying to redefine an already defined value", ctx, errPtr);
1852
+ let unsafe = k === "__proto__";
1853
+ if (ctx.uk && (unsafe || k === "constructor")) {
1854
+ t = ctx.uk !== 1 && TomlError.x("document contains an unsafe property", ctx, errPtr);
1855
+ break;
1856
1856
  }
1857
- if (hasOwn) throw new TomlError("trying to redefine an already defined value", {
1858
- toml: str,
1859
- ptr
1857
+ if (!hasOwn && unsafe) Object.defineProperty(t, k, {
1858
+ enumerable: true,
1859
+ configurable: true,
1860
+ writable: true
1860
1861
  });
1861
- let [value, valueEndPtr] = extractValue(str, keyEndPtr, "}", depth - 1, integersAsBigInt);
1862
- seen.add(value);
1863
- t[k] = value;
1864
- ptr = valueEndPtr;
1865
- comma = str[ptr - 1] === "," ? ptr - 1 : 0;
1866
1862
  }
1867
- }
1868
- if (comma) throw new TomlError("trailing commas are not allowed in inline tables", {
1869
- toml: str,
1870
- ptr: comma
1871
- });
1872
- if (!c) throw new TomlError("unfinished table encountered", {
1873
- toml: str,
1874
- ptr
1875
- });
1876
- return [res, ptr];
1877
- }
1878
- function parseArray(str, ptr, depth, integersAsBigInt) {
1863
+ if (hasOwn) TomlError.x("trying to redefine an already defined value", ctx, errPtr);
1864
+ skipVoid(ctx, true, true);
1865
+ let value = extractValue(ctx, 125);
1866
+ if (t && typeof (t[k] = value) === "object") seen.add(value);
1867
+ skipVoid(ctx);
1868
+ if ((c = ctx.s.charCodeAt(ctx.p++)) === 125) return res;
1869
+ if (c !== 44) TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
1870
+ }
1871
+ TomlError.x("unfinished table", ctx, startPtr);
1872
+ }
1873
+ /** @internal */
1874
+ function parseArray(ctx) {
1875
+ let startPtr = ctx.p++;
1879
1876
  let res = [];
1880
1877
  let c;
1881
- ptr++;
1882
- while ((c = str[ptr++]) !== "]" && c) if (c === ",") throw new TomlError("expected value, found comma", {
1883
- toml: str,
1884
- ptr: ptr - 1
1885
- });
1886
- else if (c === "#") ptr = skipComment(str, ptr);
1887
- else if (c !== " " && c !== " " && c !== "\n" && c !== "\r") {
1888
- let e = extractValue(str, ptr - 1, "]", depth - 1, integersAsBigInt);
1889
- res.push(e[0]);
1890
- ptr = e[1];
1891
- }
1892
- if (!c) throw new TomlError("unfinished array encountered", {
1893
- toml: str,
1894
- ptr
1895
- });
1896
- return [res, ptr];
1878
+ while (ctx.p < ctx.s.length) {
1879
+ skipVoid(ctx);
1880
+ if ((c = ctx.s.charCodeAt(ctx.p)) === 93) {
1881
+ ctx.p++;
1882
+ return res;
1883
+ }
1884
+ res.push(extractValue(ctx, 93));
1885
+ skipVoid(ctx);
1886
+ if ((c = ctx.s.charCodeAt(ctx.p++)) === 93) return res;
1887
+ if (c !== 44) TomlError.x("expected comma or end of structure", ctx, ctx.p - 1);
1888
+ }
1889
+ TomlError.x("unfinished array", ctx, startPtr);
1897
1890
  }
1898
1891
 
1899
1892
  //#endregion
@@ -1925,7 +1918,7 @@ function parseArray(str, ptr, depth, integersAsBigInt) {
1925
1918
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1926
1919
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1927
1920
  */
1928
- function peekTable(key, table, meta, type) {
1921
+ function peekTable(ctx, key, table, meta, type) {
1929
1922
  let t = table;
1930
1923
  let m = meta;
1931
1924
  let k;
@@ -1933,7 +1926,7 @@ function peekTable(key, table, meta, type) {
1933
1926
  let state;
1934
1927
  for (let i = 0; i < key.length; i++) {
1935
1928
  if (i) {
1936
- t = hasOwn ? t[k] : t[k] = {};
1929
+ t = hasOwn ? t[k] : t[k] = Object.create(null);
1937
1930
  m = (state = m[k]).c;
1938
1931
  if (type === 0 && (state.t === 1 || state.t === 2)) return null;
1939
1932
  if (state.t === 2) {
@@ -1945,7 +1938,9 @@ function peekTable(key, table, meta, type) {
1945
1938
  k = key[i];
1946
1939
  if ((hasOwn = Object.hasOwn(t, k)) && m[k]?.t === 0 && m[k]?.d) return null;
1947
1940
  if (!hasOwn) {
1948
- if (k === "__proto__") {
1941
+ let unsafe = k === "__proto__";
1942
+ if (ctx.uk && (unsafe || k === "constructor")) return false;
1943
+ if (unsafe) {
1949
1944
  Object.defineProperty(t, k, {
1950
1945
  enumerable: true,
1951
1946
  configurable: true,
@@ -1961,7 +1956,7 @@ function peekTable(key, table, meta, type) {
1961
1956
  t: i < key.length - 1 && type === 2 ? 3 : type,
1962
1957
  d: false,
1963
1958
  i: 0,
1964
- c: {}
1959
+ c: Object.create(null)
1965
1960
  };
1966
1961
  }
1967
1962
  }
@@ -1972,17 +1967,17 @@ function peekTable(key, table, meta, type) {
1972
1967
  state.d = true;
1973
1968
  t[k] = [];
1974
1969
  }
1975
- t[k].push(t = {});
1970
+ t[k].push(t = Object.create(null));
1976
1971
  state.c[state.i++] = state = {
1977
1972
  t: 1,
1978
1973
  d: false,
1979
1974
  i: 0,
1980
- c: {}
1975
+ c: Object.create(null)
1981
1976
  };
1982
1977
  }
1983
1978
  if (state.d) return null;
1984
1979
  state.d = true;
1985
- if (type === 1) t = hasOwn ? t[k] : t[k] = {};
1980
+ if (type === 1) t = hasOwn ? t[k] : t[k] = Object.create(null);
1986
1981
  else if (type === 0 && hasOwn) return null;
1987
1982
  return [
1988
1983
  k,
@@ -1990,47 +1985,55 @@ function peekTable(key, table, meta, type) {
1990
1985
  state.c
1991
1986
  ];
1992
1987
  }
1993
- function parse$1(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
1994
- let res = {};
1995
- let meta = {};
1988
+ function validateTablePeek(ctx, peek, ptr) {
1989
+ if (peek === null || ctx.uk === 2) TomlError.x(peek === null ? "trying to redefine an already defined table or value" : "document contains an unsafe property", ctx, ptr);
1990
+ }
1991
+ function parse$1(toml, options = {}) {
1992
+ let ctx = {
1993
+ s: toml,
1994
+ p: 0,
1995
+ d: options.maxDepth ?? 1e3,
1996
+ bi: options.integersAsBigInt ?? false,
1997
+ ld: options.useLegacyDate ?? true,
1998
+ uk: options.unsafeKeyBehaviour === "throw" ? 2 : options.unsafeKeyBehaviour === "drop" ? 1 : 0
1999
+ };
2000
+ let res = Object.create(null);
2001
+ let meta = Object.create(null);
2002
+ let tmp;
2003
+ let skipping = false;
1996
2004
  let tbl = res;
1997
2005
  let m = meta;
1998
- for (let ptr = skipVoid(toml, 0); ptr < toml.length;) {
1999
- if (toml[ptr] === "[") {
2000
- let isTableArray = toml[++ptr] === "[";
2001
- let k = parseKey(toml, ptr += +isTableArray, "]");
2006
+ if (toml.charCodeAt(0) === 65279) ctx.p++;
2007
+ skipVoid(ctx);
2008
+ while (ctx.p < toml.length) {
2009
+ if (toml.charCodeAt(ctx.p) === 91) {
2010
+ let isTableArray = toml.charCodeAt(++ctx.p) === 91;
2011
+ tmp = ctx.p += +isTableArray;
2012
+ skipping = false;
2013
+ let k = parseKey(ctx, 93);
2002
2014
  if (isTableArray) {
2003
- if (toml[k[1] - 1] !== "]") throw new TomlError("expected end of table declaration", {
2004
- toml,
2005
- ptr: k[1] - 1
2006
- });
2007
- k[1]++;
2015
+ if (toml.charCodeAt(ctx.p) !== 93) TomlError.x("expected end of table array declaration", ctx);
2016
+ ctx.p++;
2017
+ }
2018
+ let p = peekTable(ctx, k, res, meta, isTableArray ? 2 : 1);
2019
+ if (!p) {
2020
+ validateTablePeek(ctx, p, tmp);
2021
+ skipping = true;
2022
+ } else {
2023
+ m = p[2];
2024
+ tbl = p[1];
2008
2025
  }
2009
- let p = peekTable(k[0], res, meta, isTableArray ? 2 : 1);
2010
- if (!p) throw new TomlError("trying to redefine an already defined table or value", {
2011
- toml,
2012
- ptr
2013
- });
2014
- m = p[2];
2015
- tbl = p[1];
2016
- ptr = k[1];
2017
2026
  } else {
2018
- let k = parseKey(toml, ptr);
2019
- let p = peekTable(k[0], tbl, m, 0);
2020
- if (!p) throw new TomlError("trying to redefine an already defined table or value", {
2021
- toml,
2022
- ptr
2023
- });
2024
- let v = extractValue(toml, k[1], void 0, maxDepth, integersAsBigInt);
2025
- p[1][p[0]] = v[0];
2026
- ptr = v[1];
2027
+ tmp = ctx.p;
2028
+ let p = peekTable(ctx, parseKey(ctx), tbl, m, 0);
2029
+ if (!p && !skipping) validateTablePeek(ctx, p, tmp);
2030
+ skipVoid(ctx, true, true);
2031
+ let v = extractValue(ctx, void 0);
2032
+ if (p && !skipping) p[1][p[0]] = v;
2027
2033
  }
2028
- ptr = skipVoid(toml, ptr, true);
2029
- if (toml[ptr] && toml[ptr] !== "\n" && toml[ptr] !== "\r") throw new TomlError("each key-value declaration must be followed by an end-of-line", {
2030
- toml,
2031
- ptr
2032
- });
2033
- ptr = skipVoid(toml, ptr);
2034
+ skipVoid(ctx, true);
2035
+ if (ctx.p < toml.length && (tmp = toml.charCodeAt(ctx.p)) !== 10 && (tmp !== 13 || toml.charCodeAt(ctx.p + 1) !== 10)) TomlError.x("each key-value declaration must be followed by an end-of-line", ctx);
2036
+ skipVoid(ctx);
2034
2037
  }
2035
2038
  return res;
2036
2039
  }
@@ -2065,11 +2068,20 @@ function parse$1(toml, { maxDepth = 1e3, integersAsBigInt } = {}) {
2065
2068
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2066
2069
  */
2067
2070
  let BARE_KEY = /^[a-z0-9-_]+$/i;
2071
+ let HAS_WELLFORMED = !!"".isWellFormed;
2068
2072
  function extendedTypeOf(obj) {
2069
2073
  let type = typeof obj;
2070
2074
  if (type === "object") {
2071
2075
  if (Array.isArray(obj)) return "array";
2072
- if (obj instanceof Date) return "date";
2076
+ if (typeof obj.getUTCDate === "function" && obj instanceof Date) return "date";
2077
+ if (globalThis.Temporal) {
2078
+ if (obj.until) {
2079
+ if (obj instanceof Temporal.ZonedDateTime) return "temporal/tz+uc";
2080
+ if (obj instanceof Temporal.PlainDateTime || obj instanceof Temporal.PlainDate) return "temporal/uc";
2081
+ if (obj instanceof Temporal.PlainTime || obj instanceof Temporal.Instant) return "temporal";
2082
+ if (obj instanceof Temporal.PlainYearMonth) return "temporal/x";
2083
+ } else if (obj.toPlainDate && obj instanceof Temporal.PlainMonthDay || obj.negated && obj instanceof Temporal.Duration) return "temporal/x";
2084
+ }
2073
2085
  }
2074
2086
  return type;
2075
2087
  }
@@ -2077,61 +2089,79 @@ function isArrayOfTables(obj) {
2077
2089
  for (let i = 0; i < obj.length; i++) if (extendedTypeOf(obj[i]) !== "object") return false;
2078
2090
  return obj.length != 0;
2079
2091
  }
2092
+ function formatWellFormedStringUnchecked(s) {
2093
+ return JSON.stringify(s).replaceAll("", "\\u007f");
2094
+ }
2080
2095
  function formatString(s) {
2081
- return JSON.stringify(s).replace(/\x7f/g, "\\u007f");
2096
+ return formatWellFormedStringUnchecked(HAS_WELLFORMED ? s.toWellFormed() : s);
2082
2097
  }
2083
- function stringifyValue(val, type, depth, numberAsFloat) {
2098
+ function formatKey(s) {
2099
+ if (BARE_KEY.test(s)) return s;
2100
+ if (HAS_WELLFORMED && !s.isWellFormed()) throw new RangeError("key contains illegal lone surrogates");
2101
+ return formatWellFormedStringUnchecked(s);
2102
+ }
2103
+ function stringifyValue(val, type, depth, numberAsFloat, strictTemporal) {
2084
2104
  if (depth === 0) throw new Error("Could not stringify the object: maximum object depth exceeded");
2085
- if (type === "number") {
2086
- if (isNaN(val)) return "nan";
2087
- if (val === Infinity) return "inf";
2088
- if (val === -Infinity) return "-inf";
2089
- if (numberAsFloat && Number.isInteger(val)) return val.toFixed(1);
2090
- return val.toString();
2091
- }
2092
- if (type === "bigint" || type === "boolean") return val.toString();
2093
- if (type === "string") return formatString(val);
2094
- if (type === "date") {
2095
- if (isNaN(val.getTime())) throw new TypeError("cannot serialize invalid date");
2096
- return val.toISOString();
2097
- }
2098
- if (type === "object") return stringifyInlineTable(val, depth, numberAsFloat);
2099
- if (type === "array") return stringifyArray(val, depth, numberAsFloat);
2100
- }
2101
- function stringifyInlineTable(obj, depth, numberAsFloat) {
2105
+ switch (type) {
2106
+ case "number":
2107
+ if (isNaN(val)) return "nan";
2108
+ if (val === Infinity) return "inf";
2109
+ if (val === -Infinity) return "-inf";
2110
+ if (Number.isInteger(val) && (numberAsFloat || !Number.isSafeInteger(val))) return val.toFixed(1);
2111
+ case "bigint":
2112
+ case "boolean":
2113
+ case "temporal": return val.toString();
2114
+ case "string": return formatString(val);
2115
+ case "date":
2116
+ if (isNaN(val.getTime())) throw new TypeError("cannot serialize invalid date");
2117
+ return val.toISOString();
2118
+ case "object": return stringifyInlineTable(val, depth, numberAsFloat, strictTemporal);
2119
+ case "array": return stringifyArray(val, depth, numberAsFloat, strictTemporal);
2120
+ case "temporal/tz+uc": if (strictTemporal) {
2121
+ let tz = val.timeZoneId;
2122
+ let tzc = tz.charCodeAt(0);
2123
+ if (tzc !== 43 && tzc !== 45 && (tzc !== 85 && tzc !== 71 && tzc !== 90 && tzc !== 69 || tz !== "UTC" && tz !== "UCT" && tz !== "Universal" && tz !== "Zulu" && !tz.startsWith("GMT") && tz !== "Greenwich" && !tz.startsWith("Etc/"))) throw new TypeError("Temporal objects with an IANA timezone are not allowed in Temporal strict mode");
2124
+ }
2125
+ case "temporal/uc":
2126
+ if (strictTemporal && val.calendarId !== "iso8601") throw new TypeError("Temporal objects with a non-default calendar are not allowed in Temporal strict mode");
2127
+ return val.toString({
2128
+ calendarName: "never",
2129
+ timeZoneName: "never"
2130
+ });
2131
+ case "temporal/x": throw new TypeError("Unsupported " + val[Symbol.toStringTag]);
2132
+ }
2133
+ }
2134
+ function stringifyInlineTable(obj, depth, numberAsFloat, strictTemporal) {
2102
2135
  let keys = Object.keys(obj);
2103
2136
  if (keys.length === 0) return "{}";
2104
2137
  let res = "{ ";
2105
2138
  for (let i = 0; i < keys.length; i++) {
2106
2139
  let k = keys[i];
2107
2140
  if (i) res += ", ";
2108
- res += BARE_KEY.test(k) ? k : formatString(k);
2109
- res += " = ";
2110
- res += stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat);
2141
+ res += formatKey(k) + " = " + stringifyValue(obj[k], extendedTypeOf(obj[k]), depth - 1, numberAsFloat, strictTemporal);
2111
2142
  }
2112
2143
  return res + " }";
2113
2144
  }
2114
- function stringifyArray(array, depth, numberAsFloat) {
2145
+ function stringifyArray(array, depth, numberAsFloat, strictTemporal) {
2115
2146
  if (array.length === 0) return "[]";
2116
2147
  let res = "[ ";
2117
2148
  for (let i = 0; i < array.length; i++) {
2118
2149
  if (i) res += ", ";
2119
2150
  if (array[i] === null || array[i] === void 0) throw new TypeError("arrays cannot contain null or undefined values");
2120
- res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat);
2151
+ res += stringifyValue(array[i], extendedTypeOf(array[i]), depth - 1, numberAsFloat, strictTemporal);
2121
2152
  }
2122
2153
  return res + " ]";
2123
2154
  }
2124
- function stringifyArrayTable(array, key, depth, numberAsFloat) {
2155
+ function stringifyArrayTable(array, key, depth, numberAsFloat, strictTemporal) {
2125
2156
  if (depth === 0) throw new Error("Could not stringify the object: maximum object depth exceeded");
2126
2157
  let res = "";
2127
2158
  for (let i = 0; i < array.length; i++) {
2128
- res += `[[${key}]]\n`;
2129
- res += stringifyTable(array[i], key, depth, numberAsFloat);
2130
- res += "\n\n";
2159
+ res += `${res && "\n"}[[${key}]]\n`;
2160
+ res += stringifyTable(0, array[i], key, depth, numberAsFloat, strictTemporal);
2131
2161
  }
2132
2162
  return res;
2133
2163
  }
2134
- function stringifyTable(obj, prefix, depth, numberAsFloat) {
2164
+ function stringifyTable(tableKey, obj, prefix, depth, numberAsFloat, strictTemporal) {
2135
2165
  if (depth === 0) throw new Error("Could not stringify the object: maximum object depth exceeded");
2136
2166
  let preamble = "";
2137
2167
  let tables = "";
@@ -2141,39 +2171,78 @@ function stringifyTable(obj, prefix, depth, numberAsFloat) {
2141
2171
  if (obj[k] !== null && obj[k] !== void 0) {
2142
2172
  let type = extendedTypeOf(obj[k]);
2143
2173
  if (type === "symbol" || type === "function") throw new TypeError(`cannot serialize values of type '${type}'`);
2144
- let key = BARE_KEY.test(k) ? k : formatString(k);
2145
- if (type === "array" && isArrayOfTables(obj[k])) tables += stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat);
2174
+ let key = formatKey(k);
2175
+ if (type === "array" && isArrayOfTables(obj[k])) tables += (tables && "\n") + stringifyArrayTable(obj[k], prefix ? `${prefix}.${key}` : key, depth - 1, numberAsFloat, strictTemporal);
2146
2176
  else if (type === "object") {
2147
2177
  let tblKey = prefix ? `${prefix}.${key}` : key;
2148
- tables += `[${tblKey}]\n`;
2149
- tables += stringifyTable(obj[k], tblKey, depth - 1, numberAsFloat);
2150
- tables += "\n\n";
2178
+ tables += (tables && "\n") + stringifyTable(tblKey, obj[k], tblKey, depth - 1, numberAsFloat, strictTemporal);
2151
2179
  } else {
2152
2180
  preamble += key;
2153
2181
  preamble += " = ";
2154
- preamble += stringifyValue(obj[k], type, depth, numberAsFloat);
2182
+ preamble += stringifyValue(obj[k], type, depth, numberAsFloat, strictTemporal);
2155
2183
  preamble += "\n";
2156
2184
  }
2157
2185
  }
2158
2186
  }
2159
- return `${preamble}\n${tables}`.trim();
2187
+ if (tableKey && (preamble || !tables)) preamble = preamble ? `[${tableKey}]\n${preamble}` : `[${tableKey}]`;
2188
+ return preamble && tables ? `${preamble}\n${tables}` : preamble || tables;
2160
2189
  }
2161
- function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false } = {}) {
2190
+ function stringify(obj, { maxDepth = 1e3, numbersAsFloat = false, strictTemporal = false } = {}) {
2162
2191
  if (extendedTypeOf(obj) !== "object") throw new TypeError("stringify can only be called with an object");
2163
- return stringifyTable(obj, "", maxDepth, numbersAsFloat);
2192
+ let str = stringifyTable(0, obj, "", maxDepth, numbersAsFloat, strictTemporal);
2193
+ if (str[str.length - 1] !== "\n") return str + "\n";
2194
+ return str;
2164
2195
  }
2165
2196
 
2197
+ //#endregion
2198
+ //#region node_modules/smol-toml/dist/index.js
2199
+ /*!
2200
+ * Copyright (c) Squirrel Chat et al., All rights reserved.
2201
+ * SPDX-License-Identifier: BSD-3-Clause
2202
+ *
2203
+ * Redistribution and use in source and binary forms, with or without
2204
+ * modification, are permitted provided that the following conditions are met:
2205
+ *
2206
+ * 1. Redistributions of source code must retain the above copyright notice, this
2207
+ * list of conditions and the following disclaimer.
2208
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
2209
+ * this list of conditions and the following disclaimer in the
2210
+ * documentation and/or other materials provided with the distribution.
2211
+ * 3. Neither the name of the copyright holder nor the names of its contributors
2212
+ * may be used to endorse or promote products derived from this software without
2213
+ * specific prior written permission.
2214
+ *
2215
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
2216
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2217
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2218
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
2219
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2220
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2221
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2222
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2223
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
2224
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2225
+ */
2226
+
2166
2227
  //#endregion
2167
2228
  //#region src/config.js
2168
2229
  async function assertSafePath(path) {
2169
- let current = parse(resolve(path)).root;
2170
- for (const part of resolve(path).slice(current.length).split(/[\\/]/).filter(Boolean)) {
2230
+ const full = resolve(path);
2231
+ let current = parse(full).root;
2232
+ for (const part of full.slice(current.length).split(/[\\/]/).filter(Boolean)) {
2171
2233
  current = join(current, part);
2234
+ let info;
2172
2235
  try {
2173
- if ((await lstat(current)).isSymbolicLink()) throw new Error(`Refusing symbolic link: ${current}`);
2236
+ info = await lstat(current);
2174
2237
  } catch (error) {
2175
- if (error.code !== "ENOENT") throw error;
2238
+ if (error.code === "ENOENT") return;
2239
+ throw error;
2176
2240
  }
2241
+ if (!info.isSymbolicLink()) continue;
2242
+ if (current === full) throw new Error(`Refusing symbolic link: ${current}`);
2243
+ await stat(current).catch((error) => {
2244
+ throw error.code === "ENOENT" ? /* @__PURE__ */ new Error(`Refusing dangling symbolic link: ${current}`) : error;
2245
+ });
2177
2246
  }
2178
2247
  }
2179
2248
  async function readConfig(path) {
@@ -2188,6 +2257,8 @@ async function readConfig(path) {
2188
2257
  function object(value) {
2189
2258
  return value !== null && typeof value === "object" && !Array.isArray(value);
2190
2259
  }
2260
+ const plain$1 = (value) => Array.isArray(value) ? value.map(plain$1) : value !== null && typeof value === "object" && Object.getPrototypeOf(value) === null ? Object.fromEntries(Object.entries(value).map(([key, item]) => [key, plain$1(item)])) : value;
2261
+ const parseToml = (text) => plain$1(parse$1(text));
2191
2262
  function parseJson(text, path) {
2192
2263
  const errors = [];
2193
2264
  const value = parse$2(text ?? "{}", errors, { allowTrailingComma: true });
@@ -2215,7 +2286,7 @@ function editJson(text, changes, path) {
2215
2286
  function updateToml(text, desired, path, obsolete = []) {
2216
2287
  const before = text ?? "";
2217
2288
  try {
2218
- parse$1(before);
2289
+ parseToml(before);
2219
2290
  } catch {
2220
2291
  throw new Error(`Invalid TOML in ${path}; nothing overwritten.`);
2221
2292
  }
@@ -2240,7 +2311,7 @@ function updateToml(text, desired, path, obsolete = []) {
2240
2311
  }
2241
2312
  let block = lines[i], parsed;
2242
2313
  for (;;) try {
2243
- parsed = parse$1(block);
2314
+ parsed = parseToml(block);
2244
2315
  break;
2245
2316
  } catch {
2246
2317
  if (++i >= lines.length) throw new Error(`Cannot safely update TOML in ${path}.`);
@@ -2275,7 +2346,7 @@ function updateToml(text, desired, path, obsolete = []) {
2275
2346
  else if (char === "=") break;
2276
2347
  }
2277
2348
  const rawKey = block.slice(0, equal).trim();
2278
- let cursor = parse$1(`${rawKey} = 0`), keys = [];
2349
+ let cursor = parseToml(`${rawKey} = 0`), keys = [];
2279
2350
  while (object(cursor)) {
2280
2351
  const key = Object.keys(cursor)[0];
2281
2352
  keys.push(key);
@@ -2309,7 +2380,7 @@ function updateToml(text, desired, path, obsolete = []) {
2309
2380
  }
2310
2381
  const leaves = (value, prefix = []) => Object.entries(value).flatMap(([key, item]) => object(item) ? leaves(item, [...prefix, key]) : [[[...prefix, key], item]]);
2311
2382
  for (const [keys, value] of leaves(desired)) {
2312
- const current = parse$1(statements.map((item) => item.text).join(eol));
2383
+ const current = parseToml(statements.map((item) => item.text).join(eol));
2313
2384
  if (isDeepStrictEqual(valueAt(current, keys), value)) continue;
2314
2385
  let header = -1, prefix = [];
2315
2386
  statements.forEach((item, index) => {
@@ -2326,7 +2397,7 @@ function updateToml(text, desired, path, obsolete = []) {
2326
2397
  });
2327
2398
  }
2328
2399
  const after = statements.map((item) => item.text).join(eol);
2329
- const result = parse$1(after);
2400
+ const result = parseToml(after);
2330
2401
  for (const [keys, value] of leaves(desired)) if (!isDeepStrictEqual(valueAt(result, keys), value)) throw new Error(`Cannot safely update ${keys.join(".")} in ${path}.`);
2331
2402
  return after === before ? before : `${after.replace(/\s+$/, "")}${eol}`;
2332
2403
  }
@@ -2380,9 +2451,50 @@ async function writeChange(change) {
2380
2451
 
2381
2452
  //#endregion
2382
2453
  //#region src/assistants.js
2383
- const MODEL = "callstack/Apex";
2384
- const BASE_URL = "https://api.callstack.ai/v1";
2385
- const GUIDE_URL = "https://app.notion.com/p/callstack/Apex-how-to-use-it-36d5d027c0f880e99d03d1c37a77382f";
2454
+ const VERCEL = "https://ai-gateway.vercel.sh";
2455
+ const PROVIDERS = {
2456
+ vercel: {
2457
+ id: "vercel",
2458
+ name: "Vercel AI Gateway",
2459
+ label: "Vercel AI Gateway",
2460
+ model: "callstack/apex",
2461
+ envVar: "AI_GATEWAY_API_KEY",
2462
+ keyName: "your Vercel AI Gateway API key",
2463
+ keysUrl: "https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai-gateway&title=AI+Gateway",
2464
+ guideUrl: "https://vercel.com/docs/ai-gateway/coding-agents",
2465
+ baseUrl: `${VERCEL}/coding-agent/v1`,
2466
+ codexUrl: `${VERCEL}/codex/v1`,
2467
+ cursorUrl: `${VERCEL}/cursor/v1`,
2468
+ anthropicUrl: `${VERCEL}/claude-code`,
2469
+ appUrl: `${VERCEL}/v1`,
2470
+ opencode: "apex-vercel",
2471
+ pi: "apex-vercel",
2472
+ codex: "apex_vercel"
2473
+ },
2474
+ callstack: {
2475
+ id: "callstack",
2476
+ name: "Callstack portal",
2477
+ label: "callstack.ai",
2478
+ model: "callstack/Apex",
2479
+ envVar: "CALLSTACK_AUTH_TOKEN",
2480
+ keyName: "your callstack.ai key",
2481
+ keysUrl: null,
2482
+ guideUrl: "https://app.notion.com/p/callstack/Apex-how-to-use-it-36d5d027c0f880e99d03d1c37a77382f",
2483
+ baseUrl: "https://api.callstack.ai/v1",
2484
+ codexUrl: "https://api.callstack.ai/v1",
2485
+ cursorUrl: "https://api.callstack.ai/v1",
2486
+ anthropicUrl: "https://api.callstack.ai",
2487
+ appUrl: "https://api.callstack.ai/v1",
2488
+ opencode: "callstack.ai",
2489
+ pi: "callstack",
2490
+ codex: "callstack_ai"
2491
+ }
2492
+ };
2493
+ const PROVIDER_IDS = Object.keys(PROVIDERS);
2494
+ function defaultProvider(env = process.env) {
2495
+ const keyed = PROVIDER_IDS.filter((id) => env[PROVIDERS[id].envVar]?.trim());
2496
+ return PROVIDERS[keyed.length === 1 ? keyed[0] : "vercel"];
2497
+ }
2386
2498
  const IDS = [
2387
2499
  "opencode",
2388
2500
  "codex",
@@ -2431,30 +2543,25 @@ const OPENCODE_MODEL = {
2431
2543
  options: { reasoningEffort: "medium" },
2432
2544
  variants: Object.fromEntries(EFFORTS.map((effort) => [effort, { reasoningEffort: effort }]))
2433
2545
  };
2434
- const OPENCODE_V2_PROVIDER = {
2435
- name: "callstack.ai",
2436
- package: "@opencode/ai/providers/openai-compatible",
2437
- settings: { baseURL: BASE_URL },
2438
- models: { [MODEL]: {
2439
- name: "Apex",
2440
- capabilities: {
2441
- tools: true,
2442
- input: ["text", "image"],
2443
- output: ["text"]
2444
- },
2445
- limit: {
2446
- context: CONTEXT_WINDOW,
2447
- output: MAX_OUTPUT
2448
- },
2449
- settings: { reasoningEffort: "medium" },
2450
- variants: EFFORTS.map((effort) => ({
2451
- id: effort,
2452
- settings: { reasoningEffort: effort }
2453
- }))
2454
- } }
2546
+ const OPENCODE_V2_PACKAGE = "@opencode/ai/providers/openai-compatible";
2547
+ const OPENCODE_V2_MODEL = {
2548
+ name: "Apex",
2549
+ capabilities: {
2550
+ tools: true,
2551
+ input: ["text", "image"],
2552
+ output: ["text"]
2553
+ },
2554
+ limit: {
2555
+ context: CONTEXT_WINDOW,
2556
+ output: MAX_OUTPUT
2557
+ },
2558
+ settings: { reasoningEffort: "medium" },
2559
+ variants: EFFORTS.map((effort) => ({
2560
+ id: effort,
2561
+ settings: { reasoningEffort: effort }
2562
+ }))
2455
2563
  };
2456
2564
  const PI_MODEL = {
2457
- id: MODEL,
2458
2565
  reasoning: true,
2459
2566
  input: ["text", "image"],
2460
2567
  thinkingLevelMap: {
@@ -2561,16 +2668,17 @@ async function detect(options = {}) {
2561
2668
  };
2562
2669
  }));
2563
2670
  }
2564
- async function openCodeHasKey(authFile) {
2671
+ async function openCodeHasKey(authFile, providerId) {
2565
2672
  if (!authFile) return false;
2566
2673
  try {
2567
- return Object.hasOwn(JSON.parse(await readConfig(authFile) ?? "{}"), "callstack.ai");
2674
+ return Object.hasOwn(JSON.parse(await readConfig(authFile) ?? "{}"), providerId);
2568
2675
  } catch {
2569
2676
  return false;
2570
2677
  }
2571
2678
  }
2572
2679
  const PI_PLACEHOLDER = "XXX";
2573
- async function planAssistant(assistant) {
2680
+ async function planAssistant(assistant, provider = PROVIDERS.vercel) {
2681
+ const { model, envVar } = provider;
2574
2682
  const changes = [];
2575
2683
  const json = async (filename, updates) => {
2576
2684
  const path = join(assistant.directory, filename);
@@ -2589,124 +2697,131 @@ async function planAssistant(assistant) {
2589
2697
  const hasJsonc = await exists(join(assistant.directory, "opencode.jsonc"));
2590
2698
  if (hasJson && hasJsonc) throw new Error("Both opencode.json and opencode.jsonc exist. Consolidate them before init.");
2591
2699
  let v2 = false;
2592
- const storedKey = await openCodeHasKey(assistant.authFile);
2700
+ const id = provider.opencode;
2701
+ const storedKey = await openCodeHasKey(assistant.authFile, id);
2593
2702
  await json(hasJsonc ? "opencode.jsonc" : "opencode.json", (existing) => {
2594
2703
  v2 = Object.hasOwn(existing, "providers");
2595
2704
  if (v2) return [
2596
2705
  [[
2597
2706
  "providers",
2598
- "callstack.ai",
2707
+ id,
2599
2708
  "name"
2600
- ], OPENCODE_V2_PROVIDER.name],
2709
+ ], provider.label],
2601
2710
  [[
2602
2711
  "providers",
2603
- "callstack.ai",
2712
+ id,
2604
2713
  "package"
2605
- ], OPENCODE_V2_PROVIDER.package],
2714
+ ], OPENCODE_V2_PACKAGE],
2606
2715
  [[
2607
2716
  "providers",
2608
- "callstack.ai",
2717
+ id,
2609
2718
  "settings",
2610
2719
  "baseURL"
2611
- ], BASE_URL],
2612
- ...Object.entries(OPENCODE_V2_PROVIDER.models[MODEL]).map(([key, value]) => [[
2720
+ ], provider.baseUrl],
2721
+ ...Object.entries(OPENCODE_V2_MODEL).map(([key, value]) => [[
2613
2722
  "providers",
2614
- "callstack.ai",
2723
+ id,
2615
2724
  "models",
2616
- MODEL,
2725
+ model,
2617
2726
  key
2618
2727
  ], key === "settings" ? {
2619
- ...existing.providers?.["callstack.ai"]?.models?.[MODEL]?.settings,
2728
+ ...existing.providers?.[id]?.models?.[model]?.settings,
2620
2729
  ...value
2621
2730
  } : value])
2622
2731
  ];
2623
2732
  return [
2624
2733
  [[
2625
2734
  "provider",
2626
- "callstack.ai",
2735
+ id,
2627
2736
  "npm"
2628
2737
  ], "@ai-sdk/openai-compatible"],
2629
2738
  [[
2630
2739
  "provider",
2631
- "callstack.ai",
2740
+ id,
2632
2741
  "name"
2633
- ], "callstack.ai"],
2742
+ ], provider.label],
2634
2743
  [[
2635
2744
  "provider",
2636
- "callstack.ai",
2745
+ id,
2637
2746
  "options",
2638
2747
  "baseURL"
2639
- ], BASE_URL],
2640
- ...storedKey || existing.provider?.["callstack.ai"]?.options?.apiKey ? [] : [[[
2748
+ ], provider.baseUrl],
2749
+ ...storedKey || existing.provider?.[id]?.options?.apiKey ? [] : [[[
2641
2750
  "provider",
2642
- "callstack.ai",
2751
+ id,
2643
2752
  "options",
2644
2753
  "apiKey"
2645
- ], "{env:CALLSTACK_AUTH_TOKEN}"]],
2754
+ ], `{env:${envVar}}`]],
2646
2755
  ...Object.entries(OPENCODE_MODEL).map(([key, value]) => [[
2647
2756
  "provider",
2648
- "callstack.ai",
2757
+ id,
2649
2758
  "models",
2650
- MODEL,
2759
+ model,
2651
2760
  key
2652
2761
  ], key === "options" ? {
2653
- ...existing.provider?.["callstack.ai"]?.models?.[MODEL]?.options,
2762
+ ...existing.provider?.[id]?.models?.[model]?.options,
2654
2763
  ...value
2655
2764
  } : value])
2656
2765
  ];
2657
2766
  });
2658
- if (v2) changes[0].steps = ["OpenCode 2 stores provider keys itself: run /connect in OpenCode, pick callstack.ai → \"Manually enter API Key\", and paste your Callstack key."];
2767
+ if (v2) changes[0].steps = [`OpenCode 2 stores provider keys itself: run /connect in OpenCode, pick ${provider.label} → "Manually enter API Key", and paste ${provider.keyName}.`];
2659
2768
  break;
2660
2769
  }
2661
- case "pi":
2770
+ case "pi": {
2771
+ const id = provider.pi;
2772
+ const entry = {
2773
+ id: model,
2774
+ ...PI_MODEL
2775
+ };
2662
2776
  await json("models.json", (existing) => {
2663
- const models = existing.providers?.callstack?.models ?? [];
2664
- const key = existing.providers?.callstack?.apiKey;
2665
- if (!Array.isArray(models) || models.some((model) => !model || typeof model.id !== "string")) throw new Error("Expected Pi models to be an array of model objects.");
2777
+ const models = existing.providers?.[id]?.models ?? [];
2778
+ const key = existing.providers?.[id]?.apiKey;
2779
+ if (!Array.isArray(models) || models.some((item) => !item || typeof item.id !== "string")) throw new Error("Expected Pi models to be an array of model objects.");
2666
2780
  return [
2667
2781
  [[
2668
2782
  "providers",
2669
- "callstack",
2783
+ id,
2670
2784
  "baseUrl"
2671
- ], BASE_URL],
2785
+ ], provider.baseUrl],
2672
2786
  [[
2673
2787
  "providers",
2674
- "callstack",
2788
+ id,
2675
2789
  "api"
2676
2790
  ], "openai-completions"],
2677
2791
  ...key && key !== PI_PLACEHOLDER ? [] : [[[
2678
2792
  "providers",
2679
- "callstack",
2793
+ id,
2680
2794
  "apiKey"
2681
- ], "$CALLSTACK_AUTH_TOKEN"]],
2795
+ ], `$${envVar}`]],
2682
2796
  [[
2683
2797
  "providers",
2684
- "callstack",
2798
+ id,
2685
2799
  "models"
2686
- ], models.some((model) => model.id === "callstack/Apex") ? models.map((model) => model.id === "callstack/Apex" ? {
2687
- ...model,
2688
- ...PI_MODEL,
2689
- ...model.compat ? { compat: Object.fromEntries(Object.entries(model.compat).filter(([key]) => key !== "reasoningEffortMap")) } : {}
2690
- } : model) : [...models, PI_MODEL]]
2800
+ ], models.some((item) => item.id === model) ? models.map((item) => item.id === model ? {
2801
+ ...item,
2802
+ ...entry,
2803
+ ...item.compat ? { compat: Object.fromEntries(Object.entries(item.compat).filter(([key]) => key !== "reasoningEffortMap")) } : {}
2804
+ } : item) : [...models, entry]]
2691
2805
  ];
2692
2806
  });
2693
- await json("settings.json", [[["modelThinkingLevels", `callstack/${MODEL}`], "medium"]]);
2807
+ await json("settings.json", [[["modelThinkingLevels", `${id}/${model}`], "medium"]]);
2694
2808
  break;
2809
+ }
2695
2810
  case "claude":
2696
2811
  await json("settings.json", [[["env", "CLAUDE_CODE_ATTRIBUTION_HEADER"], "0"]]);
2697
2812
  break;
2698
2813
  case "codex": {
2699
- const path = join(assistant.directory, "callstack_ai.config.toml");
2814
+ const path = join(assistant.directory, `${provider.codex}.config.toml`);
2700
2815
  const before = await readConfig(path);
2701
2816
  const after = updateToml(before, {
2702
- model_provider: "callstack_ai",
2703
- model: MODEL,
2817
+ model_provider: provider.codex,
2818
+ model,
2704
2819
  model_context_window: CONTEXT_WINDOW,
2705
2820
  model_reasoning_effort: "medium",
2706
- model_providers: { callstack_ai: {
2707
- name: "callstack.ai",
2708
- base_url: BASE_URL,
2709
- env_key: "CALLSTACK_AUTH_TOKEN",
2821
+ model_providers: { [provider.codex]: {
2822
+ name: provider.label,
2823
+ base_url: provider.codexUrl,
2824
+ env_key: envVar,
2710
2825
  wire_api: "responses",
2711
2826
  requires_openai_auth: false
2712
2827
  } }
@@ -2722,25 +2837,26 @@ async function planAssistant(assistant) {
2722
2837
  }
2723
2838
  return changes;
2724
2839
  }
2725
- function launchOptions(id, env = process.env) {
2726
- const token = env.CALLSTACK_AUTH_TOKEN;
2727
- if (!token?.trim()) throw new Error("Set CALLSTACK_AUTH_TOKEN in your environment before launching.");
2840
+ function launchOptions(id, env = process.env, provider = defaultProvider(env)) {
2841
+ const { model, envVar } = provider;
2842
+ const token = env[envVar];
2843
+ if (!token?.trim()) throw new Error(`Set ${envVar} in your environment before launching with ${provider.name}.`);
2728
2844
  const childEnv = { ...env };
2729
2845
  switch (id) {
2730
2846
  case "opencode": return {
2731
- args: ["--model", `callstack.ai/${MODEL}`],
2847
+ args: ["--model", `${provider.opencode}/${model}`],
2732
2848
  env: childEnv
2733
2849
  };
2734
2850
  case "codex": return {
2735
- args: ["--profile", "callstack_ai"],
2851
+ args: ["--profile", provider.codex],
2736
2852
  env: childEnv
2737
2853
  };
2738
2854
  case "pi": return {
2739
2855
  args: [
2740
2856
  "--provider",
2741
- "callstack",
2857
+ provider.pi,
2742
2858
  "--model",
2743
- MODEL,
2859
+ model,
2744
2860
  "--thinking",
2745
2861
  "medium"
2746
2862
  ],
@@ -2755,33 +2871,33 @@ function launchOptions(id, env = process.env) {
2755
2871
  "CLAUDE_CODE_USE_FOUNDRY"
2756
2872
  ]) delete childEnv[key];
2757
2873
  Object.assign(childEnv, {
2758
- ANTHROPIC_BASE_URL: "https://api.callstack.ai",
2874
+ ANTHROPIC_BASE_URL: provider.anthropicUrl,
2759
2875
  ANTHROPIC_AUTH_TOKEN: token,
2760
- ANTHROPIC_MODEL: MODEL,
2876
+ ANTHROPIC_MODEL: model,
2761
2877
  CLAUDE_CODE_ATTRIBUTION_HEADER: "0",
2762
- ANTHROPIC_DEFAULT_OPUS_MODEL: MODEL,
2763
- ANTHROPIC_DEFAULT_SONNET_MODEL: MODEL,
2764
- ANTHROPIC_DEFAULT_HAIKU_MODEL: MODEL,
2765
- CLAUDE_CODE_SUBAGENT_MODEL: MODEL,
2878
+ ANTHROPIC_DEFAULT_OPUS_MODEL: model,
2879
+ ANTHROPIC_DEFAULT_SONNET_MODEL: model,
2880
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: model,
2881
+ CLAUDE_CODE_SUBAGENT_MODEL: model,
2766
2882
  CLAUDE_CODE_MAX_CONTEXT_TOKENS: String(CONTEXT_WINDOW),
2767
2883
  CLAUDE_CODE_MAX_OUTPUT_TOKENS: String(MAX_OUTPUT)
2768
2884
  });
2769
2885
  return {
2770
- args: ["--model", MODEL],
2886
+ args: ["--model", model],
2771
2887
  env: childEnv
2772
2888
  };
2773
2889
  default: throw new Error(`Cannot launch ${id}. Use the editor's model selector.`);
2774
2890
  }
2775
2891
  }
2776
2892
  const RUN_NOTE = { claude: "(ANTHROPIC_* gateway environment set)" };
2777
- function runExpansion(id) {
2778
- const { args } = launchOptions(id, { CALLSTACK_AUTH_TOKEN: "placeholder" });
2893
+ function runExpansion(id, provider) {
2894
+ const { args } = launchOptions(id, { [provider.envVar]: "placeholder" }, provider);
2779
2895
  return [`${id} ${args.join(" ")}`, RUN_NOTE[id]].filter(Boolean).join(" ");
2780
2896
  }
2781
- const COPILOT_MODEL = JSON.stringify({
2782
- id: MODEL,
2897
+ const copilotModel = (provider) => JSON.stringify({
2898
+ id: provider.model,
2783
2899
  name: "Apex",
2784
- url: BASE_URL,
2900
+ url: provider.baseUrl,
2785
2901
  toolCalling: true,
2786
2902
  vision: true,
2787
2903
  thinking: true,
@@ -2790,32 +2906,39 @@ const COPILOT_MODEL = JSON.stringify({
2790
2906
  supportsReasoningEffort: EFFORTS,
2791
2907
  reasoningEffortFormat: "chat-completions"
2792
2908
  }, null, 2);
2793
- const AI_SDK_SNIPPET = [
2909
+ const aiSdkSnippet = (provider) => [
2794
2910
  "import { createOpenAI } from '@ai-sdk/openai';",
2795
2911
  "",
2796
2912
  "const apex = createOpenAI({",
2797
2913
  " name: 'callstack',",
2798
- ` baseURL: '${BASE_URL}',`,
2799
- " apiKey: process.env.CALLSTACK_AUTH_TOKEN,",
2914
+ ` baseURL: '${provider.appUrl}',`,
2915
+ ` apiKey: process.env.${provider.envVar},`,
2800
2916
  "});",
2801
2917
  "const requestOptions = {",
2802
- ` model: apex('${MODEL}'),`,
2918
+ ` model: apex('${provider.model}'),`,
2803
2919
  ` maxOutputTokens: ${MAX_OUTPUT},`,
2804
2920
  "};",
2805
2921
  "// Pass requestOptions with your prompt to generateText / streamText.",
2806
2922
  `// Reasoning effort (${EFFORTS.join(", ")}):`,
2807
2923
  "// providerOptions: { callstack: { reasoningEffort: 'medium' } }"
2808
2924
  ];
2809
- const MANUAL = {
2810
- cursor: [`Cursor: Settings → Models → API Keys → OpenAI API Key. Enter your Callstack key, override the base URL with ${BASE_URL}, add and enable ${MODEL}, then select it in Agent.`, "Cursor has no way to declare what a custom model can do (tool calling, vision, reasoning); it infers that itself."],
2811
- copilot: [
2812
- "Installation of Copilot itself is not verified: Copilot → model selector → Manage Models → Add Models → Custom Endpoint → name callstack.ai → enter your key → Chat Completions.",
2813
- "Keep the generated apiKey secret reference; add this object to its models array:",
2814
- ...COPILOT_MODEL.split("\n")
2815
- ],
2816
- "ai-sdk": ["Apex CLI never writes your key into a project. Keep it in CALLSTACK_AUTH_TOKEN (for example in a .env that git ignores) and create the provider with:", ...AI_SDK_SNIPPET]
2817
- };
2818
- const MANUAL_IDS = Object.keys(MANUAL);
2925
+ const MANUAL_IDS = [
2926
+ "cursor",
2927
+ "copilot",
2928
+ "ai-sdk"
2929
+ ];
2930
+ function manualSteps(id, provider) {
2931
+ switch (id) {
2932
+ case "cursor": return [`Cursor: Settings → Models → API Keys → OpenAI API Key. Enter ${provider.keyName}, override the base URL with ${provider.cursorUrl}, add and enable ${provider.model}, then select it in Agent.`, "Cursor has no way to declare what a custom model can do (tool calling, vision, reasoning); it infers that itself."];
2933
+ case "copilot": return [
2934
+ `Installation of Copilot itself is not verified: Copilot → model selector → Manage Models → Add Models → Custom Endpoint → name ${provider.label} → enter ${provider.keyName} → Chat Completions.`,
2935
+ "Keep the generated apiKey secret reference; add this object to its models array:",
2936
+ ...copilotModel(provider).split("\n")
2937
+ ];
2938
+ case "ai-sdk": return [`Apex CLI never writes your key into a project. Keep it in ${provider.envVar} (for example in a .env that git ignores) and create the provider with:`, ...aiSdkSnippet(provider)];
2939
+ default: throw new Error(`${id} is set up automatically.`);
2940
+ }
2941
+ }
2819
2942
 
2820
2943
  //#endregion
2821
2944
  //#region node_modules/fast-string-truncated-width/dist/utils.js
@@ -3514,6 +3637,32 @@ var a = class extends y {
3514
3637
  });
3515
3638
  }
3516
3639
  };
3640
+ let n$1 = class n extends y {
3641
+ options;
3642
+ cursor = 0;
3643
+ get _selectedValue() {
3644
+ return this.options[this.cursor];
3645
+ }
3646
+ changeValue() {
3647
+ const e = this._selectedValue;
3648
+ this.value = e === void 0 ? void 0 : e.value;
3649
+ }
3650
+ constructor(e) {
3651
+ super(e, false), this.options = e.options;
3652
+ const o = this.options.findIndex(({ value: s }) => s === e.initialValue), t = o === -1 ? 0 : o;
3653
+ this.cursor = this.options[t]?.disabled ? findCursor(t, 1, this.options) : t, this.changeValue(), this.on("cursor", (s) => {
3654
+ switch (s) {
3655
+ case "left":
3656
+ case "up":
3657
+ this.cursor = findCursor(this.cursor, -1, this.options);
3658
+ break;
3659
+ case "down":
3660
+ case "right": this.cursor = findCursor(this.cursor, 1, this.options);
3661
+ }
3662
+ this.changeValue();
3663
+ });
3664
+ }
3665
+ };
3517
3666
 
3518
3667
  //#endregion
3519
3668
  //#region node_modules/@clack/prompts/dist/index.mjs
@@ -3745,6 +3894,63 @@ const u = {
3745
3894
  block: unicodeOr("█", "#")
3746
3895
  };
3747
3896
  const SELECT_INSTRUCTIONS = [`${styleText("dim", "↑/↓")} to navigate`, `${styleText("dim", "Enter:")} confirm`];
3897
+ const c = (t, o) => t.includes(`
3898
+ `) ? t.split(`
3899
+ `).map((d) => o(d)).join(`
3900
+ `) : o(t);
3901
+ const select = (t) => {
3902
+ const o = (n, m) => {
3903
+ if (n === void 0) return "";
3904
+ const s = n.label ?? String(n.value);
3905
+ switch (m) {
3906
+ case "disabled": return `${styleText("gray", S_RADIO_INACTIVE)} ${c(s, (i) => styleText("gray", i))}${n.hint ? ` ${styleText("dim", `(${n.hint ?? "disabled"})`)}` : ""}`;
3907
+ case "selected": return `${c(s, (i) => styleText("dim", i))}`;
3908
+ case "active": return `${styleText("green", S_RADIO_ACTIVE)} ${s}${n.hint ? ` ${styleText("dim", `(${n.hint})`)}` : ""}`;
3909
+ case "cancelled": return `${c(s, (i) => styleText(["strikethrough", "dim"], i))}`;
3910
+ default: return `${styleText("dim", S_RADIO_INACTIVE)} ${c(s, (i) => styleText("dim", i))}`;
3911
+ }
3912
+ }, d = t.showInstructions ?? true;
3913
+ return new n$1({
3914
+ options: t.options,
3915
+ signal: t.signal,
3916
+ input: t.input,
3917
+ output: t.output,
3918
+ initialValue: t.initialValue,
3919
+ render() {
3920
+ const n = t.withGuide ?? settings.withGuide, m = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i = wrapTextWithPrefix(t.output, t.message, s, m), u = `${n ? `${styleText("gray", S_BAR)}
3921
+ ` : ""}${i}
3922
+ `;
3923
+ switch (this.state) {
3924
+ case "submit": {
3925
+ const r = n ? `${styleText("gray", S_BAR)} ` : "";
3926
+ return `${u}${wrapTextWithPrefix(t.output, o(this.options[this.cursor], "selected"), r)}`;
3927
+ }
3928
+ case "cancel": {
3929
+ const r = n ? `${styleText("gray", S_BAR)} ` : "";
3930
+ return `${u}${wrapTextWithPrefix(t.output, o(this.options[this.cursor], "cancelled"), r)}${n ? `
3931
+ ${styleText("gray", S_BAR)}` : ""}`;
3932
+ }
3933
+ default: {
3934
+ const r = n ? `${styleText("cyan", S_BAR)} ` : "", a = u.split(`
3935
+ `).length, p = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n) : n ? [styleText("cyan", S_BAR_END)] : [], f = p.join(`
3936
+ `), b = p.length + 1;
3937
+ return `${u}${r}${limitOptions({
3938
+ output: t.output,
3939
+ cursor: this.cursor,
3940
+ options: this.options,
3941
+ maxItems: t.maxItems,
3942
+ columnPadding: r.length,
3943
+ rowPadding: a + b,
3944
+ style: (g, x) => o(g, g.disabled ? "disabled" : x ? "active" : "inactive")
3945
+ }).join(`
3946
+ ${r}`)}
3947
+ ${f}
3948
+ `;
3949
+ }
3950
+ }
3951
+ }
3952
+ }).prompt();
3953
+ };
3748
3954
  const i = `${styleText("gray", S_BAR)} `;
3749
3955
 
3750
3956
  //#endregion
@@ -3792,7 +3998,7 @@ const maskChanges = (changes, secret) => changes.map((change) => ({
3792
3998
  //#region src/diff.js
3793
3999
  function readValues(text, format) {
3794
4000
  if (format === "toml") try {
3795
- return parse$1(text);
4001
+ return parseToml(text);
3796
4002
  } catch {
3797
4003
  throw new Error("Invalid TOML while reading values.");
3798
4004
  }
@@ -4001,7 +4207,8 @@ const pad = (text, column) => {
4001
4207
  const value = String(text);
4002
4208
  return value + " ".repeat(Math.max(1, column - visible(value).length));
4003
4209
  };
4004
- const MODEL_PATTERN = new RegExp(`(?<![\\w/.-])${MODEL.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`, "g");
4210
+ const MODELS = [...new Set(Object.values(PROVIDERS).map((provider) => provider.model))].map((id) => id.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
4211
+ const MODEL_PATTERN = new RegExp(`(?<![\\w/.-])(?:${MODELS.join("|")})(?![\\w-])`, "g");
4005
4212
  const model = (text) => String(text).replace(MODEL_PATTERN, (match) => green(match));
4006
4213
  const STATUS_COLUMN = columnWidth(Object.values(STATUS).map((status) => status.word));
4007
4214
  function clip(text, limit) {
@@ -4105,9 +4312,21 @@ function bullet(marker, message) {
4105
4312
  const success = (message) => bullet(green("✔"), message);
4106
4313
  const warn = (message) => bullet(yellow("!"), message);
4107
4314
  const error = (message) => bullet(red("✖"), message);
4108
- async function selectAssistants(options, initial) {
4315
+ async function selectProvider(options, initial) {
4316
+ const chosen = await select({
4317
+ message: "Which gateway should your assistants use for Apex?",
4318
+ options,
4319
+ initialValue: initial
4320
+ });
4321
+ if (isCancel(chosen)) {
4322
+ cancel("Cancelled. Nothing was written.");
4323
+ return false;
4324
+ }
4325
+ return chosen;
4326
+ }
4327
+ async function selectAssistants(options, initial, modelId) {
4109
4328
  const chosen = await multiselect({
4110
- message: model(`Set up ${MODEL} for which assistants? ${dim("(space toggles, enter confirms)")}`),
4329
+ message: model(`Set up ${modelId} for which assistants? ${dim("(space toggles, enter confirms)")}`),
4111
4330
  options,
4112
4331
  initialValues: initial,
4113
4332
  required: false,
@@ -4316,6 +4535,12 @@ const FLAGS = {
4316
4535
  hint: "assistant ids",
4317
4536
  text: `comma list of: ${IDS.join(", ")} (skips the picker)`
4318
4537
  },
4538
+ provider: {
4539
+ type: "string",
4540
+ usage: "--provider <id>",
4541
+ hint: "gateway serving Apex",
4542
+ text: `${PROVIDER_IDS.join(" or ")}; defaults to the one whose key is set, else vercel (skips the question)`
4543
+ },
4319
4544
  "no-interactive": {
4320
4545
  type: "boolean",
4321
4546
  usage: "--no-interactive",
@@ -4360,6 +4585,7 @@ const COMMANDS = {
4360
4585
  summary: "configure assistants",
4361
4586
  flags: [
4362
4587
  "assistants",
4588
+ "provider",
4363
4589
  "no-interactive",
4364
4590
  "apply",
4365
4591
  "no-diff",
@@ -4368,9 +4594,13 @@ const COMMANDS = {
4368
4594
  ]
4369
4595
  },
4370
4596
  detect: {
4371
- args: "[--json]",
4597
+ args: "[--provider <id>] [--json]",
4372
4598
  summary: "show what Apex CLI can see on this machine",
4373
- flags: ["json", "help"]
4599
+ flags: [
4600
+ "provider",
4601
+ "json",
4602
+ "help"
4603
+ ]
4374
4604
  },
4375
4605
  undo: {
4376
4606
  args: "[--list] [options]",
@@ -4385,7 +4615,7 @@ const COMMANDS = {
4385
4615
  ]
4386
4616
  },
4387
4617
  run: {
4388
- args: `<${RUNNABLE.join("|")}> [-- <args>]`,
4618
+ args: `[--provider <id>] <${RUNNABLE.join("|")}> [-- <args>]`,
4389
4619
  summary: "launch an assistant with the gateway set",
4390
4620
  flags: []
4391
4621
  },
@@ -4449,12 +4679,13 @@ const exampleRows = [
4449
4679
  ["apex init", "pick assistants, review, confirm"],
4450
4680
  ["apex init --assistants codex,pi", "preview two tools (agent and CI friendly)"],
4451
4681
  ["apex init --assistants codex,pi --apply", "write those two without asking"],
4682
+ ["apex init --provider callstack", "use the Callstack portal instead of Vercel AI Gateway"],
4452
4683
  ["apex undo", "preview the reversal"],
4453
4684
  ["apex undo --apply", "reverse the last setup without asking"],
4454
4685
  ["apex detect --json", "machine-readable inventory"]
4455
4686
  ];
4456
4687
  const environmentRows = [
4457
- ["CALLSTACK_AUTH_TOKEN", "your callstack.ai key, needed by apex run and by every assistant you configure"],
4688
+ ...Object.values(PROVIDERS).map((provider) => [provider.envVar, `${provider.keyName}, needed by apex run and by every assistant you configure for ${provider.name}`]),
4458
4689
  ["Config directories", "XDG_CONFIG_HOME, CODEX_HOME, CLAUDE_CONFIG_DIR, PI_CODING_AGENT_DIR"],
4459
4690
  ["Undo journal", "APEX_STATE_DIR, XDG_STATE_HOME (default ~/.local/state/apex)"]
4460
4691
  ];
@@ -4503,7 +4734,7 @@ function helpText() {
4503
4734
  ""
4504
4735
  ];
4505
4736
  return [
4506
- ...wrap(`Apex CLI: point your coding assistants at ${MODEL}`, width$1).map((line) => bold(model(line))),
4737
+ ...wrap(`Apex CLI: point your coding assistants at Apex via ${Object.values(PROVIDERS).map((provider) => provider.name).join(" or the ")}`, width$1).map((line) => bold(model(line))),
4507
4738
  "",
4508
4739
  ...section("Usage", usageRows.map(([lead, text]) => [
4509
4740
  lead,
@@ -4543,9 +4774,11 @@ function readFlags(rest, command) {
4543
4774
  const selected = values.assistants === void 0 ? null : [...new Set(values.assistants.split(",").map((id) => id.trim()))];
4544
4775
  if (selected?.includes("")) throw new Error("--assistants needs at least one id.");
4545
4776
  if (selected?.some((id) => !IDS.includes(id))) throw new Error(`Unknown assistant in --assistants. Choose from: ${IDS.join(", ")}`);
4777
+ if (values.provider !== void 0 && !PROVIDER_IDS.includes(values.provider)) throw new Error(`Unknown --provider. Choose from: ${PROVIDER_IDS.join(", ")}`);
4546
4778
  const json = Boolean(values.json);
4547
4779
  return {
4548
4780
  selected,
4781
+ provider: values.provider === void 0 ? null : PROVIDERS[values.provider],
4549
4782
  showDiff: !values["no-diff"],
4550
4783
  json,
4551
4784
  help: Boolean(values.help),
@@ -4556,7 +4789,7 @@ function readFlags(rest, command) {
4556
4789
  })
4557
4790
  };
4558
4791
  }
4559
- async function planAll(assistants, options) {
4792
+ async function planAll(assistants, options, provider) {
4560
4793
  return Promise.all(assistants.map(async (assistant) => {
4561
4794
  const base = {
4562
4795
  id: assistant.id,
@@ -4569,7 +4802,7 @@ async function planAll(assistants, options) {
4569
4802
  steps: []
4570
4803
  };
4571
4804
  try {
4572
- base.files = (await planAssistant(assistant)).map((change) => describeFile(change, options));
4805
+ base.files = (await planAssistant(assistant, provider)).map((change) => describeFile(change, options));
4573
4806
  base.steps = base.files.flatMap((file) => file.change.steps ?? []);
4574
4807
  } catch (error) {
4575
4808
  base.error = error.message;
@@ -4577,7 +4810,7 @@ async function planAll(assistants, options) {
4577
4810
  return base;
4578
4811
  }));
4579
4812
  }
4580
- const token = () => process.env.CALLSTACK_AUTH_TOKEN?.trim() || void 0;
4813
+ const token = (provider) => process.env[provider.envVar]?.trim() || void 0;
4581
4814
  const stamp = (iso) => iso.replace("T", " ").replace(/\.\d{3}Z$/, " UTC");
4582
4815
  const pendingOf = (entry) => entry.files.filter((file) => file.status !== "unchanged");
4583
4816
  async function applyAll(items, apply) {
@@ -4610,6 +4843,11 @@ const jsonAssistant = (entry, secret) => ({
4610
4843
  ...entry.steps.length ? { steps: entry.steps } : {},
4611
4844
  files: entry.files.map((file) => jsonFile(file, secret))
4612
4845
  });
4846
+ const providerOptions = () => Object.values(PROVIDERS).map((provider) => ({
4847
+ value: provider.id,
4848
+ label: provider.name,
4849
+ hint: `${provider.model}, key in ${provider.envVar}${token(provider) ? " (set)" : ""}`
4850
+ }));
4613
4851
  function pickerOptions(entries) {
4614
4852
  return entries.map((entry) => {
4615
4853
  const pending = pendingOf(entry).length;
@@ -4626,24 +4864,29 @@ async function commandInit(rest) {
4626
4864
  printHelp();
4627
4865
  return;
4628
4866
  }
4629
- const secret = token();
4867
+ const journalFile = journalPath();
4868
+ if (flags.mode !== "preview") await readJournal(journalFile);
4869
+ const batch = randomUUID();
4870
+ const asking = !flags.json && flags.mode === "prompt";
4871
+ let provider = flags.provider ?? defaultProvider();
4872
+ if (!flags.json) intro("Apex CLI · Configure Apex for your favorite harness", MODE_NOTE[flags.mode]);
4873
+ if (asking && !flags.provider) {
4874
+ const picked = await selectProvider(providerOptions(), provider.id);
4875
+ if (picked === false) return;
4876
+ provider = PROVIDERS[picked];
4877
+ }
4878
+ const secret = token(provider);
4630
4879
  const options = {
4631
4880
  secret,
4632
4881
  showDiff: flags.showDiff && !flags.json
4633
4882
  };
4634
- const journalFile = journalPath();
4635
- if (flags.mode !== "preview") await readJournal(journalFile);
4636
- const batch = randomUUID();
4637
- const entries = await planAll(await detect(), options);
4883
+ const entries = await planAll(await detect(), options, provider);
4638
4884
  let ids = flags.selected ?? entries.filter((entry) => entry.detected).map((entry) => entry.id);
4639
- if (!flags.json) {
4640
- intro("Apex CLI · Configure callstack/Apex for your favorite harness", MODE_NOTE[flags.mode]);
4641
- if (flags.mode === "prompt" && !flags.selected) {
4642
- const defaults = entries.filter((entry) => entry.detected && !entry.manual && !entry.error && pendingOf(entry).length).map((entry) => entry.id);
4643
- const picked = await selectAssistants(pickerOptions(entries), defaults);
4644
- if (picked === false) return;
4645
- ids = picked;
4646
- }
4885
+ if (asking && !flags.selected) {
4886
+ const defaults = entries.filter((entry) => entry.detected && !entry.manual && !entry.error && pendingOf(entry).length).map((entry) => entry.id);
4887
+ const picked = await selectAssistants(pickerOptions(entries), defaults, provider.model);
4888
+ if (picked === false) return;
4889
+ ids = picked;
4647
4890
  }
4648
4891
  const chosen = ids.map((id) => entries.find((entry) => entry.id === id));
4649
4892
  const blocked = chosen.filter((entry) => entry.error);
@@ -4664,8 +4907,9 @@ async function commandInit(rest) {
4664
4907
  console.log(JSON.stringify({
4665
4908
  command: "init",
4666
4909
  mode: flags.mode,
4667
- model: MODEL,
4668
- endpoint: BASE_URL,
4910
+ provider: provider.id,
4911
+ model: provider.model,
4912
+ endpoint: provider.baseUrl,
4669
4913
  applied: applied.length,
4670
4914
  appliedPaths: applied,
4671
4915
  ...failure ? { error: failure.message } : {},
@@ -4677,7 +4921,7 @@ async function commandInit(rest) {
4677
4921
  assistants: chosen.map((entry) => jsonAssistant(entry, secret)),
4678
4922
  journal: journalFile,
4679
4923
  undo: `${APEX} undo`,
4680
- envVar: "CALLSTACK_AUTH_TOKEN",
4924
+ envVar: provider.envVar,
4681
4925
  nextSteps: active.filter((entry) => RUNNABLE.includes(entry.id)).map((entry) => `${APEX} run ${entry.id}`)
4682
4926
  }, null, 2));
4683
4927
  if (blocked.length || failure) process.exitCode = 1;
@@ -4687,7 +4931,10 @@ async function commandInit(rest) {
4687
4931
  outro(`No assistant selected, so nothing was written. Pick one with --assistants or run ${APEX} init interactively.`);
4688
4932
  return;
4689
4933
  }
4690
- if (flags.mode !== "prompt") prose(`${gray("setup for:")} ${chosen.map((entry) => entry.name + (entry.detected ? "" : " (not detected)")).join(", ")}`);
4934
+ if (flags.mode !== "prompt") {
4935
+ prose(`${gray("gateway:")} ${provider.name}`);
4936
+ prose(`${gray("setup for:")} ${chosen.map((entry) => entry.name + (entry.detected ? "" : " (not detected)")).join(", ")}`);
4937
+ }
4691
4938
  if (blocked.length) {
4692
4939
  plain("");
4693
4940
  for (const entry of blocked) error(`${entry.name}: ${shortPath(entry.error)}`);
@@ -4715,23 +4962,24 @@ async function commandInit(rest) {
4715
4962
  }
4716
4963
  const apex = APEX !== "apex" && flags.mode === "prompt" && await installApex() ? "apex" : APEX;
4717
4964
  for (const entry of active.filter((entry) => entry.steps.length)) section(`Finish setting up ${entry.name}`, entry.steps);
4718
- for (const entry of manual) section(`Manual setup for ${entry.name}: Apex CLI writes nothing`, MANUAL[entry.id]);
4965
+ for (const entry of manual) section(`Manual setup for ${entry.name}: Apex CLI writes nothing`, manualSteps(entry.id, provider));
4719
4966
  section("Environment", [
4720
- ...secret ? [] : ["export CALLSTACK_AUTH_TOKEN=<your callstack.ai key>"],
4721
- secret ? `${green("✓")} CALLSTACK_AUTH_TOKEN is set in this shell` : `${yellow("!")} CALLSTACK_AUTH_TOKEN is not set here yet`,
4967
+ ...secret ? [] : [`export ${provider.envVar}=<${provider.keyName.replace(/^your /, "")}>`],
4968
+ secret ? `${green("✓")} ${provider.envVar} is set in this shell` : `${yellow("!")} ${provider.envVar} is not set here yet`,
4969
+ ...!secret && provider.keysUrl ? [`Create a key at ${link(provider.keysUrl)}`] : [],
4722
4970
  dim("Apex CLI never reads, stores or logs the key itself.")
4723
4971
  ]);
4724
4972
  const runnable = active.map((entry) => entry.id).filter((id) => RUNNABLE.includes(id));
4725
4973
  const rows = runnable.map((id) => ({
4726
4974
  command: `${apex} run ${id}`,
4727
- expansion: runExpansion(id)
4975
+ expansion: runExpansion(id, provider)
4728
4976
  }));
4729
4977
  const commandWidth = columnWidth(rows.map((row) => row.command));
4730
- section(runnable.length ? `Use these commands to run ${MODEL} with your selected harnesses:` : `Use ${MODEL} with your assistant:`, [
4978
+ section(runnable.length ? `Use these commands to run ${provider.model} with your selected harnesses:` : `Use ${provider.model} with your assistant:`, [
4731
4979
  ...rows.flatMap((row) => wrap(row.expansion, width() - 3 - commandWidth).map((part, index) => `${pad(index ? "" : row.command, commandWidth)}${dim(part)}`)),
4732
4980
  "",
4733
- `...or pick "${MODEL}" from the UI when setting up manually.`,
4734
- `For more instructions, visit: ${link(GUIDE_URL)}`,
4981
+ `...or pick "${provider.model}" from the UI when setting up manually.`,
4982
+ `For more instructions, visit: ${link(provider.guideUrl)}`,
4735
4983
  ...applied ? ["", `If you want to undo the changes, run ${bold(`${apex} undo`)}`] : [],
4736
4984
  ...apex === "apex" ? [] : ["", dim("For the short apex command: npm install -g @callstack/apex")]
4737
4985
  ]);
@@ -4742,16 +4990,17 @@ async function commandDetect(rest) {
4742
4990
  printHelp();
4743
4991
  return;
4744
4992
  }
4745
- const secret = token();
4993
+ const provider = flags.provider ?? defaultProvider();
4994
+ const secret = token(provider);
4746
4995
  const entries = await planAll(await detect(), {
4747
4996
  secret,
4748
4997
  showDiff: false
4749
- });
4998
+ }, provider);
4750
4999
  if (flags.json) {
4751
5000
  console.log(JSON.stringify(entries.map((entry) => jsonAssistant(entry, secret)), null, 2));
4752
5001
  return;
4753
5002
  }
4754
- intro("Apex CLI · What this machine has", "Read only: nothing is created, edited or removed.");
5003
+ intro(`Apex CLI · What this machine has for ${provider.name}`, "Read only: nothing is created, edited or removed.");
4755
5004
  const rows = entries.map((entry) => {
4756
5005
  const pending = pendingOf(entry).length;
4757
5006
  return {
@@ -4777,7 +5026,7 @@ async function commandUndo(rest) {
4777
5026
  printHelp();
4778
5027
  return;
4779
5028
  }
4780
- const secret = token();
5029
+ const secret = token(defaultProvider());
4781
5030
  const options = {
4782
5031
  secret,
4783
5032
  showDiff: flags.showDiff && !flags.json
@@ -4875,10 +5124,33 @@ async function commandUndo(rest) {
4875
5124
  }
4876
5125
  })).applied) outro("Undone. Configs are back to how they were. Restart any open assistant to reload them.");
4877
5126
  }
5127
+ function takeProvider(args) {
5128
+ const [first, second] = args;
5129
+ if (first === "--provider") return {
5130
+ value: second ?? "",
5131
+ rest: args.slice(2)
5132
+ };
5133
+ if (first?.startsWith("--provider=")) return {
5134
+ value: first.slice(11),
5135
+ rest: args.slice(1)
5136
+ };
5137
+ return {
5138
+ value: null,
5139
+ rest: args
5140
+ };
5141
+ }
4878
5142
  async function commandRun(rest) {
4879
- const [id, ...passed] = rest;
5143
+ const before = takeProvider(rest);
5144
+ const [id, ...after] = before.rest;
4880
5145
  if (!RUNNABLE.includes(id)) throw new Error(`apex run needs one of: ${RUNNABLE.join(", ")}. See ${APEX} --help.`);
4881
- const options = launchOptions(id);
5146
+ const behind = before.value === null ? takeProvider(after) : {
5147
+ value: null,
5148
+ rest: after
5149
+ };
5150
+ const chosen = before.value ?? behind.value;
5151
+ if (chosen !== null && !PROVIDER_IDS.includes(chosen)) throw new Error(`Unknown --provider. Choose from: ${PROVIDER_IDS.join(", ")}`);
5152
+ const passed = behind.rest;
5153
+ const options = launchOptions(id, process.env, chosen === null ? defaultProvider() : PROVIDERS[chosen]);
4882
5154
  const binary = await executable(id);
4883
5155
  if (!binary) throw new Error(`${id} was not found on PATH. Install it first, then run ${APEX} init.`);
4884
5156
  if (process.platform === "win32" && /\.(cmd|bat)$/i.test(binary)) throw new Error("Windows .cmd/.bat launchers are not executed through a shell. Use WSL or launch the configured assistant directly.");
@@ -4901,7 +5173,8 @@ const completionsFor = (command) => COMMANDS[command].flags.map((flag) => ({
4901
5173
  long: `--${flag}`,
4902
5174
  short: FLAGS[flag].short ? `-${FLAGS[flag].short}` : null,
4903
5175
  hint: FLAGS[flag].hint,
4904
- ...command === "init" && flag === "assistants" ? { values: IDS } : {}
5176
+ ...command === "init" && flag === "assistants" ? { values: IDS } : {},
5177
+ ...flag === "provider" ? { values: PROVIDER_IDS } : {}
4905
5178
  }));
4906
5179
  const spellings = (entry) => [entry.long, entry.short].filter(Boolean);
4907
5180
  function completionScript(shell) {
@@ -4909,15 +5182,18 @@ function completionScript(shell) {
4909
5182
  const words = (list) => list.join(" ");
4910
5183
  if (shell === "zsh") return `#compdef apex
4911
5184
  _apex() {
4912
- local -a commands assistants runnable${taking.length ? " " : ""}${words(taking.map((name) => `${name}_flags`))}
5185
+ local -a commands assistants providers runnable${taking.length ? " " : ""}${words(taking.map((name) => `${name}_flags`))}
4913
5186
  commands=(${words([...Object.entries(COMMANDS).map(([name, command]) => `'${name}:${command.summary}'`), ...GLOBALS.map(([flag, text]) => `'${flag}:${text}'`)])})
4914
5187
  assistants=(${words(IDS)})
5188
+ providers=(${words(PROVIDER_IDS)})
4915
5189
  runnable=(${words(RUNNABLE)})
4916
5190
  ${taking.map((name) => ` ${name}_flags=(${words(completionsFor(name).flatMap((entry) => spellings(entry).map((word) => `'${word}:${entry.hint}'`)))})`).join("\n")}
4917
5191
  if (( CURRENT == 2 )); then
4918
5192
  _describe -t commands 'apex command' commands
4919
5193
  elif [[ "\${words[CURRENT - 1]}" == --assistants ]]; then
4920
5194
  _describe -t assistants 'assistant' assistants
5195
+ elif [[ "\${words[CURRENT - 1]}" == --provider ]]; then
5196
+ _describe -t providers 'gateway' providers
4921
5197
  else
4922
5198
  case "\${words[2]}" in
4923
5199
  ${taking.map((name) => ` ${name}) _describe -t flags 'option' ${name}_flags ;;`).join("\n")}
@@ -4932,6 +5208,7 @@ if [[ "\${funcstack[1]}" == _apex ]]; then _apex "$@"; else compdef _apex apex;
4932
5208
  if (shell === "bash") return `_apex_completions() {
4933
5209
  local sub="\${COMP_WORDS[1]}" prev="\${COMP_WORDS[COMP_CWORD - 1]}" current="\${COMP_WORDS[COMP_CWORD]}"
4934
5210
  if [[ "$prev" == --assistants ]]; then COMPREPLY=( $(compgen -W "${words(IDS)}" -- "$current") ); return; fi
5211
+ if [[ "$prev" == --provider ]]; then COMPREPLY=( $(compgen -W "${words(PROVIDER_IDS)}" -- "$current") ); return; fi
4935
5212
  if (( COMP_CWORD == 1 )); then
4936
5213
  COMPREPLY=( $(compgen -W "${words([...Object.keys(COMMANDS), ...GLOBALS.map(([flag]) => flag)])}" -- "$current") )
4937
5214
  return
@@ -4950,6 +5227,12 @@ complete -F _apex_completions apex
4950
5227
  ...GLOBALS.map(([flag, hint]) => `complete -c apex -f -n "__fish_use_subcommand" -l ${flag.slice(2)} -d '${hint}'`),
4951
5228
  ...taking.flatMap((name) => completionsFor(name).map((entry) => fish(`__fish_seen_subcommand_from ${name}`, entry))),
4952
5229
  ...RUNNABLE.map((id) => `complete -c apex -f -n "__fish_seen_subcommand_from run" -a ${id} -d 'assistant'`),
5230
+ fish("__fish_seen_subcommand_from run", {
5231
+ long: "--provider",
5232
+ short: null,
5233
+ hint: FLAGS.provider.hint,
5234
+ values: PROVIDER_IDS
5235
+ }),
4953
5236
  ...SHELLS.map((name) => `complete -c apex -f -n "__fish_seen_subcommand_from completion" -a ${name} -d 'shell'`)
4954
5237
  ].join("\n") + "\n";
4955
5238
  }