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/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: randomBytes2, createHash: createHash2 } = __require("crypto");
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 = randomBytes2(16).toString("base64");
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 readFileSync4, readdirSync as readdirSync3, realpathSync, rmSync as rmSync2, statSync } from "node:fs";
3709
- import { constants as osConstants, homedir as homedir5, hostname } from "node:os";
3710
- import { join as join5, resolve } from "node:path";
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
- buildInvocation: (prompt, resumeId, model) => {
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 ? ["exec", "resume", resumeId, "-", "--json", "--skip-git-repo-check", "--dangerously-bypass-approvals-and-sandbox", ...m] : ["exec", "--json", "--skip-git-repo-check", "--sandbox", "workspace-write", ...m],
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
- buildInvocation: (prompt, resumeId, model) => {
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 ? ["exec", "--json", "--skip-git-repo-check", "--dangerously-bypass-approvals-and-sandbox", ...m, "resume", resumeId, prompt] : ["exec", "--json", "--skip-git-repo-check", "--sandbox", "workspace-write", ...m, prompt]
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 { token: RAW_TOKEN, hub: HUB, dirs: DIRS, tunnel: TUNNEL, port: TUNNEL_PORT } = parseArgs(process.argv.slice(2));
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 (!statSync(real).isDirectory()) return { error: `"${p}" is not a directory` };
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(readFileSync4(new URL("../package.json", import.meta.url), "utf-8")).version;
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 { id: def.id, label: def.label, detected: true, bin, models, ...version ? { version } : {} };
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 = readdirSync3(real, { withFileTypes: true }).filter((e) => e.isDirectory() && !e.name.startsWith(".")).map((e) => join5(real, e.name)).sort();
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", () => stopTunnel?.());
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
- send(ws, { type: "register", hostname: hostname(), daemonVersion: ownVersion(), dirs: DIRS, home: homedir5(), agents, e2e: CRED.enckey !== void 0 });
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(credentialFile, { force: true });
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
  }