@great-arrow/cli 0.1.64 → 0.1.66
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.
- package/README.md +3 -1
- package/dist/index.js +2034 -547
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -108,7 +108,7 @@ var require_polyfills = __commonJS({
|
|
|
108
108
|
}
|
|
109
109
|
if (platform2 === "win32") {
|
|
110
110
|
fs6.rename = typeof fs6.rename !== "function" ? fs6.rename : (function(fs$rename) {
|
|
111
|
-
function
|
|
111
|
+
function rename3(from, to, cb) {
|
|
112
112
|
var start = Date.now();
|
|
113
113
|
var backoff = 0;
|
|
114
114
|
fs$rename(from, to, function CB(er) {
|
|
@@ -128,8 +128,8 @@ var require_polyfills = __commonJS({
|
|
|
128
128
|
if (cb) cb(er);
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
-
if (Object.setPrototypeOf) Object.setPrototypeOf(
|
|
132
|
-
return
|
|
131
|
+
if (Object.setPrototypeOf) Object.setPrototypeOf(rename3, fs$rename);
|
|
132
|
+
return rename3;
|
|
133
133
|
})(fs6.rename);
|
|
134
134
|
}
|
|
135
135
|
fs6.read = typeof fs6.read !== "function" ? fs6.read : (function(fs$read) {
|
|
@@ -172,14 +172,14 @@ var require_polyfills = __commonJS({
|
|
|
172
172
|
path10,
|
|
173
173
|
constants2.O_WRONLY | constants2.O_SYMLINK,
|
|
174
174
|
mode,
|
|
175
|
-
function(
|
|
176
|
-
if (
|
|
177
|
-
if (callback) callback(
|
|
175
|
+
function(err2, fd) {
|
|
176
|
+
if (err2) {
|
|
177
|
+
if (callback) callback(err2);
|
|
178
178
|
return;
|
|
179
179
|
}
|
|
180
|
-
fs7.fchmod(fd, mode, function(
|
|
180
|
+
fs7.fchmod(fd, mode, function(err3) {
|
|
181
181
|
fs7.close(fd, function(err22) {
|
|
182
|
-
if (callback) callback(
|
|
182
|
+
if (callback) callback(err3 || err22);
|
|
183
183
|
});
|
|
184
184
|
});
|
|
185
185
|
}
|
|
@@ -377,9 +377,9 @@ var require_legacy_streams = __commonJS({
|
|
|
377
377
|
});
|
|
378
378
|
return;
|
|
379
379
|
}
|
|
380
|
-
fs6.open(this.path, this.flags, this.mode, function(
|
|
381
|
-
if (
|
|
382
|
-
self.emit("error",
|
|
380
|
+
fs6.open(this.path, this.flags, this.mode, function(err2, fd) {
|
|
381
|
+
if (err2) {
|
|
382
|
+
self.emit("error", err2);
|
|
383
383
|
self.readable = false;
|
|
384
384
|
return;
|
|
385
385
|
}
|
|
@@ -488,8 +488,8 @@ var require_graceful_fs = __commonJS({
|
|
|
488
488
|
publishQueue(fs6, queue);
|
|
489
489
|
fs6.close = (function(fs$close) {
|
|
490
490
|
function close(fd, cb) {
|
|
491
|
-
return fs$close.call(fs6, fd, function(
|
|
492
|
-
if (!
|
|
491
|
+
return fs$close.call(fs6, fd, function(err2) {
|
|
492
|
+
if (!err2) {
|
|
493
493
|
resetQueue();
|
|
494
494
|
}
|
|
495
495
|
if (typeof cb === "function")
|
|
@@ -533,15 +533,15 @@ var require_graceful_fs = __commonJS({
|
|
|
533
533
|
fs7.createReadStream = createReadStream;
|
|
534
534
|
fs7.createWriteStream = createWriteStream;
|
|
535
535
|
var fs$readFile = fs7.readFile;
|
|
536
|
-
fs7.readFile =
|
|
537
|
-
function
|
|
536
|
+
fs7.readFile = readFile9;
|
|
537
|
+
function readFile9(path10, options, cb) {
|
|
538
538
|
if (typeof options === "function")
|
|
539
539
|
cb = options, options = null;
|
|
540
540
|
return go$readFile(path10, options, cb);
|
|
541
541
|
function go$readFile(path11, options2, cb2, startTime) {
|
|
542
|
-
return fs$readFile(path11, options2, function(
|
|
543
|
-
if (
|
|
544
|
-
enqueue([go$readFile, [path11, options2, cb2],
|
|
542
|
+
return fs$readFile(path11, options2, function(err2) {
|
|
543
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
544
|
+
enqueue([go$readFile, [path11, options2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
545
545
|
else {
|
|
546
546
|
if (typeof cb2 === "function")
|
|
547
547
|
cb2.apply(this, arguments);
|
|
@@ -550,15 +550,15 @@ var require_graceful_fs = __commonJS({
|
|
|
550
550
|
}
|
|
551
551
|
}
|
|
552
552
|
var fs$writeFile = fs7.writeFile;
|
|
553
|
-
fs7.writeFile =
|
|
554
|
-
function
|
|
553
|
+
fs7.writeFile = writeFile7;
|
|
554
|
+
function writeFile7(path10, data, options, cb) {
|
|
555
555
|
if (typeof options === "function")
|
|
556
556
|
cb = options, options = null;
|
|
557
557
|
return go$writeFile(path10, data, options, cb);
|
|
558
558
|
function go$writeFile(path11, data2, options2, cb2, startTime) {
|
|
559
|
-
return fs$writeFile(path11, data2, options2, function(
|
|
560
|
-
if (
|
|
561
|
-
enqueue([go$writeFile, [path11, data2, options2, cb2],
|
|
559
|
+
return fs$writeFile(path11, data2, options2, function(err2) {
|
|
560
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
561
|
+
enqueue([go$writeFile, [path11, data2, options2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
562
562
|
else {
|
|
563
563
|
if (typeof cb2 === "function")
|
|
564
564
|
cb2.apply(this, arguments);
|
|
@@ -574,9 +574,9 @@ var require_graceful_fs = __commonJS({
|
|
|
574
574
|
cb = options, options = null;
|
|
575
575
|
return go$appendFile(path10, data, options, cb);
|
|
576
576
|
function go$appendFile(path11, data2, options2, cb2, startTime) {
|
|
577
|
-
return fs$appendFile(path11, data2, options2, function(
|
|
578
|
-
if (
|
|
579
|
-
enqueue([go$appendFile, [path11, data2, options2, cb2],
|
|
577
|
+
return fs$appendFile(path11, data2, options2, function(err2) {
|
|
578
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
579
|
+
enqueue([go$appendFile, [path11, data2, options2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
580
580
|
else {
|
|
581
581
|
if (typeof cb2 === "function")
|
|
582
582
|
cb2.apply(this, arguments);
|
|
@@ -594,9 +594,9 @@ var require_graceful_fs = __commonJS({
|
|
|
594
594
|
}
|
|
595
595
|
return go$copyFile(src, dest, flags, cb);
|
|
596
596
|
function go$copyFile(src2, dest2, flags2, cb2, startTime) {
|
|
597
|
-
return fs$copyFile(src2, dest2, flags2, function(
|
|
598
|
-
if (
|
|
599
|
-
enqueue([go$copyFile, [src2, dest2, flags2, cb2],
|
|
597
|
+
return fs$copyFile(src2, dest2, flags2, function(err2) {
|
|
598
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
599
|
+
enqueue([go$copyFile, [src2, dest2, flags2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
600
600
|
else {
|
|
601
601
|
if (typeof cb2 === "function")
|
|
602
602
|
cb2.apply(this, arguments);
|
|
@@ -627,12 +627,12 @@ var require_graceful_fs = __commonJS({
|
|
|
627
627
|
};
|
|
628
628
|
return go$readdir(path10, options, cb);
|
|
629
629
|
function fs$readdirCallback(path11, options2, cb2, startTime) {
|
|
630
|
-
return function(
|
|
631
|
-
if (
|
|
630
|
+
return function(err2, files) {
|
|
631
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
632
632
|
enqueue([
|
|
633
633
|
go$readdir,
|
|
634
634
|
[path11, options2, cb2],
|
|
635
|
-
|
|
635
|
+
err2,
|
|
636
636
|
startTime || Date.now(),
|
|
637
637
|
Date.now()
|
|
638
638
|
]);
|
|
@@ -640,7 +640,7 @@ var require_graceful_fs = __commonJS({
|
|
|
640
640
|
if (files && files.sort)
|
|
641
641
|
files.sort();
|
|
642
642
|
if (typeof cb2 === "function")
|
|
643
|
-
cb2.call(this,
|
|
643
|
+
cb2.call(this, err2, files);
|
|
644
644
|
}
|
|
645
645
|
};
|
|
646
646
|
}
|
|
@@ -710,11 +710,11 @@ var require_graceful_fs = __commonJS({
|
|
|
710
710
|
}
|
|
711
711
|
function ReadStream$open() {
|
|
712
712
|
var that = this;
|
|
713
|
-
open4(that.path, that.flags, that.mode, function(
|
|
714
|
-
if (
|
|
713
|
+
open4(that.path, that.flags, that.mode, function(err2, fd) {
|
|
714
|
+
if (err2) {
|
|
715
715
|
if (that.autoClose)
|
|
716
716
|
that.destroy();
|
|
717
|
-
that.emit("error",
|
|
717
|
+
that.emit("error", err2);
|
|
718
718
|
} else {
|
|
719
719
|
that.fd = fd;
|
|
720
720
|
that.emit("open", fd);
|
|
@@ -730,10 +730,10 @@ var require_graceful_fs = __commonJS({
|
|
|
730
730
|
}
|
|
731
731
|
function WriteStream$open() {
|
|
732
732
|
var that = this;
|
|
733
|
-
open4(that.path, that.flags, that.mode, function(
|
|
734
|
-
if (
|
|
733
|
+
open4(that.path, that.flags, that.mode, function(err2, fd) {
|
|
734
|
+
if (err2) {
|
|
735
735
|
that.destroy();
|
|
736
|
-
that.emit("error",
|
|
736
|
+
that.emit("error", err2);
|
|
737
737
|
} else {
|
|
738
738
|
that.fd = fd;
|
|
739
739
|
that.emit("open", fd);
|
|
@@ -753,9 +753,9 @@ var require_graceful_fs = __commonJS({
|
|
|
753
753
|
cb = mode, mode = null;
|
|
754
754
|
return go$open(path10, flags, mode, cb);
|
|
755
755
|
function go$open(path11, flags2, mode2, cb2, startTime) {
|
|
756
|
-
return fs$open(path11, flags2, mode2, function(
|
|
757
|
-
if (
|
|
758
|
-
enqueue([go$open, [path11, flags2, mode2, cb2],
|
|
756
|
+
return fs$open(path11, flags2, mode2, function(err2, fd) {
|
|
757
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
758
|
+
enqueue([go$open, [path11, flags2, mode2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
759
759
|
else {
|
|
760
760
|
if (typeof cb2 === "function")
|
|
761
761
|
cb2.apply(this, arguments);
|
|
@@ -789,7 +789,7 @@ var require_graceful_fs = __commonJS({
|
|
|
789
789
|
var elem = fs6[gracefulQueue].shift();
|
|
790
790
|
var fn = elem[0];
|
|
791
791
|
var args = elem[1];
|
|
792
|
-
var
|
|
792
|
+
var err2 = elem[2];
|
|
793
793
|
var startTime = elem[3];
|
|
794
794
|
var lastTime = elem[4];
|
|
795
795
|
if (startTime === void 0) {
|
|
@@ -799,7 +799,7 @@ var require_graceful_fs = __commonJS({
|
|
|
799
799
|
debug("TIMEOUT", fn.name, args);
|
|
800
800
|
var cb = args.pop();
|
|
801
801
|
if (typeof cb === "function")
|
|
802
|
-
cb.call(null,
|
|
802
|
+
cb.call(null, err2);
|
|
803
803
|
} else {
|
|
804
804
|
var sinceAttempt = Date.now() - lastTime;
|
|
805
805
|
var sinceStart = Math.max(lastTime - startTime, 1);
|
|
@@ -1367,7 +1367,7 @@ var require_ini = __commonJS({
|
|
|
1367
1367
|
var eol = typeof process !== "undefined" && process.platform === "win32" ? "\r\n" : "\n";
|
|
1368
1368
|
function encode3(obj, opt) {
|
|
1369
1369
|
var children = [];
|
|
1370
|
-
var
|
|
1370
|
+
var out2 = "";
|
|
1371
1371
|
if (typeof opt === "string") {
|
|
1372
1372
|
opt = {
|
|
1373
1373
|
section: opt,
|
|
@@ -1382,15 +1382,15 @@ var require_ini = __commonJS({
|
|
|
1382
1382
|
var val = obj[k];
|
|
1383
1383
|
if (val && Array.isArray(val)) {
|
|
1384
1384
|
val.forEach(function(item) {
|
|
1385
|
-
|
|
1385
|
+
out2 += safe(k + "[]") + separator + safe(item) + "\n";
|
|
1386
1386
|
});
|
|
1387
1387
|
} else if (val && typeof val === "object")
|
|
1388
1388
|
children.push(k);
|
|
1389
1389
|
else
|
|
1390
|
-
|
|
1390
|
+
out2 += safe(k) + separator + safe(val) + eol;
|
|
1391
1391
|
});
|
|
1392
|
-
if (opt.section &&
|
|
1393
|
-
|
|
1392
|
+
if (opt.section && out2.length)
|
|
1393
|
+
out2 = "[" + safe(opt.section) + "]" + eol + out2;
|
|
1394
1394
|
children.forEach(function(k, _, __) {
|
|
1395
1395
|
var nk = dotSplit(k).join("\\.");
|
|
1396
1396
|
var section = (opt.section ? opt.section + "." : "") + nk;
|
|
@@ -1398,11 +1398,11 @@ var require_ini = __commonJS({
|
|
|
1398
1398
|
section,
|
|
1399
1399
|
whitespace: opt.whitespace
|
|
1400
1400
|
});
|
|
1401
|
-
if (
|
|
1402
|
-
|
|
1403
|
-
|
|
1401
|
+
if (out2.length && child.length)
|
|
1402
|
+
out2 += eol;
|
|
1403
|
+
out2 += child;
|
|
1404
1404
|
});
|
|
1405
|
-
return
|
|
1405
|
+
return out2;
|
|
1406
1406
|
}
|
|
1407
1407
|
function dotSplit(str) {
|
|
1408
1408
|
return str.replace(/\1/g, "LITERAL\\1LITERAL").replace(/\\\./g, "").split(/\./).map(function(part) {
|
|
@@ -1410,8 +1410,8 @@ var require_ini = __commonJS({
|
|
|
1410
1410
|
});
|
|
1411
1411
|
}
|
|
1412
1412
|
function decode3(str) {
|
|
1413
|
-
var
|
|
1414
|
-
var p =
|
|
1413
|
+
var out2 = {};
|
|
1414
|
+
var p = out2;
|
|
1415
1415
|
var section = null;
|
|
1416
1416
|
var re = /^\[([^\]]*)\]$|^([^=]+)(=(.*))?$/i;
|
|
1417
1417
|
var lines = str.split(/[\r\n]+/g);
|
|
@@ -1427,7 +1427,7 @@ var require_ini = __commonJS({
|
|
|
1427
1427
|
p = {};
|
|
1428
1428
|
return;
|
|
1429
1429
|
}
|
|
1430
|
-
p =
|
|
1430
|
+
p = out2[section] = out2[section] || {};
|
|
1431
1431
|
return;
|
|
1432
1432
|
}
|
|
1433
1433
|
var key = unsafe(match[2]);
|
|
@@ -1454,11 +1454,11 @@ var require_ini = __commonJS({
|
|
|
1454
1454
|
else
|
|
1455
1455
|
p[key] = value;
|
|
1456
1456
|
});
|
|
1457
|
-
Object.keys(
|
|
1458
|
-
if (!
|
|
1457
|
+
Object.keys(out2).filter(function(k, _, __) {
|
|
1458
|
+
if (!out2[k] || typeof out2[k] !== "object" || Array.isArray(out2[k]))
|
|
1459
1459
|
return false;
|
|
1460
1460
|
var parts = dotSplit(k);
|
|
1461
|
-
var p2 =
|
|
1461
|
+
var p2 = out2;
|
|
1462
1462
|
var l = parts.pop();
|
|
1463
1463
|
var nl = l.replace(/\\\./g, ".");
|
|
1464
1464
|
parts.forEach(function(part, _2, __2) {
|
|
@@ -1468,14 +1468,14 @@ var require_ini = __commonJS({
|
|
|
1468
1468
|
p2[part] = {};
|
|
1469
1469
|
p2 = p2[part];
|
|
1470
1470
|
});
|
|
1471
|
-
if (p2 ===
|
|
1471
|
+
if (p2 === out2 && nl === l)
|
|
1472
1472
|
return false;
|
|
1473
|
-
p2[nl] =
|
|
1473
|
+
p2[nl] = out2[k];
|
|
1474
1474
|
return true;
|
|
1475
1475
|
}).forEach(function(del, _, __) {
|
|
1476
|
-
delete
|
|
1476
|
+
delete out2[del];
|
|
1477
1477
|
});
|
|
1478
|
-
return
|
|
1478
|
+
return out2;
|
|
1479
1479
|
}
|
|
1480
1480
|
function isQuoted(val) {
|
|
1481
1481
|
return val.charAt(0) === '"' && val.slice(-1) === '"' || val.charAt(0) === "'" && val.slice(-1) === "'";
|
|
@@ -1610,7 +1610,7 @@ var require_utils = __commonJS({
|
|
|
1610
1610
|
var content;
|
|
1611
1611
|
try {
|
|
1612
1612
|
return fs6.readFileSync(file3, "utf-8");
|
|
1613
|
-
} catch (
|
|
1613
|
+
} catch (err2) {
|
|
1614
1614
|
return;
|
|
1615
1615
|
}
|
|
1616
1616
|
};
|
|
@@ -1650,7 +1650,7 @@ var require_utils = __commonJS({
|
|
|
1650
1650
|
try {
|
|
1651
1651
|
fs6.statSync(file3);
|
|
1652
1652
|
return file3;
|
|
1653
|
-
} catch (
|
|
1653
|
+
} catch (err2) {
|
|
1654
1654
|
if (path10.dirname(start) !== start)
|
|
1655
1655
|
return find2(path10.dirname(start), rel2);
|
|
1656
1656
|
}
|
|
@@ -1968,7 +1968,7 @@ var require_minimist = __commonJS({
|
|
|
1968
1968
|
var require_rc = __commonJS({
|
|
1969
1969
|
"node_modules/.pnpm/rc@1.2.8/node_modules/rc/index.js"(exports, module) {
|
|
1970
1970
|
var cc = require_utils();
|
|
1971
|
-
var
|
|
1971
|
+
var join13 = __require("path").join;
|
|
1972
1972
|
var deepExtend = require_deep_extend();
|
|
1973
1973
|
var etc = "/etc";
|
|
1974
1974
|
var win = process.platform === "win32";
|
|
@@ -1993,15 +1993,15 @@ var require_rc = __commonJS({
|
|
|
1993
1993
|
}
|
|
1994
1994
|
if (!win)
|
|
1995
1995
|
[
|
|
1996
|
-
|
|
1997
|
-
|
|
1996
|
+
join13(etc, name23, "config"),
|
|
1997
|
+
join13(etc, name23 + "rc")
|
|
1998
1998
|
].forEach(addConfigFile);
|
|
1999
1999
|
if (home)
|
|
2000
2000
|
[
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2001
|
+
join13(home, ".config", name23, "config"),
|
|
2002
|
+
join13(home, ".config", name23),
|
|
2003
|
+
join13(home, "." + name23, "config"),
|
|
2004
|
+
join13(home, "." + name23 + "rc")
|
|
2005
2005
|
].forEach(addConfigFile);
|
|
2006
2006
|
addConfigFile(cc.find("." + name23 + "rc"));
|
|
2007
2007
|
if (env4.config) addConfigFile(env4.config);
|
|
@@ -2082,7 +2082,7 @@ var require_polyfills2 = __commonJS({
|
|
|
2082
2082
|
}
|
|
2083
2083
|
if (platform2 === "win32") {
|
|
2084
2084
|
fs6.rename = typeof fs6.rename !== "function" ? fs6.rename : (function(fs$rename) {
|
|
2085
|
-
function
|
|
2085
|
+
function rename3(from, to, cb) {
|
|
2086
2086
|
var start = Date.now();
|
|
2087
2087
|
var backoff = 0;
|
|
2088
2088
|
fs$rename(from, to, function CB(er) {
|
|
@@ -2102,8 +2102,8 @@ var require_polyfills2 = __commonJS({
|
|
|
2102
2102
|
if (cb) cb(er);
|
|
2103
2103
|
});
|
|
2104
2104
|
}
|
|
2105
|
-
if (Object.setPrototypeOf) Object.setPrototypeOf(
|
|
2106
|
-
return
|
|
2105
|
+
if (Object.setPrototypeOf) Object.setPrototypeOf(rename3, fs$rename);
|
|
2106
|
+
return rename3;
|
|
2107
2107
|
})(fs6.rename);
|
|
2108
2108
|
}
|
|
2109
2109
|
fs6.read = typeof fs6.read !== "function" ? fs6.read : (function(fs$read) {
|
|
@@ -2146,14 +2146,14 @@ var require_polyfills2 = __commonJS({
|
|
|
2146
2146
|
path10,
|
|
2147
2147
|
constants2.O_WRONLY | constants2.O_SYMLINK,
|
|
2148
2148
|
mode,
|
|
2149
|
-
function(
|
|
2150
|
-
if (
|
|
2151
|
-
if (callback) callback(
|
|
2149
|
+
function(err2, fd) {
|
|
2150
|
+
if (err2) {
|
|
2151
|
+
if (callback) callback(err2);
|
|
2152
2152
|
return;
|
|
2153
2153
|
}
|
|
2154
|
-
fs7.fchmod(fd, mode, function(
|
|
2154
|
+
fs7.fchmod(fd, mode, function(err3) {
|
|
2155
2155
|
fs7.close(fd, function(err22) {
|
|
2156
|
-
if (callback) callback(
|
|
2156
|
+
if (callback) callback(err3 || err22);
|
|
2157
2157
|
});
|
|
2158
2158
|
});
|
|
2159
2159
|
}
|
|
@@ -2351,9 +2351,9 @@ var require_legacy_streams2 = __commonJS({
|
|
|
2351
2351
|
});
|
|
2352
2352
|
return;
|
|
2353
2353
|
}
|
|
2354
|
-
fs6.open(this.path, this.flags, this.mode, function(
|
|
2355
|
-
if (
|
|
2356
|
-
self.emit("error",
|
|
2354
|
+
fs6.open(this.path, this.flags, this.mode, function(err2, fd) {
|
|
2355
|
+
if (err2) {
|
|
2356
|
+
self.emit("error", err2);
|
|
2357
2357
|
self.readable = false;
|
|
2358
2358
|
return;
|
|
2359
2359
|
}
|
|
@@ -2462,8 +2462,8 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2462
2462
|
publishQueue(fs6, queue);
|
|
2463
2463
|
fs6.close = (function(fs$close) {
|
|
2464
2464
|
function close(fd, cb) {
|
|
2465
|
-
return fs$close.call(fs6, fd, function(
|
|
2466
|
-
if (!
|
|
2465
|
+
return fs$close.call(fs6, fd, function(err2) {
|
|
2466
|
+
if (!err2) {
|
|
2467
2467
|
resetQueue();
|
|
2468
2468
|
}
|
|
2469
2469
|
if (typeof cb === "function")
|
|
@@ -2507,15 +2507,15 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2507
2507
|
fs7.createReadStream = createReadStream;
|
|
2508
2508
|
fs7.createWriteStream = createWriteStream;
|
|
2509
2509
|
var fs$readFile = fs7.readFile;
|
|
2510
|
-
fs7.readFile =
|
|
2511
|
-
function
|
|
2510
|
+
fs7.readFile = readFile9;
|
|
2511
|
+
function readFile9(path10, options, cb) {
|
|
2512
2512
|
if (typeof options === "function")
|
|
2513
2513
|
cb = options, options = null;
|
|
2514
2514
|
return go$readFile(path10, options, cb);
|
|
2515
2515
|
function go$readFile(path11, options2, cb2, startTime) {
|
|
2516
|
-
return fs$readFile(path11, options2, function(
|
|
2517
|
-
if (
|
|
2518
|
-
enqueue([go$readFile, [path11, options2, cb2],
|
|
2516
|
+
return fs$readFile(path11, options2, function(err2) {
|
|
2517
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
2518
|
+
enqueue([go$readFile, [path11, options2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
2519
2519
|
else {
|
|
2520
2520
|
if (typeof cb2 === "function")
|
|
2521
2521
|
cb2.apply(this, arguments);
|
|
@@ -2524,15 +2524,15 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2524
2524
|
}
|
|
2525
2525
|
}
|
|
2526
2526
|
var fs$writeFile = fs7.writeFile;
|
|
2527
|
-
fs7.writeFile =
|
|
2528
|
-
function
|
|
2527
|
+
fs7.writeFile = writeFile7;
|
|
2528
|
+
function writeFile7(path10, data, options, cb) {
|
|
2529
2529
|
if (typeof options === "function")
|
|
2530
2530
|
cb = options, options = null;
|
|
2531
2531
|
return go$writeFile(path10, data, options, cb);
|
|
2532
2532
|
function go$writeFile(path11, data2, options2, cb2, startTime) {
|
|
2533
|
-
return fs$writeFile(path11, data2, options2, function(
|
|
2534
|
-
if (
|
|
2535
|
-
enqueue([go$writeFile, [path11, data2, options2, cb2],
|
|
2533
|
+
return fs$writeFile(path11, data2, options2, function(err2) {
|
|
2534
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
2535
|
+
enqueue([go$writeFile, [path11, data2, options2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
2536
2536
|
else {
|
|
2537
2537
|
if (typeof cb2 === "function")
|
|
2538
2538
|
cb2.apply(this, arguments);
|
|
@@ -2548,9 +2548,9 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2548
2548
|
cb = options, options = null;
|
|
2549
2549
|
return go$appendFile(path10, data, options, cb);
|
|
2550
2550
|
function go$appendFile(path11, data2, options2, cb2, startTime) {
|
|
2551
|
-
return fs$appendFile(path11, data2, options2, function(
|
|
2552
|
-
if (
|
|
2553
|
-
enqueue([go$appendFile, [path11, data2, options2, cb2],
|
|
2551
|
+
return fs$appendFile(path11, data2, options2, function(err2) {
|
|
2552
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
2553
|
+
enqueue([go$appendFile, [path11, data2, options2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
2554
2554
|
else {
|
|
2555
2555
|
if (typeof cb2 === "function")
|
|
2556
2556
|
cb2.apply(this, arguments);
|
|
@@ -2568,9 +2568,9 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2568
2568
|
}
|
|
2569
2569
|
return go$copyFile(src, dest, flags, cb);
|
|
2570
2570
|
function go$copyFile(src2, dest2, flags2, cb2, startTime) {
|
|
2571
|
-
return fs$copyFile(src2, dest2, flags2, function(
|
|
2572
|
-
if (
|
|
2573
|
-
enqueue([go$copyFile, [src2, dest2, flags2, cb2],
|
|
2571
|
+
return fs$copyFile(src2, dest2, flags2, function(err2) {
|
|
2572
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
2573
|
+
enqueue([go$copyFile, [src2, dest2, flags2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
2574
2574
|
else {
|
|
2575
2575
|
if (typeof cb2 === "function")
|
|
2576
2576
|
cb2.apply(this, arguments);
|
|
@@ -2601,12 +2601,12 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2601
2601
|
};
|
|
2602
2602
|
return go$readdir(path10, options, cb);
|
|
2603
2603
|
function fs$readdirCallback(path11, options2, cb2, startTime) {
|
|
2604
|
-
return function(
|
|
2605
|
-
if (
|
|
2604
|
+
return function(err2, files) {
|
|
2605
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
2606
2606
|
enqueue([
|
|
2607
2607
|
go$readdir,
|
|
2608
2608
|
[path11, options2, cb2],
|
|
2609
|
-
|
|
2609
|
+
err2,
|
|
2610
2610
|
startTime || Date.now(),
|
|
2611
2611
|
Date.now()
|
|
2612
2612
|
]);
|
|
@@ -2614,7 +2614,7 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2614
2614
|
if (files && files.sort)
|
|
2615
2615
|
files.sort();
|
|
2616
2616
|
if (typeof cb2 === "function")
|
|
2617
|
-
cb2.call(this,
|
|
2617
|
+
cb2.call(this, err2, files);
|
|
2618
2618
|
}
|
|
2619
2619
|
};
|
|
2620
2620
|
}
|
|
@@ -2684,11 +2684,11 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2684
2684
|
}
|
|
2685
2685
|
function ReadStream$open() {
|
|
2686
2686
|
var that = this;
|
|
2687
|
-
open4(that.path, that.flags, that.mode, function(
|
|
2688
|
-
if (
|
|
2687
|
+
open4(that.path, that.flags, that.mode, function(err2, fd) {
|
|
2688
|
+
if (err2) {
|
|
2689
2689
|
if (that.autoClose)
|
|
2690
2690
|
that.destroy();
|
|
2691
|
-
that.emit("error",
|
|
2691
|
+
that.emit("error", err2);
|
|
2692
2692
|
} else {
|
|
2693
2693
|
that.fd = fd;
|
|
2694
2694
|
that.emit("open", fd);
|
|
@@ -2704,10 +2704,10 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2704
2704
|
}
|
|
2705
2705
|
function WriteStream$open() {
|
|
2706
2706
|
var that = this;
|
|
2707
|
-
open4(that.path, that.flags, that.mode, function(
|
|
2708
|
-
if (
|
|
2707
|
+
open4(that.path, that.flags, that.mode, function(err2, fd) {
|
|
2708
|
+
if (err2) {
|
|
2709
2709
|
that.destroy();
|
|
2710
|
-
that.emit("error",
|
|
2710
|
+
that.emit("error", err2);
|
|
2711
2711
|
} else {
|
|
2712
2712
|
that.fd = fd;
|
|
2713
2713
|
that.emit("open", fd);
|
|
@@ -2727,9 +2727,9 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2727
2727
|
cb = mode, mode = null;
|
|
2728
2728
|
return go$open(path10, flags, mode, cb);
|
|
2729
2729
|
function go$open(path11, flags2, mode2, cb2, startTime) {
|
|
2730
|
-
return fs$open(path11, flags2, mode2, function(
|
|
2731
|
-
if (
|
|
2732
|
-
enqueue([go$open, [path11, flags2, mode2, cb2],
|
|
2730
|
+
return fs$open(path11, flags2, mode2, function(err2, fd) {
|
|
2731
|
+
if (err2 && (err2.code === "EMFILE" || err2.code === "ENFILE"))
|
|
2732
|
+
enqueue([go$open, [path11, flags2, mode2, cb2], err2, startTime || Date.now(), Date.now()]);
|
|
2733
2733
|
else {
|
|
2734
2734
|
if (typeof cb2 === "function")
|
|
2735
2735
|
cb2.apply(this, arguments);
|
|
@@ -2763,7 +2763,7 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2763
2763
|
var elem = fs6[gracefulQueue].shift();
|
|
2764
2764
|
var fn = elem[0];
|
|
2765
2765
|
var args = elem[1];
|
|
2766
|
-
var
|
|
2766
|
+
var err2 = elem[2];
|
|
2767
2767
|
var startTime = elem[3];
|
|
2768
2768
|
var lastTime = elem[4];
|
|
2769
2769
|
if (startTime === void 0) {
|
|
@@ -2773,7 +2773,7 @@ var require_graceful_fs2 = __commonJS({
|
|
|
2773
2773
|
debug("TIMEOUT", fn.name, args);
|
|
2774
2774
|
var cb = args.pop();
|
|
2775
2775
|
if (typeof cb === "function")
|
|
2776
|
-
cb.call(null,
|
|
2776
|
+
cb.call(null, err2);
|
|
2777
2777
|
} else {
|
|
2778
2778
|
var sinceAttempt = Date.now() - lastTime;
|
|
2779
2779
|
var sinceStart = Math.max(lastTime - startTime, 1);
|
|
@@ -2808,10 +2808,10 @@ var require_ca_file = __commonJS({
|
|
|
2808
2808
|
const delim = "-----END CERTIFICATE-----";
|
|
2809
2809
|
const output2 = contents.split(delim).filter((ca) => Boolean(ca.trim())).map((ca) => `${ca.trimLeft()}${delim}`);
|
|
2810
2810
|
return output2;
|
|
2811
|
-
} catch (
|
|
2812
|
-
if (
|
|
2811
|
+
} catch (err2) {
|
|
2812
|
+
if (err2.code === "ENOENT")
|
|
2813
2813
|
return void 0;
|
|
2814
|
-
throw
|
|
2814
|
+
throw err2;
|
|
2815
2815
|
}
|
|
2816
2816
|
}
|
|
2817
2817
|
exports.readCAFileSync = readCAFileSync;
|
|
@@ -2963,7 +2963,7 @@ var require_config_chain = __commonJS({
|
|
|
2963
2963
|
try {
|
|
2964
2964
|
fs6.statSync(file2);
|
|
2965
2965
|
return file2;
|
|
2966
|
-
} catch (
|
|
2966
|
+
} catch (err2) {
|
|
2967
2967
|
if (path10.dirname(start) !== start)
|
|
2968
2968
|
return find2(path10.dirname(start), rel2);
|
|
2969
2969
|
}
|
|
@@ -3000,7 +3000,7 @@ var require_config_chain = __commonJS({
|
|
|
3000
3000
|
var content;
|
|
3001
3001
|
try {
|
|
3002
3002
|
content = fs6.readFileSync(file2, "utf-8");
|
|
3003
|
-
} catch (
|
|
3003
|
+
} catch (err2) {
|
|
3004
3004
|
return;
|
|
3005
3005
|
}
|
|
3006
3006
|
return parse3(content, file2, "json");
|
|
@@ -3193,12 +3193,12 @@ var require_envKeyToSetting = __commonJS({
|
|
|
3193
3193
|
const secondPart = x.substr(colonIndex + 1);
|
|
3194
3194
|
return `${firstPart}:${normalize2(secondPart)}`;
|
|
3195
3195
|
};
|
|
3196
|
-
function normalize2(
|
|
3197
|
-
|
|
3198
|
-
if (
|
|
3199
|
-
let r =
|
|
3200
|
-
for (let i = 1; i <
|
|
3201
|
-
r +=
|
|
3196
|
+
function normalize2(s2) {
|
|
3197
|
+
s2 = s2.toLowerCase();
|
|
3198
|
+
if (s2 === "_authtoken") return "_authToken";
|
|
3199
|
+
let r = s2[0];
|
|
3200
|
+
for (let i = 1; i < s2.length; i++) {
|
|
3201
|
+
r += s2[i] === "_" ? "-" : s2[i];
|
|
3202
3202
|
}
|
|
3203
3203
|
return r;
|
|
3204
3204
|
}
|
|
@@ -3339,11 +3339,11 @@ var require_util = __commonJS({
|
|
|
3339
3339
|
if (files.includes("node_modules") || files.includes("package.json") || files.includes("package.json5") || files.includes("package.yaml") || files.includes("pnpm-workspace.yaml")) {
|
|
3340
3340
|
return name24;
|
|
3341
3341
|
}
|
|
3342
|
-
const
|
|
3343
|
-
if (
|
|
3342
|
+
const dirname9 = path10.dirname(name24);
|
|
3343
|
+
if (dirname9 === name24) {
|
|
3344
3344
|
return original;
|
|
3345
3345
|
}
|
|
3346
|
-
return find(
|
|
3346
|
+
return find(dirname9, original);
|
|
3347
3347
|
} catch (error62) {
|
|
3348
3348
|
if (name24 === original) {
|
|
3349
3349
|
if (error62.code === "ENOENT") {
|
|
@@ -4032,8 +4032,8 @@ var require_clean = __commonJS({
|
|
|
4032
4032
|
"use strict";
|
|
4033
4033
|
var parse3 = require_parse();
|
|
4034
4034
|
var clean = (version2, options) => {
|
|
4035
|
-
const
|
|
4036
|
-
return
|
|
4035
|
+
const s2 = parse3(version2.trim().replace(/^[=v]+/, ""), options);
|
|
4036
|
+
return s2 ? s2.version : null;
|
|
4037
4037
|
};
|
|
4038
4038
|
module.exports = clean;
|
|
4039
4039
|
}
|
|
@@ -5474,22 +5474,22 @@ var require_ini2 = __commonJS({
|
|
|
5474
5474
|
keys.filter((k) => obj[k] === null || Array.isArray(obj[k]) || typeof obj[k] !== "object").map((k) => Array.isArray(obj[k]) ? `${k}[]` : k).concat([""]).reduce((a, b) => safe(a).length >= safe(b).length ? a : b)
|
|
5475
5475
|
).length;
|
|
5476
5476
|
}
|
|
5477
|
-
let
|
|
5477
|
+
let out2 = "";
|
|
5478
5478
|
const arraySuffix = opt.bracketedArray ? "[]" : "";
|
|
5479
5479
|
for (const k of keys) {
|
|
5480
5480
|
const val = obj[k];
|
|
5481
5481
|
if (val && Array.isArray(val)) {
|
|
5482
5482
|
for (const item of val) {
|
|
5483
|
-
|
|
5483
|
+
out2 += safe(`${k}${arraySuffix}`).padEnd(padToChars, " ") + separator + safe(item) + eol;
|
|
5484
5484
|
}
|
|
5485
5485
|
} else if (val && typeof val === "object") {
|
|
5486
5486
|
children.push(k);
|
|
5487
5487
|
} else {
|
|
5488
|
-
|
|
5488
|
+
out2 += safe(k).padEnd(padToChars, " ") + separator + safe(val) + eol;
|
|
5489
5489
|
}
|
|
5490
5490
|
}
|
|
5491
|
-
if (opt.section &&
|
|
5492
|
-
|
|
5491
|
+
if (opt.section && out2.length) {
|
|
5492
|
+
out2 = "[" + safe(opt.section) + "]" + (opt.newline ? eol + eol : eol) + out2;
|
|
5493
5493
|
}
|
|
5494
5494
|
for (const k of children) {
|
|
5495
5495
|
const nk = splitSections(k, ".").join("\\.");
|
|
@@ -5498,12 +5498,12 @@ var require_ini2 = __commonJS({
|
|
|
5498
5498
|
...opt,
|
|
5499
5499
|
section
|
|
5500
5500
|
});
|
|
5501
|
-
if (
|
|
5502
|
-
|
|
5501
|
+
if (out2.length && child.length) {
|
|
5502
|
+
out2 += eol;
|
|
5503
5503
|
}
|
|
5504
|
-
|
|
5504
|
+
out2 += child;
|
|
5505
5505
|
}
|
|
5506
|
-
return
|
|
5506
|
+
return out2;
|
|
5507
5507
|
};
|
|
5508
5508
|
function splitSections(str, separator) {
|
|
5509
5509
|
var lastMatchIndex = 0;
|
|
@@ -5526,8 +5526,8 @@ var require_ini2 = __commonJS({
|
|
|
5526
5526
|
}
|
|
5527
5527
|
var decode3 = (str, opt = {}) => {
|
|
5528
5528
|
opt.bracketedArray = opt.bracketedArray !== false;
|
|
5529
|
-
const
|
|
5530
|
-
let p =
|
|
5529
|
+
const out2 = /* @__PURE__ */ Object.create(null);
|
|
5530
|
+
let p = out2;
|
|
5531
5531
|
let section = null;
|
|
5532
5532
|
const re = /^\[([^\]]*)\]\s*$|^([^=]+)(=(.*))?$/i;
|
|
5533
5533
|
const lines = str.split(/[\r\n]+/g);
|
|
@@ -5546,7 +5546,7 @@ var require_ini2 = __commonJS({
|
|
|
5546
5546
|
p = /* @__PURE__ */ Object.create(null);
|
|
5547
5547
|
continue;
|
|
5548
5548
|
}
|
|
5549
|
-
p =
|
|
5549
|
+
p = out2[section] = out2[section] || /* @__PURE__ */ Object.create(null);
|
|
5550
5550
|
continue;
|
|
5551
5551
|
}
|
|
5552
5552
|
const keyRaw = unsafe(match[2]);
|
|
@@ -5577,12 +5577,12 @@ var require_ini2 = __commonJS({
|
|
|
5577
5577
|
}
|
|
5578
5578
|
}
|
|
5579
5579
|
const remove = [];
|
|
5580
|
-
for (const k of Object.keys(
|
|
5581
|
-
if (!hasOwnProperty.call(
|
|
5580
|
+
for (const k of Object.keys(out2)) {
|
|
5581
|
+
if (!hasOwnProperty.call(out2, k) || typeof out2[k] !== "object" || Array.isArray(out2[k])) {
|
|
5582
5582
|
continue;
|
|
5583
5583
|
}
|
|
5584
5584
|
const parts = splitSections(k, ".");
|
|
5585
|
-
p =
|
|
5585
|
+
p = out2;
|
|
5586
5586
|
const l = parts.pop();
|
|
5587
5587
|
const nl = l.replace(/\\\./g, ".");
|
|
5588
5588
|
for (const part of parts) {
|
|
@@ -5594,16 +5594,16 @@ var require_ini2 = __commonJS({
|
|
|
5594
5594
|
}
|
|
5595
5595
|
p = p[part];
|
|
5596
5596
|
}
|
|
5597
|
-
if (p ===
|
|
5597
|
+
if (p === out2 && nl === l) {
|
|
5598
5598
|
continue;
|
|
5599
5599
|
}
|
|
5600
|
-
p[nl] =
|
|
5600
|
+
p[nl] = out2[k];
|
|
5601
5601
|
remove.push(k);
|
|
5602
5602
|
}
|
|
5603
5603
|
for (const del of remove) {
|
|
5604
|
-
delete
|
|
5604
|
+
delete out2[del];
|
|
5605
5605
|
}
|
|
5606
|
-
return
|
|
5606
|
+
return out2;
|
|
5607
5607
|
};
|
|
5608
5608
|
var isQuoted = (val) => {
|
|
5609
5609
|
return val.startsWith('"') && val.endsWith('"') || val.startsWith("'") && val.endsWith("'");
|
|
@@ -7475,9 +7475,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
7475
7475
|
if (fn) {
|
|
7476
7476
|
this._exitCallback = fn;
|
|
7477
7477
|
} else {
|
|
7478
|
-
this._exitCallback = (
|
|
7479
|
-
if (
|
|
7480
|
-
throw
|
|
7478
|
+
this._exitCallback = (err2) => {
|
|
7479
|
+
if (err2.code !== "commander.executeSubCommandAsync") {
|
|
7480
|
+
throw err2;
|
|
7481
7481
|
} else {
|
|
7482
7482
|
}
|
|
7483
7483
|
};
|
|
@@ -7553,12 +7553,12 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
7553
7553
|
_callParseArg(target, value, previous, invalidArgumentMessage) {
|
|
7554
7554
|
try {
|
|
7555
7555
|
return target.parseArg(value, previous);
|
|
7556
|
-
} catch (
|
|
7557
|
-
if (
|
|
7558
|
-
const message = `${invalidArgumentMessage} ${
|
|
7559
|
-
this.error(message, { exitCode:
|
|
7556
|
+
} catch (err2) {
|
|
7557
|
+
if (err2.code === "commander.invalidArgument") {
|
|
7558
|
+
const message = `${invalidArgumentMessage} ${err2.message}`;
|
|
7559
|
+
this.error(message, { exitCode: err2.exitCode, code: err2.code });
|
|
7560
7560
|
}
|
|
7561
|
-
throw
|
|
7561
|
+
throw err2;
|
|
7562
7562
|
}
|
|
7563
7563
|
}
|
|
7564
7564
|
/**
|
|
@@ -8149,14 +8149,14 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
8149
8149
|
);
|
|
8150
8150
|
}
|
|
8151
8151
|
});
|
|
8152
|
-
proc.on("error", (
|
|
8153
|
-
if (
|
|
8152
|
+
proc.on("error", (err2) => {
|
|
8153
|
+
if (err2.code === "ENOENT") {
|
|
8154
8154
|
this._checkForMissingExecutable(
|
|
8155
8155
|
executableFile,
|
|
8156
8156
|
executableDir,
|
|
8157
8157
|
subcommand._name
|
|
8158
8158
|
);
|
|
8159
|
-
} else if (
|
|
8159
|
+
} else if (err2.code === "EACCES") {
|
|
8160
8160
|
throw new Error(`'${executableFile}' not executable`);
|
|
8161
8161
|
}
|
|
8162
8162
|
if (!exitCallback) {
|
|
@@ -8167,7 +8167,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
8167
8167
|
"commander.executeSubCommandAsync",
|
|
8168
8168
|
"(error)"
|
|
8169
8169
|
);
|
|
8170
|
-
wrappedError.nestedError =
|
|
8170
|
+
wrappedError.nestedError = err2;
|
|
8171
8171
|
exitCallback(wrappedError);
|
|
8172
8172
|
}
|
|
8173
8173
|
});
|
|
@@ -8794,11 +8794,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
8794
8794
|
_excessArguments(receivedArgs) {
|
|
8795
8795
|
if (this._allowExcessArguments) return;
|
|
8796
8796
|
const expected = this.registeredArguments.length;
|
|
8797
|
-
const
|
|
8797
|
+
const s2 = expected === 1 ? "" : "s";
|
|
8798
8798
|
const received = receivedArgs.length;
|
|
8799
8799
|
const forSubcommand = this.parent ? ` for '${this.name()}'` : "";
|
|
8800
8800
|
const details = receivedArgs.join(", ");
|
|
8801
|
-
const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${
|
|
8801
|
+
const message = `error: too many arguments${forSubcommand}. Expected ${expected} argument${s2} but got ${received}: ${details}.`;
|
|
8802
8802
|
this.error(message, { code: "commander.excessArguments" });
|
|
8803
8803
|
}
|
|
8804
8804
|
/**
|
|
@@ -9373,6 +9373,25 @@ function classifyRequestFailure(error62) {
|
|
|
9373
9373
|
}
|
|
9374
9374
|
return { kind, message, hint: FAILURE_HINTS[kind] };
|
|
9375
9375
|
}
|
|
9376
|
+
var SERVER_CODE = /^[a-z][a-z0-9_]{0,63}$/;
|
|
9377
|
+
function withServerCode(error62, body) {
|
|
9378
|
+
try {
|
|
9379
|
+
const code = JSON.parse(body)?.error;
|
|
9380
|
+
if (typeof code === "string" && SERVER_CODE.test(code)) {
|
|
9381
|
+
Object.defineProperty(error62, "serverCode", {
|
|
9382
|
+
value: code,
|
|
9383
|
+
enumerable: false
|
|
9384
|
+
});
|
|
9385
|
+
}
|
|
9386
|
+
} catch {
|
|
9387
|
+
return error62;
|
|
9388
|
+
}
|
|
9389
|
+
return error62;
|
|
9390
|
+
}
|
|
9391
|
+
function serverCodeOf(error62) {
|
|
9392
|
+
const code = error62?.serverCode;
|
|
9393
|
+
return typeof code === "string" ? code : null;
|
|
9394
|
+
}
|
|
9376
9395
|
function authError(message, hint) {
|
|
9377
9396
|
return new CliError(
|
|
9378
9397
|
message,
|
|
@@ -9418,7 +9437,7 @@ function isNodeError(value) {
|
|
|
9418
9437
|
|
|
9419
9438
|
// src/lib/version.ts
|
|
9420
9439
|
var CLI_PACKAGE_NAME = "@great-arrow/cli";
|
|
9421
|
-
var CLI_VERSION = "0.1.
|
|
9440
|
+
var CLI_VERSION = "0.1.66";
|
|
9422
9441
|
var GAD_INSTALL_VERSION = "2026.08.08";
|
|
9423
9442
|
var GAD_INSTALL_MIN_VERSION = "2026.06.22";
|
|
9424
9443
|
var GAD_INSTALL_HEADER = "X-GAD-Install-Version";
|
|
@@ -9436,9 +9455,9 @@ import { homedir } from "node:os";
|
|
|
9436
9455
|
import { join, dirname } from "node:path";
|
|
9437
9456
|
|
|
9438
9457
|
// src/lib/debug.ts
|
|
9439
|
-
function debugSwallow(scope,
|
|
9458
|
+
function debugSwallow(scope, err2) {
|
|
9440
9459
|
if (!process.env.GAD_DEBUG) return;
|
|
9441
|
-
const detail =
|
|
9460
|
+
const detail = err2 instanceof Error ? err2.stack ?? err2.message : String(err2);
|
|
9442
9461
|
process.stderr.write(`gad: [debug] ${scope} swallowed: ${detail}
|
|
9443
9462
|
`);
|
|
9444
9463
|
}
|
|
@@ -9446,81 +9465,91 @@ function debugSwallow(scope, err) {
|
|
|
9446
9465
|
// src/lib/keychain.ts
|
|
9447
9466
|
var SERVICE = "GreatArrowDigital";
|
|
9448
9467
|
var ACCOUNT = "api-token";
|
|
9449
|
-
function
|
|
9450
|
-
return join(homedir(), ".great-arrow", "credential");
|
|
9468
|
+
function slotFilePath(account) {
|
|
9469
|
+
if (account === ACCOUNT) return join(homedir(), ".great-arrow", "credential");
|
|
9470
|
+
return join(homedir(), ".great-arrow", "slots", encodeURIComponent(account));
|
|
9451
9471
|
}
|
|
9452
|
-
async function loadEntry() {
|
|
9472
|
+
async function loadEntry(account) {
|
|
9453
9473
|
try {
|
|
9454
9474
|
const { AsyncEntry } = await import("@napi-rs/keyring");
|
|
9455
|
-
return new AsyncEntry(SERVICE,
|
|
9475
|
+
return new AsyncEntry(SERVICE, account);
|
|
9456
9476
|
} catch {
|
|
9457
9477
|
return null;
|
|
9458
9478
|
}
|
|
9459
9479
|
}
|
|
9460
|
-
async function readFileFallback() {
|
|
9480
|
+
async function readFileFallback(account) {
|
|
9461
9481
|
try {
|
|
9462
|
-
const raw = await readFile(
|
|
9482
|
+
const raw = await readFile(slotFilePath(account), "utf-8");
|
|
9463
9483
|
const trimmed = raw.trim();
|
|
9464
9484
|
return trimmed === "" ? null : trimmed;
|
|
9465
9485
|
} catch {
|
|
9466
9486
|
return null;
|
|
9467
9487
|
}
|
|
9468
9488
|
}
|
|
9469
|
-
async function
|
|
9470
|
-
const entry = await loadEntry();
|
|
9489
|
+
async function getSecretSlot(account) {
|
|
9490
|
+
const entry = await loadEntry(account);
|
|
9471
9491
|
if (entry) {
|
|
9472
9492
|
try {
|
|
9473
9493
|
const value = await entry.getPassword();
|
|
9474
9494
|
if (value) return value;
|
|
9475
|
-
} catch (
|
|
9476
|
-
debugSwallow("keychain.
|
|
9495
|
+
} catch (err2) {
|
|
9496
|
+
debugSwallow("keychain.getSecretSlot", err2);
|
|
9477
9497
|
}
|
|
9478
9498
|
}
|
|
9479
|
-
return readFileFallback();
|
|
9499
|
+
return readFileFallback(account);
|
|
9480
9500
|
}
|
|
9481
|
-
async function
|
|
9482
|
-
const entry = await loadEntry();
|
|
9501
|
+
async function setSecretSlot(account, value) {
|
|
9502
|
+
const entry = await loadEntry(account);
|
|
9483
9503
|
if (entry) {
|
|
9484
9504
|
try {
|
|
9485
|
-
await entry.setPassword(
|
|
9486
|
-
await removeFileFallback();
|
|
9505
|
+
await entry.setPassword(value);
|
|
9506
|
+
await removeFileFallback(account);
|
|
9487
9507
|
return true;
|
|
9488
|
-
} catch (
|
|
9489
|
-
debugSwallow("keychain.
|
|
9508
|
+
} catch (err2) {
|
|
9509
|
+
debugSwallow("keychain.setSecretSlot", err2);
|
|
9490
9510
|
}
|
|
9491
9511
|
try {
|
|
9492
9512
|
await entry.deletePassword();
|
|
9493
|
-
} catch (
|
|
9494
|
-
debugSwallow("keychain.
|
|
9513
|
+
} catch (err2) {
|
|
9514
|
+
debugSwallow("keychain.setSecretSlot(delete stale)", err2);
|
|
9495
9515
|
return false;
|
|
9496
9516
|
}
|
|
9497
9517
|
}
|
|
9498
9518
|
try {
|
|
9499
|
-
const path10 =
|
|
9519
|
+
const path10 = slotFilePath(account);
|
|
9500
9520
|
await mkdir(dirname(path10), { recursive: true, mode: 448 });
|
|
9501
|
-
await writeFile(path10,
|
|
9521
|
+
await writeFile(path10, value, { mode: 384 });
|
|
9502
9522
|
return true;
|
|
9503
9523
|
} catch {
|
|
9504
9524
|
return false;
|
|
9505
9525
|
}
|
|
9506
9526
|
}
|
|
9507
|
-
async function
|
|
9508
|
-
const entry = await loadEntry();
|
|
9527
|
+
async function deleteSecretSlot(account) {
|
|
9528
|
+
const entry = await loadEntry(account);
|
|
9509
9529
|
if (entry) {
|
|
9510
9530
|
try {
|
|
9511
9531
|
await entry.deletePassword();
|
|
9512
|
-
} catch (
|
|
9513
|
-
debugSwallow("keychain.
|
|
9532
|
+
} catch (err2) {
|
|
9533
|
+
debugSwallow("keychain.deleteSecretSlot", err2);
|
|
9514
9534
|
}
|
|
9515
9535
|
}
|
|
9516
|
-
await removeFileFallback();
|
|
9536
|
+
await removeFileFallback(account);
|
|
9537
|
+
}
|
|
9538
|
+
function getToken() {
|
|
9539
|
+
return getSecretSlot(ACCOUNT);
|
|
9540
|
+
}
|
|
9541
|
+
function setToken(token) {
|
|
9542
|
+
return setSecretSlot(ACCOUNT, token);
|
|
9543
|
+
}
|
|
9544
|
+
function deleteToken() {
|
|
9545
|
+
return deleteSecretSlot(ACCOUNT);
|
|
9517
9546
|
}
|
|
9518
|
-
async function removeFileFallback() {
|
|
9547
|
+
async function removeFileFallback(account) {
|
|
9519
9548
|
try {
|
|
9520
|
-
await unlink(
|
|
9521
|
-
} catch (
|
|
9522
|
-
if (
|
|
9523
|
-
debugSwallow("keychain.removeFileFallback",
|
|
9549
|
+
await unlink(slotFilePath(account));
|
|
9550
|
+
} catch (err2) {
|
|
9551
|
+
if (err2?.code !== "ENOENT") {
|
|
9552
|
+
debugSwallow("keychain.removeFileFallback", err2);
|
|
9524
9553
|
}
|
|
9525
9554
|
}
|
|
9526
9555
|
}
|
|
@@ -9565,6 +9594,17 @@ async function clearStoredCredential() {
|
|
|
9565
9594
|
await deleteToken();
|
|
9566
9595
|
}
|
|
9567
9596
|
|
|
9597
|
+
// src/lib/token-login-guard.ts
|
|
9598
|
+
function decideTokenLogin(input2) {
|
|
9599
|
+
const { token, stored, force } = input2;
|
|
9600
|
+
if (stored?.kind !== "oauth") return { action: "store" };
|
|
9601
|
+
if (token === stored.credential.accessToken) {
|
|
9602
|
+
return { action: "keep-oauth", reason: "same-access-token" };
|
|
9603
|
+
}
|
|
9604
|
+
if (token.startsWith("gad_v1_") || force) return { action: "store" };
|
|
9605
|
+
return { action: "refuse", reason: "would-replace-oauth" };
|
|
9606
|
+
}
|
|
9607
|
+
|
|
9568
9608
|
// src/lib/cli-locator.ts
|
|
9569
9609
|
import {
|
|
9570
9610
|
chmodSync,
|
|
@@ -9585,8 +9625,8 @@ function writeCliLocator(home = homedir2(), entry = process.argv[1]) {
|
|
|
9585
9625
|
let resolved = entry;
|
|
9586
9626
|
try {
|
|
9587
9627
|
resolved = realpathSync(entry);
|
|
9588
|
-
} catch (
|
|
9589
|
-
debugSwallow("cli-locator.realpath",
|
|
9628
|
+
} catch (err2) {
|
|
9629
|
+
debugSwallow("cli-locator.realpath", err2);
|
|
9590
9630
|
}
|
|
9591
9631
|
mkdirSync(dir, { recursive: true });
|
|
9592
9632
|
writeFileSync(
|
|
@@ -9600,8 +9640,8 @@ function writeCliLocator(home = homedir2(), entry = process.argv[1]) {
|
|
|
9600
9640
|
);
|
|
9601
9641
|
chmodSync(tmp, 384);
|
|
9602
9642
|
renameSync(tmp, target);
|
|
9603
|
-
} catch (
|
|
9604
|
-
debugSwallow("cli-locator.write",
|
|
9643
|
+
} catch (err2) {
|
|
9644
|
+
debugSwallow("cli-locator.write", err2);
|
|
9605
9645
|
try {
|
|
9606
9646
|
rmSync(tmp, { force: true });
|
|
9607
9647
|
} catch (cleanupErr) {
|
|
@@ -9699,8 +9739,8 @@ async function loadConfig() {
|
|
|
9699
9739
|
const content = await readFile2(configPath, "utf-8");
|
|
9700
9740
|
const parsed = parseConfig(content);
|
|
9701
9741
|
return { ...DEFAULTS, ...stripEmpty(parsed) };
|
|
9702
|
-
} catch (
|
|
9703
|
-
if (isNodeError2(
|
|
9742
|
+
} catch (err2) {
|
|
9743
|
+
if (isNodeError2(err2) && err2.code === "ENOENT") {
|
|
9704
9744
|
return { ...DEFAULTS };
|
|
9705
9745
|
}
|
|
9706
9746
|
return { ...DEFAULTS };
|
|
@@ -9737,8 +9777,8 @@ function stripEmpty(config2) {
|
|
|
9737
9777
|
result.telemetry_enabled = config2.telemetry_enabled;
|
|
9738
9778
|
return result;
|
|
9739
9779
|
}
|
|
9740
|
-
function isNodeError2(
|
|
9741
|
-
return
|
|
9780
|
+
function isNodeError2(err2) {
|
|
9781
|
+
return err2 instanceof Error && "code" in err2;
|
|
9742
9782
|
}
|
|
9743
9783
|
|
|
9744
9784
|
// src/lib/oauth/pkce.ts
|
|
@@ -9770,8 +9810,8 @@ var DEFAULT_CALLBACK_PORT = 51789;
|
|
|
9770
9810
|
var CALLBACK_PATH = "/callback";
|
|
9771
9811
|
var LOOPBACK_HOST = "127.0.0.1";
|
|
9772
9812
|
var DEFAULT_TIMEOUT_MS = 12e4;
|
|
9773
|
-
function escapeHtml(
|
|
9774
|
-
return
|
|
9813
|
+
function escapeHtml(s2) {
|
|
9814
|
+
return s2.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
9775
9815
|
}
|
|
9776
9816
|
var CLOSE_TAB_HTML = (ok, detail) => `<!doctype html>
|
|
9777
9817
|
<html><head><meta charset="utf-8"><title>Great Arrow CLI</title>
|
|
@@ -9782,12 +9822,12 @@ h1{font-size:1.25rem;margin:0 0 .5rem}p{color:#9a9aa3;margin:0}</style></head>
|
|
|
9782
9822
|
<body><div class="card"><h1>${ok ? "\u2713 Signed in to Great Arrow" : "\u2717 Sign-in failed"}</h1>
|
|
9783
9823
|
<p>${escapeHtml(detail)}</p></div></body></html>`;
|
|
9784
9824
|
function listen(port) {
|
|
9785
|
-
return new Promise((
|
|
9825
|
+
return new Promise((resolve5, reject) => {
|
|
9786
9826
|
const server = createServer();
|
|
9787
9827
|
server.on("error", reject);
|
|
9788
9828
|
server.listen(port, LOOPBACK_HOST, () => {
|
|
9789
9829
|
const addr = server.address();
|
|
9790
|
-
|
|
9830
|
+
resolve5({ server, port: addr.port });
|
|
9791
9831
|
});
|
|
9792
9832
|
});
|
|
9793
9833
|
}
|
|
@@ -9812,7 +9852,7 @@ async function startLoopbackServer(opts) {
|
|
|
9812
9852
|
port,
|
|
9813
9853
|
close: () => server.close(),
|
|
9814
9854
|
waitForCallback({ timeoutMs = DEFAULT_TIMEOUT_MS } = {}) {
|
|
9815
|
-
return new Promise((
|
|
9855
|
+
return new Promise((resolve5, reject) => {
|
|
9816
9856
|
const timer = setTimeout(() => {
|
|
9817
9857
|
server.close();
|
|
9818
9858
|
reject(new Error("Timed out waiting for the browser callback."));
|
|
@@ -9852,7 +9892,7 @@ async function startLoopbackServer(opts) {
|
|
|
9852
9892
|
"You can close this tab and return to your terminal."
|
|
9853
9893
|
)
|
|
9854
9894
|
);
|
|
9855
|
-
settle2(() =>
|
|
9895
|
+
settle2(() => resolve5({ code, state }));
|
|
9856
9896
|
});
|
|
9857
9897
|
});
|
|
9858
9898
|
}
|
|
@@ -10137,16 +10177,16 @@ async function confirm(message) {
|
|
|
10137
10177
|
input: process.stdin,
|
|
10138
10178
|
output: process.stdout
|
|
10139
10179
|
});
|
|
10140
|
-
return new Promise((
|
|
10180
|
+
return new Promise((resolve5) => {
|
|
10141
10181
|
rl.question(`${message} [y/N] `, (answer) => {
|
|
10142
10182
|
rl.close();
|
|
10143
10183
|
const normalized = answer.trim().toLowerCase();
|
|
10144
|
-
|
|
10184
|
+
resolve5(normalized === "y" || normalized === "yes");
|
|
10145
10185
|
});
|
|
10146
10186
|
});
|
|
10147
10187
|
}
|
|
10148
|
-
function stripControlChars(
|
|
10149
|
-
return String(
|
|
10188
|
+
function stripControlChars(s2) {
|
|
10189
|
+
return String(s2).replace(/[\u0000-\u001f\u007f-\u009f]/g, "");
|
|
10150
10190
|
}
|
|
10151
10191
|
|
|
10152
10192
|
// src/lib/formatter.ts
|
|
@@ -10307,8 +10347,8 @@ function createFormatter(options) {
|
|
|
10307
10347
|
var DEFAULT_API_URL = "https://www.greatarrow.ai";
|
|
10308
10348
|
function isLegacyApiUrl(value) {
|
|
10309
10349
|
try {
|
|
10310
|
-
const
|
|
10311
|
-
return
|
|
10350
|
+
const hostname6 = new URL(value).hostname.toLowerCase();
|
|
10351
|
+
return hostname6 === "www.greatarrowdigital.com" || hostname6 === "greatarrowdigital.com";
|
|
10312
10352
|
} catch {
|
|
10313
10353
|
return false;
|
|
10314
10354
|
}
|
|
@@ -10328,10 +10368,10 @@ function maskToken(token) {
|
|
|
10328
10368
|
}
|
|
10329
10369
|
function openBrowser(url2) {
|
|
10330
10370
|
if (!/^https?:\/\//i.test(url2)) return Promise.resolve(false);
|
|
10331
|
-
return new Promise((
|
|
10371
|
+
return new Promise((resolve5) => {
|
|
10332
10372
|
const platform2 = process.platform;
|
|
10333
10373
|
const [cmd, args] = platform2 === "darwin" ? ["open", [url2]] : platform2 === "win32" ? ["cmd", ["/c", "start", "", url2]] : ["xdg-open", [url2]];
|
|
10334
|
-
execFile(cmd, args, (error62) =>
|
|
10374
|
+
execFile(cmd, args, (error62) => resolve5(!error62));
|
|
10335
10375
|
});
|
|
10336
10376
|
}
|
|
10337
10377
|
var loginCommand = new Command("login").description("Authenticate the CLI with your Great Arrow Digital account").option(
|
|
@@ -10340,7 +10380,10 @@ var loginCommand = new Command("login").description("Authenticate the CLI with y
|
|
|
10340
10380
|
).option(
|
|
10341
10381
|
"--no-browser",
|
|
10342
10382
|
"Print the authorize URL instead of opening a browser"
|
|
10343
|
-
).option("--scope <list>", "OAuth scope to request", "mcp").
|
|
10383
|
+
).option("--scope <list>", "OAuth scope to request", "mcp").option(
|
|
10384
|
+
"--force",
|
|
10385
|
+
"With --token: replace a signed-in OAuth session even if the token may be short-lived"
|
|
10386
|
+
).action(
|
|
10344
10387
|
async (options) => {
|
|
10345
10388
|
const fmt = createFormatter({
|
|
10346
10389
|
json: false,
|
|
@@ -10351,6 +10394,24 @@ var loginCommand = new Command("login").description("Authenticate the CLI with y
|
|
|
10351
10394
|
const config2 = await loadConfig();
|
|
10352
10395
|
const apiUrl = DEFAULT_API_URL;
|
|
10353
10396
|
if (options.token) {
|
|
10397
|
+
const decision = decideTokenLogin({
|
|
10398
|
+
token: options.token,
|
|
10399
|
+
stored: await loadStoredCredential(),
|
|
10400
|
+
force: options.force === true
|
|
10401
|
+
});
|
|
10402
|
+
if (decision.action === "keep-oauth") {
|
|
10403
|
+
fmt.success(
|
|
10404
|
+
"Already signed in: that is your OAuth session's current access token. Keeping the self-refreshing session."
|
|
10405
|
+
);
|
|
10406
|
+
return;
|
|
10407
|
+
}
|
|
10408
|
+
if (decision.action === "refuse") {
|
|
10409
|
+
fmt.error(
|
|
10410
|
+
"You are signed in with a self-refreshing OAuth session, and this token is not a personal API token (gad_v1_\u2026). Storing it would replace the session, and if it is an OAuth access token it stops working within the hour. Use a gad_v1_ token, or pass --force to replace the session anyway."
|
|
10411
|
+
);
|
|
10412
|
+
process.exitCode = 1;
|
|
10413
|
+
return;
|
|
10414
|
+
}
|
|
10354
10415
|
const stored = await savePatToken(options.token);
|
|
10355
10416
|
if (!stored) {
|
|
10356
10417
|
fmt.error(
|
|
@@ -10394,8 +10455,8 @@ var loginCommand = new Command("login").description("Authenticate the CLI with y
|
|
|
10394
10455
|
fmt.success(
|
|
10395
10456
|
"Signed in. Your session will refresh automatically \u2014 no need to log in again."
|
|
10396
10457
|
);
|
|
10397
|
-
} catch (
|
|
10398
|
-
const msg =
|
|
10458
|
+
} catch (err2) {
|
|
10459
|
+
const msg = err2 instanceof Error ? err2.message : String(err2);
|
|
10399
10460
|
fmt.error(`Login failed: ${msg}`);
|
|
10400
10461
|
fmt.info(
|
|
10401
10462
|
`You can also run \`gad login --token <token>\` with a token from ${apiUrl}/install/cli`
|
|
@@ -10436,8 +10497,8 @@ async function acquireRefreshLock() {
|
|
|
10436
10497
|
const path10 = refreshLockPath();
|
|
10437
10498
|
try {
|
|
10438
10499
|
await mkdir3(join4(homedir4(), ".great-arrow"), { recursive: true });
|
|
10439
|
-
} catch (
|
|
10440
|
-
debugSwallow("refresh-lock.mkdir",
|
|
10500
|
+
} catch (err2) {
|
|
10501
|
+
debugSwallow("refresh-lock.mkdir", err2);
|
|
10441
10502
|
}
|
|
10442
10503
|
const deadline = Date.now() + REFRESH_LOCK_WAIT_MS;
|
|
10443
10504
|
for (; ; ) {
|
|
@@ -10446,8 +10507,8 @@ async function acquireRefreshLock() {
|
|
|
10446
10507
|
await handle.writeFile(String(process.pid));
|
|
10447
10508
|
await handle.close();
|
|
10448
10509
|
return true;
|
|
10449
|
-
} catch (
|
|
10450
|
-
if (
|
|
10510
|
+
} catch (err2) {
|
|
10511
|
+
if (err2.code !== "EEXIST") {
|
|
10451
10512
|
throw networkError(
|
|
10452
10513
|
"Could not lock session renewal.",
|
|
10453
10514
|
"Check local credential storage and retry; your session has been kept."
|
|
@@ -10458,8 +10519,8 @@ async function acquireRefreshLock() {
|
|
|
10458
10519
|
if (age > REFRESH_LOCK_STALE_MS) {
|
|
10459
10520
|
try {
|
|
10460
10521
|
await rm(path10, { force: true });
|
|
10461
|
-
} catch (
|
|
10462
|
-
debugSwallow("refresh-lock.stale-rm",
|
|
10522
|
+
} catch (err2) {
|
|
10523
|
+
debugSwallow("refresh-lock.stale-rm", err2);
|
|
10463
10524
|
}
|
|
10464
10525
|
continue;
|
|
10465
10526
|
}
|
|
@@ -10470,16 +10531,16 @@ async function acquireRefreshLock() {
|
|
|
10470
10531
|
async function releaseRefreshLock() {
|
|
10471
10532
|
try {
|
|
10472
10533
|
await rm(refreshLockPath(), { force: true });
|
|
10473
|
-
} catch (
|
|
10474
|
-
debugSwallow("refresh-lock.release",
|
|
10534
|
+
} catch (err2) {
|
|
10535
|
+
debugSwallow("refresh-lock.release", err2);
|
|
10475
10536
|
}
|
|
10476
10537
|
}
|
|
10477
10538
|
async function storedPairOtherThan(ours) {
|
|
10478
10539
|
let stored = null;
|
|
10479
10540
|
try {
|
|
10480
10541
|
stored = await loadStoredCredential();
|
|
10481
|
-
} catch (
|
|
10482
|
-
debugSwallow("refresh.reread",
|
|
10542
|
+
} catch (err2) {
|
|
10543
|
+
debugSwallow("refresh.reread", err2);
|
|
10483
10544
|
}
|
|
10484
10545
|
if (stored?.kind !== "oauth") {
|
|
10485
10546
|
throw authError(
|
|
@@ -10643,8 +10704,8 @@ async function doRefresh(credential) {
|
|
|
10643
10704
|
);
|
|
10644
10705
|
}
|
|
10645
10706
|
return refreshed;
|
|
10646
|
-
} catch (
|
|
10647
|
-
if (
|
|
10707
|
+
} catch (err2) {
|
|
10708
|
+
if (err2 instanceof RefreshRejected) {
|
|
10648
10709
|
const theirs = await storedPairOtherThan(current);
|
|
10649
10710
|
if (theirs) {
|
|
10650
10711
|
if (Date.now() < theirs.accessExpiresAt) return theirs;
|
|
@@ -10656,7 +10717,7 @@ async function doRefresh(credential) {
|
|
|
10656
10717
|
await clearStoredCredential();
|
|
10657
10718
|
throw sessionExpired();
|
|
10658
10719
|
}
|
|
10659
|
-
throw
|
|
10720
|
+
throw err2;
|
|
10660
10721
|
} finally {
|
|
10661
10722
|
if (held) await releaseRefreshLock();
|
|
10662
10723
|
}
|
|
@@ -10943,14 +11004,14 @@ function luhnValid(candidate) {
|
|
|
10943
11004
|
}
|
|
10944
11005
|
var SECRET_TOKEN_RE = /\b(?:gad_[A-Za-z0-9_-]{20,}|sk-[A-Za-z0-9-]{20,}|Bearer\s+[A-Za-z0-9._~+/=-]{8,})\b/gi;
|
|
10945
11006
|
var SENSITIVE_QUERY_VALUE_RE = /((?:^|[?&])(?:code|token|token_hash|data_step_token|passkey_proof|access_token|refresh_token|id_token|api_key|apikey|api_secret|apisecret|key|secret|client_secret|password|state|sig|signature|t)=)[^&#\s]+/gi;
|
|
10946
|
-
function scrubPiiFromText(
|
|
10947
|
-
return
|
|
11007
|
+
function scrubPiiFromText(s2) {
|
|
11008
|
+
return s2.replace(EMAIL_RE, "[redacted-email]").replace(
|
|
10948
11009
|
CREDIT_CARD_RE,
|
|
10949
11010
|
(m) => luhnValid(m) ? "[redacted-credit-card]" : m
|
|
10950
11011
|
).replace(SSN_RE, "[redacted-ssn]").replace(PHONE_RE, "[redacted-phone]");
|
|
10951
11012
|
}
|
|
10952
|
-
function scrubTelemetryText(
|
|
10953
|
-
return scrubPiiFromText(
|
|
11013
|
+
function scrubTelemetryText(s2) {
|
|
11014
|
+
return scrubPiiFromText(s2).replace(SENSITIVE_QUERY_VALUE_RE, "$1[redacted]").replace(
|
|
10954
11015
|
SECRET_TOKEN_RE,
|
|
10955
11016
|
(match) => match.toLowerCase().startsWith("bearer ") ? "Bearer [redacted]" : "[redacted-secret]"
|
|
10956
11017
|
);
|
|
@@ -10979,11 +11040,11 @@ function redact(value, depth = 0) {
|
|
|
10979
11040
|
if (Array.isArray(value))
|
|
10980
11041
|
return value.slice(0, 20).map((v) => redact(v, depth + 1));
|
|
10981
11042
|
if (value && typeof value === "object") {
|
|
10982
|
-
const
|
|
11043
|
+
const out2 = {};
|
|
10983
11044
|
for (const [key, v] of Object.entries(value).slice(0, 30)) {
|
|
10984
|
-
|
|
11045
|
+
out2[key] = /token|secret|password|authorization|cookie|email/i.test(key) ? "[redacted]" : redact(v, depth + 1);
|
|
10985
11046
|
}
|
|
10986
|
-
return
|
|
11047
|
+
return out2;
|
|
10987
11048
|
}
|
|
10988
11049
|
return value;
|
|
10989
11050
|
}
|
|
@@ -11026,8 +11087,8 @@ async function captureCliEvent(input2) {
|
|
|
11026
11087
|
);
|
|
11027
11088
|
if (!response.ok)
|
|
11028
11089
|
debugSwallow("telemetry.send", new Error(`HTTP ${response.status}`));
|
|
11029
|
-
} catch (
|
|
11030
|
-
debugSwallow("telemetry.send",
|
|
11090
|
+
} catch (err2) {
|
|
11091
|
+
debugSwallow("telemetry.send", err2);
|
|
11031
11092
|
}
|
|
11032
11093
|
}
|
|
11033
11094
|
|
|
@@ -11043,8 +11104,8 @@ function getCommandWorkspaceTarget(options = {}) {
|
|
|
11043
11104
|
}
|
|
11044
11105
|
|
|
11045
11106
|
// ../local-runtime/src/abortable.ts
|
|
11046
|
-
function abortable(
|
|
11047
|
-
return new Promise((
|
|
11107
|
+
function abortable(run4, signal) {
|
|
11108
|
+
return new Promise((resolve5, reject) => {
|
|
11048
11109
|
const abort = () => {
|
|
11049
11110
|
signal.removeEventListener("abort", abort);
|
|
11050
11111
|
reject(signal.reason ?? new Error("Local operation stopped"));
|
|
@@ -11053,11 +11114,11 @@ function abortable(run2, signal) {
|
|
|
11053
11114
|
signal.addEventListener("abort", abort, { once: true });
|
|
11054
11115
|
Promise.resolve().then(() => {
|
|
11055
11116
|
signal.throwIfAborted();
|
|
11056
|
-
return
|
|
11057
|
-
}).then(
|
|
11117
|
+
return run4();
|
|
11118
|
+
}).then(resolve5, reject).finally(() => signal.removeEventListener("abort", abort));
|
|
11058
11119
|
});
|
|
11059
11120
|
}
|
|
11060
|
-
async function withLocalDeadline(deadlineMs,
|
|
11121
|
+
async function withLocalDeadline(deadlineMs, run4, parentSignal) {
|
|
11061
11122
|
if (!Number.isSafeInteger(deadlineMs) || deadlineMs <= 0 || deadlineMs > 36e5)
|
|
11062
11123
|
throw new Error("Invalid local operation deadline");
|
|
11063
11124
|
const controller = new AbortController();
|
|
@@ -11067,7 +11128,7 @@ async function withLocalDeadline(deadlineMs, run2, parentSignal) {
|
|
|
11067
11128
|
deadlineMs
|
|
11068
11129
|
);
|
|
11069
11130
|
try {
|
|
11070
|
-
return await abortable(() =>
|
|
11131
|
+
return await abortable(() => run4(signal), signal);
|
|
11071
11132
|
} finally {
|
|
11072
11133
|
clearTimeout(timer);
|
|
11073
11134
|
}
|
|
@@ -11229,6 +11290,7 @@ async function withNativeResponse(context2, path10, init, consume, parentSignal)
|
|
|
11229
11290
|
|
|
11230
11291
|
// src/lib/client.ts
|
|
11231
11292
|
var DEFAULT_TIMEOUT_MS2 = 3e4;
|
|
11293
|
+
var PRESENCE_TIMEOUT_MS = 4e4;
|
|
11232
11294
|
var MAX_RETRIES = 5;
|
|
11233
11295
|
var BASE_DELAY_MS = 1e3;
|
|
11234
11296
|
function detectGitOrigin() {
|
|
@@ -11313,7 +11375,7 @@ function describeError(error62) {
|
|
|
11313
11375
|
return String(error62);
|
|
11314
11376
|
}
|
|
11315
11377
|
function sleep(ms) {
|
|
11316
|
-
return new Promise((
|
|
11378
|
+
return new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
11317
11379
|
}
|
|
11318
11380
|
var GadClient = class {
|
|
11319
11381
|
token;
|
|
@@ -11438,16 +11500,22 @@ var GadClient = class {
|
|
|
11438
11500
|
const status = response.status;
|
|
11439
11501
|
const body = await response.text().catch(() => "");
|
|
11440
11502
|
if (status === 403) {
|
|
11441
|
-
throw
|
|
11442
|
-
|
|
11443
|
-
|
|
11444
|
-
|
|
11503
|
+
throw withServerCode(
|
|
11504
|
+
new CliError(
|
|
11505
|
+
"Permission denied (HTTP 403).",
|
|
11506
|
+
1 /* AUTH_ERROR */,
|
|
11507
|
+
"Check this connection's scopes and workspace permissions at /account/connections."
|
|
11508
|
+
),
|
|
11509
|
+
body
|
|
11445
11510
|
);
|
|
11446
11511
|
}
|
|
11447
11512
|
if (status === 401) {
|
|
11448
|
-
throw
|
|
11449
|
-
|
|
11450
|
-
|
|
11513
|
+
throw withServerCode(
|
|
11514
|
+
authError(
|
|
11515
|
+
`Authentication failed (HTTP ${status}).`,
|
|
11516
|
+
"Run 'gad login' to re-authenticate, or check your GAD_TOKEN."
|
|
11517
|
+
),
|
|
11518
|
+
body
|
|
11451
11519
|
);
|
|
11452
11520
|
}
|
|
11453
11521
|
if (status >= 500) {
|
|
@@ -11457,10 +11525,13 @@ var GadClient = class {
|
|
|
11457
11525
|
);
|
|
11458
11526
|
}
|
|
11459
11527
|
const message = body ? `Request failed (HTTP ${status}): ${body.slice(0, 200)}` : `Request failed (HTTP ${status}).`;
|
|
11460
|
-
throw
|
|
11461
|
-
|
|
11462
|
-
|
|
11463
|
-
|
|
11528
|
+
throw withServerCode(
|
|
11529
|
+
new CliError(
|
|
11530
|
+
message,
|
|
11531
|
+
mapErrorToExitCode(status),
|
|
11532
|
+
"Check the command usage with --help."
|
|
11533
|
+
),
|
|
11534
|
+
body
|
|
11464
11535
|
);
|
|
11465
11536
|
}
|
|
11466
11537
|
/**
|
|
@@ -11611,6 +11682,47 @@ var GadClient = class {
|
|
|
11611
11682
|
})();
|
|
11612
11683
|
}
|
|
11613
11684
|
}
|
|
11685
|
+
/**
|
|
11686
|
+
* One request with NO retry, bounded by `AbortSignal.timeout`. For the
|
|
11687
|
+
* agent-presence routes: a replayed long-poll doubles a hold and the caller
|
|
11688
|
+
* already owns the loop and its backoff. Returns the status and parsed body
|
|
11689
|
+
* (null when not JSON) so the caller can read a 404 itself; a timeout or
|
|
11690
|
+
* network failure throws.
|
|
11691
|
+
*/
|
|
11692
|
+
async requestOnce(method, path10, opts = {}) {
|
|
11693
|
+
const qs = opts.params && Object.keys(opts.params).length > 0 ? `?${new URLSearchParams(opts.params).toString()}` : "";
|
|
11694
|
+
const signal = AbortSignal.timeout(opts.timeoutMs ?? PRESENCE_TIMEOUT_MS);
|
|
11695
|
+
const headers = this.buildHeaders();
|
|
11696
|
+
if (method === "GET") delete headers["Content-Type"];
|
|
11697
|
+
if (this.getToken) {
|
|
11698
|
+
const getToken2 = this.getToken;
|
|
11699
|
+
headers.Authorization = `Bearer ${await new Promise(
|
|
11700
|
+
(resolve5, reject) => {
|
|
11701
|
+
signal.addEventListener(
|
|
11702
|
+
"abort",
|
|
11703
|
+
() => reject(networkError("Session renewal timed out.")),
|
|
11704
|
+
{ once: true }
|
|
11705
|
+
);
|
|
11706
|
+
getToken2().then(resolve5, reject);
|
|
11707
|
+
}
|
|
11708
|
+
)}`;
|
|
11709
|
+
}
|
|
11710
|
+
const response = await fetch(`${this.apiUrl}${path10}${qs}`, {
|
|
11711
|
+
method,
|
|
11712
|
+
headers,
|
|
11713
|
+
...opts.body !== void 0 && { body: JSON.stringify(opts.body) },
|
|
11714
|
+
redirect: "error",
|
|
11715
|
+
cache: "no-store",
|
|
11716
|
+
signal
|
|
11717
|
+
});
|
|
11718
|
+
let body = null;
|
|
11719
|
+
try {
|
|
11720
|
+
body = await response.json();
|
|
11721
|
+
} catch {
|
|
11722
|
+
body = null;
|
|
11723
|
+
}
|
|
11724
|
+
return { status: response.status, body };
|
|
11725
|
+
}
|
|
11614
11726
|
/**
|
|
11615
11727
|
* Make a GET request to a REST API endpoint.
|
|
11616
11728
|
*
|
|
@@ -11685,6 +11797,38 @@ var GadClient = class {
|
|
|
11685
11797
|
}
|
|
11686
11798
|
return this.handleResponse(response);
|
|
11687
11799
|
}
|
|
11800
|
+
/**
|
|
11801
|
+
* Make a DELETE request to a REST API endpoint. Like POST, it is retried
|
|
11802
|
+
* only when the connection never reached the server.
|
|
11803
|
+
*/
|
|
11804
|
+
async delete(path10) {
|
|
11805
|
+
const url2 = `${this.apiUrl}${path10}`;
|
|
11806
|
+
const headers = this.buildHeaders();
|
|
11807
|
+
delete headers["Content-Type"];
|
|
11808
|
+
let response;
|
|
11809
|
+
try {
|
|
11810
|
+
response = await this.fetchWithRetry(
|
|
11811
|
+
url2,
|
|
11812
|
+
{ method: "DELETE", headers },
|
|
11813
|
+
void 0,
|
|
11814
|
+
"connection-only"
|
|
11815
|
+
);
|
|
11816
|
+
} catch (error62) {
|
|
11817
|
+
if (error62 instanceof CliError) throw error62;
|
|
11818
|
+
void captureCliEvent({
|
|
11819
|
+
apiUrl: this.apiUrl,
|
|
11820
|
+
token: this.token,
|
|
11821
|
+
name: "network_error",
|
|
11822
|
+
error: error62,
|
|
11823
|
+
context: { method: "DELETE", path: path10 }
|
|
11824
|
+
});
|
|
11825
|
+
throw networkError(
|
|
11826
|
+
`Network error on DELETE ${path10}.`,
|
|
11827
|
+
"Check your internet connection or run 'gad doctor'."
|
|
11828
|
+
);
|
|
11829
|
+
}
|
|
11830
|
+
return this.handleResponse(response);
|
|
11831
|
+
}
|
|
11688
11832
|
};
|
|
11689
11833
|
|
|
11690
11834
|
// src/lib/global-opts.ts
|
|
@@ -11778,10 +11922,10 @@ ${tryThese.map((t) => ` \u2022 ${t}`).join("\n")}`
|
|
|
11778
11922
|
|
|
11779
11923
|
// src/lib/stdin.ts
|
|
11780
11924
|
function readStream(stream) {
|
|
11781
|
-
return new Promise((
|
|
11925
|
+
return new Promise((resolve5, reject) => {
|
|
11782
11926
|
const chunks = [];
|
|
11783
11927
|
stream.on("data", (chunk) => chunks.push(chunk));
|
|
11784
|
-
stream.on("end", () =>
|
|
11928
|
+
stream.on("end", () => resolve5(Buffer.concat(chunks).toString("utf8")));
|
|
11785
11929
|
stream.on("error", reject);
|
|
11786
11930
|
});
|
|
11787
11931
|
}
|
|
@@ -12323,8 +12467,8 @@ function text(value) {
|
|
|
12323
12467
|
}
|
|
12324
12468
|
function formatTodoDetail(todo) {
|
|
12325
12469
|
const assignees = Array.isArray(todo.assignees) ? todo.assignees.map((a) => `${text(a.displayName)} (${text(a.type)})`).join(", ") : "";
|
|
12326
|
-
const
|
|
12327
|
-
const lastRun =
|
|
12470
|
+
const run4 = todo.lastRun ?? null;
|
|
12471
|
+
const lastRun = run4 ? `${text(run4.status)} \u2014 ${text(run4.agentName)}` : "";
|
|
12328
12472
|
return {
|
|
12329
12473
|
id: text(todo.id),
|
|
12330
12474
|
title: text(todo.title),
|
|
@@ -12460,8 +12604,8 @@ var todo_default = todoCommand;
|
|
|
12460
12604
|
import { execFileSync } from "node:child_process";
|
|
12461
12605
|
|
|
12462
12606
|
// src/lib/claim-preflight.ts
|
|
12463
|
-
function normalize(
|
|
12464
|
-
return
|
|
12607
|
+
function normalize(s2) {
|
|
12608
|
+
return s2.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
|
|
12465
12609
|
}
|
|
12466
12610
|
function mentions(haystack, normSlug) {
|
|
12467
12611
|
if (!haystack || !normSlug) return false;
|
|
@@ -12549,8 +12693,8 @@ var claimCommand = new Command("claim").description("Preflight + atomically clai
|
|
|
12549
12693
|
todos.push(
|
|
12550
12694
|
...asArray(await client2.mcpCall("todo_list", { status }))
|
|
12551
12695
|
);
|
|
12552
|
-
} catch (
|
|
12553
|
-
debugSwallow(`claim.preflight(${status})`,
|
|
12696
|
+
} catch (err2) {
|
|
12697
|
+
debugSwallow(`claim.preflight(${status})`, err2);
|
|
12554
12698
|
}
|
|
12555
12699
|
}
|
|
12556
12700
|
let activeClaims = [];
|
|
@@ -12559,8 +12703,8 @@ var claimCommand = new Command("claim").description("Preflight + atomically clai
|
|
|
12559
12703
|
activeClaims = Array.isArray(
|
|
12560
12704
|
intro?.activeClaims
|
|
12561
12705
|
) ? intro.activeClaims : [];
|
|
12562
|
-
} catch (
|
|
12563
|
-
debugSwallow("claim.preflight(introspect)",
|
|
12706
|
+
} catch (err2) {
|
|
12707
|
+
debugSwallow("claim.preflight(introspect)", err2);
|
|
12564
12708
|
activeClaims = [];
|
|
12565
12709
|
}
|
|
12566
12710
|
const conflicts = findPreflightConflicts({
|
|
@@ -12649,8 +12793,8 @@ function run(command, args, cwd) {
|
|
|
12649
12793
|
timeout: LOCAL_COMMAND_TIMEOUT_MS
|
|
12650
12794
|
});
|
|
12651
12795
|
return { status: 0, stdout, stderr: "", timedOut: false };
|
|
12652
|
-
} catch (
|
|
12653
|
-
const e =
|
|
12796
|
+
} catch (err2) {
|
|
12797
|
+
const e = err2;
|
|
12654
12798
|
return {
|
|
12655
12799
|
status: e.status ?? 1,
|
|
12656
12800
|
stdout: e.stdout ?? "",
|
|
@@ -12665,7 +12809,7 @@ function git(args, cwd) {
|
|
|
12665
12809
|
var WORKTREE_STATUS_CONCURRENCY = 8;
|
|
12666
12810
|
var WORKTREE_STATUS_TIMEOUT_MS = 2e3;
|
|
12667
12811
|
function gitAsync(args, cwd) {
|
|
12668
|
-
return new Promise((
|
|
12812
|
+
return new Promise((resolve5) => {
|
|
12669
12813
|
execFile2(
|
|
12670
12814
|
"git",
|
|
12671
12815
|
args,
|
|
@@ -12676,7 +12820,7 @@ function gitAsync(args, cwd) {
|
|
|
12676
12820
|
timeout: WORKTREE_STATUS_TIMEOUT_MS
|
|
12677
12821
|
},
|
|
12678
12822
|
(error62, stdout, stderr) => {
|
|
12679
|
-
|
|
12823
|
+
resolve5({
|
|
12680
12824
|
status: error62 ? 1 : 0,
|
|
12681
12825
|
stdout: stdout ?? "",
|
|
12682
12826
|
stderr: stderr ?? "",
|
|
@@ -13181,12 +13325,12 @@ import { execFileSync as execFileSync3 } from "node:child_process";
|
|
|
13181
13325
|
import { existsSync, readFileSync as readFileSync2, statSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
13182
13326
|
import { basename, dirname as dirname3, isAbsolute, join as join5, resolve } from "node:path";
|
|
13183
13327
|
var realExec = (cmd, args, opts) => {
|
|
13184
|
-
const
|
|
13328
|
+
const out2 = execFileSync3(cmd, args, {
|
|
13185
13329
|
cwd: opts?.cwd,
|
|
13186
13330
|
encoding: "utf8",
|
|
13187
13331
|
stdio: opts?.inherit ? ["ignore", "inherit", "inherit"] : ["ignore", "pipe", "pipe"]
|
|
13188
13332
|
});
|
|
13189
|
-
return typeof
|
|
13333
|
+
return typeof out2 === "string" ? out2 : "";
|
|
13190
13334
|
};
|
|
13191
13335
|
function assertCleanTree(statusPorcelain) {
|
|
13192
13336
|
if (statusPorcelain.trim().length === 0) return;
|
|
@@ -14478,19 +14622,19 @@ function collectConfiguredHooks(scope, file2, content) {
|
|
|
14478
14622
|
}
|
|
14479
14623
|
const hooks = asObject(asObject(parsed)?.hooks ?? null);
|
|
14480
14624
|
if (!hooks) return [];
|
|
14481
|
-
const
|
|
14625
|
+
const out2 = [];
|
|
14482
14626
|
for (const [event, groups] of Object.entries(hooks)) {
|
|
14483
14627
|
if (!Array.isArray(groups)) continue;
|
|
14484
14628
|
for (const group of groups) {
|
|
14485
14629
|
if (!group || !Array.isArray(group.hooks)) continue;
|
|
14486
14630
|
for (const hook of group.hooks) {
|
|
14487
14631
|
if (hook && typeof hook.command === "string" && hook.command.trim()) {
|
|
14488
|
-
|
|
14632
|
+
out2.push({ scope, file: file2, event, command: hook.command });
|
|
14489
14633
|
}
|
|
14490
14634
|
}
|
|
14491
14635
|
}
|
|
14492
14636
|
}
|
|
14493
|
-
return
|
|
14637
|
+
return out2;
|
|
14494
14638
|
}
|
|
14495
14639
|
function nodeScriptTarget(command) {
|
|
14496
14640
|
const m = command.match(/\bnode\s+(?:"([^"]+)"|'([^']+)'|(\S+))/);
|
|
@@ -14785,11 +14929,11 @@ async function ensureHookCredential(opts) {
|
|
|
14785
14929
|
status: verified ? "pass" : "fail",
|
|
14786
14930
|
message: verified ? "Rewritten token authenticates" : `Rewritten token still failing (HTTP ${status})`
|
|
14787
14931
|
});
|
|
14788
|
-
} catch (
|
|
14932
|
+
} catch (err2) {
|
|
14789
14933
|
checks.push({
|
|
14790
14934
|
name: "Hook credential: after repair",
|
|
14791
14935
|
status: "warn",
|
|
14792
|
-
message: `Rewrote the token but could not re-probe it (${
|
|
14936
|
+
message: `Rewrote the token but could not re-probe it (${err2 instanceof Error ? err2.message : String(err2)})`,
|
|
14793
14937
|
hint: "Re-run `gad doctor` once the network is reachable to confirm."
|
|
14794
14938
|
});
|
|
14795
14939
|
}
|
|
@@ -16335,9 +16479,9 @@ async function resolveBridgeAuth(options = {}) {
|
|
|
16335
16479
|
apiUrl: (apiUrlOverride || stored.apiUrl).replace(/\/$/, ""),
|
|
16336
16480
|
source: "stored"
|
|
16337
16481
|
};
|
|
16338
|
-
} catch (
|
|
16339
|
-
if (
|
|
16340
|
-
throw
|
|
16482
|
+
} catch (err2) {
|
|
16483
|
+
if (err2 instanceof CliError && err2.code === 1 /* AUTH_ERROR */ && /expired/i.test(err2.message)) {
|
|
16484
|
+
throw err2;
|
|
16341
16485
|
}
|
|
16342
16486
|
throw missingTokenError();
|
|
16343
16487
|
}
|
|
@@ -16429,9 +16573,9 @@ async function forwardLine(line, config2) {
|
|
|
16429
16573
|
return rpcError(id, -32603, "Upstream MCP endpoint returned non-JSON");
|
|
16430
16574
|
}
|
|
16431
16575
|
return text3.trim();
|
|
16432
|
-
} catch (
|
|
16576
|
+
} catch (err2) {
|
|
16433
16577
|
if (isNotification) return null;
|
|
16434
|
-
const message =
|
|
16578
|
+
const message = err2 instanceof Error ? err2.message : String(err2);
|
|
16435
16579
|
return rpcError(
|
|
16436
16580
|
id,
|
|
16437
16581
|
-32603,
|
|
@@ -16472,8 +16616,8 @@ async function runStdioBridge(options) {
|
|
|
16472
16616
|
if (response) writeLine(response);
|
|
16473
16617
|
});
|
|
16474
16618
|
});
|
|
16475
|
-
await new Promise((
|
|
16476
|
-
rl.on("close", () =>
|
|
16619
|
+
await new Promise((resolve5) => {
|
|
16620
|
+
rl.on("close", () => resolve5());
|
|
16477
16621
|
});
|
|
16478
16622
|
}
|
|
16479
16623
|
|
|
@@ -16506,7 +16650,7 @@ async function enableSuggestTools(home, deps = {}) {
|
|
|
16506
16650
|
return { verified: credential.verified };
|
|
16507
16651
|
}
|
|
16508
16652
|
async function applySuggestToolsChoice(choice2, home = homedir6(), deps = {}) {
|
|
16509
|
-
const
|
|
16653
|
+
const out2 = deps.out ?? createFormatter({
|
|
16510
16654
|
json: false,
|
|
16511
16655
|
quiet: false,
|
|
16512
16656
|
isTTY: isTTY(),
|
|
@@ -16516,7 +16660,7 @@ async function applySuggestToolsChoice(choice2, home = homedir6(), deps = {}) {
|
|
|
16516
16660
|
const outcome = await runSuggestHookOptIn({
|
|
16517
16661
|
choice: choice2,
|
|
16518
16662
|
interactive: deps.interactive ?? Boolean(process.stdin.isTTY && process.stdout.isTTY),
|
|
16519
|
-
print: (line) =>
|
|
16663
|
+
print: (line) => out2.info(line),
|
|
16520
16664
|
confirm: deps.confirm ?? confirm,
|
|
16521
16665
|
enable: async () => {
|
|
16522
16666
|
verified = (await enableSuggestTools(home, deps)).verified;
|
|
@@ -16525,10 +16669,10 @@ async function applySuggestToolsChoice(choice2, home = homedir6(), deps = {}) {
|
|
|
16525
16669
|
});
|
|
16526
16670
|
const { settingsPath } = suggestHookPaths(home);
|
|
16527
16671
|
if (outcome === "enabled") {
|
|
16528
|
-
|
|
16529
|
-
if (!verified)
|
|
16672
|
+
out2.success(`Tool suggestions ON (registered in ${settingsPath}).`);
|
|
16673
|
+
if (!verified) out2.warn(HOOK_CREDENTIAL_FIX_LINE);
|
|
16530
16674
|
} else if (outcome === "disabled") {
|
|
16531
|
-
|
|
16675
|
+
out2.success("Tool suggestions OFF (our hook entry removed).");
|
|
16532
16676
|
}
|
|
16533
16677
|
return outcome;
|
|
16534
16678
|
}
|
|
@@ -16596,12 +16740,12 @@ var CLIENT_IDS = {
|
|
|
16596
16740
|
};
|
|
16597
16741
|
async function mcpJsonAtRiskOfCommit(dir) {
|
|
16598
16742
|
try {
|
|
16599
|
-
const { execFile:
|
|
16743
|
+
const { execFile: execFile5 } = await import("node:child_process");
|
|
16600
16744
|
const { promisify: promisify2 } = await import("node:util");
|
|
16601
|
-
const
|
|
16602
|
-
await
|
|
16745
|
+
const run4 = promisify2(execFile5);
|
|
16746
|
+
await run4("git", ["rev-parse", "--is-inside-work-tree"], { cwd: dir });
|
|
16603
16747
|
try {
|
|
16604
|
-
await
|
|
16748
|
+
await run4("git", ["check-ignore", "-q", ".mcp.json"], { cwd: dir });
|
|
16605
16749
|
return false;
|
|
16606
16750
|
} catch {
|
|
16607
16751
|
return true;
|
|
@@ -16691,33 +16835,33 @@ async function pathExists(path10) {
|
|
|
16691
16835
|
}
|
|
16692
16836
|
}
|
|
16693
16837
|
async function installCodexConfig(apiUrl, token, repoUrl) {
|
|
16694
|
-
const { homedir:
|
|
16695
|
-
const { join:
|
|
16696
|
-
const { chmod:
|
|
16697
|
-
const codexDir =
|
|
16698
|
-
const configPath =
|
|
16699
|
-
const envPath =
|
|
16838
|
+
const { homedir: homedir11 } = await import("node:os");
|
|
16839
|
+
const { join: join13 } = await import("node:path");
|
|
16840
|
+
const { chmod: chmod3, copyFile: copyFile3, mkdir: mkdir9, readFile: readFile9, writeFile: writeFile7 } = await import("node:fs/promises");
|
|
16841
|
+
const codexDir = join13(homedir11(), ".codex");
|
|
16842
|
+
const configPath = join13(codexDir, "config.toml");
|
|
16843
|
+
const envPath = join13(codexDir, ".env");
|
|
16700
16844
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
16701
|
-
await
|
|
16702
|
-
const existingConfig = await pathExists(configPath) ? await
|
|
16845
|
+
await mkdir9(codexDir, { recursive: true });
|
|
16846
|
+
const existingConfig = await pathExists(configPath) ? await readFile9(configPath, "utf8") : "";
|
|
16703
16847
|
if (existingConfig.trim()) {
|
|
16704
16848
|
await copyFile3(configPath, `${configPath}.bak.${timestamp}`);
|
|
16705
16849
|
}
|
|
16706
|
-
await
|
|
16850
|
+
await writeFile7(
|
|
16707
16851
|
configPath,
|
|
16708
16852
|
upsertCodexServerBlock(existingConfig, apiUrl, repoUrl),
|
|
16709
16853
|
"utf8"
|
|
16710
16854
|
);
|
|
16711
|
-
const existingEnv = await pathExists(envPath) ? await
|
|
16855
|
+
const existingEnv = await pathExists(envPath) ? await readFile9(envPath, "utf8") : "";
|
|
16712
16856
|
if (existingEnv.trim()) {
|
|
16713
16857
|
await copyFile3(envPath, `${envPath}.bak.${timestamp}`);
|
|
16714
16858
|
}
|
|
16715
|
-
await
|
|
16859
|
+
await writeFile7(
|
|
16716
16860
|
envPath,
|
|
16717
16861
|
upsertEnvValue(existingEnv, "GREAT_ARROW_TOKEN", token),
|
|
16718
16862
|
"utf8"
|
|
16719
16863
|
);
|
|
16720
|
-
await
|
|
16864
|
+
await chmod3(envPath, 384);
|
|
16721
16865
|
return { configPath, envPath };
|
|
16722
16866
|
}
|
|
16723
16867
|
var startCommand = new Command("start").description(
|
|
@@ -16846,8 +16990,8 @@ async function checkDns(apiUrl, verbose, c) {
|
|
|
16846
16990
|
if (verbose) process.stdout.write(`${c.green("\u2713")}
|
|
16847
16991
|
`);
|
|
16848
16992
|
return { check: "DNS Resolution", status: "pass", detail: url2.hostname };
|
|
16849
|
-
} catch (
|
|
16850
|
-
const msg =
|
|
16993
|
+
} catch (err2) {
|
|
16994
|
+
const msg = err2 instanceof Error ? err2.message : "failed";
|
|
16851
16995
|
if (verbose) process.stdout.write(`${c.red("\u2717")} ${msg}
|
|
16852
16996
|
`);
|
|
16853
16997
|
return { check: "DNS Resolution", status: "fail", detail: msg };
|
|
@@ -16871,8 +17015,8 @@ async function checkEdgePing(apiUrl, verbose, c) {
|
|
|
16871
17015
|
if (verbose) process.stdout.write(`${c.yellow("\u26A0")} ${detail}
|
|
16872
17016
|
`);
|
|
16873
17017
|
return { check: "Edge Ping", status: "warn", detail };
|
|
16874
|
-
} catch (
|
|
16875
|
-
const msg =
|
|
17018
|
+
} catch (err2) {
|
|
17019
|
+
const msg = err2 instanceof Error ? err2.message : "failed";
|
|
16876
17020
|
if (verbose) process.stdout.write(`${c.red("\u2717")} ${msg}
|
|
16877
17021
|
`);
|
|
16878
17022
|
return { check: "Edge Ping", status: "fail", detail: msg };
|
|
@@ -16894,8 +17038,8 @@ async function checkJsonRpc(client2, verbose, c) {
|
|
|
16894
17038
|
if (verbose) process.stdout.write(`${c.green("\u2713")} ${detail}
|
|
16895
17039
|
`);
|
|
16896
17040
|
return { check: "JSON-RPC Handshake", status: "pass", detail };
|
|
16897
|
-
} catch (
|
|
16898
|
-
const msg =
|
|
17041
|
+
} catch (err2) {
|
|
17042
|
+
const msg = err2 instanceof Error ? err2.message : "failed";
|
|
16899
17043
|
if (verbose) process.stdout.write(`${c.red("\u2717")} ${msg}
|
|
16900
17044
|
`);
|
|
16901
17045
|
return { check: "JSON-RPC Handshake", status: "fail", detail: msg };
|
|
@@ -17005,15 +17149,15 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
17005
17149
|
process.stdout.write(configJson2 + "\n");
|
|
17006
17150
|
return;
|
|
17007
17151
|
}
|
|
17008
|
-
const { homedir:
|
|
17009
|
-
const { join:
|
|
17010
|
-
const { mkdir:
|
|
17011
|
-
const geminiDir =
|
|
17012
|
-
const mcpPath =
|
|
17013
|
-
await
|
|
17152
|
+
const { homedir: homedir11 } = await import("node:os");
|
|
17153
|
+
const { join: join14 } = await import("node:path");
|
|
17154
|
+
const { mkdir: mkdir9, readFile: readFile9, writeFile: writeFile8 } = await import("node:fs/promises");
|
|
17155
|
+
const geminiDir = join14(homedir11(), ".gemini");
|
|
17156
|
+
const mcpPath = join14(geminiDir, "settings.json");
|
|
17157
|
+
await mkdir9(geminiDir, { recursive: true });
|
|
17014
17158
|
let existingConfig = {};
|
|
17015
17159
|
try {
|
|
17016
|
-
const content = await
|
|
17160
|
+
const content = await readFile9(mcpPath, "utf-8");
|
|
17017
17161
|
existingConfig = JSON.parse(content);
|
|
17018
17162
|
} catch {
|
|
17019
17163
|
existingConfig = {};
|
|
@@ -17025,20 +17169,20 @@ var installCommand = new Command("install").description("Generate MCP configurat
|
|
|
17025
17169
|
...config3.mcpServers
|
|
17026
17170
|
}
|
|
17027
17171
|
};
|
|
17028
|
-
await
|
|
17172
|
+
await writeFile8(
|
|
17029
17173
|
mcpPath,
|
|
17030
17174
|
JSON.stringify(existingConfig, null, 2) + "\n",
|
|
17031
17175
|
"utf-8"
|
|
17032
17176
|
);
|
|
17033
17177
|
fmt.success(`Wrote gemini MCP config to ${mcpPath}`);
|
|
17034
|
-
const agyMcpDir =
|
|
17178
|
+
const agyMcpDir = join14(
|
|
17035
17179
|
geminiDir,
|
|
17036
17180
|
"antigravity-cli",
|
|
17037
17181
|
"mcp",
|
|
17038
17182
|
MCP_SERVER_NAME
|
|
17039
17183
|
);
|
|
17040
|
-
await
|
|
17041
|
-
const instructionsPath =
|
|
17184
|
+
await mkdir9(agyMcpDir, { recursive: true });
|
|
17185
|
+
const instructionsPath = join14(agyMcpDir, "instructions.md");
|
|
17042
17186
|
const instructionsContent = `You are connected to greatarrow.ai - the user's private workspace memory + integrations brain.
|
|
17043
17187
|
|
|
17044
17188
|
CRITICAL DIRECTIVE (MANDATORY STANDARD):
|
|
@@ -17054,7 +17198,7 @@ THREE-LAYER LIVE TASK TRACKING:
|
|
|
17054
17198
|
- Maintain client-native harness plans, Great Arrow Kanban cards (\`todo_create\`, \`todo_update\`), and resume states.
|
|
17055
17199
|
|
|
17056
17200
|
Always assume full autonomy to leverage these tools to their maximum extent.`;
|
|
17057
|
-
await
|
|
17201
|
+
await writeFile8(instructionsPath, instructionsContent, "utf-8");
|
|
17058
17202
|
fmt.success(`Wrote gemini MCP instructions to ${instructionsPath}`);
|
|
17059
17203
|
return;
|
|
17060
17204
|
}
|
|
@@ -17069,10 +17213,10 @@ Always assume full autonomy to leverage these tools to their maximum extent.`;
|
|
|
17069
17213
|
process.stdout.write(configJson + "\n");
|
|
17070
17214
|
return;
|
|
17071
17215
|
}
|
|
17072
|
-
const { writeFile:
|
|
17073
|
-
const { join:
|
|
17074
|
-
const outputPath =
|
|
17075
|
-
await
|
|
17216
|
+
const { writeFile: writeFile7 } = await import("node:fs/promises");
|
|
17217
|
+
const { join: join13 } = await import("node:path");
|
|
17218
|
+
const outputPath = join13(process.cwd(), ".mcp.json");
|
|
17219
|
+
await writeFile7(outputPath, configJson + "\n", { mode: 384 });
|
|
17076
17220
|
fmt.success(`Wrote ${clientName} MCP config to .mcp.json`);
|
|
17077
17221
|
if (await mcpJsonAtRiskOfCommit(process.cwd())) {
|
|
17078
17222
|
fmt.warn(
|
|
@@ -17088,9 +17232,9 @@ var KEYCHAIN_SERVICE = "GreatArrowDigital";
|
|
|
17088
17232
|
var KEYCHAIN_ACCOUNT = "api-token";
|
|
17089
17233
|
var OAUTH_CRED_FILENAME = "oauth-credential.json";
|
|
17090
17234
|
async function readIfExists(path10) {
|
|
17091
|
-
const { readFile:
|
|
17235
|
+
const { readFile: readFile9 } = await import("node:fs/promises");
|
|
17092
17236
|
try {
|
|
17093
|
-
return await
|
|
17237
|
+
return await readFile9(path10, "utf8");
|
|
17094
17238
|
} catch {
|
|
17095
17239
|
return null;
|
|
17096
17240
|
}
|
|
@@ -17105,13 +17249,13 @@ async function readKeychainOnly() {
|
|
|
17105
17249
|
}
|
|
17106
17250
|
}
|
|
17107
17251
|
async function resolveProxyScript(override) {
|
|
17108
|
-
const { homedir:
|
|
17109
|
-
const { join:
|
|
17252
|
+
const { homedir: homedir11 } = await import("node:os");
|
|
17253
|
+
const { join: join13 } = await import("node:path");
|
|
17110
17254
|
const candidates = [
|
|
17111
17255
|
override,
|
|
17112
17256
|
process.env.GAD_PROXY_SCRIPT,
|
|
17113
|
-
|
|
17114
|
-
|
|
17257
|
+
join13(homedir11(), ".great-arrow", "mcp-server.mjs"),
|
|
17258
|
+
join13(process.cwd(), "scripts", "mcp-server.mjs")
|
|
17115
17259
|
].filter((c) => Boolean(c));
|
|
17116
17260
|
for (const candidate of candidates) {
|
|
17117
17261
|
if (await pathExists(candidate)) return candidate;
|
|
@@ -17119,11 +17263,11 @@ async function resolveProxyScript(override) {
|
|
|
17119
17263
|
return null;
|
|
17120
17264
|
}
|
|
17121
17265
|
async function runProxyDiagnostics(scriptPath) {
|
|
17122
|
-
const { execFile:
|
|
17266
|
+
const { execFile: execFile5 } = await import("node:child_process");
|
|
17123
17267
|
const { promisify: promisify2 } = await import("node:util");
|
|
17124
|
-
const
|
|
17268
|
+
const run4 = promisify2(execFile5);
|
|
17125
17269
|
try {
|
|
17126
|
-
const { stdout } = await
|
|
17270
|
+
const { stdout } = await run4(
|
|
17127
17271
|
process.execPath,
|
|
17128
17272
|
[scriptPath, "--print-diagnostics"],
|
|
17129
17273
|
{ timeout: 1e4, maxBuffer: 1024 * 1024 }
|
|
@@ -17135,22 +17279,22 @@ async function runProxyDiagnostics(scriptPath) {
|
|
|
17135
17279
|
}
|
|
17136
17280
|
}
|
|
17137
17281
|
async function findLegacyStores(cwd) {
|
|
17138
|
-
const { join:
|
|
17282
|
+
const { join: join13 } = await import("node:path");
|
|
17139
17283
|
const { readdir } = await import("node:fs/promises");
|
|
17140
17284
|
const dirs = /* @__PURE__ */ new Set([cwd]);
|
|
17141
17285
|
try {
|
|
17142
|
-
const worktreeRoot =
|
|
17286
|
+
const worktreeRoot = join13(cwd, ".claude", "worktrees");
|
|
17143
17287
|
for (const entry of await readdir(worktreeRoot, { withFileTypes: true })) {
|
|
17144
|
-
if (entry.isDirectory()) dirs.add(
|
|
17288
|
+
if (entry.isDirectory()) dirs.add(join13(worktreeRoot, entry.name));
|
|
17145
17289
|
}
|
|
17146
|
-
} catch (
|
|
17147
|
-
debugSwallow("mcp.findLegacyStores(worktrees)",
|
|
17290
|
+
} catch (err2) {
|
|
17291
|
+
debugSwallow("mcp.findLegacyStores(worktrees)", err2);
|
|
17148
17292
|
}
|
|
17149
17293
|
try {
|
|
17150
|
-
const { execFile:
|
|
17294
|
+
const { execFile: execFile5 } = await import("node:child_process");
|
|
17151
17295
|
const { promisify: promisify2 } = await import("node:util");
|
|
17152
|
-
const
|
|
17153
|
-
const { stdout } = await
|
|
17296
|
+
const run4 = promisify2(execFile5);
|
|
17297
|
+
const { stdout } = await run4("git", ["worktree", "list", "--porcelain"], {
|
|
17154
17298
|
cwd,
|
|
17155
17299
|
timeout: 5e3
|
|
17156
17300
|
});
|
|
@@ -17158,23 +17302,23 @@ async function findLegacyStores(cwd) {
|
|
|
17158
17302
|
if (line.startsWith("worktree "))
|
|
17159
17303
|
dirs.add(line.slice("worktree ".length));
|
|
17160
17304
|
}
|
|
17161
|
-
} catch (
|
|
17162
|
-
debugSwallow("mcp.findLegacyStores(git)",
|
|
17305
|
+
} catch (err2) {
|
|
17306
|
+
debugSwallow("mcp.findLegacyStores(git)", err2);
|
|
17163
17307
|
}
|
|
17164
17308
|
const stores = [];
|
|
17165
17309
|
for (const dir of dirs) {
|
|
17166
|
-
const path10 =
|
|
17310
|
+
const path10 = join13(dir, ".mcp", OAUTH_CRED_FILENAME);
|
|
17167
17311
|
const raw = await readIfExists(path10);
|
|
17168
17312
|
if (raw !== null) stores.push({ path: path10, raw });
|
|
17169
17313
|
}
|
|
17170
17314
|
return stores;
|
|
17171
17315
|
}
|
|
17172
17316
|
async function scanConnections() {
|
|
17173
|
-
const { homedir:
|
|
17174
|
-
const { join:
|
|
17175
|
-
const home =
|
|
17317
|
+
const { homedir: homedir11 } = await import("node:os");
|
|
17318
|
+
const { join: join13 } = await import("node:path");
|
|
17319
|
+
const home = homedir11();
|
|
17176
17320
|
const hookSettings = await readIfExists(
|
|
17177
|
-
|
|
17321
|
+
join13(home, ".claude", "settings.json")
|
|
17178
17322
|
);
|
|
17179
17323
|
const hooksInstalled = hookSettings ? hasGreatArrowHooks(hookSettings) : false;
|
|
17180
17324
|
const entries = [];
|
|
@@ -17207,29 +17351,29 @@ async function probeEndpoint() {
|
|
|
17207
17351
|
}
|
|
17208
17352
|
}
|
|
17209
17353
|
async function applyMigration(plan) {
|
|
17210
|
-
const { homedir:
|
|
17211
|
-
const { join:
|
|
17212
|
-
const { mkdir:
|
|
17354
|
+
const { homedir: homedir11 } = await import("node:os");
|
|
17355
|
+
const { join: join13 } = await import("node:path");
|
|
17356
|
+
const { mkdir: mkdir9, rename: rename3, writeFile: writeFile7 } = await import("node:fs/promises");
|
|
17213
17357
|
const applied = [];
|
|
17214
|
-
const dir =
|
|
17215
|
-
await
|
|
17358
|
+
const dir = join13(homedir11(), ".great-arrow");
|
|
17359
|
+
await mkdir9(dir, { recursive: true, mode: 448 });
|
|
17216
17360
|
if (plan.seedFrom) {
|
|
17217
17361
|
const raw = await readIfExists(plan.seedFrom);
|
|
17218
17362
|
if (raw !== null) {
|
|
17219
|
-
const target =
|
|
17363
|
+
const target = join13(dir, OAUTH_CRED_FILENAME);
|
|
17220
17364
|
const tmp = `${target}.tmp`;
|
|
17221
|
-
await
|
|
17222
|
-
await
|
|
17365
|
+
await writeFile7(tmp, raw, { mode: 384 });
|
|
17366
|
+
await rename3(tmp, target);
|
|
17223
17367
|
applied.push(`Copied ${plan.seedFrom} \u2192 ${target}`);
|
|
17224
17368
|
}
|
|
17225
17369
|
}
|
|
17226
17370
|
if (plan.syncKeychainToFile) {
|
|
17227
17371
|
const raw = await readKeychainOnly();
|
|
17228
17372
|
if (raw) {
|
|
17229
|
-
const target =
|
|
17373
|
+
const target = join13(dir, "credential");
|
|
17230
17374
|
const tmp = `${target}.tmp`;
|
|
17231
|
-
await
|
|
17232
|
-
await
|
|
17375
|
+
await writeFile7(tmp, raw, { mode: 384 });
|
|
17376
|
+
await rename3(tmp, target);
|
|
17233
17377
|
applied.push(`Wrote the keychain credential to ${target}`);
|
|
17234
17378
|
}
|
|
17235
17379
|
}
|
|
@@ -17252,19 +17396,19 @@ var doctorSubcommand = new Command("doctor").description(
|
|
|
17252
17396
|
noColor: false
|
|
17253
17397
|
});
|
|
17254
17398
|
const c = createColor(jsonFlag);
|
|
17255
|
-
const { homedir:
|
|
17256
|
-
const { join:
|
|
17257
|
-
const home =
|
|
17399
|
+
const { homedir: homedir11 } = await import("node:os");
|
|
17400
|
+
const { join: join13 } = await import("node:path");
|
|
17401
|
+
const home = homedir11();
|
|
17258
17402
|
const proxyPath = await resolveProxyScript(options.proxy);
|
|
17259
17403
|
const diagnostics = proxyPath ? await runProxyDiagnostics(proxyPath) : null;
|
|
17260
17404
|
const entries = await scanConnections();
|
|
17261
17405
|
const duplicates = detectDuplicates(entries);
|
|
17262
17406
|
const keychain = await readKeychainOnly();
|
|
17263
17407
|
const credentialFile = await readIfExists(
|
|
17264
|
-
|
|
17408
|
+
join13(home, ".great-arrow", "credential")
|
|
17265
17409
|
);
|
|
17266
17410
|
const userStore = await readIfExists(
|
|
17267
|
-
|
|
17411
|
+
join13(home, ".great-arrow", OAUTH_CRED_FILENAME)
|
|
17268
17412
|
);
|
|
17269
17413
|
const legacyStores = await findLegacyStores(process.cwd());
|
|
17270
17414
|
const findings = [
|
|
@@ -17404,9 +17548,9 @@ async function runSmokeTest(client2, test) {
|
|
|
17404
17548
|
await client2.mcpCall(test.tool, test.args);
|
|
17405
17549
|
const durationMs = Math.round(performance.now() - start);
|
|
17406
17550
|
return { name: test.name, tool: test.tool, status: "pass", durationMs };
|
|
17407
|
-
} catch (
|
|
17551
|
+
} catch (err2) {
|
|
17408
17552
|
const durationMs = Math.round(performance.now() - start);
|
|
17409
|
-
const error62 =
|
|
17553
|
+
const error62 = err2 instanceof Error ? err2.message : "Unknown error";
|
|
17410
17554
|
return {
|
|
17411
17555
|
name: test.name,
|
|
17412
17556
|
tool: test.tool,
|
|
@@ -17679,6 +17823,137 @@ var agentsCommand = new Command("agents").description(
|
|
|
17679
17823
|
process.stdout.write(renderAgentsNow(result) + "\n");
|
|
17680
17824
|
});
|
|
17681
17825
|
|
|
17826
|
+
// src/commands/inbox.ts
|
|
17827
|
+
var BACKOFF_BASE_MS = 15e3;
|
|
17828
|
+
var BACKOFF_MAX_MS = 12e4;
|
|
17829
|
+
var DEFAULT_MAX_MINUTES = 50;
|
|
17830
|
+
var PRESENCE_NOT_ENABLED = "Agent presence is not enabled.";
|
|
17831
|
+
function waitBackoffMs(emptyHolds) {
|
|
17832
|
+
if (emptyHolds < 3) return 0;
|
|
17833
|
+
return Math.min(2 ** (emptyHolds - 3) * BACKOFF_BASE_MS, BACKOFF_MAX_MS);
|
|
17834
|
+
}
|
|
17835
|
+
function asMessage(body) {
|
|
17836
|
+
if (!body || typeof body !== "object") return null;
|
|
17837
|
+
const b = body;
|
|
17838
|
+
return b.status === "message" && typeof b.messageId === "string" && typeof b.block === "string" ? { messageId: b.messageId, block: b.block } : null;
|
|
17839
|
+
}
|
|
17840
|
+
async function runInboxWait(o) {
|
|
17841
|
+
const sleep2 = o.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
17842
|
+
const now = o.now ?? Date.now;
|
|
17843
|
+
const write = o.write ?? ((t) => void process.stdout.write(t));
|
|
17844
|
+
const writeErr = o.writeErr ?? ((t) => void process.stderr.write(t));
|
|
17845
|
+
const stopAt = now() + (o.maxMinutes ?? DEFAULT_MAX_MINUTES) * 6e4;
|
|
17846
|
+
let emptyHolds = 0;
|
|
17847
|
+
while (now() < stopAt) {
|
|
17848
|
+
const params = { as: o.as };
|
|
17849
|
+
if (o.after) params.after = o.after;
|
|
17850
|
+
if (o.waitingOn !== void 0) params.waiting_on = o.waitingOn;
|
|
17851
|
+
let res = null;
|
|
17852
|
+
try {
|
|
17853
|
+
res = await o.request(params);
|
|
17854
|
+
} catch {
|
|
17855
|
+
res = null;
|
|
17856
|
+
}
|
|
17857
|
+
if (res?.status === 404) {
|
|
17858
|
+
writeErr(`${PRESENCE_NOT_ENABLED}
|
|
17859
|
+
`);
|
|
17860
|
+
return 2;
|
|
17861
|
+
}
|
|
17862
|
+
const msg = res && res.status === 200 ? asMessage(res.body) : null;
|
|
17863
|
+
if (msg) {
|
|
17864
|
+
const block = msg.block.endsWith("\n") ? msg.block : `${msg.block}
|
|
17865
|
+
`;
|
|
17866
|
+
write(`${block}after=${msg.messageId}
|
|
17867
|
+
`);
|
|
17868
|
+
return 0;
|
|
17869
|
+
}
|
|
17870
|
+
const gap = Math.min(waitBackoffMs(emptyHolds++), stopAt - now());
|
|
17871
|
+
if (gap > 0) await sleep2(gap);
|
|
17872
|
+
}
|
|
17873
|
+
return 3;
|
|
17874
|
+
}
|
|
17875
|
+
function parseMaxMinutes(raw) {
|
|
17876
|
+
const n = Number(raw);
|
|
17877
|
+
return Number.isFinite(n) && n > 0 ? n : DEFAULT_MAX_MINUTES;
|
|
17878
|
+
}
|
|
17879
|
+
var waitCommand = new Command("wait").description(
|
|
17880
|
+
"Wait for a peer's message to this connection; run as a background task"
|
|
17881
|
+
).requiredOption("--as <id>", "Your connection id (from agent_inbox)").option("--after <id>", "Only wake for messages newer than this id").option("--waiting-on <text>", "What you are waiting on, shown to peers").option("--max-minutes <n>", "Give up after this many minutes", "50").action(
|
|
17882
|
+
async (opts) => {
|
|
17883
|
+
const auth = await resolveAuth();
|
|
17884
|
+
const client2 = new GadClient({
|
|
17885
|
+
token: auth.token,
|
|
17886
|
+
getToken: auth.getToken,
|
|
17887
|
+
apiUrl: auth.apiUrl
|
|
17888
|
+
});
|
|
17889
|
+
process.exitCode = await runInboxWait({
|
|
17890
|
+
request: (params) => client2.requestOnce("GET", "/api/agent-comms/wait", { params }),
|
|
17891
|
+
as: opts.as,
|
|
17892
|
+
after: opts.after,
|
|
17893
|
+
waitingOn: opts.waitingOn,
|
|
17894
|
+
maxMinutes: parseMaxMinutes(opts.maxMinutes)
|
|
17895
|
+
});
|
|
17896
|
+
}
|
|
17897
|
+
);
|
|
17898
|
+
var inboxCommand = new Command("inbox").description("Agent inbox \u2014 wait for a peer's message").addCommand(waitCommand);
|
|
17899
|
+
|
|
17900
|
+
// src/commands/presence.ts
|
|
17901
|
+
function doNotDisturbBody(raw, as) {
|
|
17902
|
+
if (raw.trim().toLowerCase() === "off") {
|
|
17903
|
+
return { action: "do_not_disturb", as, minutes: null };
|
|
17904
|
+
}
|
|
17905
|
+
const minutes = Number(raw);
|
|
17906
|
+
if (!Number.isFinite(minutes) || minutes <= 0) {
|
|
17907
|
+
throw new CliError(
|
|
17908
|
+
`Expected a number of minutes or "off", got "${raw}".`,
|
|
17909
|
+
3 /* VALIDATION_ERROR */
|
|
17910
|
+
);
|
|
17911
|
+
}
|
|
17912
|
+
return { action: "do_not_disturb", as, minutes };
|
|
17913
|
+
}
|
|
17914
|
+
async function sendPresence(o) {
|
|
17915
|
+
const write = o.write ?? ((t) => void process.stdout.write(t));
|
|
17916
|
+
const writeErr = o.writeErr ?? ((t) => void process.stderr.write(t));
|
|
17917
|
+
const res = await o.request(o.body);
|
|
17918
|
+
if (res.status === 404) {
|
|
17919
|
+
writeErr(`${PRESENCE_NOT_ENABLED}
|
|
17920
|
+
`);
|
|
17921
|
+
return 2;
|
|
17922
|
+
}
|
|
17923
|
+
if (res.status < 200 || res.status >= 300) {
|
|
17924
|
+
writeErr(`Presence update failed (HTTP ${res.status}).
|
|
17925
|
+
`);
|
|
17926
|
+
return res.status === 401 || res.status === 403 ? 1 /* AUTH_ERROR */ : res.status === 400 ? 3 /* VALIDATION_ERROR */ : 2 /* NETWORK_ERROR */;
|
|
17927
|
+
}
|
|
17928
|
+
const b = o.body;
|
|
17929
|
+
write(
|
|
17930
|
+
b.action === "sign_off" ? "Signed off.\n" : b.minutes === null ? "Do not disturb is off.\n" : `Do not disturb for ${b.minutes} minutes.
|
|
17931
|
+
`
|
|
17932
|
+
);
|
|
17933
|
+
return 0;
|
|
17934
|
+
}
|
|
17935
|
+
async function run2(body) {
|
|
17936
|
+
const auth = await resolveAuth();
|
|
17937
|
+
const client2 = new GadClient({
|
|
17938
|
+
token: auth.token,
|
|
17939
|
+
getToken: auth.getToken,
|
|
17940
|
+
apiUrl: auth.apiUrl
|
|
17941
|
+
});
|
|
17942
|
+
process.exitCode = await sendPresence({
|
|
17943
|
+
request: (b) => client2.requestOnce("POST", "/api/agent-comms/presence", { body: b }),
|
|
17944
|
+
body
|
|
17945
|
+
});
|
|
17946
|
+
}
|
|
17947
|
+
var presenceCommand = new Command("presence").description("Tell peers you are away: do not disturb, or sign off").addCommand(
|
|
17948
|
+
new Command("do-not-disturb").description("Tell peers not to disturb you for a while, or turn it off").argument("<minutes|off>", "Minutes (up to 480), or off").requiredOption("--as <id>", "Your connection id (from agent_inbox)").action(async (raw, opts) => {
|
|
17949
|
+
await run2(doNotDisturbBody(raw, opts.as));
|
|
17950
|
+
})
|
|
17951
|
+
).addCommand(
|
|
17952
|
+
new Command("sign-off").description("Mark this connection as signed off").requiredOption("--as <id>", "Your connection id (from agent_inbox)").action(async (opts) => {
|
|
17953
|
+
await run2({ action: "sign_off", as: opts.as });
|
|
17954
|
+
})
|
|
17955
|
+
);
|
|
17956
|
+
|
|
17682
17957
|
// src/commands/ask.ts
|
|
17683
17958
|
var ORCHESTRATOR_TIMEOUT_MS = 9e4;
|
|
17684
17959
|
var ANSWER_FIELDS = [
|
|
@@ -17931,8 +18206,8 @@ async function maybeShowGlanceFooter(argv) {
|
|
|
17931
18206
|
token: auth.token,
|
|
17932
18207
|
keys: printed
|
|
17933
18208
|
});
|
|
17934
|
-
} catch (
|
|
17935
|
-
debugSwallow("glance-footer",
|
|
18209
|
+
} catch (err2) {
|
|
18210
|
+
debugSwallow("glance-footer", err2);
|
|
17936
18211
|
}
|
|
17937
18212
|
}
|
|
17938
18213
|
function shouldRunGlanceFooter(argv) {
|
|
@@ -18161,6 +18436,17 @@ function normalizeGlance(raw) {
|
|
|
18161
18436
|
dismissKey: r.dismissKey
|
|
18162
18437
|
} : null;
|
|
18163
18438
|
})(),
|
|
18439
|
+
// Same rule: both counts must be counts, or the line is dropped.
|
|
18440
|
+
keyRotation: (() => {
|
|
18441
|
+
const raw2 = obj.keyRotation;
|
|
18442
|
+
if (typeof raw2 !== "object" || raw2 === null) return null;
|
|
18443
|
+
const r = raw2;
|
|
18444
|
+
const count2 = (v) => typeof v === "number" && Number.isInteger(v) && v >= 0;
|
|
18445
|
+
return count2(r.needsYou) && count2(r.pendingDevices) ? {
|
|
18446
|
+
needsYou: r.needsYou,
|
|
18447
|
+
pendingDevices: r.pendingDevices
|
|
18448
|
+
} : null;
|
|
18449
|
+
})(),
|
|
18164
18450
|
...(() => {
|
|
18165
18451
|
const raw2 = obj.landing;
|
|
18166
18452
|
if (typeof raw2 !== "object" || raw2 === null) return {};
|
|
@@ -18195,9 +18481,9 @@ function asNullableString(value) {
|
|
|
18195
18481
|
function normalizeTodaySections(raw) {
|
|
18196
18482
|
return raw.flatMap((section) => {
|
|
18197
18483
|
if (typeof section !== "object" || section === null) return [];
|
|
18198
|
-
const
|
|
18199
|
-
if (typeof
|
|
18200
|
-
const rows = asArray2(
|
|
18484
|
+
const s2 = section;
|
|
18485
|
+
if (typeof s2.key !== "string" || typeof s2.title !== "string") return [];
|
|
18486
|
+
const rows = asArray2(s2.rows).flatMap((row) => {
|
|
18201
18487
|
if (typeof row !== "object" || row === null) return [];
|
|
18202
18488
|
const r = row;
|
|
18203
18489
|
if (typeof r.id !== "string" || typeof r.title !== "string") return [];
|
|
@@ -18212,7 +18498,7 @@ function normalizeTodaySections(raw) {
|
|
|
18212
18498
|
}
|
|
18213
18499
|
];
|
|
18214
18500
|
});
|
|
18215
|
-
return rows.length > 0 ? [{ key:
|
|
18501
|
+
return rows.length > 0 ? [{ key: s2.key, title: s2.title, rows }] : [];
|
|
18216
18502
|
});
|
|
18217
18503
|
}
|
|
18218
18504
|
function asArray2(value) {
|
|
@@ -18688,8 +18974,8 @@ function createLocalDeviceLocator(scope, directory = join10(homedir9(), ".great-
|
|
|
18688
18974
|
let file2;
|
|
18689
18975
|
try {
|
|
18690
18976
|
file2 = await open2(path10, constants.O_RDONLY | constants.O_NOFOLLOW);
|
|
18691
|
-
} catch (
|
|
18692
|
-
if (
|
|
18977
|
+
} catch (err2) {
|
|
18978
|
+
if (err2.code === "ENOENT") return null;
|
|
18693
18979
|
throw new Error("Device locator could not be read");
|
|
18694
18980
|
}
|
|
18695
18981
|
try {
|
|
@@ -20786,10 +21072,10 @@ function defineLazyInternal(inst, key, compute) {
|
|
|
20786
21072
|
Object.defineProperty(this, key, { configurable: true, writable: true, value });
|
|
20787
21073
|
broke = broke || outer;
|
|
20788
21074
|
return value;
|
|
20789
|
-
} catch (
|
|
21075
|
+
} catch (err2) {
|
|
20790
21076
|
delete this[key];
|
|
20791
21077
|
broke = broke || outer;
|
|
20792
|
-
throw
|
|
21078
|
+
throw err2;
|
|
20793
21079
|
}
|
|
20794
21080
|
},
|
|
20795
21081
|
set(value) {
|
|
@@ -22212,9 +22498,9 @@ var asciiTabOrNewline = /[\t\n\r]/g;
|
|
|
22212
22498
|
function stripTabAndNewline(value) {
|
|
22213
22499
|
return value.replace(asciiTabOrNewline, "");
|
|
22214
22500
|
}
|
|
22215
|
-
function urlHostnameOk(url2,
|
|
22216
|
-
|
|
22217
|
-
return
|
|
22501
|
+
function urlHostnameOk(url2, hostname6) {
|
|
22502
|
+
hostname6.lastIndex = 0;
|
|
22503
|
+
return hostname6.test(url2.hostname);
|
|
22218
22504
|
}
|
|
22219
22505
|
function urlProtocolOk(url2, protocol) {
|
|
22220
22506
|
protocol.lastIndex = 0;
|
|
@@ -23406,7 +23692,7 @@ function handleIntersectionResults(result, left, right) {
|
|
|
23406
23692
|
const unrecKeys = /* @__PURE__ */ new Map();
|
|
23407
23693
|
let unrecIssue;
|
|
23408
23694
|
const keyIssues = /* @__PURE__ */ new Map();
|
|
23409
|
-
const
|
|
23695
|
+
const collect3 = (iss, side) => {
|
|
23410
23696
|
let keys;
|
|
23411
23697
|
if (iss.code === "unrecognized_keys" && !iss.path?.length) {
|
|
23412
23698
|
unrecIssue ?? (unrecIssue = iss);
|
|
@@ -23427,11 +23713,11 @@ function handleIntersectionResults(result, left, right) {
|
|
|
23427
23713
|
return true;
|
|
23428
23714
|
};
|
|
23429
23715
|
for (const iss of left.issues) {
|
|
23430
|
-
if (!
|
|
23716
|
+
if (!collect3(iss, "l"))
|
|
23431
23717
|
result.issues.push(iss);
|
|
23432
23718
|
}
|
|
23433
23719
|
for (const iss of right.issues) {
|
|
23434
|
-
if (!
|
|
23720
|
+
if (!collect3(iss, "r"))
|
|
23435
23721
|
result.issues.push(iss);
|
|
23436
23722
|
}
|
|
23437
23723
|
const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k]) => k);
|
|
@@ -24255,7 +24541,7 @@ function partPattern(schema) {
|
|
|
24255
24541
|
if (def.options) {
|
|
24256
24542
|
const sources = def.options.map(partPattern);
|
|
24257
24543
|
if (sources.every(Boolean))
|
|
24258
|
-
return `^(${sources.map((
|
|
24544
|
+
return `^(${sources.map((s2) => cleanRegex(s2)).join("|")})$`;
|
|
24259
24545
|
}
|
|
24260
24546
|
return leafPattern(schema);
|
|
24261
24547
|
}
|
|
@@ -24453,7 +24739,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
24453
24739
|
var NONE = 0;
|
|
24454
24740
|
var ASSUMED = 1;
|
|
24455
24741
|
var PROVEN = 2;
|
|
24456
|
-
function isRecursive(inst, stack,
|
|
24742
|
+
function isRecursive(inst, stack, resolve5) {
|
|
24457
24743
|
const cached2 = recursive.get(inst);
|
|
24458
24744
|
if (cached2 !== void 0)
|
|
24459
24745
|
return cached2 ? PROVEN : NONE;
|
|
@@ -24463,7 +24749,7 @@ function isRecursive(inst, stack, resolve4) {
|
|
|
24463
24749
|
let result = NONE;
|
|
24464
24750
|
const check2 = (child) => {
|
|
24465
24751
|
if (result !== PROVEN && child?._zod) {
|
|
24466
|
-
const answer = isRecursive(child, stack,
|
|
24752
|
+
const answer = isRecursive(child, stack, resolve5);
|
|
24467
24753
|
if (answer > result)
|
|
24468
24754
|
result = answer;
|
|
24469
24755
|
}
|
|
@@ -24474,7 +24760,7 @@ function isRecursive(inst, stack, resolve4) {
|
|
|
24474
24760
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
24475
24761
|
if (spread && !desc.enumerable)
|
|
24476
24762
|
continue;
|
|
24477
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
24763
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve5) : NONE;
|
|
24478
24764
|
if (child > answer)
|
|
24479
24765
|
answer = child;
|
|
24480
24766
|
}
|
|
@@ -24538,7 +24824,7 @@ function isRecursive(inst, stack, resolve4) {
|
|
|
24538
24824
|
break;
|
|
24539
24825
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
24540
24826
|
case "lazy": {
|
|
24541
|
-
const inner = def._cachedInner ?? (
|
|
24827
|
+
const inner = def._cachedInner ?? (resolve5 ? inst._zod.innerType : void 0);
|
|
24542
24828
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
24543
24829
|
break;
|
|
24544
24830
|
}
|
|
@@ -32357,9 +32643,9 @@ function compile(schema, options) {
|
|
|
32357
32643
|
const clone2 = withParser(schema, parser);
|
|
32358
32644
|
clone2._zod.bag.validator = compileValidator(schema, parser);
|
|
32359
32645
|
return clone2;
|
|
32360
|
-
} catch (
|
|
32646
|
+
} catch (err2) {
|
|
32361
32647
|
if (options?.strict)
|
|
32362
|
-
throw
|
|
32648
|
+
throw err2;
|
|
32363
32649
|
return schema;
|
|
32364
32650
|
}
|
|
32365
32651
|
}
|
|
@@ -32377,9 +32663,9 @@ function withParser(schema, parser) {
|
|
|
32377
32663
|
if (ctx && isBackEdge(ctx, payload.value)) {
|
|
32378
32664
|
return originalRun(payload, ctx);
|
|
32379
32665
|
}
|
|
32380
|
-
const
|
|
32381
|
-
if (
|
|
32382
|
-
payload.value =
|
|
32666
|
+
const out2 = parser(payload.value);
|
|
32667
|
+
if (out2 !== INVALID) {
|
|
32668
|
+
payload.value = out2;
|
|
32383
32669
|
return payload;
|
|
32384
32670
|
}
|
|
32385
32671
|
if (ctx)
|
|
@@ -32400,9 +32686,9 @@ function installCompiledUserMethods(target, source, parser) {
|
|
|
32400
32686
|
if (typeof sourceAny.safeParse === "function") {
|
|
32401
32687
|
const originalSafeParse = sourceAny.safeParse;
|
|
32402
32688
|
targetAny.safeParse = (data, params) => {
|
|
32403
|
-
const
|
|
32404
|
-
if (
|
|
32405
|
-
return { success: true, data:
|
|
32689
|
+
const out2 = parser(data);
|
|
32690
|
+
if (out2 !== INVALID) {
|
|
32691
|
+
return { success: true, data: out2 };
|
|
32406
32692
|
}
|
|
32407
32693
|
return originalSafeParse(data, params);
|
|
32408
32694
|
};
|
|
@@ -32410,9 +32696,9 @@ function installCompiledUserMethods(target, source, parser) {
|
|
|
32410
32696
|
if (typeof sourceAny.parse === "function") {
|
|
32411
32697
|
const originalParse = sourceAny.parse;
|
|
32412
32698
|
targetAny.parse = (data, params) => {
|
|
32413
|
-
const
|
|
32414
|
-
if (
|
|
32415
|
-
return
|
|
32699
|
+
const out2 = parser(data);
|
|
32700
|
+
if (out2 !== INVALID) {
|
|
32701
|
+
return out2;
|
|
32416
32702
|
}
|
|
32417
32703
|
return originalParse(data, params);
|
|
32418
32704
|
};
|
|
@@ -32449,8 +32735,8 @@ ${code}
|
|
|
32449
32735
|
try {
|
|
32450
32736
|
const factory = new F(...constantNames, factoryCode);
|
|
32451
32737
|
fn = factory(...constantValues);
|
|
32452
|
-
} catch (
|
|
32453
|
-
throw new ZodCompileUnsupportedError(`this schema (generated code failed to evaluate: ${
|
|
32738
|
+
} catch (err2) {
|
|
32739
|
+
throw new ZodCompileUnsupportedError(`this schema (generated code failed to evaluate: ${err2.message})`);
|
|
32454
32740
|
}
|
|
32455
32741
|
if (options?.debug) {
|
|
32456
32742
|
fn.code = fullCode;
|
|
@@ -32488,9 +32774,9 @@ function compileChild(doc, ctx, schema, accessor, needsValue = true) {
|
|
|
32488
32774
|
const varCounter = ctx.varCounter;
|
|
32489
32775
|
try {
|
|
32490
32776
|
return generateCheck(doc, ctx, schema, accessor, needsValue);
|
|
32491
|
-
} catch (
|
|
32492
|
-
if (!(
|
|
32493
|
-
throw
|
|
32777
|
+
} catch (err2) {
|
|
32778
|
+
if (!(err2 instanceof ZodCompileUnsupportedError) || !err2.islandable)
|
|
32779
|
+
throw err2;
|
|
32494
32780
|
doc.content.length = contentLen;
|
|
32495
32781
|
if (ctx.constants.size > constantCount) {
|
|
32496
32782
|
const trailing = Array.from(ctx.constants.keys()).slice(constantCount);
|
|
@@ -33173,13 +33459,13 @@ function generateObjectCheck(doc, ctx, schema, accessor, buildsValue = true) {
|
|
|
33173
33459
|
doc.write(`const ${outputVar} = {};`);
|
|
33174
33460
|
for (const k of allKeys) {
|
|
33175
33461
|
const kx = keyExpr(k);
|
|
33176
|
-
const
|
|
33462
|
+
const out2 = propOutputs.get(k);
|
|
33177
33463
|
if (dropsWhenAbsent(propShape[k])) {
|
|
33178
|
-
doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${
|
|
33464
|
+
doc.write(`if (${kx} in ${accessor}) ${outputVar}[${kx}] = ${out2};`);
|
|
33179
33465
|
} else if (mayOmitUndefined(propShape[k])) {
|
|
33180
|
-
doc.write(`if (${
|
|
33466
|
+
doc.write(`if (${out2} !== undefined || ${kx} in ${accessor}) ${outputVar}[${kx}] = ${out2};`);
|
|
33181
33467
|
} else {
|
|
33182
|
-
doc.write(`${outputVar}[${kx}] = ${
|
|
33468
|
+
doc.write(`${outputVar}[${kx}] = ${out2};`);
|
|
33183
33469
|
}
|
|
33184
33470
|
}
|
|
33185
33471
|
}
|
|
@@ -34811,11 +35097,11 @@ function _catch(Class2, innerType, catchValue) {
|
|
|
34811
35097
|
});
|
|
34812
35098
|
}
|
|
34813
35099
|
// @__NO_SIDE_EFFECTS__
|
|
34814
|
-
function _pipe(Class2, in_,
|
|
35100
|
+
function _pipe(Class2, in_, out2) {
|
|
34815
35101
|
return new Class2({
|
|
34816
35102
|
type: "pipe",
|
|
34817
35103
|
in: in_,
|
|
34818
|
-
out
|
|
35104
|
+
out: out2
|
|
34819
35105
|
});
|
|
34820
35106
|
}
|
|
34821
35107
|
// @__NO_SIDE_EFFECTS__
|
|
@@ -37930,11 +38216,11 @@ var ZodPipe = /* @__PURE__ */ $constructor("ZodPipe", (inst, def) => {
|
|
|
37930
38216
|
inst.in = def.in;
|
|
37931
38217
|
inst.out = def.out;
|
|
37932
38218
|
});
|
|
37933
|
-
function pipe(in_,
|
|
38219
|
+
function pipe(in_, out2) {
|
|
37934
38220
|
return new ZodPipe({
|
|
37935
38221
|
type: "pipe",
|
|
37936
38222
|
in: in_,
|
|
37937
|
-
out
|
|
38223
|
+
out: out2
|
|
37938
38224
|
// ...util.normalizeParams(params),
|
|
37939
38225
|
});
|
|
37940
38226
|
}
|
|
@@ -37942,11 +38228,11 @@ var ZodCodec = /* @__PURE__ */ $constructor("ZodCodec", (inst, def) => {
|
|
|
37942
38228
|
ZodPipe.init(inst, def);
|
|
37943
38229
|
$ZodCodec.init(inst, def);
|
|
37944
38230
|
});
|
|
37945
|
-
function codec(in_,
|
|
38231
|
+
function codec(in_, out2, params) {
|
|
37946
38232
|
return new ZodCodec({
|
|
37947
38233
|
type: "pipe",
|
|
37948
38234
|
in: in_,
|
|
37949
|
-
out,
|
|
38235
|
+
out: out2,
|
|
37950
38236
|
transform: params.decode,
|
|
37951
38237
|
reverseTransform: params.encode
|
|
37952
38238
|
});
|
|
@@ -38784,12 +39070,12 @@ function convertSchema(schema, ctx) {
|
|
|
38784
39070
|
let baseSchema = convertBaseSchema(schema, ctx);
|
|
38785
39071
|
const hasExplicitType = schema.type || schema.enum !== void 0 || schema.const !== void 0;
|
|
38786
39072
|
if (schema.anyOf && Array.isArray(schema.anyOf)) {
|
|
38787
|
-
const options = schema.anyOf.map((
|
|
39073
|
+
const options = schema.anyOf.map((s2) => convertSchema(s2, ctx));
|
|
38788
39074
|
const anyOfUnion = z.union(options);
|
|
38789
39075
|
baseSchema = hasExplicitType ? z.intersection(baseSchema, anyOfUnion) : anyOfUnion;
|
|
38790
39076
|
}
|
|
38791
39077
|
if (schema.oneOf && Array.isArray(schema.oneOf)) {
|
|
38792
|
-
const options = schema.oneOf.map((
|
|
39078
|
+
const options = schema.oneOf.map((s2) => convertSchema(s2, ctx));
|
|
38793
39079
|
const oneOfUnion = z.xor(options);
|
|
38794
39080
|
baseSchema = hasExplicitType ? z.intersection(baseSchema, oneOfUnion) : oneOfUnion;
|
|
38795
39081
|
}
|
|
@@ -38889,24 +39175,24 @@ function visit(schema, fnOrHandlers) {
|
|
|
38889
39175
|
return h ? h(node2, rewritten) : node2;
|
|
38890
39176
|
};
|
|
38891
39177
|
const cache = /* @__PURE__ */ new Map();
|
|
38892
|
-
function
|
|
38893
|
-
const cached2 = cache.get(
|
|
39178
|
+
function run4(s2) {
|
|
39179
|
+
const cached2 = cache.get(s2);
|
|
38894
39180
|
if (cached2 === RESOLVING) {
|
|
38895
39181
|
return new $ZodLazy({
|
|
38896
39182
|
type: "lazy",
|
|
38897
|
-
getter: () => cache.get(
|
|
39183
|
+
getter: () => cache.get(s2)
|
|
38898
39184
|
});
|
|
38899
39185
|
}
|
|
38900
39186
|
if (cached2 !== void 0)
|
|
38901
39187
|
return cached2;
|
|
38902
|
-
cache.set(
|
|
38903
|
-
const inner = mapInner(
|
|
38904
|
-
const mapped = fn(inner, inner !==
|
|
38905
|
-
cache.set(
|
|
39188
|
+
cache.set(s2, RESOLVING);
|
|
39189
|
+
const inner = mapInner(s2);
|
|
39190
|
+
const mapped = fn(inner, inner !== s2);
|
|
39191
|
+
cache.set(s2, mapped);
|
|
38906
39192
|
return mapped;
|
|
38907
39193
|
}
|
|
38908
|
-
function mapInner(
|
|
38909
|
-
const def =
|
|
39194
|
+
function mapInner(s2) {
|
|
39195
|
+
const def = s2._zod.def;
|
|
38910
39196
|
const kind = def.type;
|
|
38911
39197
|
switch (kind) {
|
|
38912
39198
|
case "object": {
|
|
@@ -38915,67 +39201,67 @@ function visit(schema, fnOrHandlers) {
|
|
|
38915
39201
|
let changed = false;
|
|
38916
39202
|
const newShape = {};
|
|
38917
39203
|
for (const k of keys) {
|
|
38918
|
-
const mapped =
|
|
39204
|
+
const mapped = run4(oldShape[k]);
|
|
38919
39205
|
if (mapped !== oldShape[k])
|
|
38920
39206
|
changed = true;
|
|
38921
39207
|
newShape[k] = mapped;
|
|
38922
39208
|
}
|
|
38923
39209
|
let newCatchall = def.catchall;
|
|
38924
39210
|
if (def.catchall) {
|
|
38925
|
-
newCatchall =
|
|
39211
|
+
newCatchall = run4(def.catchall);
|
|
38926
39212
|
if (newCatchall !== def.catchall)
|
|
38927
39213
|
changed = true;
|
|
38928
39214
|
}
|
|
38929
|
-
return changed ? clone(
|
|
39215
|
+
return changed ? clone(s2, { ...def, shape: newShape, catchall: newCatchall }) : s2;
|
|
38930
39216
|
}
|
|
38931
39217
|
case "array": {
|
|
38932
|
-
const mapped =
|
|
38933
|
-
return mapped === def.element ?
|
|
39218
|
+
const mapped = run4(def.element);
|
|
39219
|
+
return mapped === def.element ? s2 : clone(s2, { ...def, element: mapped });
|
|
38934
39220
|
}
|
|
38935
39221
|
case "tuple": {
|
|
38936
39222
|
const oldItems = def.items;
|
|
38937
39223
|
let changed = false;
|
|
38938
39224
|
const newItems = [];
|
|
38939
39225
|
for (const item of oldItems) {
|
|
38940
|
-
const mapped =
|
|
39226
|
+
const mapped = run4(item);
|
|
38941
39227
|
if (mapped !== item)
|
|
38942
39228
|
changed = true;
|
|
38943
39229
|
newItems.push(mapped);
|
|
38944
39230
|
}
|
|
38945
39231
|
let newRest = def.rest;
|
|
38946
39232
|
if (def.rest) {
|
|
38947
|
-
newRest =
|
|
39233
|
+
newRest = run4(def.rest);
|
|
38948
39234
|
if (newRest !== def.rest)
|
|
38949
39235
|
changed = true;
|
|
38950
39236
|
}
|
|
38951
|
-
return changed ? clone(
|
|
39237
|
+
return changed ? clone(s2, { ...def, items: newItems, rest: newRest }) : s2;
|
|
38952
39238
|
}
|
|
38953
39239
|
case "record":
|
|
38954
39240
|
case "map": {
|
|
38955
|
-
const newKey =
|
|
38956
|
-
const newVal =
|
|
38957
|
-
return newKey === def.keyType && newVal === def.valueType ?
|
|
39241
|
+
const newKey = run4(def.keyType);
|
|
39242
|
+
const newVal = run4(def.valueType);
|
|
39243
|
+
return newKey === def.keyType && newVal === def.valueType ? s2 : clone(s2, { ...def, keyType: newKey, valueType: newVal });
|
|
38958
39244
|
}
|
|
38959
39245
|
case "set": {
|
|
38960
|
-
const newVal =
|
|
38961
|
-
return newVal === def.valueType ?
|
|
39246
|
+
const newVal = run4(def.valueType);
|
|
39247
|
+
return newVal === def.valueType ? s2 : clone(s2, { ...def, valueType: newVal });
|
|
38962
39248
|
}
|
|
38963
39249
|
case "union": {
|
|
38964
39250
|
const oldOptions = def.options;
|
|
38965
39251
|
let changed = false;
|
|
38966
39252
|
const newOptions = [];
|
|
38967
39253
|
for (const opt of oldOptions) {
|
|
38968
|
-
const mapped =
|
|
39254
|
+
const mapped = run4(opt);
|
|
38969
39255
|
if (mapped !== opt)
|
|
38970
39256
|
changed = true;
|
|
38971
39257
|
newOptions.push(mapped);
|
|
38972
39258
|
}
|
|
38973
|
-
return changed ? clone(
|
|
39259
|
+
return changed ? clone(s2, { ...def, options: newOptions }) : s2;
|
|
38974
39260
|
}
|
|
38975
39261
|
case "intersection": {
|
|
38976
|
-
const newLeft =
|
|
38977
|
-
const newRight =
|
|
38978
|
-
return newLeft === def.left && newRight === def.right ?
|
|
39262
|
+
const newLeft = run4(def.left);
|
|
39263
|
+
const newRight = run4(def.right);
|
|
39264
|
+
return newLeft === def.left && newRight === def.right ? s2 : clone(s2, { ...def, left: newLeft, right: newRight });
|
|
38979
39265
|
}
|
|
38980
39266
|
case "optional":
|
|
38981
39267
|
case "nullable":
|
|
@@ -38986,23 +39272,23 @@ function visit(schema, fnOrHandlers) {
|
|
|
38986
39272
|
case "nonoptional":
|
|
38987
39273
|
case "promise":
|
|
38988
39274
|
case "success": {
|
|
38989
|
-
const newInner =
|
|
38990
|
-
return newInner === def.innerType ?
|
|
39275
|
+
const newInner = run4(def.innerType);
|
|
39276
|
+
return newInner === def.innerType ? s2 : clone(s2, { ...def, innerType: newInner });
|
|
38991
39277
|
}
|
|
38992
39278
|
case "pipe": {
|
|
38993
|
-
const newIn =
|
|
38994
|
-
const newOut =
|
|
38995
|
-
return newIn === def.in && newOut === def.out ?
|
|
39279
|
+
const newIn = run4(def.in);
|
|
39280
|
+
const newOut = run4(def.out);
|
|
39281
|
+
return newIn === def.in && newOut === def.out ? s2 : clone(s2, { ...def, in: newIn, out: newOut });
|
|
38996
39282
|
}
|
|
38997
39283
|
case "function": {
|
|
38998
|
-
const newInput =
|
|
38999
|
-
const newOutput =
|
|
39000
|
-
return newInput === def.input && newOutput === def.output ?
|
|
39284
|
+
const newInput = run4(def.input);
|
|
39285
|
+
const newOutput = run4(def.output);
|
|
39286
|
+
return newInput === def.input && newOutput === def.output ? s2 : clone(s2, { ...def, input: newInput, output: newOutput });
|
|
39001
39287
|
}
|
|
39002
39288
|
case "lazy": {
|
|
39003
39289
|
const original = def.getter;
|
|
39004
39290
|
const { _cachedInner, ...rest } = def;
|
|
39005
|
-
return clone(
|
|
39291
|
+
return clone(s2, { ...rest, getter: () => run4(original()) });
|
|
39006
39292
|
}
|
|
39007
39293
|
// A leaf by choice: `parts` are regex fragments, not data positions.
|
|
39008
39294
|
case "template_literal":
|
|
@@ -39026,24 +39312,24 @@ function visit(schema, fnOrHandlers) {
|
|
|
39026
39312
|
case "file":
|
|
39027
39313
|
case "transform":
|
|
39028
39314
|
case "custom":
|
|
39029
|
-
return
|
|
39315
|
+
return s2;
|
|
39030
39316
|
default: {
|
|
39031
39317
|
kind;
|
|
39032
|
-
return
|
|
39318
|
+
return s2;
|
|
39033
39319
|
}
|
|
39034
39320
|
}
|
|
39035
39321
|
}
|
|
39036
|
-
return
|
|
39322
|
+
return run4(schema);
|
|
39037
39323
|
}
|
|
39038
39324
|
|
|
39039
39325
|
// ../../node_modules/zod/v4/classic/deep-partial.js
|
|
39040
39326
|
function deepPartial(schema) {
|
|
39041
39327
|
return visit(schema, {
|
|
39042
|
-
object: (
|
|
39328
|
+
object: (s2) => s2.partial(),
|
|
39043
39329
|
// Every partialed option now admits `undefined`, which the constructor rejects as a duplicate.
|
|
39044
|
-
union: (
|
|
39045
|
-
const def =
|
|
39046
|
-
return def.discriminator === void 0 ?
|
|
39330
|
+
union: (s2) => {
|
|
39331
|
+
const def = s2._zod.def;
|
|
39332
|
+
return def.discriminator === void 0 ? s2 : union(def.options);
|
|
39047
39333
|
}
|
|
39048
39334
|
});
|
|
39049
39335
|
}
|
|
@@ -39063,18 +39349,18 @@ function inSide(def) {
|
|
|
39063
39349
|
}
|
|
39064
39350
|
function input(schema) {
|
|
39065
39351
|
return visit(schema, {
|
|
39066
|
-
pipe: (
|
|
39352
|
+
pipe: (s2) => inSide(s2._zod.def),
|
|
39067
39353
|
// A default value belongs to the output side, so a rewritten inner type leaves it stranded. `.default()` widens the declared input type with `undefined`, and `optional` is what carries that across.
|
|
39068
|
-
default: (
|
|
39354
|
+
default: (s2, rewritten) => rewritten ? optional(s2._zod.def.innerType) : s2,
|
|
39069
39355
|
// A catch value is output-side too, but `.catch()` leaves the declared input type alone, so the inner schema stands on its own.
|
|
39070
|
-
catch: (
|
|
39356
|
+
catch: (s2, rewritten) => rewritten ? s2._zod.def.innerType : s2
|
|
39071
39357
|
});
|
|
39072
39358
|
}
|
|
39073
39359
|
function output(schema) {
|
|
39074
39360
|
return visit(schema, {
|
|
39075
|
-
pipe: (
|
|
39361
|
+
pipe: (s2) => outSide(s2._zod.def),
|
|
39076
39362
|
// A prefault value is fed through the schema, which makes it input-side, so a rewritten inner type leaves it stranded.
|
|
39077
|
-
prefault: (
|
|
39363
|
+
prefault: (s2, rewritten) => rewritten ? s2._zod.def.innerType : s2
|
|
39078
39364
|
});
|
|
39079
39365
|
}
|
|
39080
39366
|
|
|
@@ -39534,12 +39820,12 @@ var ParseStatus = class _ParseStatus {
|
|
|
39534
39820
|
}
|
|
39535
39821
|
static mergeArray(status, results) {
|
|
39536
39822
|
const arrayValue = [];
|
|
39537
|
-
for (const
|
|
39538
|
-
if (
|
|
39823
|
+
for (const s2 of results) {
|
|
39824
|
+
if (s2.status === "aborted")
|
|
39539
39825
|
return INVALID2;
|
|
39540
|
-
if (
|
|
39826
|
+
if (s2.status === "dirty")
|
|
39541
39827
|
status.dirty();
|
|
39542
|
-
arrayValue.push(
|
|
39828
|
+
arrayValue.push(s2.value);
|
|
39543
39829
|
}
|
|
39544
39830
|
return { status: status.value, value: arrayValue };
|
|
39545
39831
|
}
|
|
@@ -39736,8 +40022,8 @@ var ZodType2 = class {
|
|
|
39736
40022
|
} : {
|
|
39737
40023
|
issues: ctx.common.issues
|
|
39738
40024
|
};
|
|
39739
|
-
} catch (
|
|
39740
|
-
if (
|
|
40025
|
+
} catch (err2) {
|
|
40026
|
+
if (err2?.message?.toLowerCase()?.includes("encountered")) {
|
|
39741
40027
|
this["~standard"].async = true;
|
|
39742
40028
|
}
|
|
39743
40029
|
ctx.common = {
|
|
@@ -43260,34 +43546,34 @@ function validateDownloadUrl(url2) {
|
|
|
43260
43546
|
message: `URL scheme must be http, https, or data, got ${parsed.protocol}`
|
|
43261
43547
|
});
|
|
43262
43548
|
}
|
|
43263
|
-
const
|
|
43264
|
-
if (!
|
|
43549
|
+
const hostname6 = parsed.hostname.toLowerCase().replace(/\.+$/, "");
|
|
43550
|
+
if (!hostname6) {
|
|
43265
43551
|
throw new DownloadError({
|
|
43266
43552
|
url: url2,
|
|
43267
43553
|
message: `URL must have a hostname`
|
|
43268
43554
|
});
|
|
43269
43555
|
}
|
|
43270
|
-
if (
|
|
43556
|
+
if (hostname6 === "localhost" || hostname6.endsWith(".local") || hostname6.endsWith(".localhost") || hostname6.endsWith(".internal")) {
|
|
43271
43557
|
throw new DownloadError({
|
|
43272
43558
|
url: url2,
|
|
43273
|
-
message: `URL with hostname ${
|
|
43559
|
+
message: `URL with hostname ${hostname6} is not allowed`
|
|
43274
43560
|
});
|
|
43275
43561
|
}
|
|
43276
|
-
if (
|
|
43277
|
-
const ipv63 =
|
|
43562
|
+
if (hostname6.startsWith("[") && hostname6.endsWith("]")) {
|
|
43563
|
+
const ipv63 = hostname6.slice(1, -1);
|
|
43278
43564
|
if (isPrivateIPv6(ipv63)) {
|
|
43279
43565
|
throw new DownloadError({
|
|
43280
43566
|
url: url2,
|
|
43281
|
-
message: `URL with IPv6 address ${
|
|
43567
|
+
message: `URL with IPv6 address ${hostname6} is not allowed`
|
|
43282
43568
|
});
|
|
43283
43569
|
}
|
|
43284
43570
|
return;
|
|
43285
43571
|
}
|
|
43286
|
-
if (isIPv4(
|
|
43287
|
-
if (isPrivateIPv4(
|
|
43572
|
+
if (isIPv4(hostname6)) {
|
|
43573
|
+
if (isPrivateIPv4(hostname6)) {
|
|
43288
43574
|
throw new DownloadError({
|
|
43289
43575
|
url: url2,
|
|
43290
|
-
message: `URL with IP address ${
|
|
43576
|
+
message: `URL with IP address ${hostname6} is not allowed`
|
|
43291
43577
|
});
|
|
43292
43578
|
}
|
|
43293
43579
|
}
|
|
@@ -43295,18 +43581,18 @@ function validateDownloadUrl(url2) {
|
|
|
43295
43581
|
function validateDownloadAddress({
|
|
43296
43582
|
address,
|
|
43297
43583
|
family,
|
|
43298
|
-
hostname:
|
|
43584
|
+
hostname: hostname6
|
|
43299
43585
|
}) {
|
|
43300
43586
|
const isUnsafe = family === 4 ? !isIPv4(address) || isPrivateIPv4(address) : family === 6 ? isPrivateIPv6(address) : true;
|
|
43301
43587
|
if (isUnsafe) {
|
|
43302
43588
|
throw new DownloadError({
|
|
43303
|
-
url:
|
|
43304
|
-
message: `Hostname ${
|
|
43589
|
+
url: hostname6,
|
|
43590
|
+
message: `Hostname ${hostname6} resolved to disallowed IP address ${address}`
|
|
43305
43591
|
});
|
|
43306
43592
|
}
|
|
43307
43593
|
}
|
|
43308
|
-
function isIPv4(
|
|
43309
|
-
const parts =
|
|
43594
|
+
function isIPv4(hostname6) {
|
|
43595
|
+
const parts = hostname6.split(".");
|
|
43310
43596
|
if (parts.length !== 4) return false;
|
|
43311
43597
|
return parts.every((part) => {
|
|
43312
43598
|
const num = Number(part);
|
|
@@ -43391,8 +43677,8 @@ function isPrivateIPv6(ip) {
|
|
|
43391
43677
|
return false;
|
|
43392
43678
|
}
|
|
43393
43679
|
function createSafeLookup(lookup) {
|
|
43394
|
-
return ((
|
|
43395
|
-
lookup(
|
|
43680
|
+
return ((hostname6, options, callback) => {
|
|
43681
|
+
lookup(hostname6, { ...options, all: true }, (error62, addresses) => {
|
|
43396
43682
|
if (error62) {
|
|
43397
43683
|
callback(error62);
|
|
43398
43684
|
return;
|
|
@@ -43400,10 +43686,10 @@ function createSafeLookup(lookup) {
|
|
|
43400
43686
|
try {
|
|
43401
43687
|
const [firstAddress] = addresses;
|
|
43402
43688
|
if (firstAddress == null) {
|
|
43403
|
-
throw new Error(`Hostname ${
|
|
43689
|
+
throw new Error(`Hostname ${hostname6} did not resolve to an address`);
|
|
43404
43690
|
}
|
|
43405
43691
|
for (const { address, family } of addresses) {
|
|
43406
|
-
validateDownloadAddress({ address, family, hostname:
|
|
43692
|
+
validateDownloadAddress({ address, family, hostname: hostname6 });
|
|
43407
43693
|
}
|
|
43408
43694
|
if (options.all === true) {
|
|
43409
43695
|
callback(null, addresses);
|
|
@@ -47105,9 +47391,9 @@ function createAsyncIterableStream(source) {
|
|
|
47105
47391
|
* @param err The error to throw.
|
|
47106
47392
|
* @returns A promise that rejects with the provided error.
|
|
47107
47393
|
*/
|
|
47108
|
-
async throw(
|
|
47394
|
+
async throw(err2) {
|
|
47109
47395
|
await cleanup(true);
|
|
47110
|
-
throw
|
|
47396
|
+
throw err2;
|
|
47111
47397
|
}
|
|
47112
47398
|
};
|
|
47113
47399
|
};
|
|
@@ -47711,9 +47997,9 @@ function platformFetch(apiUrl, transport, engineFetch) {
|
|
|
47711
47997
|
if (input2 instanceof Request)
|
|
47712
47998
|
throw new Error("Local turn transport requires an explicit request path");
|
|
47713
47999
|
const raw = String(input2);
|
|
47714
|
-
const
|
|
48000
|
+
const relative2 = raw.startsWith("/");
|
|
47715
48001
|
const target = new URL(raw, platform2);
|
|
47716
|
-
if (!
|
|
48002
|
+
if (!relative2 && target.origin !== platform2.origin)
|
|
47717
48003
|
return engineFetch(input2, init);
|
|
47718
48004
|
if (target.origin !== platform2.origin || !target.pathname.startsWith("/api/") || target.username || target.password || target.hash)
|
|
47719
48005
|
throw new Error("Local turn requests must use a platform API path");
|
|
@@ -47890,18 +48176,18 @@ function argumentsAsText(value) {
|
|
|
47890
48176
|
function readOllamaToolCalls(message) {
|
|
47891
48177
|
const raw = message?.tool_calls;
|
|
47892
48178
|
if (!Array.isArray(raw)) return [];
|
|
47893
|
-
const
|
|
48179
|
+
const out2 = [];
|
|
47894
48180
|
raw.forEach((entry, position) => {
|
|
47895
48181
|
if (!entry || typeof entry !== "object") return;
|
|
47896
48182
|
const fn = entry.function;
|
|
47897
48183
|
if (typeof fn?.name !== "string") return;
|
|
47898
|
-
|
|
48184
|
+
out2.push({
|
|
47899
48185
|
position,
|
|
47900
48186
|
name: fn.name,
|
|
47901
48187
|
argumentsFragment: argumentsAsText(fn.arguments)
|
|
47902
48188
|
});
|
|
47903
48189
|
});
|
|
47904
|
-
return
|
|
48190
|
+
return out2;
|
|
47905
48191
|
}
|
|
47906
48192
|
function readOllamaLine(line) {
|
|
47907
48193
|
let parsed;
|
|
@@ -47926,19 +48212,19 @@ function readOllamaLine(line) {
|
|
|
47926
48212
|
function readOpenAiToolCalls(deltaObj) {
|
|
47927
48213
|
const raw = deltaObj?.tool_calls;
|
|
47928
48214
|
if (!Array.isArray(raw)) return [];
|
|
47929
|
-
const
|
|
48215
|
+
const out2 = [];
|
|
47930
48216
|
raw.forEach((entry, fallbackPosition) => {
|
|
47931
48217
|
if (!entry || typeof entry !== "object") return;
|
|
47932
48218
|
const row = entry;
|
|
47933
48219
|
const fn = row.function;
|
|
47934
|
-
|
|
48220
|
+
out2.push({
|
|
47935
48221
|
position: typeof row.index === "number" ? row.index : fallbackPosition,
|
|
47936
48222
|
id: typeof row.id === "string" ? row.id : void 0,
|
|
47937
48223
|
name: typeof fn?.name === "string" ? fn.name : void 0,
|
|
47938
48224
|
argumentsFragment: typeof fn?.arguments === "string" ? fn.arguments : void 0
|
|
47939
48225
|
});
|
|
47940
48226
|
});
|
|
47941
|
-
return
|
|
48227
|
+
return out2;
|
|
47942
48228
|
}
|
|
47943
48229
|
function readOpenAiLine(line) {
|
|
47944
48230
|
if (!line.startsWith("data:")) return null;
|
|
@@ -48184,11 +48470,11 @@ function origin(apiUrl) {
|
|
|
48184
48470
|
function appAwareFetch(apiUrl, token, base, getToken2) {
|
|
48185
48471
|
return async (input2, init) => {
|
|
48186
48472
|
const target = typeof input2 === "string" ? input2 : String(input2);
|
|
48187
|
-
const
|
|
48188
|
-
if (!
|
|
48473
|
+
const relative2 = target.startsWith("/") && !target.startsWith("//");
|
|
48474
|
+
if (!relative2 && !target.startsWith(`${origin(apiUrl)}/`))
|
|
48189
48475
|
return base(input2, init);
|
|
48190
48476
|
const currentToken = getToken2 ? await renewToken(getToken2) : token;
|
|
48191
|
-
return base(
|
|
48477
|
+
return base(relative2 ? `${origin(apiUrl)}${target}` : target, {
|
|
48192
48478
|
...init,
|
|
48193
48479
|
headers: {
|
|
48194
48480
|
...init?.headers,
|
|
@@ -48316,10 +48602,10 @@ async function askForTheTurn(opts) {
|
|
|
48316
48602
|
};
|
|
48317
48603
|
response = received.response;
|
|
48318
48604
|
responseText = received.text;
|
|
48319
|
-
} catch (
|
|
48605
|
+
} catch (err2) {
|
|
48320
48606
|
throw new LocalTurnFailed(
|
|
48321
48607
|
"handoff",
|
|
48322
|
-
opts.signal?.aborted ? "Stopped this request." :
|
|
48608
|
+
opts.signal?.aborted ? "Stopped this request." : err2 instanceof Error && err2.name === "AbortError" ? "Great Arrow did not answer in time." : cloudSessionId ? "Great Arrow\u2019s reply was interrupted." : "Could not reach Great Arrow.",
|
|
48323
48609
|
false,
|
|
48324
48610
|
cloudSessionId
|
|
48325
48611
|
);
|
|
@@ -48509,17 +48795,17 @@ function firstString(...candidates) {
|
|
|
48509
48795
|
}
|
|
48510
48796
|
function collect(entries, read) {
|
|
48511
48797
|
if (!Array.isArray(entries)) return [];
|
|
48512
|
-
const
|
|
48798
|
+
const out2 = [];
|
|
48513
48799
|
const seen = /* @__PURE__ */ new Set();
|
|
48514
48800
|
for (const entry of entries) {
|
|
48515
|
-
if (
|
|
48801
|
+
if (out2.length >= MAX_LOCAL_MODELS) break;
|
|
48516
48802
|
if (!entry || typeof entry !== "object") continue;
|
|
48517
48803
|
const { id, label, contextLength } = read(entry);
|
|
48518
48804
|
if (!isValidLocalModelId(id)) continue;
|
|
48519
48805
|
if (seen.has(id)) continue;
|
|
48520
48806
|
if (isEmbeddingOnlyModelId(id)) continue;
|
|
48521
48807
|
seen.add(id);
|
|
48522
|
-
|
|
48808
|
+
out2.push({
|
|
48523
48809
|
id,
|
|
48524
48810
|
label: typeof label === "string" && label.length > 0 ? label : id,
|
|
48525
48811
|
// Never assumed. A model is only marked tool-capable once the provider
|
|
@@ -48529,7 +48815,7 @@ function collect(entries, read) {
|
|
|
48529
48815
|
contextLength: positiveInt(contextLength)
|
|
48530
48816
|
});
|
|
48531
48817
|
}
|
|
48532
|
-
return
|
|
48818
|
+
return out2;
|
|
48533
48819
|
}
|
|
48534
48820
|
function normalizeOllamaTags(json3) {
|
|
48535
48821
|
if (!json3 || typeof json3 !== "object") return [];
|
|
@@ -48634,10 +48920,10 @@ async function findInstalledModels(opts) {
|
|
|
48634
48920
|
let response;
|
|
48635
48921
|
try {
|
|
48636
48922
|
response = await ask(doFetch, url2, { method: "GET" }, timeoutMs);
|
|
48637
|
-
} catch (
|
|
48923
|
+
} catch (err2) {
|
|
48638
48924
|
throw new LocalAppUnreachable(
|
|
48639
48925
|
opts.baseUrl,
|
|
48640
|
-
|
|
48926
|
+
err2 instanceof Error && err2.name === "AbortError" ? "It did not answer in time." : "Nothing answered there."
|
|
48641
48927
|
);
|
|
48642
48928
|
}
|
|
48643
48929
|
if (!response.ok) {
|
|
@@ -48730,15 +49016,15 @@ function checkCommand() {
|
|
|
48730
49016
|
let models;
|
|
48731
49017
|
try {
|
|
48732
49018
|
models = await findInstalledModels({ baseUrl, provider });
|
|
48733
|
-
} catch (
|
|
48734
|
-
if (
|
|
49019
|
+
} catch (err2) {
|
|
49020
|
+
if (err2 instanceof LocalAppUnreachable) {
|
|
48735
49021
|
throw new CliError(
|
|
48736
|
-
`Could not reach ${LOCAL_PROVIDER_PRESETS[provider].label} at ${
|
|
49022
|
+
`Could not reach ${LOCAL_PROVIDER_PRESETS[provider].label} at ${err2.baseUrl}. ${err2.message}`,
|
|
48737
49023
|
2 /* NETWORK_ERROR */,
|
|
48738
49024
|
`Start it on this computer and try again, or point somewhere else with --url.`
|
|
48739
49025
|
);
|
|
48740
49026
|
}
|
|
48741
|
-
throw
|
|
49027
|
+
throw err2;
|
|
48742
49028
|
}
|
|
48743
49029
|
const saved = await client2.mcpCall(
|
|
48744
49030
|
"model_local_set",
|
|
@@ -48927,15 +49213,15 @@ function askHereCommand() {
|
|
|
48927
49213
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
48928
49214
|
...g.json ? {} : { onWords: (delta) => process.stdout.write(delta) }
|
|
48929
49215
|
});
|
|
48930
|
-
} catch (
|
|
48931
|
-
if (
|
|
49216
|
+
} catch (err2) {
|
|
49217
|
+
if (err2 instanceof LocalTurnFailed) {
|
|
48932
49218
|
throw new CliError(
|
|
48933
|
-
|
|
49219
|
+
err2.message,
|
|
48934
49220
|
2 /* NETWORK_ERROR */,
|
|
48935
|
-
|
|
49221
|
+
err2.closed ? void 0 : "Your conversation may show this one as unfinished."
|
|
48936
49222
|
);
|
|
48937
49223
|
}
|
|
48938
|
-
throw
|
|
49224
|
+
throw err2;
|
|
48939
49225
|
} finally {
|
|
48940
49226
|
process.off("SIGINT", stop2);
|
|
48941
49227
|
}
|
|
@@ -49220,8 +49506,8 @@ function statusCommand3() {
|
|
|
49220
49506
|
let result;
|
|
49221
49507
|
try {
|
|
49222
49508
|
result = await client2.mcpCall("glance", {});
|
|
49223
|
-
} catch (
|
|
49224
|
-
if (
|
|
49509
|
+
} catch (err2) {
|
|
49510
|
+
if (err2 instanceof CliError) throw err2;
|
|
49225
49511
|
fmt.error(
|
|
49226
49512
|
"Couldn't reach Great Arrow. Check your connection, or run 'gad doctor'."
|
|
49227
49513
|
);
|
|
@@ -49255,7 +49541,7 @@ function renderStatus2(payload, plain, apiUrl) {
|
|
|
49255
49541
|
lines.push(c.badge(` ${payload.workspace} `));
|
|
49256
49542
|
lines.push("");
|
|
49257
49543
|
}
|
|
49258
|
-
const hasAny = payload.needsYou.length > 0 || payload.topGoal !== null || payload.integrations.length > 0 || payload.agents.length > 0 || Boolean(payload.healthTriage) || Boolean(payload.credentialRotation) || Boolean(payload.landing) || payload.warRoom !== null && payload.warRoom.priorityCount > 0;
|
|
49544
|
+
const hasAny = payload.needsYou.length > 0 || payload.topGoal !== null || payload.integrations.length > 0 || payload.agents.length > 0 || Boolean(payload.healthTriage) || Boolean(payload.credentialRotation) || Boolean(payload.keyRotation) || Boolean(payload.landing) || payload.warRoom !== null && payload.warRoom.priorityCount > 0;
|
|
49259
49545
|
if (!hasAny) {
|
|
49260
49546
|
lines.push(
|
|
49261
49547
|
`${c.green("\u2713")} You're all clear \u2014 nothing needs you right now.`
|
|
@@ -49329,6 +49615,17 @@ function renderStatus2(payload, plain, apiUrl) {
|
|
|
49329
49615
|
if (url2) lines.push(` ${c.dim("\u2192")} ${link("Open rotation", url2)}`);
|
|
49330
49616
|
lines.push("");
|
|
49331
49617
|
}
|
|
49618
|
+
if (payload.keyRotation) {
|
|
49619
|
+
const k = payload.keyRotation;
|
|
49620
|
+
lines.push(c.bold("Key rotation"));
|
|
49621
|
+
lines.push(
|
|
49622
|
+
` ${k.needsYou} need you \xB7 ${k.pendingDevices} machine updates pending`
|
|
49623
|
+
);
|
|
49624
|
+
const url2 = glanceItemUrl("/settings/key-rotation", apiUrl);
|
|
49625
|
+
if (url2)
|
|
49626
|
+
lines.push(` ${c.dim("\u2192")} ${link("Open key rotation", url2)}`);
|
|
49627
|
+
lines.push("");
|
|
49628
|
+
}
|
|
49332
49629
|
if (payload.landing) {
|
|
49333
49630
|
lines.push(c.bold("Merge queue"));
|
|
49334
49631
|
for (const r of payload.landing.repos) {
|
|
@@ -49385,8 +49682,8 @@ function browserLaunchCommand(url2, platform2 = process.platform) {
|
|
|
49385
49682
|
function openBrowser2(url2) {
|
|
49386
49683
|
const command = browserLaunchCommand(url2);
|
|
49387
49684
|
if (!command) return Promise.resolve(false);
|
|
49388
|
-
return new Promise((
|
|
49389
|
-
execFile3(command.file, command.args, (error62) =>
|
|
49685
|
+
return new Promise((resolve5) => {
|
|
49686
|
+
execFile3(command.file, command.args, (error62) => resolve5(!error62));
|
|
49390
49687
|
});
|
|
49391
49688
|
}
|
|
49392
49689
|
function toSurfaceRow(value) {
|
|
@@ -49644,6 +49941,1166 @@ function callCommand() {
|
|
|
49644
49941
|
});
|
|
49645
49942
|
}
|
|
49646
49943
|
|
|
49944
|
+
// src/commands/keys.ts
|
|
49945
|
+
import { createInterface as createInterface3 } from "node:readline";
|
|
49946
|
+
import { Writable } from "node:stream";
|
|
49947
|
+
|
|
49948
|
+
// src/lib/keys-apply.ts
|
|
49949
|
+
import { spawn } from "node:child_process";
|
|
49950
|
+
import {
|
|
49951
|
+
chmod as chmod2,
|
|
49952
|
+
mkdir as mkdir8,
|
|
49953
|
+
readFile as readFile7,
|
|
49954
|
+
realpath,
|
|
49955
|
+
rename as rename2,
|
|
49956
|
+
stat as stat2,
|
|
49957
|
+
writeFile as writeFile6
|
|
49958
|
+
} from "node:fs/promises";
|
|
49959
|
+
import { homedir as homedir10 } from "node:os";
|
|
49960
|
+
import { basename as basename2, dirname as dirname8, isAbsolute as isAbsolute3, join as join12, relative, sep } from "node:path";
|
|
49961
|
+
var GH_APPLY_TIMEOUT_MS = 3e4;
|
|
49962
|
+
var GIT_APPLY_TIMEOUT_MS = 3e4;
|
|
49963
|
+
function runWithStdin(file2, args, input2, timeoutMs) {
|
|
49964
|
+
return new Promise((resolve5) => {
|
|
49965
|
+
let settled = false;
|
|
49966
|
+
const done = (o) => {
|
|
49967
|
+
if (settled) return;
|
|
49968
|
+
settled = true;
|
|
49969
|
+
clearTimeout(timer);
|
|
49970
|
+
resolve5(o);
|
|
49971
|
+
};
|
|
49972
|
+
let child;
|
|
49973
|
+
try {
|
|
49974
|
+
child = spawn(file2, args, { stdio: ["pipe", "ignore", "ignore"] });
|
|
49975
|
+
} catch {
|
|
49976
|
+
resolve5("not_found");
|
|
49977
|
+
return;
|
|
49978
|
+
}
|
|
49979
|
+
const timer = setTimeout(() => {
|
|
49980
|
+
child.kill("SIGKILL");
|
|
49981
|
+
done("timeout");
|
|
49982
|
+
}, timeoutMs);
|
|
49983
|
+
child.on(
|
|
49984
|
+
"error",
|
|
49985
|
+
(err2) => done(
|
|
49986
|
+
err2.code === "ENOENT" ? "not_found" : "failed"
|
|
49987
|
+
)
|
|
49988
|
+
);
|
|
49989
|
+
child.on("close", (code) => done(code === 0 ? "ok" : "failed"));
|
|
49990
|
+
child.stdin?.on("error", () => done("failed"));
|
|
49991
|
+
child.stdin?.end(input2);
|
|
49992
|
+
});
|
|
49993
|
+
}
|
|
49994
|
+
async function applyGhCli(value) {
|
|
49995
|
+
const outcome = await runWithStdin(
|
|
49996
|
+
"gh",
|
|
49997
|
+
["auth", "login", "--hostname", "github.com", "--with-token"],
|
|
49998
|
+
value,
|
|
49999
|
+
GH_APPLY_TIMEOUT_MS
|
|
50000
|
+
);
|
|
50001
|
+
if (outcome === "ok") return { ok: true, code: "applied" };
|
|
50002
|
+
return { ok: false, code: `gh_${outcome}` };
|
|
50003
|
+
}
|
|
50004
|
+
async function applyGitCredential(value, helper) {
|
|
50005
|
+
if (helper === "gh") return { ok: true, code: "via_gh" };
|
|
50006
|
+
const rejected = await runWithStdin(
|
|
50007
|
+
"git",
|
|
50008
|
+
["credential", "reject"],
|
|
50009
|
+
"protocol=https\nhost=github.com\n\n",
|
|
50010
|
+
GIT_APPLY_TIMEOUT_MS
|
|
50011
|
+
);
|
|
50012
|
+
if (rejected === "not_found" || rejected === "timeout") {
|
|
50013
|
+
return { ok: false, code: `git_${rejected}` };
|
|
50014
|
+
}
|
|
50015
|
+
const approved = await runWithStdin(
|
|
50016
|
+
"git",
|
|
50017
|
+
["credential", "approve"],
|
|
50018
|
+
`protocol=https
|
|
50019
|
+
host=github.com
|
|
50020
|
+
username=x-access-token
|
|
50021
|
+
password=${value}
|
|
50022
|
+
|
|
50023
|
+
`,
|
|
50024
|
+
GIT_APPLY_TIMEOUT_MS
|
|
50025
|
+
);
|
|
50026
|
+
if (approved === "ok") return { ok: true, code: "applied" };
|
|
50027
|
+
return { ok: false, code: `git_${approved}` };
|
|
50028
|
+
}
|
|
50029
|
+
function expandHome(path10) {
|
|
50030
|
+
if (path10 === "~") return homedir10();
|
|
50031
|
+
if (path10.startsWith("~/")) return join12(homedir10(), path10.slice(2));
|
|
50032
|
+
return path10;
|
|
50033
|
+
}
|
|
50034
|
+
function escapeRegExp(s2) {
|
|
50035
|
+
return s2.replace(/[.*+?^${}()|[\]\\-]/g, "\\$&");
|
|
50036
|
+
}
|
|
50037
|
+
function unquote(raw) {
|
|
50038
|
+
const t = raw.trim();
|
|
50039
|
+
if (t.length >= 2) {
|
|
50040
|
+
const q = t[0];
|
|
50041
|
+
if ((q === '"' || q === "'") && t.endsWith(q)) {
|
|
50042
|
+
return { inner: t.slice(1, -1), quote: q };
|
|
50043
|
+
}
|
|
50044
|
+
}
|
|
50045
|
+
return { inner: t, quote: "" };
|
|
50046
|
+
}
|
|
50047
|
+
function formatEnvValue(value, quote) {
|
|
50048
|
+
const needsDouble = /[\n\r]/.test(value);
|
|
50049
|
+
if (quote === "'" && !needsDouble && !value.includes("'")) {
|
|
50050
|
+
return `'${value}'`;
|
|
50051
|
+
}
|
|
50052
|
+
if (quote !== "" || needsDouble || /[\s#"'`$\\]/.test(value)) {
|
|
50053
|
+
const escaped = value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\r/g, "\\r").replace(/\n/g, "\\n");
|
|
50054
|
+
return `"${escaped}"`;
|
|
50055
|
+
}
|
|
50056
|
+
return value;
|
|
50057
|
+
}
|
|
50058
|
+
async function writeAtomic(path10, content, mode) {
|
|
50059
|
+
const tmp = `${path10}.tmp`;
|
|
50060
|
+
await writeFile6(tmp, content, { mode });
|
|
50061
|
+
await chmod2(tmp, mode);
|
|
50062
|
+
await rename2(tmp, path10);
|
|
50063
|
+
}
|
|
50064
|
+
async function applyEnvFile(path10, key, value) {
|
|
50065
|
+
const file2 = expandHome(path10);
|
|
50066
|
+
let original;
|
|
50067
|
+
let mode = 384;
|
|
50068
|
+
try {
|
|
50069
|
+
original = await readFile7(file2, "utf8");
|
|
50070
|
+
mode = (await stat2(file2)).mode & 511;
|
|
50071
|
+
} catch (err2) {
|
|
50072
|
+
if (err2?.code !== "ENOENT") {
|
|
50073
|
+
return { ok: false, code: "env_read_failed" };
|
|
50074
|
+
}
|
|
50075
|
+
original = null;
|
|
50076
|
+
}
|
|
50077
|
+
const lineRe = new RegExp(
|
|
50078
|
+
`^(\\s*(?:export\\s+)?${escapeRegExp(key)}\\s*=\\s*)(.*?)(\\r?)$`
|
|
50079
|
+
);
|
|
50080
|
+
const lines = original === null ? [] : original.split("\n");
|
|
50081
|
+
let found = false;
|
|
50082
|
+
for (const [i, line] of lines.entries()) {
|
|
50083
|
+
const m = lineRe.exec(line);
|
|
50084
|
+
if (!m) continue;
|
|
50085
|
+
const head = m[1] ?? "";
|
|
50086
|
+
const raw = m[2] ?? "";
|
|
50087
|
+
const cr = m[3] ?? "";
|
|
50088
|
+
const { inner, quote } = unquote(raw);
|
|
50089
|
+
if (inner.startsWith("op://")) {
|
|
50090
|
+
return { ok: true, code: "reference_reread" };
|
|
50091
|
+
}
|
|
50092
|
+
lines[i] = `${head}${formatEnvValue(value, quote)}${cr}`;
|
|
50093
|
+
found = true;
|
|
50094
|
+
}
|
|
50095
|
+
if (!found) {
|
|
50096
|
+
const entry = `${key}=${formatEnvValue(value, "")}`;
|
|
50097
|
+
if (lines.length === 0) {
|
|
50098
|
+
lines.push(entry, "");
|
|
50099
|
+
} else if (lines[lines.length - 1] === "") {
|
|
50100
|
+
lines.splice(lines.length - 1, 0, entry);
|
|
50101
|
+
} else {
|
|
50102
|
+
lines.push(entry);
|
|
50103
|
+
}
|
|
50104
|
+
}
|
|
50105
|
+
try {
|
|
50106
|
+
await writeAtomic(file2, lines.join("\n"), mode);
|
|
50107
|
+
} catch {
|
|
50108
|
+
return { ok: false, code: "env_write_failed" };
|
|
50109
|
+
}
|
|
50110
|
+
return { ok: true, code: "applied" };
|
|
50111
|
+
}
|
|
50112
|
+
async function applySshKey(path10, privatePem) {
|
|
50113
|
+
const file2 = expandHome(path10);
|
|
50114
|
+
const content = privatePem.endsWith("\n") ? privatePem : `${privatePem}
|
|
50115
|
+
`;
|
|
50116
|
+
try {
|
|
50117
|
+
await mkdir8(dirname8(file2), { recursive: true, mode: 448 });
|
|
50118
|
+
await writeAtomic(file2, content, 384);
|
|
50119
|
+
} catch {
|
|
50120
|
+
return { ok: false, code: "ssh_write_failed" };
|
|
50121
|
+
}
|
|
50122
|
+
return { ok: true, code: "applied" };
|
|
50123
|
+
}
|
|
50124
|
+
function envTargetRefusal(path10, key, reported) {
|
|
50125
|
+
if (!isAbsolute3(path10)) return { ok: false, code: "target_invalid" };
|
|
50126
|
+
const known = reported.some((r) => r.path === path10 && r.key === key);
|
|
50127
|
+
return known ? null : { ok: false, code: "target_not_reported" };
|
|
50128
|
+
}
|
|
50129
|
+
var SSH_NOT_A_KEY = /* @__PURE__ */ new Set([
|
|
50130
|
+
"authorized_keys",
|
|
50131
|
+
"authorized_keys2",
|
|
50132
|
+
"config",
|
|
50133
|
+
"known_hosts"
|
|
50134
|
+
]);
|
|
50135
|
+
async function sshTargetRefusal(path10, sshDir = join12(homedir10(), ".ssh")) {
|
|
50136
|
+
const file2 = expandHome(path10);
|
|
50137
|
+
if (!isAbsolute3(file2)) return { ok: false, code: "target_invalid" };
|
|
50138
|
+
if (SSH_NOT_A_KEY.has(basename2(file2))) {
|
|
50139
|
+
return { ok: false, code: "target_not_a_key" };
|
|
50140
|
+
}
|
|
50141
|
+
let root;
|
|
50142
|
+
let parent;
|
|
50143
|
+
try {
|
|
50144
|
+
root = await realpath(sshDir);
|
|
50145
|
+
parent = await realpath(dirname8(file2));
|
|
50146
|
+
} catch {
|
|
50147
|
+
return { ok: false, code: "target_outside_ssh_dir" };
|
|
50148
|
+
}
|
|
50149
|
+
const rel = relative(root, parent);
|
|
50150
|
+
if (rel === ".." || rel.startsWith(`..${sep}`) || isAbsolute3(rel)) {
|
|
50151
|
+
return { ok: false, code: "target_outside_ssh_dir" };
|
|
50152
|
+
}
|
|
50153
|
+
return null;
|
|
50154
|
+
}
|
|
50155
|
+
async function applyUpdate(targetKind, targetRef, value, scope) {
|
|
50156
|
+
try {
|
|
50157
|
+
switch (targetKind) {
|
|
50158
|
+
case "machine_gh_cli":
|
|
50159
|
+
return await applyGhCli(value);
|
|
50160
|
+
case "machine_git_credential":
|
|
50161
|
+
return await applyGitCredential(value, targetRef.helper ?? "other");
|
|
50162
|
+
case "machine_env_file": {
|
|
50163
|
+
if (!targetRef.path || !targetRef.key) {
|
|
50164
|
+
return { ok: false, code: "target_invalid" };
|
|
50165
|
+
}
|
|
50166
|
+
const refused = envTargetRefusal(
|
|
50167
|
+
targetRef.path,
|
|
50168
|
+
targetRef.key,
|
|
50169
|
+
scope.reported
|
|
50170
|
+
);
|
|
50171
|
+
if (refused) return refused;
|
|
50172
|
+
return await applyEnvFile(targetRef.path, targetRef.key, value);
|
|
50173
|
+
}
|
|
50174
|
+
case "machine_ssh_key": {
|
|
50175
|
+
if (!targetRef.path) return { ok: false, code: "target_invalid" };
|
|
50176
|
+
const refused = await sshTargetRefusal(targetRef.path, scope.sshDir);
|
|
50177
|
+
if (refused) return refused;
|
|
50178
|
+
return await applySshKey(targetRef.path, value);
|
|
50179
|
+
}
|
|
50180
|
+
default:
|
|
50181
|
+
return { ok: false, code: "unsupported_target" };
|
|
50182
|
+
}
|
|
50183
|
+
} catch {
|
|
50184
|
+
return { ok: false, code: "apply_error" };
|
|
50185
|
+
}
|
|
50186
|
+
}
|
|
50187
|
+
|
|
50188
|
+
// src/lib/keys-device.ts
|
|
50189
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
50190
|
+
import { readFile as readFile8 } from "node:fs/promises";
|
|
50191
|
+
import { hostname as hostname5 } from "node:os";
|
|
50192
|
+
import { resolve as resolve4 } from "node:path";
|
|
50193
|
+
|
|
50194
|
+
// src/lib/keys-envelope.ts
|
|
50195
|
+
import {
|
|
50196
|
+
createDecipheriv,
|
|
50197
|
+
createPrivateKey,
|
|
50198
|
+
createPublicKey,
|
|
50199
|
+
diffieHellman,
|
|
50200
|
+
generateKeyPairSync,
|
|
50201
|
+
hkdfSync
|
|
50202
|
+
} from "node:crypto";
|
|
50203
|
+
var DEVICE_ENVELOPE_INFO = "gad:key-rotation-device:v1";
|
|
50204
|
+
var MAGIC = Buffer.from("kd1", "ascii");
|
|
50205
|
+
var KEY_LEN = 32;
|
|
50206
|
+
var IV_LEN = 12;
|
|
50207
|
+
var TAG_LEN = 16;
|
|
50208
|
+
var HEADER_LEN = MAGIC.length + KEY_LEN + IV_LEN + TAG_LEN;
|
|
50209
|
+
var SPKI_PREFIX = Buffer.from("302a300506032b656e032100", "hex");
|
|
50210
|
+
var PKCS8_PREFIX = Buffer.from("302e020100300506032b656e04220420", "hex");
|
|
50211
|
+
var EnvelopeError = class extends Error {
|
|
50212
|
+
constructor(code) {
|
|
50213
|
+
super(code);
|
|
50214
|
+
this.code = code;
|
|
50215
|
+
this.name = "EnvelopeError";
|
|
50216
|
+
}
|
|
50217
|
+
code;
|
|
50218
|
+
};
|
|
50219
|
+
function rawKey(b64) {
|
|
50220
|
+
const raw = Buffer.from(b64, "base64");
|
|
50221
|
+
if (raw.length !== KEY_LEN || raw.toString("base64") !== b64) {
|
|
50222
|
+
throw new EnvelopeError("device_key_invalid");
|
|
50223
|
+
}
|
|
50224
|
+
return raw;
|
|
50225
|
+
}
|
|
50226
|
+
function rawPublic(key) {
|
|
50227
|
+
const der = key.export({ format: "der", type: "spki" });
|
|
50228
|
+
return Buffer.from(der.subarray(der.length - KEY_LEN));
|
|
50229
|
+
}
|
|
50230
|
+
function rawPrivate(key) {
|
|
50231
|
+
const der = key.export({ format: "der", type: "pkcs8" });
|
|
50232
|
+
return Buffer.from(der.subarray(der.length - KEY_LEN));
|
|
50233
|
+
}
|
|
50234
|
+
function generateDeviceKeyPair() {
|
|
50235
|
+
const pair = generateKeyPairSync("x25519");
|
|
50236
|
+
return {
|
|
50237
|
+
publicKey: rawPublic(pair.publicKey).toString("base64"),
|
|
50238
|
+
privateKey: rawPrivate(pair.privateKey).toString("base64")
|
|
50239
|
+
};
|
|
50240
|
+
}
|
|
50241
|
+
function openFromServer(sealed, devicePrivateKeyB64) {
|
|
50242
|
+
if (sealed.length < HEADER_LEN || !sealed.subarray(0, MAGIC.length).equals(MAGIC)) {
|
|
50243
|
+
throw new EnvelopeError("envelope_invalid");
|
|
50244
|
+
}
|
|
50245
|
+
const priv = createPrivateKey({
|
|
50246
|
+
key: Buffer.concat([PKCS8_PREFIX, rawKey(devicePrivateKeyB64)]),
|
|
50247
|
+
format: "der",
|
|
50248
|
+
type: "pkcs8"
|
|
50249
|
+
});
|
|
50250
|
+
const devicePub = rawPublic(createPublicKey(priv));
|
|
50251
|
+
let o = MAGIC.length;
|
|
50252
|
+
const ephPub = Buffer.from(sealed.subarray(o, o += KEY_LEN));
|
|
50253
|
+
const iv = sealed.subarray(o, o += IV_LEN);
|
|
50254
|
+
const tag = sealed.subarray(o, o += TAG_LEN);
|
|
50255
|
+
const ct = sealed.subarray(o);
|
|
50256
|
+
let shared;
|
|
50257
|
+
try {
|
|
50258
|
+
shared = diffieHellman({
|
|
50259
|
+
privateKey: priv,
|
|
50260
|
+
publicKey: createPublicKey({
|
|
50261
|
+
key: Buffer.concat([SPKI_PREFIX, ephPub]),
|
|
50262
|
+
format: "der",
|
|
50263
|
+
type: "spki"
|
|
50264
|
+
})
|
|
50265
|
+
});
|
|
50266
|
+
} catch {
|
|
50267
|
+
throw new EnvelopeError("envelope_invalid");
|
|
50268
|
+
}
|
|
50269
|
+
if (shared.every((b) => b === 0)) {
|
|
50270
|
+
throw new EnvelopeError("envelope_invalid");
|
|
50271
|
+
}
|
|
50272
|
+
const key = Buffer.from(
|
|
50273
|
+
hkdfSync(
|
|
50274
|
+
"sha256",
|
|
50275
|
+
shared,
|
|
50276
|
+
Buffer.concat([ephPub, devicePub]),
|
|
50277
|
+
Buffer.from(DEVICE_ENVELOPE_INFO, "utf8"),
|
|
50278
|
+
KEY_LEN
|
|
50279
|
+
)
|
|
50280
|
+
);
|
|
50281
|
+
try {
|
|
50282
|
+
const decipher = createDecipheriv("aes-256-gcm", key, iv);
|
|
50283
|
+
decipher.setAuthTag(tag);
|
|
50284
|
+
return Buffer.concat([decipher.update(ct), decipher.final()]).toString(
|
|
50285
|
+
"utf8"
|
|
50286
|
+
);
|
|
50287
|
+
} catch {
|
|
50288
|
+
throw new EnvelopeError("envelope_invalid");
|
|
50289
|
+
}
|
|
50290
|
+
}
|
|
50291
|
+
|
|
50292
|
+
// src/lib/keys-handoff.ts
|
|
50293
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
50294
|
+
|
|
50295
|
+
// src/lib/keys-paths.ts
|
|
50296
|
+
function keyRotationPath() {
|
|
50297
|
+
return "/settings/key-rotation";
|
|
50298
|
+
}
|
|
50299
|
+
function keyRotationRunPath(runId) {
|
|
50300
|
+
return `/settings/key-rotation/runs/${encodeURIComponent(runId)}`;
|
|
50301
|
+
}
|
|
50302
|
+
function keyRotationHandoffPath(jti) {
|
|
50303
|
+
return `/settings/key-rotation/handoff/${encodeURIComponent(jti)}`;
|
|
50304
|
+
}
|
|
50305
|
+
|
|
50306
|
+
// src/lib/keys-handoff.ts
|
|
50307
|
+
var HANDOFF_POLL_INTERVAL_MS = 2e3;
|
|
50308
|
+
var HANDOFF_DEADLINE_MS = 5 * 6e4;
|
|
50309
|
+
var BROWSER_LAUNCH_TIMEOUT_MS = 5e3;
|
|
50310
|
+
function openInBrowser(url2) {
|
|
50311
|
+
const command = browserLaunchCommand(url2);
|
|
50312
|
+
if (!command) return Promise.resolve(false);
|
|
50313
|
+
return new Promise((resolve5) => {
|
|
50314
|
+
let settled = false;
|
|
50315
|
+
const done = (ok) => {
|
|
50316
|
+
if (settled) return;
|
|
50317
|
+
settled = true;
|
|
50318
|
+
clearTimeout(timer);
|
|
50319
|
+
resolve5(ok);
|
|
50320
|
+
};
|
|
50321
|
+
const timer = setTimeout(() => done(false), BROWSER_LAUNCH_TIMEOUT_MS);
|
|
50322
|
+
timer.unref?.();
|
|
50323
|
+
try {
|
|
50324
|
+
const child = spawn2(command.file, command.args, {
|
|
50325
|
+
detached: true,
|
|
50326
|
+
stdio: "ignore"
|
|
50327
|
+
});
|
|
50328
|
+
child.once("error", () => done(false));
|
|
50329
|
+
child.once("spawn", () => {
|
|
50330
|
+
child.unref();
|
|
50331
|
+
done(true);
|
|
50332
|
+
});
|
|
50333
|
+
} catch {
|
|
50334
|
+
done(false);
|
|
50335
|
+
}
|
|
50336
|
+
});
|
|
50337
|
+
}
|
|
50338
|
+
var defaultSleep = (ms) => new Promise((resolve5) => setTimeout(resolve5, ms));
|
|
50339
|
+
function stepUpError(message, hint) {
|
|
50340
|
+
return new CliError(message, 1 /* AUTH_ERROR */, hint);
|
|
50341
|
+
}
|
|
50342
|
+
async function requestBrowserStepUp(client2, kind, subjectId, opts = {}) {
|
|
50343
|
+
const openUrl = opts.openUrl ?? openInBrowser;
|
|
50344
|
+
const notify = opts.notify ?? ((line) => process.stderr.write(`${line}
|
|
50345
|
+
`));
|
|
50346
|
+
const sleep2 = opts.sleep ?? defaultSleep;
|
|
50347
|
+
const now = opts.now ?? Date.now;
|
|
50348
|
+
const interval = opts.pollIntervalMs ?? HANDOFF_POLL_INTERVAL_MS;
|
|
50349
|
+
const deadline = now() + (opts.deadlineMs ?? HANDOFF_DEADLINE_MS);
|
|
50350
|
+
const created = await client2.post("/api/key-rotation/handoffs", {
|
|
50351
|
+
kind,
|
|
50352
|
+
subjectId
|
|
50353
|
+
});
|
|
50354
|
+
const jti = typeof created?.jti === "string" ? created.jti : null;
|
|
50355
|
+
if (!jti || !/^[A-Za-z0-9-]{1,64}$/.test(jti)) {
|
|
50356
|
+
throw stepUpError("The server did not return a browser approval.");
|
|
50357
|
+
}
|
|
50358
|
+
const url2 = `${client2.apiOrigin}${keyRotationHandoffPath(jti)}`;
|
|
50359
|
+
notify(`Approve this in your browser (passkey or two-step code): ${url2}`);
|
|
50360
|
+
if (!await openUrl(url2)) {
|
|
50361
|
+
notify("Couldn't launch a browser. Open the URL above to approve.");
|
|
50362
|
+
}
|
|
50363
|
+
while (now() < deadline) {
|
|
50364
|
+
const polled = await client2.get(
|
|
50365
|
+
`/api/key-rotation/handoffs/${encodeURIComponent(jti)}`
|
|
50366
|
+
);
|
|
50367
|
+
const status = polled?.status;
|
|
50368
|
+
if (status === "approved") {
|
|
50369
|
+
if (typeof polled.token === "string" && polled.token.length > 0) {
|
|
50370
|
+
return polled.token;
|
|
50371
|
+
}
|
|
50372
|
+
throw stepUpError(
|
|
50373
|
+
"This approval was already collected by another request.",
|
|
50374
|
+
"Run the command again to request a new approval."
|
|
50375
|
+
);
|
|
50376
|
+
}
|
|
50377
|
+
if (status === "consumed") {
|
|
50378
|
+
throw stepUpError(
|
|
50379
|
+
"This approval was already used.",
|
|
50380
|
+
"Run the command again to request a new approval."
|
|
50381
|
+
);
|
|
50382
|
+
}
|
|
50383
|
+
if (status === "expired") {
|
|
50384
|
+
throw stepUpError(
|
|
50385
|
+
"The browser approval expired.",
|
|
50386
|
+
"Run the command again and approve within 5 minutes."
|
|
50387
|
+
);
|
|
50388
|
+
}
|
|
50389
|
+
await sleep2(interval);
|
|
50390
|
+
}
|
|
50391
|
+
throw stepUpError(
|
|
50392
|
+
"Timed out waiting for the browser approval.",
|
|
50393
|
+
"Run the command again and approve within 5 minutes."
|
|
50394
|
+
);
|
|
50395
|
+
}
|
|
50396
|
+
|
|
50397
|
+
// src/lib/keys-device.ts
|
|
50398
|
+
var DEFAULT_ENV_FILE = ".env.local";
|
|
50399
|
+
var DETECT_TIMEOUT_MS = 5e3;
|
|
50400
|
+
var MAX_ENV_KEYS = 500;
|
|
50401
|
+
var REPORT_KEY = /^[A-Z_][A-Z0-9_]{0,127}$/;
|
|
50402
|
+
var REPORT_PATH = /^[ -~]{1,200}$/;
|
|
50403
|
+
var TOKEN_SHAPED = /[A-Za-z0-9]{33,}/;
|
|
50404
|
+
var SECRET_PREFIX = /(gh[pousr]_|github_pat_|-----BEGIN)/;
|
|
50405
|
+
var UUID5 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
50406
|
+
function deviceSlot(workspaceId) {
|
|
50407
|
+
return `key-rotation-device:${workspaceId}`;
|
|
50408
|
+
}
|
|
50409
|
+
function parseReported(v) {
|
|
50410
|
+
if (!Array.isArray(v)) return [];
|
|
50411
|
+
return v.flatMap((r) => {
|
|
50412
|
+
const o = r;
|
|
50413
|
+
return typeof o?.path === "string" && typeof o.key === "string" ? [{ path: o.path, key: o.key }] : [];
|
|
50414
|
+
});
|
|
50415
|
+
}
|
|
50416
|
+
function parsePending(v) {
|
|
50417
|
+
const o = v;
|
|
50418
|
+
if (typeof o?.publicKey !== "string" || typeof o.privateKey !== "string") {
|
|
50419
|
+
return null;
|
|
50420
|
+
}
|
|
50421
|
+
return {
|
|
50422
|
+
enrollmentId: typeof o.enrollmentId === "string" ? o.enrollmentId : null,
|
|
50423
|
+
publicKey: o.publicKey,
|
|
50424
|
+
privateKey: o.privateKey,
|
|
50425
|
+
reported: parseReported(o.reported)
|
|
50426
|
+
};
|
|
50427
|
+
}
|
|
50428
|
+
async function loadDevice(workspaceId) {
|
|
50429
|
+
const raw = await getSecretSlot(deviceSlot(workspaceId));
|
|
50430
|
+
if (!raw) return null;
|
|
50431
|
+
try {
|
|
50432
|
+
const parsed = JSON.parse(raw);
|
|
50433
|
+
if (parsed?.v !== 1 || typeof parsed.privateKey !== "string" || typeof parsed.publicKey !== "string") {
|
|
50434
|
+
return null;
|
|
50435
|
+
}
|
|
50436
|
+
return {
|
|
50437
|
+
v: 1,
|
|
50438
|
+
deviceId: typeof parsed.deviceId === "string" ? parsed.deviceId : null,
|
|
50439
|
+
enrollmentId: typeof parsed.enrollmentId === "string" ? parsed.enrollmentId : null,
|
|
50440
|
+
publicKey: parsed.publicKey,
|
|
50441
|
+
privateKey: parsed.privateKey,
|
|
50442
|
+
reported: parseReported(parsed.reported),
|
|
50443
|
+
pendingReplacement: parsePending(parsed.pendingReplacement)
|
|
50444
|
+
};
|
|
50445
|
+
} catch {
|
|
50446
|
+
return null;
|
|
50447
|
+
}
|
|
50448
|
+
}
|
|
50449
|
+
async function saveDevice(workspaceId, device) {
|
|
50450
|
+
if (!await setSecretSlot(deviceSlot(workspaceId), JSON.stringify(device))) {
|
|
50451
|
+
throw new CliError(
|
|
50452
|
+
"Could not store this machine's device key in the keychain.",
|
|
50453
|
+
3 /* VALIDATION_ERROR */,
|
|
50454
|
+
"Unlock your keychain (or check ~/.great-arrow permissions) and try again."
|
|
50455
|
+
);
|
|
50456
|
+
}
|
|
50457
|
+
}
|
|
50458
|
+
async function requireEnrolledDevice(workspaceId) {
|
|
50459
|
+
const device = await loadDevice(workspaceId);
|
|
50460
|
+
if (!device?.deviceId) {
|
|
50461
|
+
throw new CliError(
|
|
50462
|
+
"This machine is not enrolled for key rotation in this workspace.",
|
|
50463
|
+
3 /* VALIDATION_ERROR */,
|
|
50464
|
+
"Run 'gad keys enroll' first."
|
|
50465
|
+
);
|
|
50466
|
+
}
|
|
50467
|
+
return { ...device, deviceId: device.deviceId };
|
|
50468
|
+
}
|
|
50469
|
+
function nameOk(s2) {
|
|
50470
|
+
return !TOKEN_SHAPED.test(s2) && !SECRET_PREFIX.test(s2);
|
|
50471
|
+
}
|
|
50472
|
+
function isOpReference(rawValue) {
|
|
50473
|
+
const t = rawValue.trim();
|
|
50474
|
+
const q = t[0];
|
|
50475
|
+
const inner = t.length >= 2 && (q === '"' || q === "'") && t.endsWith(q) ? t.slice(1, -1) : t;
|
|
50476
|
+
return inner.startsWith("op://");
|
|
50477
|
+
}
|
|
50478
|
+
async function scanEnvKeys(paths) {
|
|
50479
|
+
const out2 = [];
|
|
50480
|
+
const seen = /* @__PURE__ */ new Set();
|
|
50481
|
+
for (const p of paths) {
|
|
50482
|
+
const path10 = resolve4(p);
|
|
50483
|
+
if (seen.has(path10)) continue;
|
|
50484
|
+
seen.add(path10);
|
|
50485
|
+
if (!REPORT_PATH.test(path10) || !nameOk(path10)) continue;
|
|
50486
|
+
let text3;
|
|
50487
|
+
try {
|
|
50488
|
+
text3 = await readFile8(path10, "utf8");
|
|
50489
|
+
} catch {
|
|
50490
|
+
continue;
|
|
50491
|
+
}
|
|
50492
|
+
for (const line of text3.split(/\r?\n/)) {
|
|
50493
|
+
const m = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_.-]*)\s*=(.*)$/.exec(
|
|
50494
|
+
line
|
|
50495
|
+
);
|
|
50496
|
+
const key = m?.[1];
|
|
50497
|
+
if (!key || !REPORT_KEY.test(key)) continue;
|
|
50498
|
+
out2.push({ path: path10, key, isReference: isOpReference(m?.[2] ?? "") });
|
|
50499
|
+
if (out2.length >= MAX_ENV_KEYS) return out2;
|
|
50500
|
+
}
|
|
50501
|
+
}
|
|
50502
|
+
return out2;
|
|
50503
|
+
}
|
|
50504
|
+
function helperKind(raw) {
|
|
50505
|
+
const v = raw.trim();
|
|
50506
|
+
if (!v) return null;
|
|
50507
|
+
if (/\bgh(\.exe)?\s+auth\s+git-credential\b/.test(v)) return "gh";
|
|
50508
|
+
if (/osxkeychain/.test(v)) return "osxkeychain";
|
|
50509
|
+
if (/^store\b/.test(v)) return "store";
|
|
50510
|
+
return "other";
|
|
50511
|
+
}
|
|
50512
|
+
function run3(file2, args) {
|
|
50513
|
+
return new Promise((done) => {
|
|
50514
|
+
execFile4(
|
|
50515
|
+
file2,
|
|
50516
|
+
args,
|
|
50517
|
+
{ timeout: DETECT_TIMEOUT_MS, encoding: "utf8" },
|
|
50518
|
+
(error62, stdout) => done(error62 ? null : String(stdout))
|
|
50519
|
+
);
|
|
50520
|
+
});
|
|
50521
|
+
}
|
|
50522
|
+
async function detectGhCli() {
|
|
50523
|
+
return await run3("gh", ["--version"]) !== null;
|
|
50524
|
+
}
|
|
50525
|
+
async function detectGitHelper() {
|
|
50526
|
+
const out2 = await run3("git", [
|
|
50527
|
+
"config",
|
|
50528
|
+
"--get-urlmatch",
|
|
50529
|
+
"credential.helper",
|
|
50530
|
+
"https://github.com"
|
|
50531
|
+
]);
|
|
50532
|
+
return out2 === null ? null : helperKind(out2);
|
|
50533
|
+
}
|
|
50534
|
+
async function buildDeviceReport(envFiles) {
|
|
50535
|
+
const [envKeys, ghCli, gitHelper] = await Promise.all([
|
|
50536
|
+
scanEnvKeys([...envFiles, DEFAULT_ENV_FILE]),
|
|
50537
|
+
detectGhCli(),
|
|
50538
|
+
detectGitHelper()
|
|
50539
|
+
]);
|
|
50540
|
+
return { envKeys, ghCli, gitHelper };
|
|
50541
|
+
}
|
|
50542
|
+
function defaultDeviceLabel() {
|
|
50543
|
+
const label = hostname5().replace(/[^ -~]/g, "-").slice(0, 80).trim();
|
|
50544
|
+
return label && nameOk(label) ? label : "this machine";
|
|
50545
|
+
}
|
|
50546
|
+
async function enroll(client2, workspaceId, opts = {}) {
|
|
50547
|
+
const existing = await loadDevice(workspaceId);
|
|
50548
|
+
const replacing = existing?.deviceId ? existing : null;
|
|
50549
|
+
if (replacing && !opts.replace) {
|
|
50550
|
+
throw new CliError(
|
|
50551
|
+
"This machine is already enrolled for key rotation in this workspace.",
|
|
50552
|
+
3 /* VALIDATION_ERROR */,
|
|
50553
|
+
"Run 'gad keys pending' to see its updates, or 'gad keys enroll --replace' to enroll it again with a new key."
|
|
50554
|
+
);
|
|
50555
|
+
}
|
|
50556
|
+
const label = opts.label ?? defaultDeviceLabel();
|
|
50557
|
+
const report = await (opts.report ?? buildDeviceReport)(opts.envFiles ?? []);
|
|
50558
|
+
const pair = generateDeviceKeyPair();
|
|
50559
|
+
const pending = {
|
|
50560
|
+
enrollmentId: null,
|
|
50561
|
+
publicKey: pair.publicKey,
|
|
50562
|
+
privateKey: pair.privateKey,
|
|
50563
|
+
reported: report.envKeys.map(({ path: path10, key }) => ({ path: path10, key }))
|
|
50564
|
+
};
|
|
50565
|
+
const savePending = () => saveDevice(
|
|
50566
|
+
workspaceId,
|
|
50567
|
+
replacing ? { ...replacing, pendingReplacement: { ...pending } } : {
|
|
50568
|
+
v: 1,
|
|
50569
|
+
deviceId: null,
|
|
50570
|
+
enrollmentId: pending.enrollmentId,
|
|
50571
|
+
publicKey: pending.publicKey,
|
|
50572
|
+
privateKey: pending.privateKey,
|
|
50573
|
+
reported: pending.reported,
|
|
50574
|
+
pendingReplacement: null
|
|
50575
|
+
}
|
|
50576
|
+
);
|
|
50577
|
+
await savePending();
|
|
50578
|
+
const begun = await client2.post("/api/key-rotation/devices", {
|
|
50579
|
+
label,
|
|
50580
|
+
publicKey: pair.publicKey,
|
|
50581
|
+
report
|
|
50582
|
+
});
|
|
50583
|
+
const enrollmentId = typeof begun?.enrollmentId === "string" && UUID5.test(begun.enrollmentId) ? begun.enrollmentId : null;
|
|
50584
|
+
if (!enrollmentId) {
|
|
50585
|
+
throw new CliError(
|
|
50586
|
+
"The server did not start the enrollment.",
|
|
50587
|
+
2 /* NETWORK_ERROR */
|
|
50588
|
+
);
|
|
50589
|
+
}
|
|
50590
|
+
pending.enrollmentId = enrollmentId;
|
|
50591
|
+
await savePending();
|
|
50592
|
+
const approvalToken = await (opts.stepUp ?? requestBrowserStepUp)(
|
|
50593
|
+
client2,
|
|
50594
|
+
"device_enroll",
|
|
50595
|
+
enrollmentId
|
|
50596
|
+
);
|
|
50597
|
+
const done = await client2.post(`/api/key-rotation/devices/${enrollmentId}`, {
|
|
50598
|
+
action: "enroll",
|
|
50599
|
+
approvalToken
|
|
50600
|
+
});
|
|
50601
|
+
const deviceId = typeof done?.deviceId === "string" && UUID5.test(done.deviceId) ? done.deviceId : null;
|
|
50602
|
+
if (!deviceId) {
|
|
50603
|
+
throw new CliError(
|
|
50604
|
+
"The server did not complete the enrollment.",
|
|
50605
|
+
2 /* NETWORK_ERROR */
|
|
50606
|
+
);
|
|
50607
|
+
}
|
|
50608
|
+
await saveDevice(workspaceId, {
|
|
50609
|
+
v: 1,
|
|
50610
|
+
deviceId,
|
|
50611
|
+
enrollmentId,
|
|
50612
|
+
publicKey: pending.publicKey,
|
|
50613
|
+
privateKey: pending.privateKey,
|
|
50614
|
+
reported: pending.reported,
|
|
50615
|
+
pendingReplacement: null
|
|
50616
|
+
});
|
|
50617
|
+
let replaced = null;
|
|
50618
|
+
if (replacing?.deviceId && replacing.deviceId !== deviceId) {
|
|
50619
|
+
try {
|
|
50620
|
+
await client2.delete(`/api/key-rotation/devices/${replacing.deviceId}`);
|
|
50621
|
+
replaced = { deviceId: replacing.deviceId, revoked: true };
|
|
50622
|
+
} catch {
|
|
50623
|
+
replaced = { deviceId: replacing.deviceId, revoked: false };
|
|
50624
|
+
}
|
|
50625
|
+
}
|
|
50626
|
+
return { deviceId, report, replaced };
|
|
50627
|
+
}
|
|
50628
|
+
|
|
50629
|
+
// src/commands/keys.ts
|
|
50630
|
+
var UUID6 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
50631
|
+
function patRequired(apiUrl) {
|
|
50632
|
+
return authError(
|
|
50633
|
+
"gad keys needs a personal access token; this sign-in is an OAuth session.",
|
|
50634
|
+
`Create a token at ${apiUrl}/install/cli, then run 'gad login --token <PAT>'.`
|
|
50635
|
+
);
|
|
50636
|
+
}
|
|
50637
|
+
function keyRotationError(error62, apiUrl) {
|
|
50638
|
+
switch (serverCodeOf(error62)) {
|
|
50639
|
+
case "oauth_not_allowed":
|
|
50640
|
+
return patRequired(apiUrl);
|
|
50641
|
+
case "web_session_required":
|
|
50642
|
+
return new CliError(
|
|
50643
|
+
"This key-rotation action is only available in a signed-in browser.",
|
|
50644
|
+
1 /* AUTH_ERROR */,
|
|
50645
|
+
`Open ${apiUrl}${keyRotationPath()} to do it there.`
|
|
50646
|
+
);
|
|
50647
|
+
case "step_up_required":
|
|
50648
|
+
return new CliError(
|
|
50649
|
+
"The browser approval was missing, expired or already used.",
|
|
50650
|
+
1 /* AUTH_ERROR */,
|
|
50651
|
+
"Run the command again and approve it in your browser."
|
|
50652
|
+
);
|
|
50653
|
+
default:
|
|
50654
|
+
return error62;
|
|
50655
|
+
}
|
|
50656
|
+
}
|
|
50657
|
+
function keysClient(inner, apiUrl) {
|
|
50658
|
+
const mapped = async (call) => {
|
|
50659
|
+
try {
|
|
50660
|
+
return await call();
|
|
50661
|
+
} catch (e) {
|
|
50662
|
+
throw keyRotationError(e, apiUrl);
|
|
50663
|
+
}
|
|
50664
|
+
};
|
|
50665
|
+
return {
|
|
50666
|
+
apiOrigin: new URL(apiUrl).origin,
|
|
50667
|
+
get: (path10, params) => mapped(() => inner.get(path10, params)),
|
|
50668
|
+
post: (path10, body) => mapped(() => inner.post(path10, body)),
|
|
50669
|
+
delete: (path10) => mapped(() => inner.delete(path10))
|
|
50670
|
+
};
|
|
50671
|
+
}
|
|
50672
|
+
async function keysContext() {
|
|
50673
|
+
const auth = await resolveAuth();
|
|
50674
|
+
const apiUrl = auth.apiUrl.replace(/\/$/, "");
|
|
50675
|
+
if (auth.tokenType === "oauth") throw patRequired(apiUrl);
|
|
50676
|
+
const probe = new GadClient({
|
|
50677
|
+
token: auth.token,
|
|
50678
|
+
getToken: auth.getToken,
|
|
50679
|
+
apiUrl: auth.apiUrl
|
|
50680
|
+
});
|
|
50681
|
+
const value = await probe.mcpCall("workspace_introspect", {}, 5e3);
|
|
50682
|
+
const workspaceId = value?.workspace?.id;
|
|
50683
|
+
if (value?.error || !workspaceId || !UUID6.test(workspaceId)) {
|
|
50684
|
+
throw validationError(
|
|
50685
|
+
"GreatArrow.ai could not confirm your workspace.",
|
|
50686
|
+
"Run 'gad whoami', or choose one with 'gad --workspace <id>'."
|
|
50687
|
+
);
|
|
50688
|
+
}
|
|
50689
|
+
return {
|
|
50690
|
+
client: keysClient(
|
|
50691
|
+
new GadClient({
|
|
50692
|
+
token: auth.token,
|
|
50693
|
+
getToken: auth.getToken,
|
|
50694
|
+
apiUrl: auth.apiUrl,
|
|
50695
|
+
workspaceId
|
|
50696
|
+
}),
|
|
50697
|
+
apiUrl
|
|
50698
|
+
),
|
|
50699
|
+
workspaceId,
|
|
50700
|
+
apiUrl
|
|
50701
|
+
};
|
|
50702
|
+
}
|
|
50703
|
+
function requireRunId(runId) {
|
|
50704
|
+
if (!UUID6.test(runId)) {
|
|
50705
|
+
throw validationError(
|
|
50706
|
+
`'${stripControlChars(runId)}' is not a run id.`,
|
|
50707
|
+
"Copy the run id from 'gad keys list' or the run page."
|
|
50708
|
+
);
|
|
50709
|
+
}
|
|
50710
|
+
return runId.toLowerCase();
|
|
50711
|
+
}
|
|
50712
|
+
var s = (v) => typeof v === "string" ? stripControlChars(v) : "";
|
|
50713
|
+
function out(line) {
|
|
50714
|
+
process.stdout.write(`${line}
|
|
50715
|
+
`);
|
|
50716
|
+
}
|
|
50717
|
+
function err(line) {
|
|
50718
|
+
process.stderr.write(`${line}
|
|
50719
|
+
`);
|
|
50720
|
+
}
|
|
50721
|
+
function listCommand4() {
|
|
50722
|
+
return new Command("list").description("List the credentials registered for key rotation").action(async (_opts, command) => {
|
|
50723
|
+
const g = globalOutputOpts(command);
|
|
50724
|
+
const { client: client2 } = await keysContext();
|
|
50725
|
+
const res = await client2.get("/api/key-rotation/credentials");
|
|
50726
|
+
const rows = Array.isArray(res?.credentials) ? res.credentials : [];
|
|
50727
|
+
if (g.json) {
|
|
50728
|
+
out(JSON.stringify(rows));
|
|
50729
|
+
return;
|
|
50730
|
+
}
|
|
50731
|
+
if (rows.length === 0) {
|
|
50732
|
+
out(
|
|
50733
|
+
"No credentials registered. Add one under Settings \u2192 Key rotation."
|
|
50734
|
+
);
|
|
50735
|
+
return;
|
|
50736
|
+
}
|
|
50737
|
+
const c = createColor(g.noColor || g.quiet);
|
|
50738
|
+
for (const r of rows) {
|
|
50739
|
+
const flags = [
|
|
50740
|
+
r.openLeak === true ? c.red("leak") : "",
|
|
50741
|
+
typeof r.liveRunId === "string" ? `run ${s(r.liveRunId)}` : ""
|
|
50742
|
+
].filter(Boolean).join(" \xB7 ");
|
|
50743
|
+
out(
|
|
50744
|
+
`${c.bold(s(r.label))} ${c.dim(s(r.kind))} ${s(r.id)} usages ${typeof r.usageCount === "number" ? r.usageCount : 0} rotated ${s(r.lastRotatedAt) || "never"}` + (flags ? ` ${flags}` : "")
|
|
50745
|
+
);
|
|
50746
|
+
}
|
|
50747
|
+
});
|
|
50748
|
+
}
|
|
50749
|
+
function statusCommand4() {
|
|
50750
|
+
return new Command("status").description("Show one rotation run: steps, checklist and devices").argument("<run>", "Run id").action(async (runArg, _opts, command) => {
|
|
50751
|
+
const g = globalOutputOpts(command);
|
|
50752
|
+
const runId = requireRunId(runArg);
|
|
50753
|
+
const { client: client2, apiUrl } = await keysContext();
|
|
50754
|
+
const res = await client2.get(`/api/key-rotation/runs/${runId}`);
|
|
50755
|
+
const run4 = res?.run ?? {};
|
|
50756
|
+
if (g.json) {
|
|
50757
|
+
out(JSON.stringify(run4));
|
|
50758
|
+
return;
|
|
50759
|
+
}
|
|
50760
|
+
const c = createColor(g.noColor || g.quiet);
|
|
50761
|
+
out(
|
|
50762
|
+
`${c.bold(`Run ${runId}`)} ${s(run4.state)}` + (s(run4.waitingOn) ? c.dim(` waiting on ${s(run4.waitingOn)}`) : "")
|
|
50763
|
+
);
|
|
50764
|
+
for (const st of run4.steps ?? []) {
|
|
50765
|
+
const detail = s(st.detailCode);
|
|
50766
|
+
out(
|
|
50767
|
+
` ${s(st.step)} ${c.dim(s(st.targetKind))} ${s(st.status)}` + (detail ? c.dim(` (${detail})`) : "")
|
|
50768
|
+
);
|
|
50769
|
+
}
|
|
50770
|
+
const open4 = (run4.checklist ?? []).filter((i) => i.ticked !== true);
|
|
50771
|
+
if (open4.length > 0) {
|
|
50772
|
+
out(c.yellow("Checklist (tick these in the browser):"));
|
|
50773
|
+
for (const item of open4) {
|
|
50774
|
+
out(` \u2610 ${s(item.label)} ${c.cyan(s(item.href))}`);
|
|
50775
|
+
}
|
|
50776
|
+
}
|
|
50777
|
+
for (const d of run4.devices ?? []) {
|
|
50778
|
+
out(` device ${s(d.label)} ${s(d.state)}`);
|
|
50779
|
+
}
|
|
50780
|
+
out(c.dim(`${apiUrl}${keyRotationRunPath(runId)}`));
|
|
50781
|
+
});
|
|
50782
|
+
}
|
|
50783
|
+
function collect2(value, previous) {
|
|
50784
|
+
return [...previous, value];
|
|
50785
|
+
}
|
|
50786
|
+
function enrollCommand() {
|
|
50787
|
+
return new Command("enroll").description(
|
|
50788
|
+
"Enroll this machine to receive rotated keys (approve in the browser)"
|
|
50789
|
+
).option("--label <label>", "Device label (defaults to the host name)").option(
|
|
50790
|
+
"--env-file <path>",
|
|
50791
|
+
"An env file to report key NAMES from (repeatable; ./.env.local is always included)",
|
|
50792
|
+
collect2,
|
|
50793
|
+
[]
|
|
50794
|
+
).option(
|
|
50795
|
+
"--replace",
|
|
50796
|
+
"Enroll again with a new key, replacing this machine's"
|
|
50797
|
+
).action(async (opts, command) => {
|
|
50798
|
+
const g = globalOutputOpts(command);
|
|
50799
|
+
const { client: client2, workspaceId } = await keysContext();
|
|
50800
|
+
const { deviceId, report, replaced } = await enroll(client2, workspaceId, {
|
|
50801
|
+
...typeof opts.label === "string" ? { label: opts.label } : {},
|
|
50802
|
+
envFiles: Array.isArray(opts.envFile) ? opts.envFile : [],
|
|
50803
|
+
replace: opts.replace === true
|
|
50804
|
+
});
|
|
50805
|
+
if (g.json) {
|
|
50806
|
+
out(JSON.stringify({ deviceId, report, replaced }));
|
|
50807
|
+
} else {
|
|
50808
|
+
out(`Enrolled this machine as device ${deviceId}.`);
|
|
50809
|
+
out(
|
|
50810
|
+
`Reported ${report.envKeys.length} env key name(s), gh CLI ${report.ghCli ? "found" : "not found"}, git helper ${report.gitHelper ?? "none"}.`
|
|
50811
|
+
);
|
|
50812
|
+
if (replaced?.revoked) {
|
|
50813
|
+
out(
|
|
50814
|
+
`Revoked the device it replaced (${replaced.deviceId}); its queued updates expired.`
|
|
50815
|
+
);
|
|
50816
|
+
out(
|
|
50817
|
+
"Usages confirmed for that device still point at it: confirm them for this one under Settings \u2192 Key rotation."
|
|
50818
|
+
);
|
|
50819
|
+
}
|
|
50820
|
+
}
|
|
50821
|
+
if (replaced && !replaced.revoked) {
|
|
50822
|
+
throw new CliError(
|
|
50823
|
+
`Enrolled, but the device it replaced (${replaced.deviceId}) could not be revoked.`,
|
|
50824
|
+
2 /* NETWORK_ERROR */,
|
|
50825
|
+
"Revoke it under Settings \u2192 Key rotation; updates sealed to it can no longer be opened on this machine."
|
|
50826
|
+
);
|
|
50827
|
+
}
|
|
50828
|
+
});
|
|
50829
|
+
}
|
|
50830
|
+
function toUpdateRow(v) {
|
|
50831
|
+
if (typeof v !== "object" || v === null) return null;
|
|
50832
|
+
const r = v;
|
|
50833
|
+
if (typeof r.id !== "string" || !UUID6.test(r.id)) return null;
|
|
50834
|
+
const ref = {};
|
|
50835
|
+
if (typeof r.targetRef === "object" && r.targetRef !== null) {
|
|
50836
|
+
for (const [k, val] of Object.entries(r.targetRef)) {
|
|
50837
|
+
if (typeof val === "string") ref[k] = val;
|
|
50838
|
+
}
|
|
50839
|
+
}
|
|
50840
|
+
return {
|
|
50841
|
+
id: r.id,
|
|
50842
|
+
runId: typeof r.runId === "string" ? r.runId : "",
|
|
50843
|
+
targetKind: typeof r.targetKind === "string" ? r.targetKind : "",
|
|
50844
|
+
targetRef: ref
|
|
50845
|
+
};
|
|
50846
|
+
}
|
|
50847
|
+
function describeTarget(u) {
|
|
50848
|
+
const ref = u.targetRef;
|
|
50849
|
+
switch (u.targetKind) {
|
|
50850
|
+
case "machine_env_file":
|
|
50851
|
+
return `${s(ref.key)} in ${s(ref.path)}`;
|
|
50852
|
+
case "machine_ssh_key":
|
|
50853
|
+
return `SSH key ${s(ref.path)}`;
|
|
50854
|
+
case "machine_git_credential":
|
|
50855
|
+
return `git credential (${s(ref.helper)})`;
|
|
50856
|
+
case "machine_gh_cli":
|
|
50857
|
+
return "gh CLI login";
|
|
50858
|
+
default:
|
|
50859
|
+
return s(u.targetKind);
|
|
50860
|
+
}
|
|
50861
|
+
}
|
|
50862
|
+
async function listUpdates(client2, deviceId) {
|
|
50863
|
+
const res = await client2.get(
|
|
50864
|
+
`/api/key-rotation/devices/${deviceId}/updates`
|
|
50865
|
+
);
|
|
50866
|
+
return (Array.isArray(res?.updates) ? res.updates : []).map(toUpdateRow).filter((u) => u !== null);
|
|
50867
|
+
}
|
|
50868
|
+
function pendingCommand() {
|
|
50869
|
+
return new Command("pending").description("List the key updates queued for this machine").action(async (_opts, command) => {
|
|
50870
|
+
const g = globalOutputOpts(command);
|
|
50871
|
+
const { client: client2, workspaceId } = await keysContext();
|
|
50872
|
+
const device = await requireEnrolledDevice(workspaceId);
|
|
50873
|
+
const updates = await listUpdates(client2, device.deviceId);
|
|
50874
|
+
if (g.json) {
|
|
50875
|
+
out(JSON.stringify(updates));
|
|
50876
|
+
return;
|
|
50877
|
+
}
|
|
50878
|
+
if (updates.length === 0) {
|
|
50879
|
+
out("No key updates are waiting for this machine.");
|
|
50880
|
+
return;
|
|
50881
|
+
}
|
|
50882
|
+
for (const u of updates) out(` ${describeTarget(u)} ${u.id}`);
|
|
50883
|
+
out("Run 'gad keys apply' to apply them.");
|
|
50884
|
+
});
|
|
50885
|
+
}
|
|
50886
|
+
async function ack(client2, deviceId, updateId, result) {
|
|
50887
|
+
await client2.post(
|
|
50888
|
+
`/api/key-rotation/devices/${deviceId}/updates/${updateId}`,
|
|
50889
|
+
{
|
|
50890
|
+
action: "ack",
|
|
50891
|
+
ok: result.ok,
|
|
50892
|
+
detailCode: result.code
|
|
50893
|
+
}
|
|
50894
|
+
);
|
|
50895
|
+
}
|
|
50896
|
+
async function fetchOpenApply(client2, device, u, approvalToken) {
|
|
50897
|
+
let sealed;
|
|
50898
|
+
try {
|
|
50899
|
+
const fetched = await client2.post(
|
|
50900
|
+
`/api/key-rotation/devices/${device.deviceId}/updates/${u.id}`,
|
|
50901
|
+
{ action: "fetch", approvalToken }
|
|
50902
|
+
);
|
|
50903
|
+
if (typeof fetched?.sealedPayload !== "string") {
|
|
50904
|
+
return { ack: false, ok: false, code: "fetch_failed" };
|
|
50905
|
+
}
|
|
50906
|
+
sealed = fetched.sealedPayload;
|
|
50907
|
+
} catch {
|
|
50908
|
+
return { ack: false, ok: false, code: "fetch_failed" };
|
|
50909
|
+
}
|
|
50910
|
+
let value;
|
|
50911
|
+
try {
|
|
50912
|
+
value = openFromServer(Buffer.from(sealed, "base64"), device.privateKey);
|
|
50913
|
+
} catch (e) {
|
|
50914
|
+
return {
|
|
50915
|
+
ack: true,
|
|
50916
|
+
ok: false,
|
|
50917
|
+
code: e instanceof EnvelopeError ? e.code : "envelope_invalid"
|
|
50918
|
+
};
|
|
50919
|
+
}
|
|
50920
|
+
const result = await applyUpdate(u.targetKind, u.targetRef, value, {
|
|
50921
|
+
reported: device.reported
|
|
50922
|
+
});
|
|
50923
|
+
return { ack: true, ...result };
|
|
50924
|
+
}
|
|
50925
|
+
async function applyBatch(client2, device, updates) {
|
|
50926
|
+
if (updates.length === 0) return [];
|
|
50927
|
+
const approvalToken = await requestBrowserStepUp(
|
|
50928
|
+
client2,
|
|
50929
|
+
"device_apply",
|
|
50930
|
+
device.deviceId
|
|
50931
|
+
);
|
|
50932
|
+
const results = [];
|
|
50933
|
+
for (const u of updates) {
|
|
50934
|
+
const { ack: shouldAck, ...result } = await fetchOpenApply(
|
|
50935
|
+
client2,
|
|
50936
|
+
device,
|
|
50937
|
+
u,
|
|
50938
|
+
approvalToken
|
|
50939
|
+
);
|
|
50940
|
+
if (!shouldAck) {
|
|
50941
|
+
results.push({ id: u.id, targetKind: u.targetKind, ...result });
|
|
50942
|
+
continue;
|
|
50943
|
+
}
|
|
50944
|
+
try {
|
|
50945
|
+
await ack(client2, device.deviceId, u.id, result);
|
|
50946
|
+
results.push({ id: u.id, targetKind: u.targetKind, ...result });
|
|
50947
|
+
} catch {
|
|
50948
|
+
results.push({
|
|
50949
|
+
id: u.id,
|
|
50950
|
+
targetKind: u.targetKind,
|
|
50951
|
+
ok: false,
|
|
50952
|
+
code: "ack_failed"
|
|
50953
|
+
});
|
|
50954
|
+
}
|
|
50955
|
+
}
|
|
50956
|
+
return results;
|
|
50957
|
+
}
|
|
50958
|
+
function applyCommand() {
|
|
50959
|
+
return new Command("apply").description(
|
|
50960
|
+
"Apply the key updates queued for this machine (one browser approval)"
|
|
50961
|
+
).option("--yes", "Apply without the local confirmation prompt").action(async (opts, command) => {
|
|
50962
|
+
const g = globalOutputOpts(command);
|
|
50963
|
+
const { client: client2, workspaceId } = await keysContext();
|
|
50964
|
+
const device = await requireEnrolledDevice(workspaceId);
|
|
50965
|
+
const updates = await listUpdates(client2, device.deviceId);
|
|
50966
|
+
if (updates.length === 0) {
|
|
50967
|
+
if (g.json) out("[]");
|
|
50968
|
+
else out("No key updates are waiting for this machine.");
|
|
50969
|
+
return;
|
|
50970
|
+
}
|
|
50971
|
+
if (opts.yes !== true) {
|
|
50972
|
+
if (!process.stdin.isTTY) {
|
|
50973
|
+
throw validationError(
|
|
50974
|
+
"Refusing to apply key updates without confirmation.",
|
|
50975
|
+
"Run 'gad keys apply --yes' in a script."
|
|
50976
|
+
);
|
|
50977
|
+
}
|
|
50978
|
+
for (const u of updates) err(` ${describeTarget(u)}`);
|
|
50979
|
+
if (!await confirm(`Apply ${updates.length} key update(s)?`)) {
|
|
50980
|
+
err("Nothing applied.");
|
|
50981
|
+
return;
|
|
50982
|
+
}
|
|
50983
|
+
}
|
|
50984
|
+
const results = await applyBatch(client2, device, updates);
|
|
50985
|
+
if (g.json) {
|
|
50986
|
+
out(JSON.stringify(results));
|
|
50987
|
+
} else {
|
|
50988
|
+
const c = createColor(g.noColor || g.quiet);
|
|
50989
|
+
for (const r of results) {
|
|
50990
|
+
const u = updates.find((x) => x.id === r.id);
|
|
50991
|
+
const where = u ? describeTarget(u) : r.targetKind;
|
|
50992
|
+
out(`${r.ok ? c.green("\u2713") : c.red("\u2717")} ${where} ${c.dim(r.code)}`);
|
|
50993
|
+
}
|
|
50994
|
+
}
|
|
50995
|
+
const failed = results.filter((r) => !r.ok).length;
|
|
50996
|
+
if (failed > 0) {
|
|
50997
|
+
throw new CliError(
|
|
50998
|
+
`${failed} of ${results.length} key update(s) failed on this machine.`,
|
|
50999
|
+
3 /* VALIDATION_ERROR */,
|
|
51000
|
+
"An update that could not be fetched stays queued: run 'gad keys apply' again. The run page shows every other failed step."
|
|
51001
|
+
);
|
|
51002
|
+
}
|
|
51003
|
+
});
|
|
51004
|
+
}
|
|
51005
|
+
function readHiddenFromTty(prompt, io = {
|
|
51006
|
+
input: process.stdin,
|
|
51007
|
+
output: process.stderr
|
|
51008
|
+
}) {
|
|
51009
|
+
let muted = false;
|
|
51010
|
+
const sink = new Writable({
|
|
51011
|
+
write(chunk, encoding, callback) {
|
|
51012
|
+
if (!muted) io.output.write(chunk, encoding);
|
|
51013
|
+
callback();
|
|
51014
|
+
}
|
|
51015
|
+
});
|
|
51016
|
+
const rl = createInterface3({
|
|
51017
|
+
input: io.input,
|
|
51018
|
+
output: sink,
|
|
51019
|
+
terminal: true
|
|
51020
|
+
});
|
|
51021
|
+
io.output.write(prompt);
|
|
51022
|
+
muted = true;
|
|
51023
|
+
return new Promise((resolve5, reject) => {
|
|
51024
|
+
const lines = [];
|
|
51025
|
+
let pem = false;
|
|
51026
|
+
const finish = () => {
|
|
51027
|
+
rl.close();
|
|
51028
|
+
io.output.write("\n");
|
|
51029
|
+
resolve5(lines.join("\n"));
|
|
51030
|
+
};
|
|
51031
|
+
rl.on("line", (line) => {
|
|
51032
|
+
if (lines.length === 0) pem = /^-----BEGIN /.test(line.trim());
|
|
51033
|
+
lines.push(line);
|
|
51034
|
+
if (!pem || /^-----END .*-----\s*$/.test(line.trim())) finish();
|
|
51035
|
+
});
|
|
51036
|
+
rl.on("SIGINT", () => {
|
|
51037
|
+
rl.close();
|
|
51038
|
+
reject(new CliError("Paste cancelled.", 3 /* VALIDATION_ERROR */));
|
|
51039
|
+
});
|
|
51040
|
+
});
|
|
51041
|
+
}
|
|
51042
|
+
function pasteRefusal(error62, apiUrl, runId) {
|
|
51043
|
+
const code = serverCodeOf(error62);
|
|
51044
|
+
if (code !== null && (code === "invalid_grants" || code === "storage_token_missing" || code.startsWith("onepassword_"))) {
|
|
51045
|
+
return new CliError(
|
|
51046
|
+
"This run needs its 1Password access granted again, which the CLI cannot send.",
|
|
51047
|
+
3 /* VALIDATION_ERROR */,
|
|
51048
|
+
`Paste the key on the run page instead: ${apiUrl}${keyRotationRunPath(runId)}`
|
|
51049
|
+
);
|
|
51050
|
+
}
|
|
51051
|
+
return error62;
|
|
51052
|
+
}
|
|
51053
|
+
function pasteCommand() {
|
|
51054
|
+
return new Command("paste").description(
|
|
51055
|
+
"Paste the new PAT or App private key for a run (no echo; browser step-up)"
|
|
51056
|
+
).argument("<run>", "Run id").option("--stdin", "Read the value from piped stdin instead of a prompt").action(async (runArg, opts, command) => {
|
|
51057
|
+
const g = globalOutputOpts(command);
|
|
51058
|
+
const runId = requireRunId(runArg);
|
|
51059
|
+
const fromStdin = opts.stdin === true;
|
|
51060
|
+
if (!fromStdin && !process.stdin.isTTY) {
|
|
51061
|
+
throw validationError(
|
|
51062
|
+
"Refusing to read a key from a non-interactive stdin.",
|
|
51063
|
+
"Pass --stdin to read the value from a pipe."
|
|
51064
|
+
);
|
|
51065
|
+
}
|
|
51066
|
+
const { client: client2, apiUrl } = await keysContext();
|
|
51067
|
+
const approvalToken = await requestBrowserStepUp(client2, "paste", runId);
|
|
51068
|
+
const raw = fromStdin ? await readStream(process.stdin) : await readHiddenFromTty("Paste the new key (input hidden): ");
|
|
51069
|
+
const value = raw.trim();
|
|
51070
|
+
if (!value) {
|
|
51071
|
+
throw validationError("Nothing was pasted.");
|
|
51072
|
+
}
|
|
51073
|
+
try {
|
|
51074
|
+
await client2.post(`/api/key-rotation/runs/${runId}/paste`, {
|
|
51075
|
+
value,
|
|
51076
|
+
approvalToken
|
|
51077
|
+
});
|
|
51078
|
+
} catch (e) {
|
|
51079
|
+
throw pasteRefusal(e, apiUrl, runId);
|
|
51080
|
+
}
|
|
51081
|
+
if (g.json) out(JSON.stringify({ ok: true, runId }));
|
|
51082
|
+
else out("Pasted. The run continues on GreatArrow.ai.");
|
|
51083
|
+
});
|
|
51084
|
+
}
|
|
51085
|
+
function approveCommand() {
|
|
51086
|
+
return new Command("approve").description("Open a run's approval page in the browser").argument("<run>", "Run id").action(async (runArg, _opts, command) => {
|
|
51087
|
+
const g = globalOutputOpts(command);
|
|
51088
|
+
const runId = requireRunId(runArg);
|
|
51089
|
+
const auth = await resolveAuth();
|
|
51090
|
+
const url2 = `${auth.apiUrl.replace(/\/$/, "")}${keyRotationRunPath(runId)}`;
|
|
51091
|
+
if (g.json) {
|
|
51092
|
+
out(JSON.stringify({ url: url2 }));
|
|
51093
|
+
return;
|
|
51094
|
+
}
|
|
51095
|
+
const opened = await openInBrowser(url2);
|
|
51096
|
+
out(url2);
|
|
51097
|
+
if (!opened) err("Couldn't launch a browser \u2014 open the URL above.");
|
|
51098
|
+
});
|
|
51099
|
+
}
|
|
51100
|
+
function keysCommand() {
|
|
51101
|
+
return new Command("keys").description("Rotate leaked or expiring keys (GreatArrow.ai key rotation)").addCommand(listCommand4()).addCommand(statusCommand4()).addCommand(enrollCommand()).addCommand(pendingCommand()).addCommand(applyCommand()).addCommand(pasteCommand()).addCommand(approveCommand());
|
|
51102
|
+
}
|
|
51103
|
+
|
|
49647
51104
|
// src/lib/completions.ts
|
|
49648
51105
|
var COMMANDS = [
|
|
49649
51106
|
"login",
|
|
@@ -49658,6 +51115,8 @@ var COMMANDS = [
|
|
|
49658
51115
|
"smoke",
|
|
49659
51116
|
"agent",
|
|
49660
51117
|
"ask",
|
|
51118
|
+
"inbox",
|
|
51119
|
+
"presence",
|
|
49661
51120
|
"runtime",
|
|
49662
51121
|
"open",
|
|
49663
51122
|
"completions"
|
|
@@ -49699,6 +51158,12 @@ _gad_completions() {
|
|
|
49699
51158
|
agent)
|
|
49700
51159
|
COMPREPLY=( $(compgen -W "list invoke" -- "\${cur}") )
|
|
49701
51160
|
;;
|
|
51161
|
+
inbox)
|
|
51162
|
+
COMPREPLY=( $(compgen -W "wait" -- "\${cur}") )
|
|
51163
|
+
;;
|
|
51164
|
+
presence)
|
|
51165
|
+
COMPREPLY=( $(compgen -W "do-not-disturb sign-off" -- "\${cur}") )
|
|
51166
|
+
;;
|
|
49702
51167
|
runtime)
|
|
49703
51168
|
COMPREPLY=( $(compgen -W "status set sync policy" -- "\${cur}") )
|
|
49704
51169
|
;;
|
|
@@ -49734,6 +51199,8 @@ _gad() {
|
|
|
49734
51199
|
'smoke:Run smoke tests'
|
|
49735
51200
|
'agent:Manage agents (list, invoke)'
|
|
49736
51201
|
'ask:Ask the orchestrator a question'
|
|
51202
|
+
'inbox:Agent inbox (wait)'
|
|
51203
|
+
'presence:Agent presence (do-not-disturb, sign-off)'
|
|
49737
51204
|
'runtime:Choose your computer or the cloud per lane'
|
|
49738
51205
|
'open:Open an app surface in the browser'
|
|
49739
51206
|
'completions:Generate shell completions'
|
|
@@ -49769,6 +51236,14 @@ _gad() {
|
|
|
49769
51236
|
subcommands=('list:List agents' 'invoke:Invoke an agent')
|
|
49770
51237
|
_describe -t subcommands 'agent subcommands' subcommands
|
|
49771
51238
|
;;
|
|
51239
|
+
inbox)
|
|
51240
|
+
subcommands=('wait:Wait for a peer message')
|
|
51241
|
+
_describe -t subcommands 'inbox subcommands' subcommands
|
|
51242
|
+
;;
|
|
51243
|
+
presence)
|
|
51244
|
+
subcommands=('do-not-disturb:Do not disturb for a while, or off' 'sign-off:Sign off this connection')
|
|
51245
|
+
_describe -t subcommands 'presence subcommands' subcommands
|
|
51246
|
+
;;
|
|
49772
51247
|
runtime)
|
|
49773
51248
|
subcommands=('status:Where each lane runs' 'set:Set a lane' 'sync:Apply to this checkout' 'policy:Workspace policy')
|
|
49774
51249
|
_describe -t subcommands 'runtime subcommands' subcommands
|
|
@@ -49797,6 +51272,8 @@ function generateFish() {
|
|
|
49797
51272
|
smoke: "Run smoke tests",
|
|
49798
51273
|
agent: "Manage agents",
|
|
49799
51274
|
ask: "Ask the orchestrator a question",
|
|
51275
|
+
inbox: "Agent inbox",
|
|
51276
|
+
presence: "Agent presence",
|
|
49800
51277
|
runtime: "Choose your computer or the cloud per lane",
|
|
49801
51278
|
open: "Open an app surface in the browser",
|
|
49802
51279
|
completions: "Generate shell completions"
|
|
@@ -49835,6 +51312,13 @@ function generateFish() {
|
|
|
49835
51312
|
list: "List agents",
|
|
49836
51313
|
invoke: "Invoke an agent"
|
|
49837
51314
|
},
|
|
51315
|
+
inbox: {
|
|
51316
|
+
wait: "Wait for a peer message"
|
|
51317
|
+
},
|
|
51318
|
+
presence: {
|
|
51319
|
+
"do-not-disturb": "Do not disturb for a while, or off",
|
|
51320
|
+
"sign-off": "Sign off this connection"
|
|
51321
|
+
},
|
|
49838
51322
|
runtime: {
|
|
49839
51323
|
status: "Where each lane runs",
|
|
49840
51324
|
set: "Set a lane",
|
|
@@ -49898,7 +51382,7 @@ function completionsCommand() {
|
|
|
49898
51382
|
|
|
49899
51383
|
// node_modules/.pnpm/update-notifier@7.3.1/node_modules/update-notifier/update-notifier.js
|
|
49900
51384
|
import process11 from "node:process";
|
|
49901
|
-
import { spawn } from "node:child_process";
|
|
51385
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
49902
51386
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
49903
51387
|
import path9 from "node:path";
|
|
49904
51388
|
import { format } from "node:util";
|
|
@@ -49974,7 +51458,7 @@ var retryifyAsync = (fn, options) => {
|
|
|
49974
51458
|
throw error62;
|
|
49975
51459
|
const delay2 = Math.round(interval * Math.random());
|
|
49976
51460
|
if (delay2 > 0) {
|
|
49977
|
-
const delayPromise = new Promise((
|
|
51461
|
+
const delayPromise = new Promise((resolve5) => setTimeout(resolve5, delay2));
|
|
49978
51462
|
return delayPromise.then(() => attempt.apply(void 0, args));
|
|
49979
51463
|
} else {
|
|
49980
51464
|
return attempt.apply(void 0, args);
|
|
@@ -50233,14 +51717,14 @@ var Temp = {
|
|
|
50233
51717
|
}
|
|
50234
51718
|
},
|
|
50235
51719
|
truncate: (filePath) => {
|
|
50236
|
-
const
|
|
50237
|
-
if (
|
|
51720
|
+
const basename3 = path3.basename(filePath);
|
|
51721
|
+
if (basename3.length <= LIMIT_BASENAME_LENGTH)
|
|
50238
51722
|
return filePath;
|
|
50239
|
-
const truncable = /^(\.?)(.*?)((?:\.[^.]+)?(?:\.tmp-\d{10}[a-f0-9]{6})?)$/.exec(
|
|
51723
|
+
const truncable = /^(\.?)(.*?)((?:\.[^.]+)?(?:\.tmp-\d{10}[a-f0-9]{6})?)$/.exec(basename3);
|
|
50240
51724
|
if (!truncable)
|
|
50241
51725
|
return filePath;
|
|
50242
|
-
const truncationLength =
|
|
50243
|
-
return `${filePath.slice(0, -
|
|
51726
|
+
const truncationLength = basename3.length - LIMIT_BASENAME_LENGTH;
|
|
51727
|
+
return `${filePath.slice(0, -basename3.length)}${truncable[1]}${truncable[2].slice(0, -truncationLength)}${truncable[3]}`;
|
|
50244
51728
|
}
|
|
50245
51729
|
};
|
|
50246
51730
|
node_default(Temp.purgeSyncAll);
|
|
@@ -51540,14 +53024,14 @@ var TimeoutError = class extends Error {
|
|
|
51540
53024
|
|
|
51541
53025
|
// node_modules/.pnpm/ky@1.14.3/node_modules/ky/distribution/utils/timeout.js
|
|
51542
53026
|
async function timeout(request, init, abortController, options) {
|
|
51543
|
-
return new Promise((
|
|
53027
|
+
return new Promise((resolve5, reject) => {
|
|
51544
53028
|
const timeoutId = setTimeout(() => {
|
|
51545
53029
|
if (abortController) {
|
|
51546
53030
|
abortController.abort();
|
|
51547
53031
|
}
|
|
51548
53032
|
reject(new TimeoutError(request));
|
|
51549
53033
|
}, options.timeout);
|
|
51550
|
-
void options.fetch(request, init).then(
|
|
53034
|
+
void options.fetch(request, init).then(resolve5).catch(reject).then(() => {
|
|
51551
53035
|
clearTimeout(timeoutId);
|
|
51552
53036
|
});
|
|
51553
53037
|
});
|
|
@@ -51555,7 +53039,7 @@ async function timeout(request, init, abortController, options) {
|
|
|
51555
53039
|
|
|
51556
53040
|
// node_modules/.pnpm/ky@1.14.3/node_modules/ky/distribution/utils/delay.js
|
|
51557
53041
|
async function delay(ms, { signal }) {
|
|
51558
|
-
return new Promise((
|
|
53042
|
+
return new Promise((resolve5, reject) => {
|
|
51559
53043
|
if (signal) {
|
|
51560
53044
|
signal.throwIfAborted();
|
|
51561
53045
|
signal.addEventListener("abort", abortHandler, { once: true });
|
|
@@ -51566,7 +53050,7 @@ async function delay(ms, { signal }) {
|
|
|
51566
53050
|
}
|
|
51567
53051
|
const timeoutId = setTimeout(() => {
|
|
51568
53052
|
signal?.removeEventListener("abort", abortHandler);
|
|
51569
|
-
|
|
53053
|
+
resolve5();
|
|
51570
53054
|
}, ms);
|
|
51571
53055
|
});
|
|
51572
53056
|
}
|
|
@@ -52868,7 +54352,7 @@ var makeContentText = (text3, { padding, width, textAlignment, height }) => {
|
|
|
52868
54352
|
const createdLines = wrapAnsi(line, max, { hard: true });
|
|
52869
54353
|
const alignedLines = (0, import_ansi_align.default)(createdLines, { align: textAlignment });
|
|
52870
54354
|
const alignedLinesArray = alignedLines.split("\n");
|
|
52871
|
-
const longestLength = Math.max(...alignedLinesArray.map((
|
|
54355
|
+
const longestLength = Math.max(...alignedLinesArray.map((s2) => stringWidth(s2)));
|
|
52872
54356
|
for (const alignedLine of alignedLinesArray) {
|
|
52873
54357
|
let paddedLine;
|
|
52874
54358
|
switch (textAlignment) {
|
|
@@ -53195,7 +54679,7 @@ var UpdateNotifier = class {
|
|
|
53195
54679
|
if (Date.now() - this.config.get("lastUpdateCheck") < this.#updateCheckInterval) {
|
|
53196
54680
|
return;
|
|
53197
54681
|
}
|
|
53198
|
-
|
|
54682
|
+
spawn3(process11.execPath, [path9.join(__dirname3, "check.js"), JSON.stringify(this.#options)], {
|
|
53199
54683
|
detached: true,
|
|
53200
54684
|
stdio: "ignore"
|
|
53201
54685
|
}).unref();
|
|
@@ -53314,10 +54798,13 @@ program2.addCommand(integrations_default);
|
|
|
53314
54798
|
program2.addCommand(mcp_default);
|
|
53315
54799
|
program2.addCommand(agentCommand);
|
|
53316
54800
|
program2.addCommand(agentsCommand);
|
|
54801
|
+
program2.addCommand(inboxCommand);
|
|
54802
|
+
program2.addCommand(presenceCommand);
|
|
53317
54803
|
program2.addCommand(askCommand());
|
|
53318
54804
|
program2.addCommand(localCommand());
|
|
53319
54805
|
program2.addCommand(runtimeCommand());
|
|
53320
54806
|
program2.addCommand(smokeCommand());
|
|
54807
|
+
program2.addCommand(keysCommand());
|
|
53321
54808
|
program2.addCommand(openCommand());
|
|
53322
54809
|
program2.addCommand(completionsCommand());
|
|
53323
54810
|
try {
|