alink-cli 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/agentlink.js +252 -26
- package/dist/daemon.js +2054 -27
- package/package.json +7 -3
package/dist/daemon.js
CHANGED
|
@@ -2271,7 +2271,7 @@ var require_websocket = __commonJS({
|
|
|
2271
2271
|
var http = __require("http");
|
|
2272
2272
|
var net = __require("net");
|
|
2273
2273
|
var tls = __require("tls");
|
|
2274
|
-
var { randomBytes:
|
|
2274
|
+
var { randomBytes: randomBytes3, createHash: createHash2 } = __require("crypto");
|
|
2275
2275
|
var { Duplex, Readable } = __require("stream");
|
|
2276
2276
|
var { URL: URL2 } = __require("url");
|
|
2277
2277
|
var PerMessageDeflate2 = require_permessage_deflate();
|
|
@@ -2809,7 +2809,7 @@ var require_websocket = __commonJS({
|
|
|
2809
2809
|
}
|
|
2810
2810
|
}
|
|
2811
2811
|
const defaultPort = isSecure ? 443 : 80;
|
|
2812
|
-
const key =
|
|
2812
|
+
const key = randomBytes3(16).toString("base64");
|
|
2813
2813
|
const request = isSecure ? https.request : http.request;
|
|
2814
2814
|
const protocolSet = /* @__PURE__ */ new Set();
|
|
2815
2815
|
let perMessageDeflate;
|
|
@@ -3702,12 +3702,1082 @@ var require_websocket_server = __commonJS({
|
|
|
3702
3702
|
}
|
|
3703
3703
|
});
|
|
3704
3704
|
|
|
3705
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRMode.js
|
|
3706
|
+
var require_QRMode = __commonJS({
|
|
3707
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRMode.js"(exports, module) {
|
|
3708
|
+
module.exports = {
|
|
3709
|
+
MODE_NUMBER: 1 << 0,
|
|
3710
|
+
MODE_ALPHA_NUM: 1 << 1,
|
|
3711
|
+
MODE_8BIT_BYTE: 1 << 2,
|
|
3712
|
+
MODE_KANJI: 1 << 3
|
|
3713
|
+
};
|
|
3714
|
+
}
|
|
3715
|
+
});
|
|
3716
|
+
|
|
3717
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QR8bitByte.js
|
|
3718
|
+
var require_QR8bitByte = __commonJS({
|
|
3719
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QR8bitByte.js"(exports, module) {
|
|
3720
|
+
var QRMode = require_QRMode();
|
|
3721
|
+
function QR8bitByte(data) {
|
|
3722
|
+
this.mode = QRMode.MODE_8BIT_BYTE;
|
|
3723
|
+
this.data = data;
|
|
3724
|
+
}
|
|
3725
|
+
QR8bitByte.prototype = {
|
|
3726
|
+
getLength: function() {
|
|
3727
|
+
return this.data.length;
|
|
3728
|
+
},
|
|
3729
|
+
write: function(buffer) {
|
|
3730
|
+
for (var i = 0; i < this.data.length; i++) {
|
|
3731
|
+
buffer.put(this.data.charCodeAt(i), 8);
|
|
3732
|
+
}
|
|
3733
|
+
}
|
|
3734
|
+
};
|
|
3735
|
+
module.exports = QR8bitByte;
|
|
3736
|
+
}
|
|
3737
|
+
});
|
|
3738
|
+
|
|
3739
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRMath.js
|
|
3740
|
+
var require_QRMath = __commonJS({
|
|
3741
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRMath.js"(exports, module) {
|
|
3742
|
+
var QRMath = {
|
|
3743
|
+
glog: function(n) {
|
|
3744
|
+
if (n < 1) {
|
|
3745
|
+
throw new Error("glog(" + n + ")");
|
|
3746
|
+
}
|
|
3747
|
+
return QRMath.LOG_TABLE[n];
|
|
3748
|
+
},
|
|
3749
|
+
gexp: function(n) {
|
|
3750
|
+
while (n < 0) {
|
|
3751
|
+
n += 255;
|
|
3752
|
+
}
|
|
3753
|
+
while (n >= 256) {
|
|
3754
|
+
n -= 255;
|
|
3755
|
+
}
|
|
3756
|
+
return QRMath.EXP_TABLE[n];
|
|
3757
|
+
},
|
|
3758
|
+
EXP_TABLE: new Array(256),
|
|
3759
|
+
LOG_TABLE: new Array(256)
|
|
3760
|
+
};
|
|
3761
|
+
for (i = 0; i < 8; i++) {
|
|
3762
|
+
QRMath.EXP_TABLE[i] = 1 << i;
|
|
3763
|
+
}
|
|
3764
|
+
var i;
|
|
3765
|
+
for (i = 8; i < 256; i++) {
|
|
3766
|
+
QRMath.EXP_TABLE[i] = QRMath.EXP_TABLE[i - 4] ^ QRMath.EXP_TABLE[i - 5] ^ QRMath.EXP_TABLE[i - 6] ^ QRMath.EXP_TABLE[i - 8];
|
|
3767
|
+
}
|
|
3768
|
+
var i;
|
|
3769
|
+
for (i = 0; i < 255; i++) {
|
|
3770
|
+
QRMath.LOG_TABLE[QRMath.EXP_TABLE[i]] = i;
|
|
3771
|
+
}
|
|
3772
|
+
var i;
|
|
3773
|
+
module.exports = QRMath;
|
|
3774
|
+
}
|
|
3775
|
+
});
|
|
3776
|
+
|
|
3777
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRPolynomial.js
|
|
3778
|
+
var require_QRPolynomial = __commonJS({
|
|
3779
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRPolynomial.js"(exports, module) {
|
|
3780
|
+
var QRMath = require_QRMath();
|
|
3781
|
+
function QRPolynomial(num, shift) {
|
|
3782
|
+
if (num.length === void 0) {
|
|
3783
|
+
throw new Error(num.length + "/" + shift);
|
|
3784
|
+
}
|
|
3785
|
+
var offset = 0;
|
|
3786
|
+
while (offset < num.length && num[offset] === 0) {
|
|
3787
|
+
offset++;
|
|
3788
|
+
}
|
|
3789
|
+
this.num = new Array(num.length - offset + shift);
|
|
3790
|
+
for (var i = 0; i < num.length - offset; i++) {
|
|
3791
|
+
this.num[i] = num[i + offset];
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
QRPolynomial.prototype = {
|
|
3795
|
+
get: function(index) {
|
|
3796
|
+
return this.num[index];
|
|
3797
|
+
},
|
|
3798
|
+
getLength: function() {
|
|
3799
|
+
return this.num.length;
|
|
3800
|
+
},
|
|
3801
|
+
multiply: function(e) {
|
|
3802
|
+
var num = new Array(this.getLength() + e.getLength() - 1);
|
|
3803
|
+
for (var i = 0; i < this.getLength(); i++) {
|
|
3804
|
+
for (var j = 0; j < e.getLength(); j++) {
|
|
3805
|
+
num[i + j] ^= QRMath.gexp(QRMath.glog(this.get(i)) + QRMath.glog(e.get(j)));
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
return new QRPolynomial(num, 0);
|
|
3809
|
+
},
|
|
3810
|
+
mod: function(e) {
|
|
3811
|
+
if (this.getLength() - e.getLength() < 0) {
|
|
3812
|
+
return this;
|
|
3813
|
+
}
|
|
3814
|
+
var ratio = QRMath.glog(this.get(0)) - QRMath.glog(e.get(0));
|
|
3815
|
+
var num = new Array(this.getLength());
|
|
3816
|
+
for (var i = 0; i < this.getLength(); i++) {
|
|
3817
|
+
num[i] = this.get(i);
|
|
3818
|
+
}
|
|
3819
|
+
for (var x = 0; x < e.getLength(); x++) {
|
|
3820
|
+
num[x] ^= QRMath.gexp(QRMath.glog(e.get(x)) + ratio);
|
|
3821
|
+
}
|
|
3822
|
+
return new QRPolynomial(num, 0).mod(e);
|
|
3823
|
+
}
|
|
3824
|
+
};
|
|
3825
|
+
module.exports = QRPolynomial;
|
|
3826
|
+
}
|
|
3827
|
+
});
|
|
3828
|
+
|
|
3829
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRMaskPattern.js
|
|
3830
|
+
var require_QRMaskPattern = __commonJS({
|
|
3831
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRMaskPattern.js"(exports, module) {
|
|
3832
|
+
module.exports = {
|
|
3833
|
+
PATTERN000: 0,
|
|
3834
|
+
PATTERN001: 1,
|
|
3835
|
+
PATTERN010: 2,
|
|
3836
|
+
PATTERN011: 3,
|
|
3837
|
+
PATTERN100: 4,
|
|
3838
|
+
PATTERN101: 5,
|
|
3839
|
+
PATTERN110: 6,
|
|
3840
|
+
PATTERN111: 7
|
|
3841
|
+
};
|
|
3842
|
+
}
|
|
3843
|
+
});
|
|
3844
|
+
|
|
3845
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRUtil.js
|
|
3846
|
+
var require_QRUtil = __commonJS({
|
|
3847
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRUtil.js"(exports, module) {
|
|
3848
|
+
var QRMode = require_QRMode();
|
|
3849
|
+
var QRPolynomial = require_QRPolynomial();
|
|
3850
|
+
var QRMath = require_QRMath();
|
|
3851
|
+
var QRMaskPattern = require_QRMaskPattern();
|
|
3852
|
+
var QRUtil = {
|
|
3853
|
+
PATTERN_POSITION_TABLE: [
|
|
3854
|
+
[],
|
|
3855
|
+
[6, 18],
|
|
3856
|
+
[6, 22],
|
|
3857
|
+
[6, 26],
|
|
3858
|
+
[6, 30],
|
|
3859
|
+
[6, 34],
|
|
3860
|
+
[6, 22, 38],
|
|
3861
|
+
[6, 24, 42],
|
|
3862
|
+
[6, 26, 46],
|
|
3863
|
+
[6, 28, 50],
|
|
3864
|
+
[6, 30, 54],
|
|
3865
|
+
[6, 32, 58],
|
|
3866
|
+
[6, 34, 62],
|
|
3867
|
+
[6, 26, 46, 66],
|
|
3868
|
+
[6, 26, 48, 70],
|
|
3869
|
+
[6, 26, 50, 74],
|
|
3870
|
+
[6, 30, 54, 78],
|
|
3871
|
+
[6, 30, 56, 82],
|
|
3872
|
+
[6, 30, 58, 86],
|
|
3873
|
+
[6, 34, 62, 90],
|
|
3874
|
+
[6, 28, 50, 72, 94],
|
|
3875
|
+
[6, 26, 50, 74, 98],
|
|
3876
|
+
[6, 30, 54, 78, 102],
|
|
3877
|
+
[6, 28, 54, 80, 106],
|
|
3878
|
+
[6, 32, 58, 84, 110],
|
|
3879
|
+
[6, 30, 58, 86, 114],
|
|
3880
|
+
[6, 34, 62, 90, 118],
|
|
3881
|
+
[6, 26, 50, 74, 98, 122],
|
|
3882
|
+
[6, 30, 54, 78, 102, 126],
|
|
3883
|
+
[6, 26, 52, 78, 104, 130],
|
|
3884
|
+
[6, 30, 56, 82, 108, 134],
|
|
3885
|
+
[6, 34, 60, 86, 112, 138],
|
|
3886
|
+
[6, 30, 58, 86, 114, 142],
|
|
3887
|
+
[6, 34, 62, 90, 118, 146],
|
|
3888
|
+
[6, 30, 54, 78, 102, 126, 150],
|
|
3889
|
+
[6, 24, 50, 76, 102, 128, 154],
|
|
3890
|
+
[6, 28, 54, 80, 106, 132, 158],
|
|
3891
|
+
[6, 32, 58, 84, 110, 136, 162],
|
|
3892
|
+
[6, 26, 54, 82, 110, 138, 166],
|
|
3893
|
+
[6, 30, 58, 86, 114, 142, 170]
|
|
3894
|
+
],
|
|
3895
|
+
G15: 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0,
|
|
3896
|
+
G18: 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0,
|
|
3897
|
+
G15_MASK: 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1,
|
|
3898
|
+
getBCHTypeInfo: function(data) {
|
|
3899
|
+
var d = data << 10;
|
|
3900
|
+
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15) >= 0) {
|
|
3901
|
+
d ^= QRUtil.G15 << QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G15);
|
|
3902
|
+
}
|
|
3903
|
+
return (data << 10 | d) ^ QRUtil.G15_MASK;
|
|
3904
|
+
},
|
|
3905
|
+
getBCHTypeNumber: function(data) {
|
|
3906
|
+
var d = data << 12;
|
|
3907
|
+
while (QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18) >= 0) {
|
|
3908
|
+
d ^= QRUtil.G18 << QRUtil.getBCHDigit(d) - QRUtil.getBCHDigit(QRUtil.G18);
|
|
3909
|
+
}
|
|
3910
|
+
return data << 12 | d;
|
|
3911
|
+
},
|
|
3912
|
+
getBCHDigit: function(data) {
|
|
3913
|
+
var digit = 0;
|
|
3914
|
+
while (data !== 0) {
|
|
3915
|
+
digit++;
|
|
3916
|
+
data >>>= 1;
|
|
3917
|
+
}
|
|
3918
|
+
return digit;
|
|
3919
|
+
},
|
|
3920
|
+
getPatternPosition: function(typeNumber) {
|
|
3921
|
+
return QRUtil.PATTERN_POSITION_TABLE[typeNumber - 1];
|
|
3922
|
+
},
|
|
3923
|
+
getMask: function(maskPattern, i, j) {
|
|
3924
|
+
switch (maskPattern) {
|
|
3925
|
+
case QRMaskPattern.PATTERN000:
|
|
3926
|
+
return (i + j) % 2 === 0;
|
|
3927
|
+
case QRMaskPattern.PATTERN001:
|
|
3928
|
+
return i % 2 === 0;
|
|
3929
|
+
case QRMaskPattern.PATTERN010:
|
|
3930
|
+
return j % 3 === 0;
|
|
3931
|
+
case QRMaskPattern.PATTERN011:
|
|
3932
|
+
return (i + j) % 3 === 0;
|
|
3933
|
+
case QRMaskPattern.PATTERN100:
|
|
3934
|
+
return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0;
|
|
3935
|
+
case QRMaskPattern.PATTERN101:
|
|
3936
|
+
return i * j % 2 + i * j % 3 === 0;
|
|
3937
|
+
case QRMaskPattern.PATTERN110:
|
|
3938
|
+
return (i * j % 2 + i * j % 3) % 2 === 0;
|
|
3939
|
+
case QRMaskPattern.PATTERN111:
|
|
3940
|
+
return (i * j % 3 + (i + j) % 2) % 2 === 0;
|
|
3941
|
+
default:
|
|
3942
|
+
throw new Error("bad maskPattern:" + maskPattern);
|
|
3943
|
+
}
|
|
3944
|
+
},
|
|
3945
|
+
getErrorCorrectPolynomial: function(errorCorrectLength) {
|
|
3946
|
+
var a = new QRPolynomial([1], 0);
|
|
3947
|
+
for (var i = 0; i < errorCorrectLength; i++) {
|
|
3948
|
+
a = a.multiply(new QRPolynomial([1, QRMath.gexp(i)], 0));
|
|
3949
|
+
}
|
|
3950
|
+
return a;
|
|
3951
|
+
},
|
|
3952
|
+
getLengthInBits: function(mode, type) {
|
|
3953
|
+
if (1 <= type && type < 10) {
|
|
3954
|
+
switch (mode) {
|
|
3955
|
+
case QRMode.MODE_NUMBER:
|
|
3956
|
+
return 10;
|
|
3957
|
+
case QRMode.MODE_ALPHA_NUM:
|
|
3958
|
+
return 9;
|
|
3959
|
+
case QRMode.MODE_8BIT_BYTE:
|
|
3960
|
+
return 8;
|
|
3961
|
+
case QRMode.MODE_KANJI:
|
|
3962
|
+
return 8;
|
|
3963
|
+
default:
|
|
3964
|
+
throw new Error("mode:" + mode);
|
|
3965
|
+
}
|
|
3966
|
+
} else if (type < 27) {
|
|
3967
|
+
switch (mode) {
|
|
3968
|
+
case QRMode.MODE_NUMBER:
|
|
3969
|
+
return 12;
|
|
3970
|
+
case QRMode.MODE_ALPHA_NUM:
|
|
3971
|
+
return 11;
|
|
3972
|
+
case QRMode.MODE_8BIT_BYTE:
|
|
3973
|
+
return 16;
|
|
3974
|
+
case QRMode.MODE_KANJI:
|
|
3975
|
+
return 10;
|
|
3976
|
+
default:
|
|
3977
|
+
throw new Error("mode:" + mode);
|
|
3978
|
+
}
|
|
3979
|
+
} else if (type < 41) {
|
|
3980
|
+
switch (mode) {
|
|
3981
|
+
case QRMode.MODE_NUMBER:
|
|
3982
|
+
return 14;
|
|
3983
|
+
case QRMode.MODE_ALPHA_NUM:
|
|
3984
|
+
return 13;
|
|
3985
|
+
case QRMode.MODE_8BIT_BYTE:
|
|
3986
|
+
return 16;
|
|
3987
|
+
case QRMode.MODE_KANJI:
|
|
3988
|
+
return 12;
|
|
3989
|
+
default:
|
|
3990
|
+
throw new Error("mode:" + mode);
|
|
3991
|
+
}
|
|
3992
|
+
} else {
|
|
3993
|
+
throw new Error("type:" + type);
|
|
3994
|
+
}
|
|
3995
|
+
},
|
|
3996
|
+
getLostPoint: function(qrCode) {
|
|
3997
|
+
var moduleCount = qrCode.getModuleCount();
|
|
3998
|
+
var lostPoint = 0;
|
|
3999
|
+
var row = 0;
|
|
4000
|
+
var col = 0;
|
|
4001
|
+
for (row = 0; row < moduleCount; row++) {
|
|
4002
|
+
for (col = 0; col < moduleCount; col++) {
|
|
4003
|
+
var sameCount = 0;
|
|
4004
|
+
var dark = qrCode.isDark(row, col);
|
|
4005
|
+
for (var r = -1; r <= 1; r++) {
|
|
4006
|
+
if (row + r < 0 || moduleCount <= row + r) {
|
|
4007
|
+
continue;
|
|
4008
|
+
}
|
|
4009
|
+
for (var c = -1; c <= 1; c++) {
|
|
4010
|
+
if (col + c < 0 || moduleCount <= col + c) {
|
|
4011
|
+
continue;
|
|
4012
|
+
}
|
|
4013
|
+
if (r === 0 && c === 0) {
|
|
4014
|
+
continue;
|
|
4015
|
+
}
|
|
4016
|
+
if (dark === qrCode.isDark(row + r, col + c)) {
|
|
4017
|
+
sameCount++;
|
|
4018
|
+
}
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
if (sameCount > 5) {
|
|
4022
|
+
lostPoint += 3 + sameCount - 5;
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
}
|
|
4026
|
+
for (row = 0; row < moduleCount - 1; row++) {
|
|
4027
|
+
for (col = 0; col < moduleCount - 1; col++) {
|
|
4028
|
+
var count = 0;
|
|
4029
|
+
if (qrCode.isDark(row, col)) count++;
|
|
4030
|
+
if (qrCode.isDark(row + 1, col)) count++;
|
|
4031
|
+
if (qrCode.isDark(row, col + 1)) count++;
|
|
4032
|
+
if (qrCode.isDark(row + 1, col + 1)) count++;
|
|
4033
|
+
if (count === 0 || count === 4) {
|
|
4034
|
+
lostPoint += 3;
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
}
|
|
4038
|
+
for (row = 0; row < moduleCount; row++) {
|
|
4039
|
+
for (col = 0; col < moduleCount - 6; col++) {
|
|
4040
|
+
if (qrCode.isDark(row, col) && !qrCode.isDark(row, col + 1) && qrCode.isDark(row, col + 2) && qrCode.isDark(row, col + 3) && qrCode.isDark(row, col + 4) && !qrCode.isDark(row, col + 5) && qrCode.isDark(row, col + 6)) {
|
|
4041
|
+
lostPoint += 40;
|
|
4042
|
+
}
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
for (col = 0; col < moduleCount; col++) {
|
|
4046
|
+
for (row = 0; row < moduleCount - 6; row++) {
|
|
4047
|
+
if (qrCode.isDark(row, col) && !qrCode.isDark(row + 1, col) && qrCode.isDark(row + 2, col) && qrCode.isDark(row + 3, col) && qrCode.isDark(row + 4, col) && !qrCode.isDark(row + 5, col) && qrCode.isDark(row + 6, col)) {
|
|
4048
|
+
lostPoint += 40;
|
|
4049
|
+
}
|
|
4050
|
+
}
|
|
4051
|
+
}
|
|
4052
|
+
var darkCount = 0;
|
|
4053
|
+
for (col = 0; col < moduleCount; col++) {
|
|
4054
|
+
for (row = 0; row < moduleCount; row++) {
|
|
4055
|
+
if (qrCode.isDark(row, col)) {
|
|
4056
|
+
darkCount++;
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
}
|
|
4060
|
+
var ratio = Math.abs(100 * darkCount / moduleCount / moduleCount - 50) / 5;
|
|
4061
|
+
lostPoint += ratio * 10;
|
|
4062
|
+
return lostPoint;
|
|
4063
|
+
}
|
|
4064
|
+
};
|
|
4065
|
+
module.exports = QRUtil;
|
|
4066
|
+
}
|
|
4067
|
+
});
|
|
4068
|
+
|
|
4069
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js
|
|
4070
|
+
var require_QRErrorCorrectLevel = __commonJS({
|
|
4071
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRErrorCorrectLevel.js"(exports, module) {
|
|
4072
|
+
module.exports = {
|
|
4073
|
+
L: 1,
|
|
4074
|
+
M: 0,
|
|
4075
|
+
Q: 3,
|
|
4076
|
+
H: 2
|
|
4077
|
+
};
|
|
4078
|
+
}
|
|
4079
|
+
});
|
|
4080
|
+
|
|
4081
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRRSBlock.js
|
|
4082
|
+
var require_QRRSBlock = __commonJS({
|
|
4083
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRRSBlock.js"(exports, module) {
|
|
4084
|
+
var QRErrorCorrectLevel = require_QRErrorCorrectLevel();
|
|
4085
|
+
function QRRSBlock(totalCount, dataCount) {
|
|
4086
|
+
this.totalCount = totalCount;
|
|
4087
|
+
this.dataCount = dataCount;
|
|
4088
|
+
}
|
|
4089
|
+
QRRSBlock.RS_BLOCK_TABLE = [
|
|
4090
|
+
// L
|
|
4091
|
+
// M
|
|
4092
|
+
// Q
|
|
4093
|
+
// H
|
|
4094
|
+
// 1
|
|
4095
|
+
[1, 26, 19],
|
|
4096
|
+
[1, 26, 16],
|
|
4097
|
+
[1, 26, 13],
|
|
4098
|
+
[1, 26, 9],
|
|
4099
|
+
// 2
|
|
4100
|
+
[1, 44, 34],
|
|
4101
|
+
[1, 44, 28],
|
|
4102
|
+
[1, 44, 22],
|
|
4103
|
+
[1, 44, 16],
|
|
4104
|
+
// 3
|
|
4105
|
+
[1, 70, 55],
|
|
4106
|
+
[1, 70, 44],
|
|
4107
|
+
[2, 35, 17],
|
|
4108
|
+
[2, 35, 13],
|
|
4109
|
+
// 4
|
|
4110
|
+
[1, 100, 80],
|
|
4111
|
+
[2, 50, 32],
|
|
4112
|
+
[2, 50, 24],
|
|
4113
|
+
[4, 25, 9],
|
|
4114
|
+
// 5
|
|
4115
|
+
[1, 134, 108],
|
|
4116
|
+
[2, 67, 43],
|
|
4117
|
+
[2, 33, 15, 2, 34, 16],
|
|
4118
|
+
[2, 33, 11, 2, 34, 12],
|
|
4119
|
+
// 6
|
|
4120
|
+
[2, 86, 68],
|
|
4121
|
+
[4, 43, 27],
|
|
4122
|
+
[4, 43, 19],
|
|
4123
|
+
[4, 43, 15],
|
|
4124
|
+
// 7
|
|
4125
|
+
[2, 98, 78],
|
|
4126
|
+
[4, 49, 31],
|
|
4127
|
+
[2, 32, 14, 4, 33, 15],
|
|
4128
|
+
[4, 39, 13, 1, 40, 14],
|
|
4129
|
+
// 8
|
|
4130
|
+
[2, 121, 97],
|
|
4131
|
+
[2, 60, 38, 2, 61, 39],
|
|
4132
|
+
[4, 40, 18, 2, 41, 19],
|
|
4133
|
+
[4, 40, 14, 2, 41, 15],
|
|
4134
|
+
// 9
|
|
4135
|
+
[2, 146, 116],
|
|
4136
|
+
[3, 58, 36, 2, 59, 37],
|
|
4137
|
+
[4, 36, 16, 4, 37, 17],
|
|
4138
|
+
[4, 36, 12, 4, 37, 13],
|
|
4139
|
+
// 10
|
|
4140
|
+
[2, 86, 68, 2, 87, 69],
|
|
4141
|
+
[4, 69, 43, 1, 70, 44],
|
|
4142
|
+
[6, 43, 19, 2, 44, 20],
|
|
4143
|
+
[6, 43, 15, 2, 44, 16],
|
|
4144
|
+
// 11
|
|
4145
|
+
[4, 101, 81],
|
|
4146
|
+
[1, 80, 50, 4, 81, 51],
|
|
4147
|
+
[4, 50, 22, 4, 51, 23],
|
|
4148
|
+
[3, 36, 12, 8, 37, 13],
|
|
4149
|
+
// 12
|
|
4150
|
+
[2, 116, 92, 2, 117, 93],
|
|
4151
|
+
[6, 58, 36, 2, 59, 37],
|
|
4152
|
+
[4, 46, 20, 6, 47, 21],
|
|
4153
|
+
[7, 42, 14, 4, 43, 15],
|
|
4154
|
+
// 13
|
|
4155
|
+
[4, 133, 107],
|
|
4156
|
+
[8, 59, 37, 1, 60, 38],
|
|
4157
|
+
[8, 44, 20, 4, 45, 21],
|
|
4158
|
+
[12, 33, 11, 4, 34, 12],
|
|
4159
|
+
// 14
|
|
4160
|
+
[3, 145, 115, 1, 146, 116],
|
|
4161
|
+
[4, 64, 40, 5, 65, 41],
|
|
4162
|
+
[11, 36, 16, 5, 37, 17],
|
|
4163
|
+
[11, 36, 12, 5, 37, 13],
|
|
4164
|
+
// 15
|
|
4165
|
+
[5, 109, 87, 1, 110, 88],
|
|
4166
|
+
[5, 65, 41, 5, 66, 42],
|
|
4167
|
+
[5, 54, 24, 7, 55, 25],
|
|
4168
|
+
[11, 36, 12],
|
|
4169
|
+
// 16
|
|
4170
|
+
[5, 122, 98, 1, 123, 99],
|
|
4171
|
+
[7, 73, 45, 3, 74, 46],
|
|
4172
|
+
[15, 43, 19, 2, 44, 20],
|
|
4173
|
+
[3, 45, 15, 13, 46, 16],
|
|
4174
|
+
// 17
|
|
4175
|
+
[1, 135, 107, 5, 136, 108],
|
|
4176
|
+
[10, 74, 46, 1, 75, 47],
|
|
4177
|
+
[1, 50, 22, 15, 51, 23],
|
|
4178
|
+
[2, 42, 14, 17, 43, 15],
|
|
4179
|
+
// 18
|
|
4180
|
+
[5, 150, 120, 1, 151, 121],
|
|
4181
|
+
[9, 69, 43, 4, 70, 44],
|
|
4182
|
+
[17, 50, 22, 1, 51, 23],
|
|
4183
|
+
[2, 42, 14, 19, 43, 15],
|
|
4184
|
+
// 19
|
|
4185
|
+
[3, 141, 113, 4, 142, 114],
|
|
4186
|
+
[3, 70, 44, 11, 71, 45],
|
|
4187
|
+
[17, 47, 21, 4, 48, 22],
|
|
4188
|
+
[9, 39, 13, 16, 40, 14],
|
|
4189
|
+
// 20
|
|
4190
|
+
[3, 135, 107, 5, 136, 108],
|
|
4191
|
+
[3, 67, 41, 13, 68, 42],
|
|
4192
|
+
[15, 54, 24, 5, 55, 25],
|
|
4193
|
+
[15, 43, 15, 10, 44, 16],
|
|
4194
|
+
// 21
|
|
4195
|
+
[4, 144, 116, 4, 145, 117],
|
|
4196
|
+
[17, 68, 42],
|
|
4197
|
+
[17, 50, 22, 6, 51, 23],
|
|
4198
|
+
[19, 46, 16, 6, 47, 17],
|
|
4199
|
+
// 22
|
|
4200
|
+
[2, 139, 111, 7, 140, 112],
|
|
4201
|
+
[17, 74, 46],
|
|
4202
|
+
[7, 54, 24, 16, 55, 25],
|
|
4203
|
+
[34, 37, 13],
|
|
4204
|
+
// 23
|
|
4205
|
+
[4, 151, 121, 5, 152, 122],
|
|
4206
|
+
[4, 75, 47, 14, 76, 48],
|
|
4207
|
+
[11, 54, 24, 14, 55, 25],
|
|
4208
|
+
[16, 45, 15, 14, 46, 16],
|
|
4209
|
+
// 24
|
|
4210
|
+
[6, 147, 117, 4, 148, 118],
|
|
4211
|
+
[6, 73, 45, 14, 74, 46],
|
|
4212
|
+
[11, 54, 24, 16, 55, 25],
|
|
4213
|
+
[30, 46, 16, 2, 47, 17],
|
|
4214
|
+
// 25
|
|
4215
|
+
[8, 132, 106, 4, 133, 107],
|
|
4216
|
+
[8, 75, 47, 13, 76, 48],
|
|
4217
|
+
[7, 54, 24, 22, 55, 25],
|
|
4218
|
+
[22, 45, 15, 13, 46, 16],
|
|
4219
|
+
// 26
|
|
4220
|
+
[10, 142, 114, 2, 143, 115],
|
|
4221
|
+
[19, 74, 46, 4, 75, 47],
|
|
4222
|
+
[28, 50, 22, 6, 51, 23],
|
|
4223
|
+
[33, 46, 16, 4, 47, 17],
|
|
4224
|
+
// 27
|
|
4225
|
+
[8, 152, 122, 4, 153, 123],
|
|
4226
|
+
[22, 73, 45, 3, 74, 46],
|
|
4227
|
+
[8, 53, 23, 26, 54, 24],
|
|
4228
|
+
[12, 45, 15, 28, 46, 16],
|
|
4229
|
+
// 28
|
|
4230
|
+
[3, 147, 117, 10, 148, 118],
|
|
4231
|
+
[3, 73, 45, 23, 74, 46],
|
|
4232
|
+
[4, 54, 24, 31, 55, 25],
|
|
4233
|
+
[11, 45, 15, 31, 46, 16],
|
|
4234
|
+
// 29
|
|
4235
|
+
[7, 146, 116, 7, 147, 117],
|
|
4236
|
+
[21, 73, 45, 7, 74, 46],
|
|
4237
|
+
[1, 53, 23, 37, 54, 24],
|
|
4238
|
+
[19, 45, 15, 26, 46, 16],
|
|
4239
|
+
// 30
|
|
4240
|
+
[5, 145, 115, 10, 146, 116],
|
|
4241
|
+
[19, 75, 47, 10, 76, 48],
|
|
4242
|
+
[15, 54, 24, 25, 55, 25],
|
|
4243
|
+
[23, 45, 15, 25, 46, 16],
|
|
4244
|
+
// 31
|
|
4245
|
+
[13, 145, 115, 3, 146, 116],
|
|
4246
|
+
[2, 74, 46, 29, 75, 47],
|
|
4247
|
+
[42, 54, 24, 1, 55, 25],
|
|
4248
|
+
[23, 45, 15, 28, 46, 16],
|
|
4249
|
+
// 32
|
|
4250
|
+
[17, 145, 115],
|
|
4251
|
+
[10, 74, 46, 23, 75, 47],
|
|
4252
|
+
[10, 54, 24, 35, 55, 25],
|
|
4253
|
+
[19, 45, 15, 35, 46, 16],
|
|
4254
|
+
// 33
|
|
4255
|
+
[17, 145, 115, 1, 146, 116],
|
|
4256
|
+
[14, 74, 46, 21, 75, 47],
|
|
4257
|
+
[29, 54, 24, 19, 55, 25],
|
|
4258
|
+
[11, 45, 15, 46, 46, 16],
|
|
4259
|
+
// 34
|
|
4260
|
+
[13, 145, 115, 6, 146, 116],
|
|
4261
|
+
[14, 74, 46, 23, 75, 47],
|
|
4262
|
+
[44, 54, 24, 7, 55, 25],
|
|
4263
|
+
[59, 46, 16, 1, 47, 17],
|
|
4264
|
+
// 35
|
|
4265
|
+
[12, 151, 121, 7, 152, 122],
|
|
4266
|
+
[12, 75, 47, 26, 76, 48],
|
|
4267
|
+
[39, 54, 24, 14, 55, 25],
|
|
4268
|
+
[22, 45, 15, 41, 46, 16],
|
|
4269
|
+
// 36
|
|
4270
|
+
[6, 151, 121, 14, 152, 122],
|
|
4271
|
+
[6, 75, 47, 34, 76, 48],
|
|
4272
|
+
[46, 54, 24, 10, 55, 25],
|
|
4273
|
+
[2, 45, 15, 64, 46, 16],
|
|
4274
|
+
// 37
|
|
4275
|
+
[17, 152, 122, 4, 153, 123],
|
|
4276
|
+
[29, 74, 46, 14, 75, 47],
|
|
4277
|
+
[49, 54, 24, 10, 55, 25],
|
|
4278
|
+
[24, 45, 15, 46, 46, 16],
|
|
4279
|
+
// 38
|
|
4280
|
+
[4, 152, 122, 18, 153, 123],
|
|
4281
|
+
[13, 74, 46, 32, 75, 47],
|
|
4282
|
+
[48, 54, 24, 14, 55, 25],
|
|
4283
|
+
[42, 45, 15, 32, 46, 16],
|
|
4284
|
+
// 39
|
|
4285
|
+
[20, 147, 117, 4, 148, 118],
|
|
4286
|
+
[40, 75, 47, 7, 76, 48],
|
|
4287
|
+
[43, 54, 24, 22, 55, 25],
|
|
4288
|
+
[10, 45, 15, 67, 46, 16],
|
|
4289
|
+
// 40
|
|
4290
|
+
[19, 148, 118, 6, 149, 119],
|
|
4291
|
+
[18, 75, 47, 31, 76, 48],
|
|
4292
|
+
[34, 54, 24, 34, 55, 25],
|
|
4293
|
+
[20, 45, 15, 61, 46, 16]
|
|
4294
|
+
];
|
|
4295
|
+
QRRSBlock.getRSBlocks = function(typeNumber, errorCorrectLevel) {
|
|
4296
|
+
var rsBlock = QRRSBlock.getRsBlockTable(typeNumber, errorCorrectLevel);
|
|
4297
|
+
if (rsBlock === void 0) {
|
|
4298
|
+
throw new Error("bad rs block @ typeNumber:" + typeNumber + "/errorCorrectLevel:" + errorCorrectLevel);
|
|
4299
|
+
}
|
|
4300
|
+
var length = rsBlock.length / 3;
|
|
4301
|
+
var list = [];
|
|
4302
|
+
for (var i = 0; i < length; i++) {
|
|
4303
|
+
var count = rsBlock[i * 3 + 0];
|
|
4304
|
+
var totalCount = rsBlock[i * 3 + 1];
|
|
4305
|
+
var dataCount = rsBlock[i * 3 + 2];
|
|
4306
|
+
for (var j = 0; j < count; j++) {
|
|
4307
|
+
list.push(new QRRSBlock(totalCount, dataCount));
|
|
4308
|
+
}
|
|
4309
|
+
}
|
|
4310
|
+
return list;
|
|
4311
|
+
};
|
|
4312
|
+
QRRSBlock.getRsBlockTable = function(typeNumber, errorCorrectLevel) {
|
|
4313
|
+
switch (errorCorrectLevel) {
|
|
4314
|
+
case QRErrorCorrectLevel.L:
|
|
4315
|
+
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 0];
|
|
4316
|
+
case QRErrorCorrectLevel.M:
|
|
4317
|
+
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 1];
|
|
4318
|
+
case QRErrorCorrectLevel.Q:
|
|
4319
|
+
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 2];
|
|
4320
|
+
case QRErrorCorrectLevel.H:
|
|
4321
|
+
return QRRSBlock.RS_BLOCK_TABLE[(typeNumber - 1) * 4 + 3];
|
|
4322
|
+
default:
|
|
4323
|
+
return void 0;
|
|
4324
|
+
}
|
|
4325
|
+
};
|
|
4326
|
+
module.exports = QRRSBlock;
|
|
4327
|
+
}
|
|
4328
|
+
});
|
|
4329
|
+
|
|
4330
|
+
// node_modules/qrcode-terminal/vendor/QRCode/QRBitBuffer.js
|
|
4331
|
+
var require_QRBitBuffer = __commonJS({
|
|
4332
|
+
"node_modules/qrcode-terminal/vendor/QRCode/QRBitBuffer.js"(exports, module) {
|
|
4333
|
+
function QRBitBuffer() {
|
|
4334
|
+
this.buffer = [];
|
|
4335
|
+
this.length = 0;
|
|
4336
|
+
}
|
|
4337
|
+
QRBitBuffer.prototype = {
|
|
4338
|
+
get: function(index) {
|
|
4339
|
+
var bufIndex = Math.floor(index / 8);
|
|
4340
|
+
return (this.buffer[bufIndex] >>> 7 - index % 8 & 1) == 1;
|
|
4341
|
+
},
|
|
4342
|
+
put: function(num, length) {
|
|
4343
|
+
for (var i = 0; i < length; i++) {
|
|
4344
|
+
this.putBit((num >>> length - i - 1 & 1) == 1);
|
|
4345
|
+
}
|
|
4346
|
+
},
|
|
4347
|
+
getLengthInBits: function() {
|
|
4348
|
+
return this.length;
|
|
4349
|
+
},
|
|
4350
|
+
putBit: function(bit) {
|
|
4351
|
+
var bufIndex = Math.floor(this.length / 8);
|
|
4352
|
+
if (this.buffer.length <= bufIndex) {
|
|
4353
|
+
this.buffer.push(0);
|
|
4354
|
+
}
|
|
4355
|
+
if (bit) {
|
|
4356
|
+
this.buffer[bufIndex] |= 128 >>> this.length % 8;
|
|
4357
|
+
}
|
|
4358
|
+
this.length++;
|
|
4359
|
+
}
|
|
4360
|
+
};
|
|
4361
|
+
module.exports = QRBitBuffer;
|
|
4362
|
+
}
|
|
4363
|
+
});
|
|
4364
|
+
|
|
4365
|
+
// node_modules/qrcode-terminal/vendor/QRCode/index.js
|
|
4366
|
+
var require_QRCode = __commonJS({
|
|
4367
|
+
"node_modules/qrcode-terminal/vendor/QRCode/index.js"(exports, module) {
|
|
4368
|
+
var QR8bitByte = require_QR8bitByte();
|
|
4369
|
+
var QRUtil = require_QRUtil();
|
|
4370
|
+
var QRPolynomial = require_QRPolynomial();
|
|
4371
|
+
var QRRSBlock = require_QRRSBlock();
|
|
4372
|
+
var QRBitBuffer = require_QRBitBuffer();
|
|
4373
|
+
function QRCode(typeNumber, errorCorrectLevel) {
|
|
4374
|
+
this.typeNumber = typeNumber;
|
|
4375
|
+
this.errorCorrectLevel = errorCorrectLevel;
|
|
4376
|
+
this.modules = null;
|
|
4377
|
+
this.moduleCount = 0;
|
|
4378
|
+
this.dataCache = null;
|
|
4379
|
+
this.dataList = [];
|
|
4380
|
+
}
|
|
4381
|
+
QRCode.prototype = {
|
|
4382
|
+
addData: function(data) {
|
|
4383
|
+
var newData = new QR8bitByte(data);
|
|
4384
|
+
this.dataList.push(newData);
|
|
4385
|
+
this.dataCache = null;
|
|
4386
|
+
},
|
|
4387
|
+
isDark: function(row, col) {
|
|
4388
|
+
if (row < 0 || this.moduleCount <= row || col < 0 || this.moduleCount <= col) {
|
|
4389
|
+
throw new Error(row + "," + col);
|
|
4390
|
+
}
|
|
4391
|
+
return this.modules[row][col];
|
|
4392
|
+
},
|
|
4393
|
+
getModuleCount: function() {
|
|
4394
|
+
return this.moduleCount;
|
|
4395
|
+
},
|
|
4396
|
+
make: function() {
|
|
4397
|
+
if (this.typeNumber < 1) {
|
|
4398
|
+
var typeNumber = 1;
|
|
4399
|
+
for (typeNumber = 1; typeNumber < 40; typeNumber++) {
|
|
4400
|
+
var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, this.errorCorrectLevel);
|
|
4401
|
+
var buffer = new QRBitBuffer();
|
|
4402
|
+
var totalDataCount = 0;
|
|
4403
|
+
for (var i = 0; i < rsBlocks.length; i++) {
|
|
4404
|
+
totalDataCount += rsBlocks[i].dataCount;
|
|
4405
|
+
}
|
|
4406
|
+
for (var x = 0; x < this.dataList.length; x++) {
|
|
4407
|
+
var data = this.dataList[x];
|
|
4408
|
+
buffer.put(data.mode, 4);
|
|
4409
|
+
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
|
|
4410
|
+
data.write(buffer);
|
|
4411
|
+
}
|
|
4412
|
+
if (buffer.getLengthInBits() <= totalDataCount * 8)
|
|
4413
|
+
break;
|
|
4414
|
+
}
|
|
4415
|
+
this.typeNumber = typeNumber;
|
|
4416
|
+
}
|
|
4417
|
+
this.makeImpl(false, this.getBestMaskPattern());
|
|
4418
|
+
},
|
|
4419
|
+
makeImpl: function(test, maskPattern) {
|
|
4420
|
+
this.moduleCount = this.typeNumber * 4 + 17;
|
|
4421
|
+
this.modules = new Array(this.moduleCount);
|
|
4422
|
+
for (var row = 0; row < this.moduleCount; row++) {
|
|
4423
|
+
this.modules[row] = new Array(this.moduleCount);
|
|
4424
|
+
for (var col = 0; col < this.moduleCount; col++) {
|
|
4425
|
+
this.modules[row][col] = null;
|
|
4426
|
+
}
|
|
4427
|
+
}
|
|
4428
|
+
this.setupPositionProbePattern(0, 0);
|
|
4429
|
+
this.setupPositionProbePattern(this.moduleCount - 7, 0);
|
|
4430
|
+
this.setupPositionProbePattern(0, this.moduleCount - 7);
|
|
4431
|
+
this.setupPositionAdjustPattern();
|
|
4432
|
+
this.setupTimingPattern();
|
|
4433
|
+
this.setupTypeInfo(test, maskPattern);
|
|
4434
|
+
if (this.typeNumber >= 7) {
|
|
4435
|
+
this.setupTypeNumber(test);
|
|
4436
|
+
}
|
|
4437
|
+
if (this.dataCache === null) {
|
|
4438
|
+
this.dataCache = QRCode.createData(this.typeNumber, this.errorCorrectLevel, this.dataList);
|
|
4439
|
+
}
|
|
4440
|
+
this.mapData(this.dataCache, maskPattern);
|
|
4441
|
+
},
|
|
4442
|
+
setupPositionProbePattern: function(row, col) {
|
|
4443
|
+
for (var r = -1; r <= 7; r++) {
|
|
4444
|
+
if (row + r <= -1 || this.moduleCount <= row + r) continue;
|
|
4445
|
+
for (var c = -1; c <= 7; c++) {
|
|
4446
|
+
if (col + c <= -1 || this.moduleCount <= col + c) continue;
|
|
4447
|
+
if (0 <= r && r <= 6 && (c === 0 || c === 6) || 0 <= c && c <= 6 && (r === 0 || r === 6) || 2 <= r && r <= 4 && 2 <= c && c <= 4) {
|
|
4448
|
+
this.modules[row + r][col + c] = true;
|
|
4449
|
+
} else {
|
|
4450
|
+
this.modules[row + r][col + c] = false;
|
|
4451
|
+
}
|
|
4452
|
+
}
|
|
4453
|
+
}
|
|
4454
|
+
},
|
|
4455
|
+
getBestMaskPattern: function() {
|
|
4456
|
+
var minLostPoint = 0;
|
|
4457
|
+
var pattern = 0;
|
|
4458
|
+
for (var i = 0; i < 8; i++) {
|
|
4459
|
+
this.makeImpl(true, i);
|
|
4460
|
+
var lostPoint = QRUtil.getLostPoint(this);
|
|
4461
|
+
if (i === 0 || minLostPoint > lostPoint) {
|
|
4462
|
+
minLostPoint = lostPoint;
|
|
4463
|
+
pattern = i;
|
|
4464
|
+
}
|
|
4465
|
+
}
|
|
4466
|
+
return pattern;
|
|
4467
|
+
},
|
|
4468
|
+
createMovieClip: function(target_mc, instance_name, depth) {
|
|
4469
|
+
var qr_mc = target_mc.createEmptyMovieClip(instance_name, depth);
|
|
4470
|
+
var cs = 1;
|
|
4471
|
+
this.make();
|
|
4472
|
+
for (var row = 0; row < this.modules.length; row++) {
|
|
4473
|
+
var y = row * cs;
|
|
4474
|
+
for (var col = 0; col < this.modules[row].length; col++) {
|
|
4475
|
+
var x = col * cs;
|
|
4476
|
+
var dark = this.modules[row][col];
|
|
4477
|
+
if (dark) {
|
|
4478
|
+
qr_mc.beginFill(0, 100);
|
|
4479
|
+
qr_mc.moveTo(x, y);
|
|
4480
|
+
qr_mc.lineTo(x + cs, y);
|
|
4481
|
+
qr_mc.lineTo(x + cs, y + cs);
|
|
4482
|
+
qr_mc.lineTo(x, y + cs);
|
|
4483
|
+
qr_mc.endFill();
|
|
4484
|
+
}
|
|
4485
|
+
}
|
|
4486
|
+
}
|
|
4487
|
+
return qr_mc;
|
|
4488
|
+
},
|
|
4489
|
+
setupTimingPattern: function() {
|
|
4490
|
+
for (var r = 8; r < this.moduleCount - 8; r++) {
|
|
4491
|
+
if (this.modules[r][6] !== null) {
|
|
4492
|
+
continue;
|
|
4493
|
+
}
|
|
4494
|
+
this.modules[r][6] = r % 2 === 0;
|
|
4495
|
+
}
|
|
4496
|
+
for (var c = 8; c < this.moduleCount - 8; c++) {
|
|
4497
|
+
if (this.modules[6][c] !== null) {
|
|
4498
|
+
continue;
|
|
4499
|
+
}
|
|
4500
|
+
this.modules[6][c] = c % 2 === 0;
|
|
4501
|
+
}
|
|
4502
|
+
},
|
|
4503
|
+
setupPositionAdjustPattern: function() {
|
|
4504
|
+
var pos = QRUtil.getPatternPosition(this.typeNumber);
|
|
4505
|
+
for (var i = 0; i < pos.length; i++) {
|
|
4506
|
+
for (var j = 0; j < pos.length; j++) {
|
|
4507
|
+
var row = pos[i];
|
|
4508
|
+
var col = pos[j];
|
|
4509
|
+
if (this.modules[row][col] !== null) {
|
|
4510
|
+
continue;
|
|
4511
|
+
}
|
|
4512
|
+
for (var r = -2; r <= 2; r++) {
|
|
4513
|
+
for (var c = -2; c <= 2; c++) {
|
|
4514
|
+
if (Math.abs(r) === 2 || Math.abs(c) === 2 || r === 0 && c === 0) {
|
|
4515
|
+
this.modules[row + r][col + c] = true;
|
|
4516
|
+
} else {
|
|
4517
|
+
this.modules[row + r][col + c] = false;
|
|
4518
|
+
}
|
|
4519
|
+
}
|
|
4520
|
+
}
|
|
4521
|
+
}
|
|
4522
|
+
}
|
|
4523
|
+
},
|
|
4524
|
+
setupTypeNumber: function(test) {
|
|
4525
|
+
var bits = QRUtil.getBCHTypeNumber(this.typeNumber);
|
|
4526
|
+
var mod;
|
|
4527
|
+
for (var i = 0; i < 18; i++) {
|
|
4528
|
+
mod = !test && (bits >> i & 1) === 1;
|
|
4529
|
+
this.modules[Math.floor(i / 3)][i % 3 + this.moduleCount - 8 - 3] = mod;
|
|
4530
|
+
}
|
|
4531
|
+
for (var x = 0; x < 18; x++) {
|
|
4532
|
+
mod = !test && (bits >> x & 1) === 1;
|
|
4533
|
+
this.modules[x % 3 + this.moduleCount - 8 - 3][Math.floor(x / 3)] = mod;
|
|
4534
|
+
}
|
|
4535
|
+
},
|
|
4536
|
+
setupTypeInfo: function(test, maskPattern) {
|
|
4537
|
+
var data = this.errorCorrectLevel << 3 | maskPattern;
|
|
4538
|
+
var bits = QRUtil.getBCHTypeInfo(data);
|
|
4539
|
+
var mod;
|
|
4540
|
+
for (var v = 0; v < 15; v++) {
|
|
4541
|
+
mod = !test && (bits >> v & 1) === 1;
|
|
4542
|
+
if (v < 6) {
|
|
4543
|
+
this.modules[v][8] = mod;
|
|
4544
|
+
} else if (v < 8) {
|
|
4545
|
+
this.modules[v + 1][8] = mod;
|
|
4546
|
+
} else {
|
|
4547
|
+
this.modules[this.moduleCount - 15 + v][8] = mod;
|
|
4548
|
+
}
|
|
4549
|
+
}
|
|
4550
|
+
for (var h = 0; h < 15; h++) {
|
|
4551
|
+
mod = !test && (bits >> h & 1) === 1;
|
|
4552
|
+
if (h < 8) {
|
|
4553
|
+
this.modules[8][this.moduleCount - h - 1] = mod;
|
|
4554
|
+
} else if (h < 9) {
|
|
4555
|
+
this.modules[8][15 - h - 1 + 1] = mod;
|
|
4556
|
+
} else {
|
|
4557
|
+
this.modules[8][15 - h - 1] = mod;
|
|
4558
|
+
}
|
|
4559
|
+
}
|
|
4560
|
+
this.modules[this.moduleCount - 8][8] = !test;
|
|
4561
|
+
},
|
|
4562
|
+
mapData: function(data, maskPattern) {
|
|
4563
|
+
var inc = -1;
|
|
4564
|
+
var row = this.moduleCount - 1;
|
|
4565
|
+
var bitIndex = 7;
|
|
4566
|
+
var byteIndex = 0;
|
|
4567
|
+
for (var col = this.moduleCount - 1; col > 0; col -= 2) {
|
|
4568
|
+
if (col === 6) col--;
|
|
4569
|
+
while (true) {
|
|
4570
|
+
for (var c = 0; c < 2; c++) {
|
|
4571
|
+
if (this.modules[row][col - c] === null) {
|
|
4572
|
+
var dark = false;
|
|
4573
|
+
if (byteIndex < data.length) {
|
|
4574
|
+
dark = (data[byteIndex] >>> bitIndex & 1) === 1;
|
|
4575
|
+
}
|
|
4576
|
+
var mask = QRUtil.getMask(maskPattern, row, col - c);
|
|
4577
|
+
if (mask) {
|
|
4578
|
+
dark = !dark;
|
|
4579
|
+
}
|
|
4580
|
+
this.modules[row][col - c] = dark;
|
|
4581
|
+
bitIndex--;
|
|
4582
|
+
if (bitIndex === -1) {
|
|
4583
|
+
byteIndex++;
|
|
4584
|
+
bitIndex = 7;
|
|
4585
|
+
}
|
|
4586
|
+
}
|
|
4587
|
+
}
|
|
4588
|
+
row += inc;
|
|
4589
|
+
if (row < 0 || this.moduleCount <= row) {
|
|
4590
|
+
row -= inc;
|
|
4591
|
+
inc = -inc;
|
|
4592
|
+
break;
|
|
4593
|
+
}
|
|
4594
|
+
}
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
};
|
|
4598
|
+
QRCode.PAD0 = 236;
|
|
4599
|
+
QRCode.PAD1 = 17;
|
|
4600
|
+
QRCode.createData = function(typeNumber, errorCorrectLevel, dataList) {
|
|
4601
|
+
var rsBlocks = QRRSBlock.getRSBlocks(typeNumber, errorCorrectLevel);
|
|
4602
|
+
var buffer = new QRBitBuffer();
|
|
4603
|
+
for (var i = 0; i < dataList.length; i++) {
|
|
4604
|
+
var data = dataList[i];
|
|
4605
|
+
buffer.put(data.mode, 4);
|
|
4606
|
+
buffer.put(data.getLength(), QRUtil.getLengthInBits(data.mode, typeNumber));
|
|
4607
|
+
data.write(buffer);
|
|
4608
|
+
}
|
|
4609
|
+
var totalDataCount = 0;
|
|
4610
|
+
for (var x = 0; x < rsBlocks.length; x++) {
|
|
4611
|
+
totalDataCount += rsBlocks[x].dataCount;
|
|
4612
|
+
}
|
|
4613
|
+
if (buffer.getLengthInBits() > totalDataCount * 8) {
|
|
4614
|
+
throw new Error("code length overflow. (" + buffer.getLengthInBits() + ">" + totalDataCount * 8 + ")");
|
|
4615
|
+
}
|
|
4616
|
+
if (buffer.getLengthInBits() + 4 <= totalDataCount * 8) {
|
|
4617
|
+
buffer.put(0, 4);
|
|
4618
|
+
}
|
|
4619
|
+
while (buffer.getLengthInBits() % 8 !== 0) {
|
|
4620
|
+
buffer.putBit(false);
|
|
4621
|
+
}
|
|
4622
|
+
while (true) {
|
|
4623
|
+
if (buffer.getLengthInBits() >= totalDataCount * 8) {
|
|
4624
|
+
break;
|
|
4625
|
+
}
|
|
4626
|
+
buffer.put(QRCode.PAD0, 8);
|
|
4627
|
+
if (buffer.getLengthInBits() >= totalDataCount * 8) {
|
|
4628
|
+
break;
|
|
4629
|
+
}
|
|
4630
|
+
buffer.put(QRCode.PAD1, 8);
|
|
4631
|
+
}
|
|
4632
|
+
return QRCode.createBytes(buffer, rsBlocks);
|
|
4633
|
+
};
|
|
4634
|
+
QRCode.createBytes = function(buffer, rsBlocks) {
|
|
4635
|
+
var offset = 0;
|
|
4636
|
+
var maxDcCount = 0;
|
|
4637
|
+
var maxEcCount = 0;
|
|
4638
|
+
var dcdata = new Array(rsBlocks.length);
|
|
4639
|
+
var ecdata = new Array(rsBlocks.length);
|
|
4640
|
+
for (var r = 0; r < rsBlocks.length; r++) {
|
|
4641
|
+
var dcCount = rsBlocks[r].dataCount;
|
|
4642
|
+
var ecCount = rsBlocks[r].totalCount - dcCount;
|
|
4643
|
+
maxDcCount = Math.max(maxDcCount, dcCount);
|
|
4644
|
+
maxEcCount = Math.max(maxEcCount, ecCount);
|
|
4645
|
+
dcdata[r] = new Array(dcCount);
|
|
4646
|
+
for (var i = 0; i < dcdata[r].length; i++) {
|
|
4647
|
+
dcdata[r][i] = 255 & buffer.buffer[i + offset];
|
|
4648
|
+
}
|
|
4649
|
+
offset += dcCount;
|
|
4650
|
+
var rsPoly = QRUtil.getErrorCorrectPolynomial(ecCount);
|
|
4651
|
+
var rawPoly = new QRPolynomial(dcdata[r], rsPoly.getLength() - 1);
|
|
4652
|
+
var modPoly = rawPoly.mod(rsPoly);
|
|
4653
|
+
ecdata[r] = new Array(rsPoly.getLength() - 1);
|
|
4654
|
+
for (var x = 0; x < ecdata[r].length; x++) {
|
|
4655
|
+
var modIndex = x + modPoly.getLength() - ecdata[r].length;
|
|
4656
|
+
ecdata[r][x] = modIndex >= 0 ? modPoly.get(modIndex) : 0;
|
|
4657
|
+
}
|
|
4658
|
+
}
|
|
4659
|
+
var totalCodeCount = 0;
|
|
4660
|
+
for (var y = 0; y < rsBlocks.length; y++) {
|
|
4661
|
+
totalCodeCount += rsBlocks[y].totalCount;
|
|
4662
|
+
}
|
|
4663
|
+
var data = new Array(totalCodeCount);
|
|
4664
|
+
var index = 0;
|
|
4665
|
+
for (var z = 0; z < maxDcCount; z++) {
|
|
4666
|
+
for (var s = 0; s < rsBlocks.length; s++) {
|
|
4667
|
+
if (z < dcdata[s].length) {
|
|
4668
|
+
data[index++] = dcdata[s][z];
|
|
4669
|
+
}
|
|
4670
|
+
}
|
|
4671
|
+
}
|
|
4672
|
+
for (var xx = 0; xx < maxEcCount; xx++) {
|
|
4673
|
+
for (var t = 0; t < rsBlocks.length; t++) {
|
|
4674
|
+
if (xx < ecdata[t].length) {
|
|
4675
|
+
data[index++] = ecdata[t][xx];
|
|
4676
|
+
}
|
|
4677
|
+
}
|
|
4678
|
+
}
|
|
4679
|
+
return data;
|
|
4680
|
+
};
|
|
4681
|
+
module.exports = QRCode;
|
|
4682
|
+
}
|
|
4683
|
+
});
|
|
4684
|
+
|
|
4685
|
+
// node_modules/qrcode-terminal/lib/main.js
|
|
4686
|
+
var require_main = __commonJS({
|
|
4687
|
+
"node_modules/qrcode-terminal/lib/main.js"(exports, module) {
|
|
4688
|
+
var QRCode = require_QRCode();
|
|
4689
|
+
var QRErrorCorrectLevel = require_QRErrorCorrectLevel();
|
|
4690
|
+
var black = "\x1B[40m \x1B[0m";
|
|
4691
|
+
var white = "\x1B[47m \x1B[0m";
|
|
4692
|
+
var toCell = function(isBlack) {
|
|
4693
|
+
return isBlack ? black : white;
|
|
4694
|
+
};
|
|
4695
|
+
var repeat = function(color) {
|
|
4696
|
+
return {
|
|
4697
|
+
times: function(count) {
|
|
4698
|
+
return new Array(count).join(color);
|
|
4699
|
+
}
|
|
4700
|
+
};
|
|
4701
|
+
};
|
|
4702
|
+
var fill = function(length, value) {
|
|
4703
|
+
var arr = new Array(length);
|
|
4704
|
+
for (var i = 0; i < length; i++) {
|
|
4705
|
+
arr[i] = value;
|
|
4706
|
+
}
|
|
4707
|
+
return arr;
|
|
4708
|
+
};
|
|
4709
|
+
module.exports = {
|
|
4710
|
+
error: QRErrorCorrectLevel.L,
|
|
4711
|
+
generate: function(input, opts, cb) {
|
|
4712
|
+
if (typeof opts === "function") {
|
|
4713
|
+
cb = opts;
|
|
4714
|
+
opts = {};
|
|
4715
|
+
}
|
|
4716
|
+
var qrcode2 = new QRCode(-1, this.error);
|
|
4717
|
+
qrcode2.addData(input);
|
|
4718
|
+
qrcode2.make();
|
|
4719
|
+
var output = "";
|
|
4720
|
+
if (opts && opts.small) {
|
|
4721
|
+
var BLACK = true, WHITE = false;
|
|
4722
|
+
var moduleCount = qrcode2.getModuleCount();
|
|
4723
|
+
var moduleData = qrcode2.modules.slice();
|
|
4724
|
+
var oddRow = moduleCount % 2 === 1;
|
|
4725
|
+
if (oddRow) {
|
|
4726
|
+
moduleData.push(fill(moduleCount, WHITE));
|
|
4727
|
+
}
|
|
4728
|
+
var platte = {
|
|
4729
|
+
WHITE_ALL: "\u2588",
|
|
4730
|
+
WHITE_BLACK: "\u2580",
|
|
4731
|
+
BLACK_WHITE: "\u2584",
|
|
4732
|
+
BLACK_ALL: " "
|
|
4733
|
+
};
|
|
4734
|
+
var borderTop = repeat(platte.BLACK_WHITE).times(moduleCount + 3);
|
|
4735
|
+
var borderBottom = repeat(platte.WHITE_BLACK).times(moduleCount + 3);
|
|
4736
|
+
output += borderTop + "\n";
|
|
4737
|
+
for (var row = 0; row < moduleCount; row += 2) {
|
|
4738
|
+
output += platte.WHITE_ALL;
|
|
4739
|
+
for (var col = 0; col < moduleCount; col++) {
|
|
4740
|
+
if (moduleData[row][col] === WHITE && moduleData[row + 1][col] === WHITE) {
|
|
4741
|
+
output += platte.WHITE_ALL;
|
|
4742
|
+
} else if (moduleData[row][col] === WHITE && moduleData[row + 1][col] === BLACK) {
|
|
4743
|
+
output += platte.WHITE_BLACK;
|
|
4744
|
+
} else if (moduleData[row][col] === BLACK && moduleData[row + 1][col] === WHITE) {
|
|
4745
|
+
output += platte.BLACK_WHITE;
|
|
4746
|
+
} else {
|
|
4747
|
+
output += platte.BLACK_ALL;
|
|
4748
|
+
}
|
|
4749
|
+
}
|
|
4750
|
+
output += platte.WHITE_ALL + "\n";
|
|
4751
|
+
}
|
|
4752
|
+
if (!oddRow) {
|
|
4753
|
+
output += borderBottom;
|
|
4754
|
+
}
|
|
4755
|
+
} else {
|
|
4756
|
+
var border = repeat(white).times(qrcode2.getModuleCount() + 3);
|
|
4757
|
+
output += border + "\n";
|
|
4758
|
+
qrcode2.modules.forEach(function(row2) {
|
|
4759
|
+
output += white;
|
|
4760
|
+
output += row2.map(toCell).join("");
|
|
4761
|
+
output += white + "\n";
|
|
4762
|
+
});
|
|
4763
|
+
output += border;
|
|
4764
|
+
}
|
|
4765
|
+
if (cb) cb(output);
|
|
4766
|
+
else console.log(output);
|
|
4767
|
+
},
|
|
4768
|
+
setErrorLevel: function(error) {
|
|
4769
|
+
this.error = QRErrorCorrectLevel[error] || this.error;
|
|
4770
|
+
}
|
|
4771
|
+
};
|
|
4772
|
+
}
|
|
4773
|
+
});
|
|
4774
|
+
|
|
3705
4775
|
// src/main.ts
|
|
3706
4776
|
import { spawn as spawn3 } from "node:child_process";
|
|
3707
|
-
import { randomUUID } from "node:crypto";
|
|
3708
|
-
import { readFileSync as
|
|
3709
|
-
import { constants as osConstants, homedir as
|
|
3710
|
-
import { join as
|
|
4777
|
+
import { randomBytes as randomBytes2, randomUUID } from "node:crypto";
|
|
4778
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync as readdirSync4, realpathSync, rmSync as rmSync2, statSync as statSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
4779
|
+
import { constants as osConstants, homedir as homedir6, hostname } from "node:os";
|
|
4780
|
+
import { join as join6, resolve } from "node:path";
|
|
3711
4781
|
import { parseArgs as nodeParseArgs } from "node:util";
|
|
3712
4782
|
|
|
3713
4783
|
// node_modules/ws/wrapper.mjs
|
|
@@ -3720,6 +4790,9 @@ var import_subprotocol = __toESM(require_subprotocol(), 1);
|
|
|
3720
4790
|
var import_websocket = __toESM(require_websocket(), 1);
|
|
3721
4791
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
3722
4792
|
|
|
4793
|
+
// src/main.ts
|
|
4794
|
+
var import_qrcode_terminal = __toESM(require_main(), 1);
|
|
4795
|
+
|
|
3723
4796
|
// src/env.ts
|
|
3724
4797
|
import { spawn } from "node:child_process";
|
|
3725
4798
|
import { existsSync, readdirSync } from "node:fs";
|
|
@@ -3882,6 +4955,63 @@ function probeClaudeModels() {
|
|
|
3882
4955
|
}
|
|
3883
4956
|
return names;
|
|
3884
4957
|
}
|
|
4958
|
+
async function runWithApproval(opts) {
|
|
4959
|
+
const { query } = await import("@anthropic-ai/claude-agent-sdk");
|
|
4960
|
+
const ac = new AbortController();
|
|
4961
|
+
if (opts.signal.aborted) ac.abort();
|
|
4962
|
+
else opts.signal.addEventListener("abort", () => ac.abort(), { once: true });
|
|
4963
|
+
const parseLine = createClaudeParser(opts.onEvent);
|
|
4964
|
+
let resultError;
|
|
4965
|
+
let resultCode = 0;
|
|
4966
|
+
try {
|
|
4967
|
+
const q = query({
|
|
4968
|
+
prompt: opts.prompt,
|
|
4969
|
+
options: {
|
|
4970
|
+
// Send-for-approval grading is the CLI's own (§1.1): default prompts
|
|
4971
|
+
// for dangerous ops, auto-allows Read/Glob/Grep.
|
|
4972
|
+
permissionMode: "default",
|
|
4973
|
+
// The suspend/approve hook. SDK deny REQUIRES a message string — the
|
|
4974
|
+
// steer note (or a default) lands there and the agent sees it next.
|
|
4975
|
+
canUseTool: async (toolName, input) => {
|
|
4976
|
+
const decision = await opts.requestPermission(toolName, input);
|
|
4977
|
+
if (decision.behavior === "deny") {
|
|
4978
|
+
return { behavior: "deny", message: decision.note ?? "\u7528\u6237\u5728\u624B\u673A\u4E0A\u62D2\u7EDD\u4E86\u672C\u6B21\u64CD\u4F5C" };
|
|
4979
|
+
}
|
|
4980
|
+
return { behavior: "allow", updatedInput: input };
|
|
4981
|
+
},
|
|
4982
|
+
// Keep token-level streaming (the stream_event → text/thinking path).
|
|
4983
|
+
includePartialMessages: true,
|
|
4984
|
+
cwd: opts.cwd,
|
|
4985
|
+
...opts.resumeId ? { resume: opts.resumeId } : {},
|
|
4986
|
+
...opts.model ? { model: opts.model } : {},
|
|
4987
|
+
// The SDK does NOT read filesystem config by default — declare the
|
|
4988
|
+
// sources explicitly so CLAUDE.md / settings.json behave like a direct
|
|
4989
|
+
// CLI run (§1.1 坑).
|
|
4990
|
+
settingSources: ["user", "project", "local"],
|
|
4991
|
+
// Run the user's probed claude, not the SDK's bundled copy — keeps
|
|
4992
|
+
// model/login state identical to a direct run (§3.5).
|
|
4993
|
+
pathToClaudeCodeExecutable: opts.bin,
|
|
4994
|
+
abortController: ac
|
|
4995
|
+
}
|
|
4996
|
+
});
|
|
4997
|
+
for await (const msg of q) {
|
|
4998
|
+
parseLine(JSON.stringify(msg));
|
|
4999
|
+
if (msg.type === "result") {
|
|
5000
|
+
const r = msg;
|
|
5001
|
+
if (r.is_error) {
|
|
5002
|
+
resultCode = 1;
|
|
5003
|
+
resultError = typeof r.result === "string" && r.result ? r.result : r.subtype ?? "claude run failed";
|
|
5004
|
+
} else {
|
|
5005
|
+
resultCode = 0;
|
|
5006
|
+
}
|
|
5007
|
+
}
|
|
5008
|
+
}
|
|
5009
|
+
} catch (err) {
|
|
5010
|
+
if (ac.signal.aborted) return { code: 143 };
|
|
5011
|
+
return { code: 1, error: err instanceof Error ? err.message : String(err) };
|
|
5012
|
+
}
|
|
5013
|
+
return { code: resultCode, ...resultError ? { error: resultError } : {} };
|
|
5014
|
+
}
|
|
3885
5015
|
var claude = {
|
|
3886
5016
|
id: "claude",
|
|
3887
5017
|
label: "Claude Code",
|
|
@@ -3907,7 +5037,8 @@ var claude = {
|
|
|
3907
5037
|
],
|
|
3908
5038
|
stdin: prompt
|
|
3909
5039
|
}),
|
|
3910
|
-
createParser: createClaudeParser
|
|
5040
|
+
createParser: createClaudeParser,
|
|
5041
|
+
runWithApproval
|
|
3911
5042
|
};
|
|
3912
5043
|
|
|
3913
5044
|
// src/adapters/codex.ts
|
|
@@ -4007,16 +5138,118 @@ var codex = {
|
|
|
4007
5138
|
// above (this system already trusts the agent fully once it's running),
|
|
4008
5139
|
// but never exercised end-to-end because of an account rate limit
|
|
4009
5140
|
// during development — verify before relying on it.
|
|
4010
|
-
|
|
5141
|
+
// Approval-mode (M1, approval-design §1.2): codex has no runWithApproval
|
|
5142
|
+
// yet (app-server integration is M2), so under --approval it still spawns —
|
|
5143
|
+
// but the resume path MUST NOT carry the naked bypass flag. The cost is
|
|
5144
|
+
// that a resume tool call needing approval fails honestly instead of
|
|
5145
|
+
// silently bypassing; fresh runs already have the workspace-write sandbox.
|
|
5146
|
+
buildInvocation: (prompt, resumeId, model, opts) => {
|
|
4011
5147
|
const m = model ? ["-m", model] : [];
|
|
4012
5148
|
return {
|
|
4013
|
-
args: resumeId ? [
|
|
5149
|
+
args: resumeId ? [
|
|
5150
|
+
"exec",
|
|
5151
|
+
"resume",
|
|
5152
|
+
resumeId,
|
|
5153
|
+
"-",
|
|
5154
|
+
"--json",
|
|
5155
|
+
"--skip-git-repo-check",
|
|
5156
|
+
...opts?.approval ? [] : ["--dangerously-bypass-approvals-and-sandbox"],
|
|
5157
|
+
...m
|
|
5158
|
+
] : ["exec", "--json", "--skip-git-repo-check", "--sandbox", "workspace-write", ...m],
|
|
4014
5159
|
stdin: prompt
|
|
4015
5160
|
};
|
|
4016
5161
|
},
|
|
4017
5162
|
createParser: createCodexParser
|
|
4018
5163
|
};
|
|
4019
5164
|
|
|
5165
|
+
// src/adapters/gemini-core.ts
|
|
5166
|
+
function createGeminiParser(emit) {
|
|
5167
|
+
let lastSessionId = null;
|
|
5168
|
+
return (line) => {
|
|
5169
|
+
const obj = parseJsonLine(line);
|
|
5170
|
+
if (!obj || typeof obj.type !== "string") return;
|
|
5171
|
+
switch (obj.type) {
|
|
5172
|
+
case "init":
|
|
5173
|
+
if (typeof obj.session_id === "string" && obj.session_id !== lastSessionId) {
|
|
5174
|
+
lastSessionId = obj.session_id;
|
|
5175
|
+
emit({ type: "session", id: obj.session_id });
|
|
5176
|
+
}
|
|
5177
|
+
return;
|
|
5178
|
+
case "message":
|
|
5179
|
+
if (obj.role === "assistant" && typeof obj.content === "string" && obj.content) {
|
|
5180
|
+
emit({ type: "text", text: obj.content });
|
|
5181
|
+
}
|
|
5182
|
+
return;
|
|
5183
|
+
case "tool_use":
|
|
5184
|
+
if (typeof obj.tool_id === "string") {
|
|
5185
|
+
emit({ type: "tool_use", id: obj.tool_id, name: String(obj.tool_name ?? "tool"), input: obj.parameters ?? null });
|
|
5186
|
+
}
|
|
5187
|
+
return;
|
|
5188
|
+
case "tool_result":
|
|
5189
|
+
if (typeof obj.tool_id === "string") {
|
|
5190
|
+
const content = typeof obj.output === "string" ? obj.output : obj.error?.message ?? "";
|
|
5191
|
+
emit({ type: "tool_result", toolUseId: obj.tool_id, content, isError: obj.status === "error" });
|
|
5192
|
+
}
|
|
5193
|
+
return;
|
|
5194
|
+
case "error":
|
|
5195
|
+
if (typeof obj.message === "string" && obj.message) {
|
|
5196
|
+
emit({ type: "error", message: obj.message });
|
|
5197
|
+
}
|
|
5198
|
+
return;
|
|
5199
|
+
case "result":
|
|
5200
|
+
if (obj.status === "error" && typeof obj.error?.message === "string" && obj.error.message) {
|
|
5201
|
+
emit({ type: "error", message: obj.error.message });
|
|
5202
|
+
}
|
|
5203
|
+
return;
|
|
5204
|
+
}
|
|
5205
|
+
};
|
|
5206
|
+
}
|
|
5207
|
+
|
|
5208
|
+
// src/adapters/gemini.ts
|
|
5209
|
+
var gemini = {
|
|
5210
|
+
id: "gemini",
|
|
5211
|
+
label: "Gemini CLI",
|
|
5212
|
+
// Suggested chips; gemini accepts any model id its account exposes via -m.
|
|
5213
|
+
// No config file reliably lists the active model, so there is no probe.
|
|
5214
|
+
models: ["gemini-2.5-pro", "gemini-2.5-flash"],
|
|
5215
|
+
buildInvocation: (prompt, resumeId, model) => {
|
|
5216
|
+
if (resumeId) {
|
|
5217
|
+
throw new Error(
|
|
5218
|
+
'Gemini CLI cannot resume a specific session in headless mode: its --resume flag takes only "latest" or a numeric index, not a session id. Start a new conversation instead.'
|
|
5219
|
+
);
|
|
5220
|
+
}
|
|
5221
|
+
const m = model ? ["-m", model] : [];
|
|
5222
|
+
return {
|
|
5223
|
+
// Prompt on argv (like joycode) so headless mode is unambiguous even if
|
|
5224
|
+
// stdin/TTY detection differs; stdin is left empty by the daemon.
|
|
5225
|
+
args: ["-p", prompt, "-o", "stream-json", "--approval-mode", "yolo", ...m]
|
|
5226
|
+
};
|
|
5227
|
+
},
|
|
5228
|
+
createParser: createGeminiParser
|
|
5229
|
+
};
|
|
5230
|
+
|
|
5231
|
+
// src/adapters/iflow.ts
|
|
5232
|
+
function createIflowParser(emit) {
|
|
5233
|
+
return (line) => {
|
|
5234
|
+
emit({ type: "text", text: line + "\n" });
|
|
5235
|
+
};
|
|
5236
|
+
}
|
|
5237
|
+
var iflow = {
|
|
5238
|
+
id: "iflow",
|
|
5239
|
+
label: "iFlow CLI",
|
|
5240
|
+
models: ["Qwen3-Coder", "Kimi-K2", "DeepSeek-V3"],
|
|
5241
|
+
buildInvocation: (prompt, resumeId, model) => {
|
|
5242
|
+
if (resumeId) {
|
|
5243
|
+
throw new Error(
|
|
5244
|
+
"iFlow CLI cannot resume a specific session here: its headless mode emits no session id (no stream-json output yet, see iflow-ai/iflow-cli#239), so there is no id to reattach to. Start a new conversation instead."
|
|
5245
|
+
);
|
|
5246
|
+
}
|
|
5247
|
+
const m = model ? ["-m", model] : [];
|
|
5248
|
+
return { args: ["-p", prompt, "--yolo", ...m] };
|
|
5249
|
+
},
|
|
5250
|
+
createParser: createIflowParser
|
|
5251
|
+
};
|
|
5252
|
+
|
|
4020
5253
|
// src/adapters/joycode.ts
|
|
4021
5254
|
async function probeJoycodeModels(bin) {
|
|
4022
5255
|
const out = await captureCommand(bin, ["models"], 5e3);
|
|
@@ -4045,10 +5278,22 @@ var joycode = {
|
|
|
4045
5278
|
// Putting flags after `resume` is a usage error (unlike codex's
|
|
4046
5279
|
// `exec resume <id> -` word order). stdin feeding is unverified, so
|
|
4047
5280
|
// fresh runs also pass the prompt via argv for consistency.
|
|
4048
|
-
|
|
5281
|
+
// Approval-mode (M1, approval-design §1.2): same treatment as codex — no
|
|
5282
|
+
// runWithApproval yet, so under --approval the resume path drops the naked
|
|
5283
|
+
// bypass flag (honest failure over silent bypass).
|
|
5284
|
+
buildInvocation: (prompt, resumeId, model, opts) => {
|
|
4049
5285
|
const m = model ? ["-m", model] : [];
|
|
4050
5286
|
return {
|
|
4051
|
-
args: resumeId ? [
|
|
5287
|
+
args: resumeId ? [
|
|
5288
|
+
"exec",
|
|
5289
|
+
"--json",
|
|
5290
|
+
"--skip-git-repo-check",
|
|
5291
|
+
...opts?.approval ? [] : ["--dangerously-bypass-approvals-and-sandbox"],
|
|
5292
|
+
...m,
|
|
5293
|
+
"resume",
|
|
5294
|
+
resumeId,
|
|
5295
|
+
prompt
|
|
5296
|
+
] : ["exec", "--json", "--skip-git-repo-check", "--sandbox", "workspace-write", ...m, prompt]
|
|
4052
5297
|
};
|
|
4053
5298
|
},
|
|
4054
5299
|
// Shares codex's parser (isomorphic JSONL), but with a JoyCode-flavored
|
|
@@ -4056,8 +5301,32 @@ var joycode = {
|
|
|
4056
5301
|
createParser: (emit) => createCodexParser(emit, "Your JoyCode CLI is out of date for this model \u2014 upgrade it (or pick a model your current version supports), then retry.")
|
|
4057
5302
|
};
|
|
4058
5303
|
|
|
5304
|
+
// src/adapters/qwen.ts
|
|
5305
|
+
var qwen = {
|
|
5306
|
+
id: "qwen",
|
|
5307
|
+
label: "Qwen Code",
|
|
5308
|
+
models: ["qwen3-coder-plus", "qwen3-coder-flash"],
|
|
5309
|
+
buildInvocation: (prompt, resumeId, model) => {
|
|
5310
|
+
const m = model ? ["-m", model] : [];
|
|
5311
|
+
return {
|
|
5312
|
+
// `-r <sessionId>` resumes by id (verified via `qwen --help`); a fresh
|
|
5313
|
+
// run omits it. Prompt on argv to force headless mode unambiguously.
|
|
5314
|
+
args: [
|
|
5315
|
+
"-p",
|
|
5316
|
+
prompt,
|
|
5317
|
+
"-o",
|
|
5318
|
+
"stream-json",
|
|
5319
|
+
"--yolo",
|
|
5320
|
+
...m,
|
|
5321
|
+
...resumeId ? ["-r", resumeId] : []
|
|
5322
|
+
]
|
|
5323
|
+
};
|
|
5324
|
+
},
|
|
5325
|
+
createParser: createGeminiParser
|
|
5326
|
+
};
|
|
5327
|
+
|
|
4059
5328
|
// src/adapters/index.ts
|
|
4060
|
-
var REGISTRY = [claude, codex, joycode];
|
|
5329
|
+
var REGISTRY = [claude, codex, joycode, gemini, qwen, iflow];
|
|
4061
5330
|
function detectAgents() {
|
|
4062
5331
|
return REGISTRY.flatMap((def) => {
|
|
4063
5332
|
const bin = resolveBin(def.id);
|
|
@@ -4068,6 +5337,108 @@ function getAgent(id) {
|
|
|
4068
5337
|
return detectAgents().find((a) => a.id === id) ?? null;
|
|
4069
5338
|
}
|
|
4070
5339
|
|
|
5340
|
+
// src/approval.ts
|
|
5341
|
+
function defaultDeps() {
|
|
5342
|
+
return {
|
|
5343
|
+
setInterval: (fn, ms) => {
|
|
5344
|
+
const t = setInterval(fn, ms);
|
|
5345
|
+
t.unref?.();
|
|
5346
|
+
return t;
|
|
5347
|
+
},
|
|
5348
|
+
clearInterval: (t) => clearInterval(t),
|
|
5349
|
+
randomId: () => globalThis.crypto?.randomUUID ? globalThis.crypto.randomUUID() : `${Date.now()}-${Math.random().toString(36).slice(2)}`,
|
|
5350
|
+
log: (m) => console.log(m)
|
|
5351
|
+
};
|
|
5352
|
+
}
|
|
5353
|
+
var RunApprovals = class {
|
|
5354
|
+
constructor(opts) {
|
|
5355
|
+
this.opts = opts;
|
|
5356
|
+
const d = defaultDeps();
|
|
5357
|
+
this.deps = { ...d, ...opts.deps };
|
|
5358
|
+
}
|
|
5359
|
+
pending = /* @__PURE__ */ new Map();
|
|
5360
|
+
deps;
|
|
5361
|
+
get sessionKey() {
|
|
5362
|
+
return this.opts.conversationId ?? this.opts.requestId;
|
|
5363
|
+
}
|
|
5364
|
+
// The function handed to the adapter (ApprovalRunOpts.requestPermission).
|
|
5365
|
+
// Resolves only when a decision lands — or never, if the run dies first
|
|
5366
|
+
// (超时不自动放行, §3.3): there is no timeout path that resolves.
|
|
5367
|
+
requestPermission(tool, input) {
|
|
5368
|
+
const grants = this.opts.sessionGrants.get(this.sessionKey);
|
|
5369
|
+
if (grants?.has(tool)) {
|
|
5370
|
+
this.deps.log(`[approval] requestId=${this.opts.requestId} tool=${tool} auto-allowed (session grant)`);
|
|
5371
|
+
return Promise.resolve({ behavior: "allow" });
|
|
5372
|
+
}
|
|
5373
|
+
const approvalId = this.deps.randomId();
|
|
5374
|
+
return new Promise((resolve2) => {
|
|
5375
|
+
const entry = { tool, input, resolve: resolve2 };
|
|
5376
|
+
this.pending.set(approvalId, entry);
|
|
5377
|
+
this.opts.callbacks.sendRequest({ approvalId, tool, input, renotify: false });
|
|
5378
|
+
if (this.opts.renotifyMs > 0) {
|
|
5379
|
+
entry.timer = this.deps.setInterval(
|
|
5380
|
+
() => this.opts.callbacks.sendRequest({ approvalId, tool, input, renotify: true }),
|
|
5381
|
+
this.opts.renotifyMs
|
|
5382
|
+
);
|
|
5383
|
+
}
|
|
5384
|
+
this.deps.log(`[approval] requestId=${this.opts.requestId} approvalId=${approvalId} tool=${tool} suspended, awaiting decision`);
|
|
5385
|
+
});
|
|
5386
|
+
}
|
|
5387
|
+
// Apply a decision from a permission_response (§2.4). Idempotent: an unknown
|
|
5388
|
+
// / already-decided approvalId is a logged no-op (returns false), so repeated
|
|
5389
|
+
// or multi-device taps are harmless. `note` must already be plaintext.
|
|
5390
|
+
resolve(approvalId, decision, note) {
|
|
5391
|
+
const entry = this.pending.get(approvalId);
|
|
5392
|
+
if (!entry) {
|
|
5393
|
+
this.deps.log(`[approval] permission_response approvalId=${approvalId} ignored (unknown / already decided / stale)`);
|
|
5394
|
+
return false;
|
|
5395
|
+
}
|
|
5396
|
+
this.pending.delete(approvalId);
|
|
5397
|
+
if (entry.timer) this.deps.clearInterval(entry.timer);
|
|
5398
|
+
if (decision === "allow_session") {
|
|
5399
|
+
let set = this.opts.sessionGrants.get(this.sessionKey);
|
|
5400
|
+
if (!set) {
|
|
5401
|
+
set = /* @__PURE__ */ new Set();
|
|
5402
|
+
this.opts.sessionGrants.set(this.sessionKey, set);
|
|
5403
|
+
}
|
|
5404
|
+
set.add(entry.tool);
|
|
5405
|
+
}
|
|
5406
|
+
this.opts.callbacks.emitResult({ approvalId, decision, note });
|
|
5407
|
+
entry.resolve(decision === "deny" ? { behavior: "deny", note } : { behavior: "allow" });
|
|
5408
|
+
this.deps.log(`[approval] requestId=${this.opts.requestId} approvalId=${approvalId} decided=${decision}`);
|
|
5409
|
+
return true;
|
|
5410
|
+
}
|
|
5411
|
+
// Run is dying (cancel / ws close / normal end): clear every pending timer
|
|
5412
|
+
// and drop the pending map. Suspended promises are simply abandoned — the
|
|
5413
|
+
// SDK run is being aborted, so nothing awaits them (§3.3 / §3.7). No decision
|
|
5414
|
+
// is fabricated: 超时/断线不自动放行.
|
|
5415
|
+
abort() {
|
|
5416
|
+
for (const [, entry] of this.pending) {
|
|
5417
|
+
if (entry.timer) this.deps.clearInterval(entry.timer);
|
|
5418
|
+
}
|
|
5419
|
+
const n = this.pending.size;
|
|
5420
|
+
this.pending.clear();
|
|
5421
|
+
if (n) this.deps.log(`[approval] requestId=${this.opts.requestId} aborted ${n} pending approval(s)`);
|
|
5422
|
+
}
|
|
5423
|
+
hasPending(approvalId) {
|
|
5424
|
+
return this.pending.has(approvalId);
|
|
5425
|
+
}
|
|
5426
|
+
get pendingCount() {
|
|
5427
|
+
return this.pending.size;
|
|
5428
|
+
}
|
|
5429
|
+
};
|
|
5430
|
+
var APPROVAL_INPUT_MAX_BYTES = 16 * 1024;
|
|
5431
|
+
function capApprovalInput(input) {
|
|
5432
|
+
let bytes;
|
|
5433
|
+
try {
|
|
5434
|
+
bytes = Buffer.byteLength(JSON.stringify(input) ?? "", "utf-8");
|
|
5435
|
+
} catch {
|
|
5436
|
+
return { input: { _truncated: true }, inputTruncated: true };
|
|
5437
|
+
}
|
|
5438
|
+
if (bytes > APPROVAL_INPUT_MAX_BYTES) return { input: { _truncated: true }, inputTruncated: true };
|
|
5439
|
+
return { input, inputTruncated: false };
|
|
5440
|
+
}
|
|
5441
|
+
|
|
4071
5442
|
// src/e2e.ts
|
|
4072
5443
|
import { createCipheriv, createDecipheriv, createHash, hkdfSync, randomBytes } from "node:crypto";
|
|
4073
5444
|
var SALT = Buffer.from("agentlink", "utf-8");
|
|
@@ -4182,6 +5553,8 @@ function putConversation(patch) {
|
|
|
4182
5553
|
if (sessionId !== void 0) merged.sessionId = sessionId;
|
|
4183
5554
|
const archived = typeof patch.archived === "boolean" ? patch.archived : existing?.archived;
|
|
4184
5555
|
if (archived === true) merged.archived = true;
|
|
5556
|
+
const takeover = typeof patch.takeover === "boolean" ? patch.takeover : existing?.takeover;
|
|
5557
|
+
if (takeover === true) merged.takeover = true;
|
|
4185
5558
|
if (!merged.agent || !merged.dir || !merged.title || !merged.createdAt || !merged.lastActiveAt) {
|
|
4186
5559
|
return { error: "creating a conversation requires agent, dir, title, createdAt and lastActiveAt" };
|
|
4187
5560
|
}
|
|
@@ -4327,6 +5700,306 @@ function history(conversationId) {
|
|
|
4327
5700
|
return runs;
|
|
4328
5701
|
}
|
|
4329
5702
|
|
|
5703
|
+
// src/sessions.ts
|
|
5704
|
+
import { closeSync, openSync, readdirSync as readdirSync3, readSync, readFileSync as readFileSync4, statSync } from "node:fs";
|
|
5705
|
+
import { homedir as homedir5 } from "node:os";
|
|
5706
|
+
import { join as join5 } from "node:path";
|
|
5707
|
+
|
|
5708
|
+
// ../core/src/session-archive.ts
|
|
5709
|
+
function resultText2(content) {
|
|
5710
|
+
if (typeof content === "string") return content;
|
|
5711
|
+
if (Array.isArray(content)) {
|
|
5712
|
+
return content.map((c) => c && c.type === "text" ? String(c.text ?? "") : JSON.stringify(c)).join("\n");
|
|
5713
|
+
}
|
|
5714
|
+
return content === void 0 ? "" : JSON.stringify(content);
|
|
5715
|
+
}
|
|
5716
|
+
function userText(message) {
|
|
5717
|
+
const content = message.content;
|
|
5718
|
+
if (typeof content === "string") return content;
|
|
5719
|
+
if (!Array.isArray(content)) return "";
|
|
5720
|
+
const parts = [];
|
|
5721
|
+
for (const b of content) {
|
|
5722
|
+
if (b && typeof b === "object" && b.type === "text" && typeof b.text === "string") {
|
|
5723
|
+
parts.push(b.text);
|
|
5724
|
+
}
|
|
5725
|
+
}
|
|
5726
|
+
return parts.join("\n");
|
|
5727
|
+
}
|
|
5728
|
+
function isHumanPrompt(message) {
|
|
5729
|
+
const content = message.content;
|
|
5730
|
+
if (typeof content === "string") return content.trim().length > 0;
|
|
5731
|
+
if (!Array.isArray(content)) return false;
|
|
5732
|
+
return content.some((b) => b && typeof b === "object" && b.type === "text" && String(b.text ?? "").trim().length > 0);
|
|
5733
|
+
}
|
|
5734
|
+
function toolResultEvents(message) {
|
|
5735
|
+
const content = message.content;
|
|
5736
|
+
if (!Array.isArray(content)) return [];
|
|
5737
|
+
const out = [];
|
|
5738
|
+
for (const b of content) {
|
|
5739
|
+
if (b && typeof b === "object" && b.type === "tool_result") {
|
|
5740
|
+
const block = b;
|
|
5741
|
+
out.push({
|
|
5742
|
+
type: "tool_result",
|
|
5743
|
+
toolUseId: String(block.tool_use_id ?? ""),
|
|
5744
|
+
content: resultText2(block.content),
|
|
5745
|
+
isError: Boolean(block.is_error)
|
|
5746
|
+
});
|
|
5747
|
+
}
|
|
5748
|
+
}
|
|
5749
|
+
return out;
|
|
5750
|
+
}
|
|
5751
|
+
function assistantEvents(message) {
|
|
5752
|
+
const content = message.content;
|
|
5753
|
+
if (!Array.isArray(content)) return { events: [], omitted: 0 };
|
|
5754
|
+
const out = [];
|
|
5755
|
+
let omitted = 0;
|
|
5756
|
+
for (const b of content) {
|
|
5757
|
+
if (!b || typeof b !== "object") {
|
|
5758
|
+
omitted++;
|
|
5759
|
+
continue;
|
|
5760
|
+
}
|
|
5761
|
+
const block = b;
|
|
5762
|
+
if (block.type === "text" && typeof block.text === "string" && block.text) {
|
|
5763
|
+
out.push({ type: "text", text: block.text });
|
|
5764
|
+
} else if (block.type === "thinking" && typeof block.thinking === "string" && block.thinking) {
|
|
5765
|
+
out.push({ type: "thinking", text: block.thinking });
|
|
5766
|
+
} else if (block.type === "tool_use") {
|
|
5767
|
+
out.push({ type: "tool_use", id: String(block.id ?? ""), name: String(block.name ?? ""), input: block.input ?? null });
|
|
5768
|
+
}
|
|
5769
|
+
}
|
|
5770
|
+
return { events: out, omitted };
|
|
5771
|
+
}
|
|
5772
|
+
function tsOf(obj) {
|
|
5773
|
+
const t = obj.timestamp;
|
|
5774
|
+
if (typeof t === "number" && Number.isFinite(t)) return t;
|
|
5775
|
+
if (typeof t === "string") {
|
|
5776
|
+
const ms = Date.parse(t);
|
|
5777
|
+
if (Number.isFinite(ms)) return ms;
|
|
5778
|
+
}
|
|
5779
|
+
return void 0;
|
|
5780
|
+
}
|
|
5781
|
+
function parseClaudeArchive(text, opts) {
|
|
5782
|
+
const maxTurns = opts?.maxTurns ?? Infinity;
|
|
5783
|
+
const turns = [];
|
|
5784
|
+
let current = null;
|
|
5785
|
+
let sessionId;
|
|
5786
|
+
let cwd;
|
|
5787
|
+
let omitted = 0;
|
|
5788
|
+
const openTurn = (prompt, startedAt) => {
|
|
5789
|
+
current = { prompt, events: [], ...startedAt !== void 0 ? { startedAt } : {} };
|
|
5790
|
+
turns.push(current);
|
|
5791
|
+
};
|
|
5792
|
+
for (const raw of text.split("\n")) {
|
|
5793
|
+
if (!raw.trim()) continue;
|
|
5794
|
+
let obj;
|
|
5795
|
+
try {
|
|
5796
|
+
obj = JSON.parse(raw);
|
|
5797
|
+
} catch {
|
|
5798
|
+
omitted++;
|
|
5799
|
+
continue;
|
|
5800
|
+
}
|
|
5801
|
+
if (!obj || typeof obj !== "object") {
|
|
5802
|
+
omitted++;
|
|
5803
|
+
continue;
|
|
5804
|
+
}
|
|
5805
|
+
if (typeof obj.sessionId === "string" && !sessionId) sessionId = obj.sessionId;
|
|
5806
|
+
if (typeof obj.cwd === "string" && !cwd) cwd = obj.cwd;
|
|
5807
|
+
const type = obj.type;
|
|
5808
|
+
const message = obj.message;
|
|
5809
|
+
if (type === "user" && message && typeof message === "object") {
|
|
5810
|
+
const msg = message;
|
|
5811
|
+
if (isHumanPrompt(msg)) {
|
|
5812
|
+
openTurn(userText(msg), tsOf(obj));
|
|
5813
|
+
} else {
|
|
5814
|
+
if (!current) openTurn("", tsOf(obj));
|
|
5815
|
+
current.events.push(...toolResultEvents(msg));
|
|
5816
|
+
}
|
|
5817
|
+
} else if (type === "assistant" && message && typeof message === "object") {
|
|
5818
|
+
if (!current) openTurn("", tsOf(obj));
|
|
5819
|
+
const { events, omitted: skipped } = assistantEvents(message);
|
|
5820
|
+
current.events.push(...events);
|
|
5821
|
+
omitted += skipped;
|
|
5822
|
+
}
|
|
5823
|
+
}
|
|
5824
|
+
let truncatedEarlier = false;
|
|
5825
|
+
let kept = turns;
|
|
5826
|
+
if (turns.length > maxTurns) {
|
|
5827
|
+
kept = turns.slice(turns.length - maxTurns);
|
|
5828
|
+
truncatedEarlier = true;
|
|
5829
|
+
}
|
|
5830
|
+
return { sessionId, cwd, turns: kept, omitted, truncatedEarlier };
|
|
5831
|
+
}
|
|
5832
|
+
function claudeArchiveMeta(headText, tailText) {
|
|
5833
|
+
let sessionId;
|
|
5834
|
+
let cwd;
|
|
5835
|
+
let title = "";
|
|
5836
|
+
for (const raw of headText.split("\n")) {
|
|
5837
|
+
if (!raw.trim()) continue;
|
|
5838
|
+
let obj;
|
|
5839
|
+
try {
|
|
5840
|
+
obj = JSON.parse(raw);
|
|
5841
|
+
} catch {
|
|
5842
|
+
continue;
|
|
5843
|
+
}
|
|
5844
|
+
if (typeof obj.sessionId === "string" && !sessionId) sessionId = obj.sessionId;
|
|
5845
|
+
if (typeof obj.cwd === "string" && !cwd) cwd = obj.cwd;
|
|
5846
|
+
if (!title && obj.type === "user" && obj.message && typeof obj.message === "object") {
|
|
5847
|
+
const msg = obj.message;
|
|
5848
|
+
if (isHumanPrompt(msg)) title = firstLine(userText(msg));
|
|
5849
|
+
}
|
|
5850
|
+
if (sessionId && cwd && title) break;
|
|
5851
|
+
}
|
|
5852
|
+
let lastLine = "";
|
|
5853
|
+
const tailLines = tailText.split("\n").filter((l) => l.trim());
|
|
5854
|
+
for (let i = tailLines.length - 1; i >= 0 && !lastLine; i--) {
|
|
5855
|
+
let obj;
|
|
5856
|
+
try {
|
|
5857
|
+
obj = JSON.parse(tailLines[i]);
|
|
5858
|
+
} catch {
|
|
5859
|
+
continue;
|
|
5860
|
+
}
|
|
5861
|
+
if ((obj.type === "assistant" || obj.type === "user") && obj.message && typeof obj.message === "object") {
|
|
5862
|
+
const msg = obj.message;
|
|
5863
|
+
const text = obj.type === "assistant" ? assistantText(msg) : isHumanPrompt(msg) ? userText(msg) : "";
|
|
5864
|
+
if (text.trim()) lastLine = firstLine(text);
|
|
5865
|
+
}
|
|
5866
|
+
}
|
|
5867
|
+
return { ...sessionId ? { sessionId } : {}, ...cwd ? { cwd } : {}, title, lastLine };
|
|
5868
|
+
}
|
|
5869
|
+
function assistantText(message) {
|
|
5870
|
+
const content = message.content;
|
|
5871
|
+
if (typeof content === "string") return content;
|
|
5872
|
+
if (!Array.isArray(content)) return "";
|
|
5873
|
+
const parts = [];
|
|
5874
|
+
for (const b of content) {
|
|
5875
|
+
if (b && typeof b === "object" && b.type === "text" && typeof b.text === "string") {
|
|
5876
|
+
parts.push(b.text);
|
|
5877
|
+
}
|
|
5878
|
+
}
|
|
5879
|
+
return parts.join(" ");
|
|
5880
|
+
}
|
|
5881
|
+
function firstLine(s) {
|
|
5882
|
+
const line = s.split("\n").find((l) => l.trim()) ?? "";
|
|
5883
|
+
return line.trim();
|
|
5884
|
+
}
|
|
5885
|
+
|
|
5886
|
+
// src/sessions.ts
|
|
5887
|
+
function claudeProjectsDir() {
|
|
5888
|
+
const base = process.env.AGENTLINK_CLAUDE_HOME || join5(homedir5(), ".claude");
|
|
5889
|
+
return join5(base, "projects");
|
|
5890
|
+
}
|
|
5891
|
+
var META_SLICE_BYTES = 64 * 1024;
|
|
5892
|
+
var MAX_SESSIONS = 40;
|
|
5893
|
+
var MAX_HISTORY_TURNS = 40;
|
|
5894
|
+
var SESSION_ID_RE = /^[A-Za-z0-9_-]{1,128}$/;
|
|
5895
|
+
function readHeadTail(path, size) {
|
|
5896
|
+
if (size <= META_SLICE_BYTES * 2) {
|
|
5897
|
+
const whole = readFileSync4(path, "utf-8");
|
|
5898
|
+
return { head: whole, tail: whole };
|
|
5899
|
+
}
|
|
5900
|
+
const fd = openSync(path, "r");
|
|
5901
|
+
try {
|
|
5902
|
+
const headBuf = Buffer.alloc(META_SLICE_BYTES);
|
|
5903
|
+
readSync(fd, headBuf, 0, META_SLICE_BYTES, 0);
|
|
5904
|
+
const tailBuf = Buffer.alloc(META_SLICE_BYTES);
|
|
5905
|
+
readSync(fd, tailBuf, 0, META_SLICE_BYTES, size - META_SLICE_BYTES);
|
|
5906
|
+
const tail = tailBuf.toString("utf-8");
|
|
5907
|
+
return { head: headBuf.toString("utf-8"), tail: tail.slice(tail.indexOf("\n") + 1) };
|
|
5908
|
+
} finally {
|
|
5909
|
+
closeSync(fd);
|
|
5910
|
+
}
|
|
5911
|
+
}
|
|
5912
|
+
function scanClaudeSessions() {
|
|
5913
|
+
const root = claudeProjectsDir();
|
|
5914
|
+
let projectDirs;
|
|
5915
|
+
try {
|
|
5916
|
+
projectDirs = readdirSync3(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => join5(root, e.name));
|
|
5917
|
+
} catch {
|
|
5918
|
+
return [];
|
|
5919
|
+
}
|
|
5920
|
+
const candidates = [];
|
|
5921
|
+
for (const dir of projectDirs) {
|
|
5922
|
+
let entries;
|
|
5923
|
+
try {
|
|
5924
|
+
entries = readdirSync3(dir).filter((f) => f.endsWith(".jsonl"));
|
|
5925
|
+
} catch {
|
|
5926
|
+
continue;
|
|
5927
|
+
}
|
|
5928
|
+
for (const name of entries) {
|
|
5929
|
+
const file = join5(dir, name);
|
|
5930
|
+
try {
|
|
5931
|
+
const st = statSync(file);
|
|
5932
|
+
if (!st.isFile() || st.size === 0) continue;
|
|
5933
|
+
candidates.push({ file, sessionId: name.replace(/\.jsonl$/, ""), mtime: st.mtimeMs, size: st.size });
|
|
5934
|
+
} catch {
|
|
5935
|
+
}
|
|
5936
|
+
}
|
|
5937
|
+
}
|
|
5938
|
+
candidates.sort((a, b) => b.mtime - a.mtime);
|
|
5939
|
+
const sessions = [];
|
|
5940
|
+
for (const c of candidates.slice(0, MAX_SESSIONS)) {
|
|
5941
|
+
let meta;
|
|
5942
|
+
try {
|
|
5943
|
+
const { head, tail } = readHeadTail(c.file, c.size);
|
|
5944
|
+
meta = claudeArchiveMeta(head, tail);
|
|
5945
|
+
} catch {
|
|
5946
|
+
continue;
|
|
5947
|
+
}
|
|
5948
|
+
sessions.push({
|
|
5949
|
+
agent: "claude",
|
|
5950
|
+
sessionId: c.sessionId,
|
|
5951
|
+
...meta.cwd ? { cwd: meta.cwd } : {},
|
|
5952
|
+
title: meta.title || "(\u65E0\u6807\u9898\u4F1A\u8BDD)",
|
|
5953
|
+
lastLine: meta.lastLine,
|
|
5954
|
+
mtime: Math.round(c.mtime)
|
|
5955
|
+
});
|
|
5956
|
+
}
|
|
5957
|
+
return sessions;
|
|
5958
|
+
}
|
|
5959
|
+
function findClaudeArchive(sessionId) {
|
|
5960
|
+
const root = claudeProjectsDir();
|
|
5961
|
+
const target = `${sessionId}.jsonl`;
|
|
5962
|
+
let projectDirs;
|
|
5963
|
+
try {
|
|
5964
|
+
projectDirs = readdirSync3(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
5965
|
+
} catch {
|
|
5966
|
+
return null;
|
|
5967
|
+
}
|
|
5968
|
+
for (const d of projectDirs) {
|
|
5969
|
+
const file = join5(root, d, target);
|
|
5970
|
+
try {
|
|
5971
|
+
if (statSync(file).isFile()) return file;
|
|
5972
|
+
} catch {
|
|
5973
|
+
}
|
|
5974
|
+
}
|
|
5975
|
+
return null;
|
|
5976
|
+
}
|
|
5977
|
+
function claudeSessionHistory(agent, sessionId) {
|
|
5978
|
+
if (agent !== "claude") return { error: `session takeover supports claude only in M1 (got "${agent}")` };
|
|
5979
|
+
if (!SESSION_ID_RE.test(sessionId)) return { error: "malformed sessionId" };
|
|
5980
|
+
const file = findClaudeArchive(sessionId);
|
|
5981
|
+
if (!file) return { error: `no archive found for session "${sessionId}"` };
|
|
5982
|
+
let text;
|
|
5983
|
+
try {
|
|
5984
|
+
text = readFileSync4(file, "utf-8");
|
|
5985
|
+
} catch (err) {
|
|
5986
|
+
return { error: `cannot read archive: ${err instanceof Error ? err.message : String(err)}` };
|
|
5987
|
+
}
|
|
5988
|
+
const parsed = parseClaudeArchive(text, { maxTurns: MAX_HISTORY_TURNS });
|
|
5989
|
+
const runs = parsed.turns.map((turn, i) => ({
|
|
5990
|
+
runId: `${sessionId}~${i}`,
|
|
5991
|
+
agent: "claude",
|
|
5992
|
+
prompt: turn.prompt,
|
|
5993
|
+
...parsed.cwd ? { cwd: parsed.cwd } : {},
|
|
5994
|
+
sessionId,
|
|
5995
|
+
startedAt: turn.startedAt ?? 0,
|
|
5996
|
+
status: "done",
|
|
5997
|
+
truncated: false,
|
|
5998
|
+
events: turn.events
|
|
5999
|
+
}));
|
|
6000
|
+
return { runs, truncatedEarlier: parsed.truncatedEarlier };
|
|
6001
|
+
}
|
|
6002
|
+
|
|
4330
6003
|
// src/tunnel.ts
|
|
4331
6004
|
import { spawn as spawn2 } from "node:child_process";
|
|
4332
6005
|
import { connect } from "node:net";
|
|
@@ -4425,10 +6098,16 @@ async function startTunnel(hubPort) {
|
|
|
4425
6098
|
var PROTOCOL_VERSION = 1;
|
|
4426
6099
|
function usage(error) {
|
|
4427
6100
|
if (error) console.error(`[daemon] ${error}`);
|
|
4428
|
-
console.error(`usage: alink-cli [--hub <ws(s)://host[:port]>] [--token <token>] [--dir <path>]
|
|
6101
|
+
console.error(`usage: alink-cli [--hub <ws(s)://host[:port]>] [--token <token>] [--dir <path>]... [--approval] [--approval-renotify <min>]`);
|
|
6102
|
+
console.error(` alink-cli --pair [--hub <wss://multi hub>] [--dir <path>]...`);
|
|
4429
6103
|
console.error(` alink-cli --tunnel [--port <local hub port>] [--token <token>] [--dir <path>]...`);
|
|
6104
|
+
console.error(` (--pair = QR pairing: bind this credential-less machine by scanning the terminal QR)`);
|
|
4430
6105
|
console.error(` (--tunnel = start a local hub + a free Cloudflare quick tunnel, all in one command)`);
|
|
4431
6106
|
console.error(` (the token may also be supplied via the AGENTLINK_TOKEN env var; --token wins)`);
|
|
6107
|
+
console.error(` (--approval = controlled-permission mode: sensitive tool calls suspend and await`);
|
|
6108
|
+
console.error(` phone approval \u2014 M1 supports claude only; env AGENTLINK_APPROVAL=1 equivalent)`);
|
|
6109
|
+
console.error(` (--approval-renotify <min> = re-push interval for a pending approval, default 5, 0 = off;`);
|
|
6110
|
+
console.error(` env AGENTLINK_APPROVAL_RENOTIFY_MIN)`);
|
|
4432
6111
|
process.exit(1);
|
|
4433
6112
|
}
|
|
4434
6113
|
function parseArgs(argv) {
|
|
@@ -4441,7 +6120,10 @@ function parseArgs(argv) {
|
|
|
4441
6120
|
token: { type: "string" },
|
|
4442
6121
|
dir: { type: "string", multiple: true },
|
|
4443
6122
|
tunnel: { type: "boolean" },
|
|
4444
|
-
port: { type: "string" }
|
|
6123
|
+
port: { type: "string" },
|
|
6124
|
+
pair: { type: "boolean" },
|
|
6125
|
+
approval: { type: "boolean" },
|
|
6126
|
+
"approval-renotify": { type: "string" }
|
|
4445
6127
|
},
|
|
4446
6128
|
strict: true,
|
|
4447
6129
|
allowPositionals: false
|
|
@@ -4451,21 +6133,148 @@ function parseArgs(argv) {
|
|
|
4451
6133
|
}
|
|
4452
6134
|
if (values.tunnel && values.hub) usage("--tunnel starts its own local hub; it cannot be combined with --hub");
|
|
4453
6135
|
if (values.port && !values.tunnel) usage("--port only applies to --tunnel mode (it is the LOCAL hub's port)");
|
|
6136
|
+
if (values.pair && values.tunnel) usage("--pair binds to a multi-tenant hub; it cannot be combined with --tunnel");
|
|
6137
|
+
if (values.pair && values.token) usage("--pair mints a fresh credential via scanning; it cannot be combined with --token");
|
|
4454
6138
|
const port = values.port === void 0 ? 8080 : Number(values.port);
|
|
4455
6139
|
if (!Number.isInteger(port) || port <= 0 || port > 65535) usage(`invalid --port "${values.port}" (expected 1-65535)`);
|
|
4456
6140
|
const dirs = (values.dir ?? []).map((d) => resolve(d));
|
|
4457
6141
|
if (dirs.length === 0) dirs.push(process.cwd());
|
|
6142
|
+
const envApproval = process.env.AGENTLINK_APPROVAL === "1" || process.env.AGENTLINK_APPROVAL === "true";
|
|
6143
|
+
const approval = values.approval ?? envApproval;
|
|
6144
|
+
const renotifyRaw = values["approval-renotify"] ?? (process.env.AGENTLINK_APPROVAL_RENOTIFY_MIN || void 0);
|
|
6145
|
+
const approvalRenotifyMin = renotifyRaw === void 0 ? 5 : Number(renotifyRaw);
|
|
6146
|
+
if (!Number.isInteger(approvalRenotifyMin) || approvalRenotifyMin < 0) {
|
|
6147
|
+
usage(`invalid --approval-renotify "${renotifyRaw}" (expected a non-negative integer, minutes; 0 = off)`);
|
|
6148
|
+
}
|
|
4458
6149
|
return {
|
|
4459
6150
|
// Credential precedence: --token > AGENTLINK_TOKEN env > generated UUID
|
|
4460
|
-
// (an empty env var counts as absent).
|
|
6151
|
+
// (an empty env var counts as absent). In --pair mode this resolved token
|
|
6152
|
+
// is ignored — pairing mints the credential.
|
|
4461
6153
|
token: values.token ?? (process.env.AGENTLINK_TOKEN || void 0) ?? randomUUID(),
|
|
4462
6154
|
hub: values.hub ?? (values.tunnel ? `ws://localhost:${port}` : "ws://localhost:8080"),
|
|
4463
6155
|
dirs,
|
|
4464
6156
|
tunnel: values.tunnel ?? false,
|
|
4465
|
-
port
|
|
6157
|
+
port,
|
|
6158
|
+
pair: values.pair ?? false,
|
|
6159
|
+
approval,
|
|
6160
|
+
approvalRenotifyMin
|
|
4466
6161
|
};
|
|
4467
6162
|
}
|
|
4468
|
-
var
|
|
6163
|
+
var ARGS = parseArgs(process.argv.slice(2));
|
|
6164
|
+
var {
|
|
6165
|
+
hub: HUB,
|
|
6166
|
+
dirs: DIRS,
|
|
6167
|
+
tunnel: TUNNEL,
|
|
6168
|
+
port: TUNNEL_PORT,
|
|
6169
|
+
pair: PAIR,
|
|
6170
|
+
approval: APPROVAL,
|
|
6171
|
+
approvalRenotifyMin: APPROVAL_RENOTIFY_MIN
|
|
6172
|
+
} = ARGS;
|
|
6173
|
+
var STATE_DIR2 = process.env.AGENTLINK_STATE_DIR || join6(homedir6(), ".agentlink");
|
|
6174
|
+
var CREDENTIAL_FILE = join6(STATE_DIR2, "credential");
|
|
6175
|
+
var PAIR_BACKOFF_BASE_MS = 1e3;
|
|
6176
|
+
var PAIR_BACKOFF_MAX_MS = 3e4;
|
|
6177
|
+
var STARTED_AT = Date.now();
|
|
6178
|
+
var STATUS_MID;
|
|
6179
|
+
function writeStatus(state, extra = {}) {
|
|
6180
|
+
try {
|
|
6181
|
+
mkdirSync2(STATE_DIR2, { recursive: true });
|
|
6182
|
+
writeFileSync2(
|
|
6183
|
+
join6(STATE_DIR2, "status.json"),
|
|
6184
|
+
JSON.stringify({
|
|
6185
|
+
pid: process.pid,
|
|
6186
|
+
state,
|
|
6187
|
+
hub: HUB,
|
|
6188
|
+
daemonVersion: ownVersion(),
|
|
6189
|
+
startedAt: STARTED_AT,
|
|
6190
|
+
ts: Date.now(),
|
|
6191
|
+
...STATUS_MID !== void 0 ? { machineId: STATUS_MID } : {},
|
|
6192
|
+
...extra
|
|
6193
|
+
})
|
|
6194
|
+
);
|
|
6195
|
+
} catch {
|
|
6196
|
+
}
|
|
6197
|
+
}
|
|
6198
|
+
function persistCredential(token) {
|
|
6199
|
+
mkdirSync2(STATE_DIR2, { recursive: true });
|
|
6200
|
+
writeFileSync2(CREDENTIAL_FILE, token, { mode: 384 });
|
|
6201
|
+
chmodSync2(CREDENTIAL_FILE, 384);
|
|
6202
|
+
}
|
|
6203
|
+
async function pairForCredential() {
|
|
6204
|
+
const enckey = randomBytes2(32).toString("base64url");
|
|
6205
|
+
const code = randomBytes2(16).toString("base64url");
|
|
6206
|
+
const pairString = `alp1.${code}.${enckey}`;
|
|
6207
|
+
const pairUrl = `${HUB}/daemon?pair=${encodeURIComponent(code)}&host=${encodeURIComponent(hostname())}&v=${PROTOCOL_VERSION}`;
|
|
6208
|
+
console.log(`[daemon] \u672C\u673A\u5C1A\u672A\u7ED1\u5B9A \u2014\u2014 \u8FDB\u5165\u914D\u5BF9\u6A21\u5F0F\uFF0C\u8FDE\u63A5 ${HUB} ...`);
|
|
6209
|
+
writeStatus("pairing");
|
|
6210
|
+
let printed = false;
|
|
6211
|
+
let attempts = 0;
|
|
6212
|
+
const token = await new Promise((resolveClaim) => {
|
|
6213
|
+
const attempt = () => {
|
|
6214
|
+
const ws = new import_websocket.default(pairUrl, { handshakeTimeout: 15e3 });
|
|
6215
|
+
let sawPending = false;
|
|
6216
|
+
ws.on("message", (raw) => {
|
|
6217
|
+
let msg;
|
|
6218
|
+
try {
|
|
6219
|
+
msg = JSON.parse(raw.toString());
|
|
6220
|
+
} catch {
|
|
6221
|
+
return;
|
|
6222
|
+
}
|
|
6223
|
+
if (msg.type === "pair_pending") {
|
|
6224
|
+
sawPending = true;
|
|
6225
|
+
attempts = 0;
|
|
6226
|
+
if (printed) {
|
|
6227
|
+
console.log(`[daemon] \u914D\u5BF9\u901A\u9053\u5DF2\u91CD\u8FDE\uFF0C\u4E8C\u7EF4\u7801\u4ECD\u7136\u6709\u6548\uFF0C\u7EE7\u7EED\u7B49\u5F85\u626B\u7801...`);
|
|
6228
|
+
return;
|
|
6229
|
+
}
|
|
6230
|
+
printed = true;
|
|
6231
|
+
console.log(``);
|
|
6232
|
+
console.log(` \u7528\u624B\u673A AgentLink \u7684\u300C\u6DFB\u52A0\u673A\u5668\u300D\u626B\u63CF\u4E0B\u9762\u7684\u4E8C\u7EF4\u7801\uFF0C\u5373\u53EF\u7ED1\u5B9A\u8FD9\u53F0\u7535\u8111\uFF1A`);
|
|
6233
|
+
console.log(``);
|
|
6234
|
+
import_qrcode_terminal.default.generate(pairString, { small: true });
|
|
6235
|
+
console.log(``);
|
|
6236
|
+
console.log(` \u65E0\u6CD5\u626B\u7801\u65F6\uFF0C\u4E5F\u53EF\u5728\u624B\u673A\u4E0A\u624B\u52A8\u7C98\u8D34\u914D\u5BF9\u4E32\uFF1A`);
|
|
6237
|
+
console.log(``);
|
|
6238
|
+
console.log(` ${pairString}`);
|
|
6239
|
+
console.log(``);
|
|
6240
|
+
console.log(` \u5BC6\u94A5\u6307\u7EB9 ${fingerprint(enckey)} \u2014\u2014 \u52A0\u5BC6\u5BC6\u94A5\u521A\u5728\u8FD9\u53F0\u7535\u8111\u4E0A\u751F\u6210\uFF0C`);
|
|
6241
|
+
console.log(` \u53EA\u968F\u4E8C\u7EF4\u7801\u8FDB\u5165\u4F60\u7684\u624B\u673A\uFF0C\u4E0D\u7ECF\u8FC7\u7F51\u7EDC\u4E0E\u670D\u52A1\u5668\u3002\u7B49\u5F85\u626B\u7801...`);
|
|
6242
|
+
return;
|
|
6243
|
+
}
|
|
6244
|
+
if (msg.type === "claimed" && typeof msg.token === "string" && msg.token.startsWith("al1.")) {
|
|
6245
|
+
ws.removeAllListeners("close");
|
|
6246
|
+
ws.close();
|
|
6247
|
+
resolveClaim(`${msg.token}.${enckey}`);
|
|
6248
|
+
}
|
|
6249
|
+
});
|
|
6250
|
+
ws.on("error", (err) => {
|
|
6251
|
+
console.error(`[daemon] \u914D\u5BF9\u8FDE\u63A5\u51FA\u9519: ${err.message}`);
|
|
6252
|
+
});
|
|
6253
|
+
ws.on("close", () => {
|
|
6254
|
+
if (!sawPending && attempts === 2) {
|
|
6255
|
+
console.error(
|
|
6256
|
+
`[daemon] hub \u4E00\u76F4\u6CA1\u6709\u5E94\u7B54\u914D\u5BF9 \u2014\u2014 \u5B83\u53EF\u80FD\u8FD8\u4E0D\u652F\u6301\u626B\u7801\u914D\u5BF9\uFF08\u5347\u7EA7\uFF1Anpx agentlink-hub@latest\uFF09\uFF0C\u6216 --hub \u6307\u5411\u4E86 single \u6A21\u5F0F\u7684 hub\u3002\u4ECD\u5728\u91CD\u8BD5...`
|
|
6257
|
+
);
|
|
6258
|
+
}
|
|
6259
|
+
const cap = Math.min(PAIR_BACKOFF_BASE_MS * 2 ** attempts, PAIR_BACKOFF_MAX_MS);
|
|
6260
|
+
attempts++;
|
|
6261
|
+
setTimeout(attempt, Math.floor(cap / 2 + Math.random() * (cap / 2)));
|
|
6262
|
+
});
|
|
6263
|
+
};
|
|
6264
|
+
attempt();
|
|
6265
|
+
});
|
|
6266
|
+
try {
|
|
6267
|
+
persistCredential(token);
|
|
6268
|
+
console.log(`[daemon] \u5DF2\u7ED1\u5B9A\u5230\u4F60\u7684\u8D26\u53F7 \u2014\u2014 \u51ED\u8BC1\u5DF2\u4FDD\u5B58\u5230 ${CREDENTIAL_FILE}\uFF080600\uFF09\uFF0C\u4E4B\u540E\u88F8\u8DD1 npx alink-cli \u76F4\u63A5\u590D\u7528\u3002`);
|
|
6269
|
+
} catch (err) {
|
|
6270
|
+
console.error(
|
|
6271
|
+
`[daemon] \u51ED\u8BC1\u5199\u5165 ${CREDENTIAL_FILE} \u5931\u8D25\uFF08${err instanceof Error ? err.message : err}\uFF09\u2014\u2014 \u672C\u6B21\u4ECD\u53EF\u7528\uFF0C\u4F46\u4E0B\u6B21\u542F\u52A8\u9700\u8981\u91CD\u65B0\u914D\u5BF9\u3002`
|
|
6272
|
+
);
|
|
6273
|
+
}
|
|
6274
|
+
return token;
|
|
6275
|
+
}
|
|
6276
|
+
writeStatus("starting");
|
|
6277
|
+
var RAW_TOKEN = PAIR ? await pairForCredential() : ARGS.token;
|
|
4469
6278
|
function fingerprint2(secret) {
|
|
4470
6279
|
return `${secret.slice(0, 8)}\u2026`;
|
|
4471
6280
|
}
|
|
@@ -4489,6 +6298,7 @@ function parseCredential(raw) {
|
|
|
4489
6298
|
}
|
|
4490
6299
|
var CRED = parseCredential(RAW_TOKEN);
|
|
4491
6300
|
var TOKEN = CRED.wireToken;
|
|
6301
|
+
STATUS_MID = CRED.machineId;
|
|
4492
6302
|
var ENCKEY = CRED.multi ? CRED.enckey : void 0;
|
|
4493
6303
|
if (CRED.multi) {
|
|
4494
6304
|
console.log(`[daemon] multi-tenant credential ${fingerprint2(TOKEN)}${CRED.machineId ? ` (machine ${CRED.machineId})` : ""}`);
|
|
@@ -4514,7 +6324,7 @@ function resolveDir(p) {
|
|
|
4514
6324
|
};
|
|
4515
6325
|
}
|
|
4516
6326
|
try {
|
|
4517
|
-
if (!
|
|
6327
|
+
if (!statSync2(real).isDirectory()) return { error: `"${p}" is not a directory` };
|
|
4518
6328
|
} catch (err) {
|
|
4519
6329
|
return {
|
|
4520
6330
|
error: err.code === "EACCES" ? `permission denied for "${p}"` : `cannot access "${p}"`
|
|
@@ -4524,7 +6334,7 @@ function resolveDir(p) {
|
|
|
4524
6334
|
}
|
|
4525
6335
|
function ownVersion() {
|
|
4526
6336
|
try {
|
|
4527
|
-
return JSON.parse(
|
|
6337
|
+
return JSON.parse(readFileSync5(new URL("../package.json", import.meta.url), "utf-8")).version;
|
|
4528
6338
|
} catch {
|
|
4529
6339
|
return "0.0.0";
|
|
4530
6340
|
}
|
|
@@ -4552,11 +6362,21 @@ async function probeAgents() {
|
|
|
4552
6362
|
def.probeModels ? def.probeModels(bin) : Promise.resolve([])
|
|
4553
6363
|
]);
|
|
4554
6364
|
const models = [.../* @__PURE__ */ new Set([...probed, ...def.models])];
|
|
4555
|
-
return {
|
|
6365
|
+
return {
|
|
6366
|
+
id: def.id,
|
|
6367
|
+
label: def.label,
|
|
6368
|
+
detected: true,
|
|
6369
|
+
bin,
|
|
6370
|
+
models,
|
|
6371
|
+
...version ? { version } : {},
|
|
6372
|
+
...APPROVAL && def.runWithApproval ? { approval: true } : {}
|
|
6373
|
+
};
|
|
4556
6374
|
})
|
|
4557
6375
|
);
|
|
4558
6376
|
}
|
|
4559
6377
|
var running = /* @__PURE__ */ new Map();
|
|
6378
|
+
var approvalRuns = /* @__PURE__ */ new Map();
|
|
6379
|
+
var sessionGrants = /* @__PURE__ */ new Map();
|
|
4560
6380
|
function send(ws, obj) {
|
|
4561
6381
|
if (ws.readyState === import_websocket.default.OPEN) ws.send(JSON.stringify(obj));
|
|
4562
6382
|
}
|
|
@@ -4592,8 +6412,6 @@ function handleRun(ws, { requestId, agent: agentId, prompt: rawPrompt, sessionId
|
|
|
4592
6412
|
if (!real) return fail(`cwd rejected: ${error}`);
|
|
4593
6413
|
runCwd = real;
|
|
4594
6414
|
}
|
|
4595
|
-
const invocation = adapter.buildInvocation(prompt, sessionId, typeof model === "string" && model ? model : void 0);
|
|
4596
|
-
console.log(`[daemon] requestId=${requestId} spawning ${adapter.bin} ${invocation.args.join(" ")} (cwd=${runCwd})`);
|
|
4597
6415
|
const recorder = recordRun(conversationId, {
|
|
4598
6416
|
runId: requestId,
|
|
4599
6417
|
agent: agentId,
|
|
@@ -4601,6 +6419,32 @@ function handleRun(ws, { requestId, agent: agentId, prompt: rawPrompt, sessionId
|
|
|
4601
6419
|
...cwd !== void 0 ? { cwd } : {},
|
|
4602
6420
|
...typeof model === "string" && model ? { model } : {}
|
|
4603
6421
|
});
|
|
6422
|
+
if (APPROVAL && adapter.runWithApproval) {
|
|
6423
|
+
runWithApprovalPath(ws, {
|
|
6424
|
+
requestId,
|
|
6425
|
+
adapter,
|
|
6426
|
+
prompt,
|
|
6427
|
+
sessionId,
|
|
6428
|
+
runCwd,
|
|
6429
|
+
model: typeof model === "string" && model ? model : void 0,
|
|
6430
|
+
conversationId,
|
|
6431
|
+
notifyDetail,
|
|
6432
|
+
recorder
|
|
6433
|
+
});
|
|
6434
|
+
return;
|
|
6435
|
+
}
|
|
6436
|
+
let invocation;
|
|
6437
|
+
try {
|
|
6438
|
+
invocation = adapter.buildInvocation(
|
|
6439
|
+
prompt,
|
|
6440
|
+
sessionId,
|
|
6441
|
+
typeof model === "string" && model ? model : void 0,
|
|
6442
|
+
{ approval: APPROVAL }
|
|
6443
|
+
);
|
|
6444
|
+
} catch (err) {
|
|
6445
|
+
return fail(err instanceof Error ? err.message : String(err));
|
|
6446
|
+
}
|
|
6447
|
+
console.log(`[daemon] requestId=${requestId} spawning ${adapter.bin} ${invocation.args.join(" ")} (cwd=${runCwd})`);
|
|
4604
6448
|
const child = spawn3(adapter.bin, invocation.args, { cwd: runCwd, env: spawnEnv() });
|
|
4605
6449
|
running.set(requestId, child);
|
|
4606
6450
|
child.stdin.on("error", () => {
|
|
@@ -4653,8 +6497,139 @@ function handleRun(ws, { requestId, agent: agentId, prompt: rawPrompt, sessionId
|
|
|
4653
6497
|
send(ws, { type: "done", requestId, code: null, error: err.message });
|
|
4654
6498
|
});
|
|
4655
6499
|
}
|
|
6500
|
+
var NOTIFY_TITLE_MAX = 200;
|
|
6501
|
+
function approvalNotify(tool, input) {
|
|
6502
|
+
let firstLine2 = "";
|
|
6503
|
+
try {
|
|
6504
|
+
firstLine2 = (JSON.stringify(input) ?? "").split("\n")[0] ?? "";
|
|
6505
|
+
} catch {
|
|
6506
|
+
firstLine2 = "";
|
|
6507
|
+
}
|
|
6508
|
+
return { title: `\u5BA1\u6279\uFF1A${tool}`.slice(0, NOTIFY_TITLE_MAX), summary: firstLine2.slice(0, NOTIFY_SUMMARY_MAX) };
|
|
6509
|
+
}
|
|
6510
|
+
function runWithApprovalPath(ws, opts) {
|
|
6511
|
+
const { requestId, adapter, recorder } = opts;
|
|
6512
|
+
console.log(`[daemon] requestId=${requestId} starting ${adapter.id} via SDK (approval mode, cwd=${opts.runCwd})`);
|
|
6513
|
+
let lastText;
|
|
6514
|
+
const emitEvent = (evt) => {
|
|
6515
|
+
if (evt.type === "text" && evt.text) lastText = evt.text;
|
|
6516
|
+
if (ENCKEY) {
|
|
6517
|
+
const capped = truncateEventContent(evt);
|
|
6518
|
+
const envelope = encryptEvent(ENCKEY, capped);
|
|
6519
|
+
recorder?.event(capped, envelope);
|
|
6520
|
+
send(ws, { type: "event", requestId, event: envelope });
|
|
6521
|
+
return envelope;
|
|
6522
|
+
}
|
|
6523
|
+
recorder?.event(evt);
|
|
6524
|
+
send(ws, { type: "event", requestId, event: evt });
|
|
6525
|
+
return evt;
|
|
6526
|
+
};
|
|
6527
|
+
const approvals = new RunApprovals({
|
|
6528
|
+
requestId,
|
|
6529
|
+
conversationId: opts.conversationId,
|
|
6530
|
+
renotifyMs: APPROVAL_RENOTIFY_MIN * 6e4,
|
|
6531
|
+
sessionGrants,
|
|
6532
|
+
callbacks: {
|
|
6533
|
+
sendRequest: ({ approvalId, tool, input, renotify }) => {
|
|
6534
|
+
const { input: cappedInput, inputTruncated } = capApprovalInput(input);
|
|
6535
|
+
const evt = { type: "permission_request", id: approvalId, tool, input: cappedInput, inputTruncated };
|
|
6536
|
+
let wireEvent;
|
|
6537
|
+
if (ENCKEY) {
|
|
6538
|
+
const capped = truncateEventContent(evt);
|
|
6539
|
+
wireEvent = encryptEvent(ENCKEY, capped);
|
|
6540
|
+
if (!renotify) recorder?.event(capped, wireEvent);
|
|
6541
|
+
} else {
|
|
6542
|
+
wireEvent = evt;
|
|
6543
|
+
if (!renotify) recorder?.event(evt);
|
|
6544
|
+
}
|
|
6545
|
+
send(ws, {
|
|
6546
|
+
type: "permission_request",
|
|
6547
|
+
requestId,
|
|
6548
|
+
approvalId,
|
|
6549
|
+
event: wireEvent,
|
|
6550
|
+
// Opt-in plaintext detail (§2.3): tool name + first input line,
|
|
6551
|
+
// ≤200 chars — same channel discipline as done.notify.
|
|
6552
|
+
...opts.notifyDetail === true ? { notify: approvalNotify(tool, input) } : {},
|
|
6553
|
+
...renotify ? { renotify: true } : {}
|
|
6554
|
+
});
|
|
6555
|
+
},
|
|
6556
|
+
emitResult: ({ approvalId, decision, note }) => {
|
|
6557
|
+
emitEvent({ type: "permission_result", id: approvalId, decision, ...note !== void 0 ? { note } : {} });
|
|
6558
|
+
}
|
|
6559
|
+
}
|
|
6560
|
+
});
|
|
6561
|
+
const controller = new AbortController();
|
|
6562
|
+
approvalRuns.set(requestId, { controller, approvals });
|
|
6563
|
+
void opts.adapter.runWithApproval({
|
|
6564
|
+
prompt: opts.prompt,
|
|
6565
|
+
resumeId: opts.sessionId,
|
|
6566
|
+
model: opts.model,
|
|
6567
|
+
cwd: opts.runCwd,
|
|
6568
|
+
bin: adapter.bin,
|
|
6569
|
+
onEvent: (evt) => void emitEvent(evt),
|
|
6570
|
+
requestPermission: (tool, input) => approvals.requestPermission(tool, input),
|
|
6571
|
+
signal: controller.signal
|
|
6572
|
+
}).then(
|
|
6573
|
+
({ code, error }) => ({ code, error }),
|
|
6574
|
+
(err) => ({ code: 1, error: err instanceof Error ? err.message : String(err) })
|
|
6575
|
+
).then(({ code, error }) => {
|
|
6576
|
+
approvals.abort();
|
|
6577
|
+
approvalRuns.delete(requestId);
|
|
6578
|
+
const done = {
|
|
6579
|
+
type: "done",
|
|
6580
|
+
requestId,
|
|
6581
|
+
code
|
|
6582
|
+
};
|
|
6583
|
+
if (error) done.error = error;
|
|
6584
|
+
if (opts.notifyDetail === true) done.notify = { title: adapter.id, summary: notifySummary(lastText) };
|
|
6585
|
+
console.log(`[daemon] requestId=${requestId} closed code=${code}${error ? ` error=${error}` : ""} (approval mode)`);
|
|
6586
|
+
recorder?.done(code, error);
|
|
6587
|
+
send(ws, done);
|
|
6588
|
+
});
|
|
6589
|
+
}
|
|
6590
|
+
function handlePermissionResponse(msg) {
|
|
6591
|
+
const run = approvalRuns.get(msg.requestId);
|
|
6592
|
+
if (!run) {
|
|
6593
|
+
console.log(`[daemon] permission_response requestId=${msg.requestId} ignored (no approval run in flight)`);
|
|
6594
|
+
return;
|
|
6595
|
+
}
|
|
6596
|
+
const decision = msg.decision;
|
|
6597
|
+
if (decision !== "allow" && decision !== "allow_session" && decision !== "deny") {
|
|
6598
|
+
console.log(`[daemon] permission_response approvalId=${msg.approvalId} ignored (bad decision)`);
|
|
6599
|
+
return;
|
|
6600
|
+
}
|
|
6601
|
+
let note;
|
|
6602
|
+
if (typeof msg.note === "string" && msg.note) {
|
|
6603
|
+
note = msg.note;
|
|
6604
|
+
if (ENCKEY) {
|
|
6605
|
+
try {
|
|
6606
|
+
const parsed = JSON.parse(msg.note);
|
|
6607
|
+
if (isEnvelope(parsed)) {
|
|
6608
|
+
const decoded = decryptEnvelope(ENCKEY, parsed);
|
|
6609
|
+
note = typeof decoded === "string" ? decoded : void 0;
|
|
6610
|
+
}
|
|
6611
|
+
} catch {
|
|
6612
|
+
}
|
|
6613
|
+
}
|
|
6614
|
+
} else if (msg.note && typeof msg.note === "object" && ENCKEY && isEnvelope(msg.note)) {
|
|
6615
|
+
try {
|
|
6616
|
+
const decoded = decryptEnvelope(ENCKEY, msg.note);
|
|
6617
|
+
note = typeof decoded === "string" ? decoded : void 0;
|
|
6618
|
+
} catch {
|
|
6619
|
+
note = void 0;
|
|
6620
|
+
}
|
|
6621
|
+
}
|
|
6622
|
+
run.approvals.resolve(msg.approvalId, decision, note);
|
|
6623
|
+
}
|
|
4656
6624
|
var SIGKILL_GRACE_MS = 2e3;
|
|
4657
6625
|
function handleCancel(requestId) {
|
|
6626
|
+
const approvalRun = approvalRuns.get(requestId);
|
|
6627
|
+
if (approvalRun) {
|
|
6628
|
+
console.log(`[daemon] cancel requestId=${requestId} \u2014 aborting SDK run`);
|
|
6629
|
+
approvalRun.approvals.abort();
|
|
6630
|
+
approvalRun.controller.abort();
|
|
6631
|
+
return;
|
|
6632
|
+
}
|
|
4658
6633
|
const child = running.get(requestId);
|
|
4659
6634
|
if (!child) {
|
|
4660
6635
|
console.log(`[daemon] cancel requestId=${requestId} ignored (unknown or already finished)`);
|
|
@@ -4678,7 +6653,7 @@ function handleListdir(ws, { requestId, path }) {
|
|
|
4678
6653
|
const { real, error } = resolveDir(path);
|
|
4679
6654
|
if (!real) return reply([], error);
|
|
4680
6655
|
try {
|
|
4681
|
-
const dirs =
|
|
6656
|
+
const dirs = readdirSync4(real, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => join6(real, e.name)).sort();
|
|
4682
6657
|
reply(dirs);
|
|
4683
6658
|
} catch (err) {
|
|
4684
6659
|
reply(
|
|
@@ -4708,6 +6683,31 @@ function handleConvClear(ws, requestId) {
|
|
|
4708
6683
|
function handleHistory(ws, requestId, conversationId) {
|
|
4709
6684
|
send(ws, { type: "history_result", requestId, runs: history(conversationId) });
|
|
4710
6685
|
}
|
|
6686
|
+
function handleScanSessions(ws, requestId) {
|
|
6687
|
+
let sessions;
|
|
6688
|
+
try {
|
|
6689
|
+
const list = scanClaudeSessions();
|
|
6690
|
+
sessions = ENCKEY ? encryptEvent(ENCKEY, list) : list;
|
|
6691
|
+
} catch (err) {
|
|
6692
|
+
return send(ws, { type: "scan_sessions_result", requestId, sessions: ENCKEY ? void 0 : [], error: err instanceof Error ? err.message : String(err) });
|
|
6693
|
+
}
|
|
6694
|
+
send(ws, { type: "scan_sessions_result", requestId, sessions });
|
|
6695
|
+
}
|
|
6696
|
+
function handleSessionHistory(ws, requestId, agent, sessionId) {
|
|
6697
|
+
if (typeof agent !== "string" || typeof sessionId !== "string") {
|
|
6698
|
+
return send(ws, { type: "session_history_result", requestId, runs: [], error: "malformed session_history: agent and sessionId are required" });
|
|
6699
|
+
}
|
|
6700
|
+
const result = claudeSessionHistory(agent, sessionId);
|
|
6701
|
+
if ("error" in result) {
|
|
6702
|
+
return send(ws, { type: "session_history_result", requestId, runs: [], error: result.error });
|
|
6703
|
+
}
|
|
6704
|
+
const runs = ENCKEY ? result.runs.map((r) => ({
|
|
6705
|
+
...r,
|
|
6706
|
+
prompt: encryptEvent(ENCKEY, r.prompt),
|
|
6707
|
+
events: r.events.map((e) => encryptEvent(ENCKEY, truncateEventContent(e)))
|
|
6708
|
+
})) : result.runs;
|
|
6709
|
+
send(ws, { type: "session_history_result", requestId, runs, truncatedEarlier: result.truncatedEarlier });
|
|
6710
|
+
}
|
|
4711
6711
|
var PUBLIC_BASE = null;
|
|
4712
6712
|
var stopTunnel = null;
|
|
4713
6713
|
if (TUNNEL) {
|
|
@@ -4716,12 +6716,21 @@ if (TUNNEL) {
|
|
|
4716
6716
|
stopTunnel = t.stop;
|
|
4717
6717
|
console.log(`[daemon] tunnel ready: ${PUBLIC_BASE}`);
|
|
4718
6718
|
}
|
|
4719
|
-
process.on("exit", () =>
|
|
6719
|
+
process.on("exit", (code) => {
|
|
6720
|
+
writeStatus("stopped", { code });
|
|
6721
|
+
stopTunnel?.();
|
|
6722
|
+
});
|
|
4720
6723
|
process.on("SIGINT", () => process.exit(130));
|
|
4721
6724
|
process.on("SIGTERM", () => process.exit(143));
|
|
4722
6725
|
var agents = await probeAgents();
|
|
4723
6726
|
var detected = agents.filter((a) => a.detected);
|
|
4724
6727
|
console.log(`[daemon] detected agents: ${detected.length ? detected.map((a) => a.id).join(", ") : "(none)"}`);
|
|
6728
|
+
if (APPROVAL) {
|
|
6729
|
+
const capable = agents.filter((a) => a.approval).map((a) => a.id);
|
|
6730
|
+
console.log(
|
|
6731
|
+
`[daemon] approval mode ON (renotify ${APPROVAL_RENOTIFY_MIN === 0 ? "off" : `${APPROVAL_RENOTIFY_MIN}min`}) \u2014 controlled agents: ${capable.length ? capable.join(", ") : "(none: no detected agent supports approval yet)"}`
|
|
6732
|
+
);
|
|
6733
|
+
}
|
|
4725
6734
|
var url = `${HUB}/daemon?token=${encodeURIComponent(TOKEN)}&v=${PROTOCOL_VERSION}`;
|
|
4726
6735
|
var urlForLog = `${HUB}/daemon?token=${fingerprint2(TOKEN)}&v=${PROTOCOL_VERSION}`;
|
|
4727
6736
|
var BACKOFF_BASE_MS = 1e3;
|
|
@@ -4777,8 +6786,14 @@ function connect2() {
|
|
|
4777
6786
|
failures = 0;
|
|
4778
6787
|
armPingWatchdog();
|
|
4779
6788
|
console.log(`[daemon] hub says hello (protocol v${msg.v}, hub ${msg.hubVersion ?? "?"})`);
|
|
4780
|
-
|
|
6789
|
+
if (APPROVAL && !(Array.isArray(msg.features) && msg.features.includes("approval"))) {
|
|
6790
|
+
console.error(
|
|
6791
|
+
`[daemon] WARNING: --approval is on but the hub at ${HUB} (${msg.hubVersion ?? "unknown version"}) predates approval support \u2014 suspended tool calls will get NO push notification and NO card. Upgrade the hub (npx agentlink-hub@latest).`
|
|
6792
|
+
);
|
|
6793
|
+
}
|
|
6794
|
+
send(ws, { type: "register", hostname: hostname(), daemonVersion: ownVersion(), dirs: DIRS, home: homedir6(), agents, e2e: CRED.enckey !== void 0 });
|
|
4781
6795
|
console.log(`[daemon] registered. Waiting for work pushed from the hub...`);
|
|
6796
|
+
writeStatus("connected");
|
|
4782
6797
|
if (printedLink) return;
|
|
4783
6798
|
printedLink = true;
|
|
4784
6799
|
if (CRED.multi) {
|
|
@@ -4797,6 +6812,8 @@ function connect2() {
|
|
|
4797
6812
|
handleRun(ws, msg);
|
|
4798
6813
|
} else if (msg.type === "cancel" && typeof msg.requestId === "string") {
|
|
4799
6814
|
handleCancel(msg.requestId);
|
|
6815
|
+
} else if (msg.type === "permission_response" && typeof msg.requestId === "string" && typeof msg.approvalId === "string") {
|
|
6816
|
+
handlePermissionResponse(msg);
|
|
4800
6817
|
} else if (msg.type === "listdir" && typeof msg.requestId === "string") {
|
|
4801
6818
|
handleListdir(ws, msg);
|
|
4802
6819
|
} else if (msg.type === "conv_list" && typeof msg.requestId === "string") {
|
|
@@ -4809,6 +6826,10 @@ function connect2() {
|
|
|
4809
6826
|
handleConvClear(ws, msg.requestId);
|
|
4810
6827
|
} else if (msg.type === "history" && typeof msg.requestId === "string") {
|
|
4811
6828
|
handleHistory(ws, msg.requestId, msg.conversationId);
|
|
6829
|
+
} else if (msg.type === "scan_sessions" && typeof msg.requestId === "string") {
|
|
6830
|
+
handleScanSessions(ws, msg.requestId);
|
|
6831
|
+
} else if (msg.type === "session_history" && typeof msg.requestId === "string") {
|
|
6832
|
+
handleSessionHistory(ws, msg.requestId, msg.agent, msg.sessionId);
|
|
4812
6833
|
} else {
|
|
4813
6834
|
console.log(`[daemon] ignoring message with unknown shape: ${raw}`);
|
|
4814
6835
|
}
|
|
@@ -4824,10 +6845,15 @@ function connect2() {
|
|
|
4824
6845
|
child.kill();
|
|
4825
6846
|
}
|
|
4826
6847
|
running.clear();
|
|
6848
|
+
for (const [requestId, run] of approvalRuns) {
|
|
6849
|
+
console.log(`[daemon] aborting in-flight approval requestId=${requestId} (hub connection closed)`);
|
|
6850
|
+
run.approvals.abort();
|
|
6851
|
+
run.controller.abort();
|
|
6852
|
+
}
|
|
6853
|
+
approvalRuns.clear();
|
|
4827
6854
|
if (code === 4403) {
|
|
4828
|
-
const credentialFile = join5(process.env.AGENTLINK_STATE_DIR || join5(homedir5(), ".agentlink"), "credential");
|
|
4829
6855
|
try {
|
|
4830
|
-
rmSync2(
|
|
6856
|
+
rmSync2(CREDENTIAL_FILE, { force: true });
|
|
4831
6857
|
} catch {
|
|
4832
6858
|
}
|
|
4833
6859
|
console.error(`[daemon] this machine was removed from your AgentLink console (close 4403). The locally saved credential has been deleted; add the machine again to reconnect.`);
|
|
@@ -4853,6 +6879,7 @@ function connect2() {
|
|
|
4853
6879
|
failures++;
|
|
4854
6880
|
const detail = code ? ` (code ${code}${reason?.length ? `, ${reason}` : ""})` : "";
|
|
4855
6881
|
console.error(`[daemon] connection to hub closed${detail} \u2014 reconnecting in ${(delay / 1e3).toFixed(1)}s (attempt ${failures})`);
|
|
6882
|
+
writeStatus("reconnecting", { attempt: failures });
|
|
4856
6883
|
setTimeout(connect2, delay);
|
|
4857
6884
|
});
|
|
4858
6885
|
}
|