dsh-dock 0.5.0 → 0.7.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/client.js CHANGED
@@ -11,6 +11,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
11
11
  var __getOwnPropNames = Object.getOwnPropertyNames;
12
12
  var __getProtoOf = Object.getPrototypeOf;
13
13
  var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __commonJS = (cb, mod) => function __require() {
15
+ try {
16
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
17
+ } catch (e) {
18
+ throw mod = 0, e;
19
+ }
20
+ };
14
21
  var __export = (target, all) => {
15
22
  for (var name in all)
16
23
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -21,17 +28,2095 @@ var __copyProps = (to, from, except, desc) => {
21
28
  if (!__hasOwnProp.call(to, key) && key !== except)
22
29
  __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
23
30
  }
24
- return to;
25
- };
26
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
27
- // If the importer is in node compatibility mode or this is not an ESM
28
- // file that has been converted to a CommonJS file using a Babel-
29
- // compatible transform (i.e. "__esModule" has not been set), then set
30
- // "default" to the CommonJS "module.exports" for node compatibility.
31
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
32
- mod
33
- ));
34
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
31
+ return to;
32
+ };
33
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
34
+ // If the importer is in node compatibility mode or this is not an ESM
35
+ // file that has been converted to a CommonJS file using a Babel-
36
+ // compatible transform (i.e. "__esModule" has not been set), then set
37
+ // "default" to the CommonJS "module.exports" for node compatibility.
38
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
39
+ mod
40
+ ));
41
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
42
+
43
+ // node_modules/qrcode/lib/can-promise.js
44
+ var require_can_promise = __commonJS({
45
+ "node_modules/qrcode/lib/can-promise.js"(exports, module2) {
46
+ module2.exports = function() {
47
+ return typeof Promise === "function" && Promise.prototype && Promise.prototype.then;
48
+ };
49
+ }
50
+ });
51
+
52
+ // node_modules/qrcode/lib/core/utils.js
53
+ var require_utils = __commonJS({
54
+ "node_modules/qrcode/lib/core/utils.js"(exports) {
55
+ var toSJISFunction;
56
+ var CODEWORDS_COUNT = [
57
+ 0,
58
+ // Not used
59
+ 26,
60
+ 44,
61
+ 70,
62
+ 100,
63
+ 134,
64
+ 172,
65
+ 196,
66
+ 242,
67
+ 292,
68
+ 346,
69
+ 404,
70
+ 466,
71
+ 532,
72
+ 581,
73
+ 655,
74
+ 733,
75
+ 815,
76
+ 901,
77
+ 991,
78
+ 1085,
79
+ 1156,
80
+ 1258,
81
+ 1364,
82
+ 1474,
83
+ 1588,
84
+ 1706,
85
+ 1828,
86
+ 1921,
87
+ 2051,
88
+ 2185,
89
+ 2323,
90
+ 2465,
91
+ 2611,
92
+ 2761,
93
+ 2876,
94
+ 3034,
95
+ 3196,
96
+ 3362,
97
+ 3532,
98
+ 3706
99
+ ];
100
+ exports.getSymbolSize = function getSymbolSize(version) {
101
+ if (!version) throw new Error('"version" cannot be null or undefined');
102
+ if (version < 1 || version > 40) throw new Error('"version" should be in range from 1 to 40');
103
+ return version * 4 + 17;
104
+ };
105
+ exports.getSymbolTotalCodewords = function getSymbolTotalCodewords(version) {
106
+ return CODEWORDS_COUNT[version];
107
+ };
108
+ exports.getBCHDigit = function(data) {
109
+ let digit = 0;
110
+ while (data !== 0) {
111
+ digit++;
112
+ data >>>= 1;
113
+ }
114
+ return digit;
115
+ };
116
+ exports.setToSJISFunction = function setToSJISFunction(f) {
117
+ if (typeof f !== "function") {
118
+ throw new Error('"toSJISFunc" is not a valid function.');
119
+ }
120
+ toSJISFunction = f;
121
+ };
122
+ exports.isKanjiModeEnabled = function() {
123
+ return typeof toSJISFunction !== "undefined";
124
+ };
125
+ exports.toSJIS = function toSJIS(kanji) {
126
+ return toSJISFunction(kanji);
127
+ };
128
+ }
129
+ });
130
+
131
+ // node_modules/qrcode/lib/core/error-correction-level.js
132
+ var require_error_correction_level = __commonJS({
133
+ "node_modules/qrcode/lib/core/error-correction-level.js"(exports) {
134
+ exports.L = { bit: 1 };
135
+ exports.M = { bit: 0 };
136
+ exports.Q = { bit: 3 };
137
+ exports.H = { bit: 2 };
138
+ function fromString(string) {
139
+ if (typeof string !== "string") {
140
+ throw new Error("Param is not a string");
141
+ }
142
+ const lcStr = string.toLowerCase();
143
+ switch (lcStr) {
144
+ case "l":
145
+ case "low":
146
+ return exports.L;
147
+ case "m":
148
+ case "medium":
149
+ return exports.M;
150
+ case "q":
151
+ case "quartile":
152
+ return exports.Q;
153
+ case "h":
154
+ case "high":
155
+ return exports.H;
156
+ default:
157
+ throw new Error("Unknown EC Level: " + string);
158
+ }
159
+ }
160
+ exports.isValid = function isValid(level) {
161
+ return level && typeof level.bit !== "undefined" && level.bit >= 0 && level.bit < 4;
162
+ };
163
+ exports.from = function from(value, defaultValue) {
164
+ if (exports.isValid(value)) {
165
+ return value;
166
+ }
167
+ try {
168
+ return fromString(value);
169
+ } catch (e) {
170
+ return defaultValue;
171
+ }
172
+ };
173
+ }
174
+ });
175
+
176
+ // node_modules/qrcode/lib/core/bit-buffer.js
177
+ var require_bit_buffer = __commonJS({
178
+ "node_modules/qrcode/lib/core/bit-buffer.js"(exports, module2) {
179
+ function BitBuffer() {
180
+ this.buffer = [];
181
+ this.length = 0;
182
+ }
183
+ BitBuffer.prototype = {
184
+ get: function(index) {
185
+ const bufIndex = Math.floor(index / 8);
186
+ return (this.buffer[bufIndex] >>> 7 - index % 8 & 1) === 1;
187
+ },
188
+ put: function(num, length) {
189
+ for (let i = 0; i < length; i++) {
190
+ this.putBit((num >>> length - i - 1 & 1) === 1);
191
+ }
192
+ },
193
+ getLengthInBits: function() {
194
+ return this.length;
195
+ },
196
+ putBit: function(bit) {
197
+ const bufIndex = Math.floor(this.length / 8);
198
+ if (this.buffer.length <= bufIndex) {
199
+ this.buffer.push(0);
200
+ }
201
+ if (bit) {
202
+ this.buffer[bufIndex] |= 128 >>> this.length % 8;
203
+ }
204
+ this.length++;
205
+ }
206
+ };
207
+ module2.exports = BitBuffer;
208
+ }
209
+ });
210
+
211
+ // node_modules/qrcode/lib/core/bit-matrix.js
212
+ var require_bit_matrix = __commonJS({
213
+ "node_modules/qrcode/lib/core/bit-matrix.js"(exports, module2) {
214
+ function BitMatrix(size) {
215
+ if (!size || size < 1) {
216
+ throw new Error("BitMatrix size must be defined and greater than 0");
217
+ }
218
+ this.size = size;
219
+ this.data = new Uint8Array(size * size);
220
+ this.reservedBit = new Uint8Array(size * size);
221
+ }
222
+ BitMatrix.prototype.set = function(row, col, value, reserved) {
223
+ const index = row * this.size + col;
224
+ this.data[index] = value;
225
+ if (reserved) this.reservedBit[index] = true;
226
+ };
227
+ BitMatrix.prototype.get = function(row, col) {
228
+ return this.data[row * this.size + col];
229
+ };
230
+ BitMatrix.prototype.xor = function(row, col, value) {
231
+ this.data[row * this.size + col] ^= value;
232
+ };
233
+ BitMatrix.prototype.isReserved = function(row, col) {
234
+ return this.reservedBit[row * this.size + col];
235
+ };
236
+ module2.exports = BitMatrix;
237
+ }
238
+ });
239
+
240
+ // node_modules/qrcode/lib/core/alignment-pattern.js
241
+ var require_alignment_pattern = __commonJS({
242
+ "node_modules/qrcode/lib/core/alignment-pattern.js"(exports) {
243
+ var getSymbolSize = require_utils().getSymbolSize;
244
+ exports.getRowColCoords = function getRowColCoords(version) {
245
+ if (version === 1) return [];
246
+ const posCount = Math.floor(version / 7) + 2;
247
+ const size = getSymbolSize(version);
248
+ const intervals = size === 145 ? 26 : Math.ceil((size - 13) / (2 * posCount - 2)) * 2;
249
+ const positions = [size - 7];
250
+ for (let i = 1; i < posCount - 1; i++) {
251
+ positions[i] = positions[i - 1] - intervals;
252
+ }
253
+ positions.push(6);
254
+ return positions.reverse();
255
+ };
256
+ exports.getPositions = function getPositions(version) {
257
+ const coords = [];
258
+ const pos = exports.getRowColCoords(version);
259
+ const posLength = pos.length;
260
+ for (let i = 0; i < posLength; i++) {
261
+ for (let j = 0; j < posLength; j++) {
262
+ if (i === 0 && j === 0 || // top-left
263
+ i === 0 && j === posLength - 1 || // bottom-left
264
+ i === posLength - 1 && j === 0) {
265
+ continue;
266
+ }
267
+ coords.push([pos[i], pos[j]]);
268
+ }
269
+ }
270
+ return coords;
271
+ };
272
+ }
273
+ });
274
+
275
+ // node_modules/qrcode/lib/core/finder-pattern.js
276
+ var require_finder_pattern = __commonJS({
277
+ "node_modules/qrcode/lib/core/finder-pattern.js"(exports) {
278
+ var getSymbolSize = require_utils().getSymbolSize;
279
+ var FINDER_PATTERN_SIZE = 7;
280
+ exports.getPositions = function getPositions(version) {
281
+ const size = getSymbolSize(version);
282
+ return [
283
+ // top-left
284
+ [0, 0],
285
+ // top-right
286
+ [size - FINDER_PATTERN_SIZE, 0],
287
+ // bottom-left
288
+ [0, size - FINDER_PATTERN_SIZE]
289
+ ];
290
+ };
291
+ }
292
+ });
293
+
294
+ // node_modules/qrcode/lib/core/mask-pattern.js
295
+ var require_mask_pattern = __commonJS({
296
+ "node_modules/qrcode/lib/core/mask-pattern.js"(exports) {
297
+ exports.Patterns = {
298
+ PATTERN000: 0,
299
+ PATTERN001: 1,
300
+ PATTERN010: 2,
301
+ PATTERN011: 3,
302
+ PATTERN100: 4,
303
+ PATTERN101: 5,
304
+ PATTERN110: 6,
305
+ PATTERN111: 7
306
+ };
307
+ var PenaltyScores = {
308
+ N1: 3,
309
+ N2: 3,
310
+ N3: 40,
311
+ N4: 10
312
+ };
313
+ exports.isValid = function isValid(mask) {
314
+ return mask != null && mask !== "" && !isNaN(mask) && mask >= 0 && mask <= 7;
315
+ };
316
+ exports.from = function from(value) {
317
+ return exports.isValid(value) ? parseInt(value, 10) : void 0;
318
+ };
319
+ exports.getPenaltyN1 = function getPenaltyN1(data) {
320
+ const size = data.size;
321
+ let points = 0;
322
+ let sameCountCol = 0;
323
+ let sameCountRow = 0;
324
+ let lastCol = null;
325
+ let lastRow = null;
326
+ for (let row = 0; row < size; row++) {
327
+ sameCountCol = sameCountRow = 0;
328
+ lastCol = lastRow = null;
329
+ for (let col = 0; col < size; col++) {
330
+ let module3 = data.get(row, col);
331
+ if (module3 === lastCol) {
332
+ sameCountCol++;
333
+ } else {
334
+ if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
335
+ lastCol = module3;
336
+ sameCountCol = 1;
337
+ }
338
+ module3 = data.get(col, row);
339
+ if (module3 === lastRow) {
340
+ sameCountRow++;
341
+ } else {
342
+ if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
343
+ lastRow = module3;
344
+ sameCountRow = 1;
345
+ }
346
+ }
347
+ if (sameCountCol >= 5) points += PenaltyScores.N1 + (sameCountCol - 5);
348
+ if (sameCountRow >= 5) points += PenaltyScores.N1 + (sameCountRow - 5);
349
+ }
350
+ return points;
351
+ };
352
+ exports.getPenaltyN2 = function getPenaltyN2(data) {
353
+ const size = data.size;
354
+ let points = 0;
355
+ for (let row = 0; row < size - 1; row++) {
356
+ for (let col = 0; col < size - 1; col++) {
357
+ const last = data.get(row, col) + data.get(row, col + 1) + data.get(row + 1, col) + data.get(row + 1, col + 1);
358
+ if (last === 4 || last === 0) points++;
359
+ }
360
+ }
361
+ return points * PenaltyScores.N2;
362
+ };
363
+ exports.getPenaltyN3 = function getPenaltyN3(data) {
364
+ const size = data.size;
365
+ let points = 0;
366
+ let bitsCol = 0;
367
+ let bitsRow = 0;
368
+ for (let row = 0; row < size; row++) {
369
+ bitsCol = bitsRow = 0;
370
+ for (let col = 0; col < size; col++) {
371
+ bitsCol = bitsCol << 1 & 2047 | data.get(row, col);
372
+ if (col >= 10 && (bitsCol === 1488 || bitsCol === 93)) points++;
373
+ bitsRow = bitsRow << 1 & 2047 | data.get(col, row);
374
+ if (col >= 10 && (bitsRow === 1488 || bitsRow === 93)) points++;
375
+ }
376
+ }
377
+ return points * PenaltyScores.N3;
378
+ };
379
+ exports.getPenaltyN4 = function getPenaltyN4(data) {
380
+ let darkCount = 0;
381
+ const modulesCount = data.data.length;
382
+ for (let i = 0; i < modulesCount; i++) darkCount += data.data[i];
383
+ const k = Math.abs(Math.ceil(darkCount * 100 / modulesCount / 5) - 10);
384
+ return k * PenaltyScores.N4;
385
+ };
386
+ function getMaskAt(maskPattern, i, j) {
387
+ switch (maskPattern) {
388
+ case exports.Patterns.PATTERN000:
389
+ return (i + j) % 2 === 0;
390
+ case exports.Patterns.PATTERN001:
391
+ return i % 2 === 0;
392
+ case exports.Patterns.PATTERN010:
393
+ return j % 3 === 0;
394
+ case exports.Patterns.PATTERN011:
395
+ return (i + j) % 3 === 0;
396
+ case exports.Patterns.PATTERN100:
397
+ return (Math.floor(i / 2) + Math.floor(j / 3)) % 2 === 0;
398
+ case exports.Patterns.PATTERN101:
399
+ return i * j % 2 + i * j % 3 === 0;
400
+ case exports.Patterns.PATTERN110:
401
+ return (i * j % 2 + i * j % 3) % 2 === 0;
402
+ case exports.Patterns.PATTERN111:
403
+ return (i * j % 3 + (i + j) % 2) % 2 === 0;
404
+ default:
405
+ throw new Error("bad maskPattern:" + maskPattern);
406
+ }
407
+ }
408
+ exports.applyMask = function applyMask(pattern, data) {
409
+ const size = data.size;
410
+ for (let col = 0; col < size; col++) {
411
+ for (let row = 0; row < size; row++) {
412
+ if (data.isReserved(row, col)) continue;
413
+ data.xor(row, col, getMaskAt(pattern, row, col));
414
+ }
415
+ }
416
+ };
417
+ exports.getBestMask = function getBestMask(data, setupFormatFunc) {
418
+ const numPatterns = Object.keys(exports.Patterns).length;
419
+ let bestPattern = 0;
420
+ let lowerPenalty = Infinity;
421
+ for (let p = 0; p < numPatterns; p++) {
422
+ setupFormatFunc(p);
423
+ exports.applyMask(p, data);
424
+ const penalty = exports.getPenaltyN1(data) + exports.getPenaltyN2(data) + exports.getPenaltyN3(data) + exports.getPenaltyN4(data);
425
+ exports.applyMask(p, data);
426
+ if (penalty < lowerPenalty) {
427
+ lowerPenalty = penalty;
428
+ bestPattern = p;
429
+ }
430
+ }
431
+ return bestPattern;
432
+ };
433
+ }
434
+ });
435
+
436
+ // node_modules/qrcode/lib/core/error-correction-code.js
437
+ var require_error_correction_code = __commonJS({
438
+ "node_modules/qrcode/lib/core/error-correction-code.js"(exports) {
439
+ var ECLevel = require_error_correction_level();
440
+ var EC_BLOCKS_TABLE = [
441
+ // L M Q H
442
+ 1,
443
+ 1,
444
+ 1,
445
+ 1,
446
+ 1,
447
+ 1,
448
+ 1,
449
+ 1,
450
+ 1,
451
+ 1,
452
+ 2,
453
+ 2,
454
+ 1,
455
+ 2,
456
+ 2,
457
+ 4,
458
+ 1,
459
+ 2,
460
+ 4,
461
+ 4,
462
+ 2,
463
+ 4,
464
+ 4,
465
+ 4,
466
+ 2,
467
+ 4,
468
+ 6,
469
+ 5,
470
+ 2,
471
+ 4,
472
+ 6,
473
+ 6,
474
+ 2,
475
+ 5,
476
+ 8,
477
+ 8,
478
+ 4,
479
+ 5,
480
+ 8,
481
+ 8,
482
+ 4,
483
+ 5,
484
+ 8,
485
+ 11,
486
+ 4,
487
+ 8,
488
+ 10,
489
+ 11,
490
+ 4,
491
+ 9,
492
+ 12,
493
+ 16,
494
+ 4,
495
+ 9,
496
+ 16,
497
+ 16,
498
+ 6,
499
+ 10,
500
+ 12,
501
+ 18,
502
+ 6,
503
+ 10,
504
+ 17,
505
+ 16,
506
+ 6,
507
+ 11,
508
+ 16,
509
+ 19,
510
+ 6,
511
+ 13,
512
+ 18,
513
+ 21,
514
+ 7,
515
+ 14,
516
+ 21,
517
+ 25,
518
+ 8,
519
+ 16,
520
+ 20,
521
+ 25,
522
+ 8,
523
+ 17,
524
+ 23,
525
+ 25,
526
+ 9,
527
+ 17,
528
+ 23,
529
+ 34,
530
+ 9,
531
+ 18,
532
+ 25,
533
+ 30,
534
+ 10,
535
+ 20,
536
+ 27,
537
+ 32,
538
+ 12,
539
+ 21,
540
+ 29,
541
+ 35,
542
+ 12,
543
+ 23,
544
+ 34,
545
+ 37,
546
+ 12,
547
+ 25,
548
+ 34,
549
+ 40,
550
+ 13,
551
+ 26,
552
+ 35,
553
+ 42,
554
+ 14,
555
+ 28,
556
+ 38,
557
+ 45,
558
+ 15,
559
+ 29,
560
+ 40,
561
+ 48,
562
+ 16,
563
+ 31,
564
+ 43,
565
+ 51,
566
+ 17,
567
+ 33,
568
+ 45,
569
+ 54,
570
+ 18,
571
+ 35,
572
+ 48,
573
+ 57,
574
+ 19,
575
+ 37,
576
+ 51,
577
+ 60,
578
+ 19,
579
+ 38,
580
+ 53,
581
+ 63,
582
+ 20,
583
+ 40,
584
+ 56,
585
+ 66,
586
+ 21,
587
+ 43,
588
+ 59,
589
+ 70,
590
+ 22,
591
+ 45,
592
+ 62,
593
+ 74,
594
+ 24,
595
+ 47,
596
+ 65,
597
+ 77,
598
+ 25,
599
+ 49,
600
+ 68,
601
+ 81
602
+ ];
603
+ var EC_CODEWORDS_TABLE = [
604
+ // L M Q H
605
+ 7,
606
+ 10,
607
+ 13,
608
+ 17,
609
+ 10,
610
+ 16,
611
+ 22,
612
+ 28,
613
+ 15,
614
+ 26,
615
+ 36,
616
+ 44,
617
+ 20,
618
+ 36,
619
+ 52,
620
+ 64,
621
+ 26,
622
+ 48,
623
+ 72,
624
+ 88,
625
+ 36,
626
+ 64,
627
+ 96,
628
+ 112,
629
+ 40,
630
+ 72,
631
+ 108,
632
+ 130,
633
+ 48,
634
+ 88,
635
+ 132,
636
+ 156,
637
+ 60,
638
+ 110,
639
+ 160,
640
+ 192,
641
+ 72,
642
+ 130,
643
+ 192,
644
+ 224,
645
+ 80,
646
+ 150,
647
+ 224,
648
+ 264,
649
+ 96,
650
+ 176,
651
+ 260,
652
+ 308,
653
+ 104,
654
+ 198,
655
+ 288,
656
+ 352,
657
+ 120,
658
+ 216,
659
+ 320,
660
+ 384,
661
+ 132,
662
+ 240,
663
+ 360,
664
+ 432,
665
+ 144,
666
+ 280,
667
+ 408,
668
+ 480,
669
+ 168,
670
+ 308,
671
+ 448,
672
+ 532,
673
+ 180,
674
+ 338,
675
+ 504,
676
+ 588,
677
+ 196,
678
+ 364,
679
+ 546,
680
+ 650,
681
+ 224,
682
+ 416,
683
+ 600,
684
+ 700,
685
+ 224,
686
+ 442,
687
+ 644,
688
+ 750,
689
+ 252,
690
+ 476,
691
+ 690,
692
+ 816,
693
+ 270,
694
+ 504,
695
+ 750,
696
+ 900,
697
+ 300,
698
+ 560,
699
+ 810,
700
+ 960,
701
+ 312,
702
+ 588,
703
+ 870,
704
+ 1050,
705
+ 336,
706
+ 644,
707
+ 952,
708
+ 1110,
709
+ 360,
710
+ 700,
711
+ 1020,
712
+ 1200,
713
+ 390,
714
+ 728,
715
+ 1050,
716
+ 1260,
717
+ 420,
718
+ 784,
719
+ 1140,
720
+ 1350,
721
+ 450,
722
+ 812,
723
+ 1200,
724
+ 1440,
725
+ 480,
726
+ 868,
727
+ 1290,
728
+ 1530,
729
+ 510,
730
+ 924,
731
+ 1350,
732
+ 1620,
733
+ 540,
734
+ 980,
735
+ 1440,
736
+ 1710,
737
+ 570,
738
+ 1036,
739
+ 1530,
740
+ 1800,
741
+ 570,
742
+ 1064,
743
+ 1590,
744
+ 1890,
745
+ 600,
746
+ 1120,
747
+ 1680,
748
+ 1980,
749
+ 630,
750
+ 1204,
751
+ 1770,
752
+ 2100,
753
+ 660,
754
+ 1260,
755
+ 1860,
756
+ 2220,
757
+ 720,
758
+ 1316,
759
+ 1950,
760
+ 2310,
761
+ 750,
762
+ 1372,
763
+ 2040,
764
+ 2430
765
+ ];
766
+ exports.getBlocksCount = function getBlocksCount(version, errorCorrectionLevel) {
767
+ switch (errorCorrectionLevel) {
768
+ case ECLevel.L:
769
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 0];
770
+ case ECLevel.M:
771
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 1];
772
+ case ECLevel.Q:
773
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 2];
774
+ case ECLevel.H:
775
+ return EC_BLOCKS_TABLE[(version - 1) * 4 + 3];
776
+ default:
777
+ return void 0;
778
+ }
779
+ };
780
+ exports.getTotalCodewordsCount = function getTotalCodewordsCount(version, errorCorrectionLevel) {
781
+ switch (errorCorrectionLevel) {
782
+ case ECLevel.L:
783
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 0];
784
+ case ECLevel.M:
785
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 1];
786
+ case ECLevel.Q:
787
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 2];
788
+ case ECLevel.H:
789
+ return EC_CODEWORDS_TABLE[(version - 1) * 4 + 3];
790
+ default:
791
+ return void 0;
792
+ }
793
+ };
794
+ }
795
+ });
796
+
797
+ // node_modules/qrcode/lib/core/galois-field.js
798
+ var require_galois_field = __commonJS({
799
+ "node_modules/qrcode/lib/core/galois-field.js"(exports) {
800
+ var EXP_TABLE = new Uint8Array(512);
801
+ var LOG_TABLE = new Uint8Array(256);
802
+ (function initTables() {
803
+ let x = 1;
804
+ for (let i = 0; i < 255; i++) {
805
+ EXP_TABLE[i] = x;
806
+ LOG_TABLE[x] = i;
807
+ x <<= 1;
808
+ if (x & 256) {
809
+ x ^= 285;
810
+ }
811
+ }
812
+ for (let i = 255; i < 512; i++) {
813
+ EXP_TABLE[i] = EXP_TABLE[i - 255];
814
+ }
815
+ })();
816
+ exports.log = function log(n) {
817
+ if (n < 1) throw new Error("log(" + n + ")");
818
+ return LOG_TABLE[n];
819
+ };
820
+ exports.exp = function exp(n) {
821
+ return EXP_TABLE[n];
822
+ };
823
+ exports.mul = function mul(x, y) {
824
+ if (x === 0 || y === 0) return 0;
825
+ return EXP_TABLE[LOG_TABLE[x] + LOG_TABLE[y]];
826
+ };
827
+ }
828
+ });
829
+
830
+ // node_modules/qrcode/lib/core/polynomial.js
831
+ var require_polynomial = __commonJS({
832
+ "node_modules/qrcode/lib/core/polynomial.js"(exports) {
833
+ var GF = require_galois_field();
834
+ exports.mul = function mul(p1, p2) {
835
+ const coeff = new Uint8Array(p1.length + p2.length - 1);
836
+ for (let i = 0; i < p1.length; i++) {
837
+ for (let j = 0; j < p2.length; j++) {
838
+ coeff[i + j] ^= GF.mul(p1[i], p2[j]);
839
+ }
840
+ }
841
+ return coeff;
842
+ };
843
+ exports.mod = function mod(divident, divisor) {
844
+ let result = new Uint8Array(divident);
845
+ while (result.length - divisor.length >= 0) {
846
+ const coeff = result[0];
847
+ for (let i = 0; i < divisor.length; i++) {
848
+ result[i] ^= GF.mul(divisor[i], coeff);
849
+ }
850
+ let offset = 0;
851
+ while (offset < result.length && result[offset] === 0) offset++;
852
+ result = result.slice(offset);
853
+ }
854
+ return result;
855
+ };
856
+ exports.generateECPolynomial = function generateECPolynomial(degree) {
857
+ let poly = new Uint8Array([1]);
858
+ for (let i = 0; i < degree; i++) {
859
+ poly = exports.mul(poly, new Uint8Array([1, GF.exp(i)]));
860
+ }
861
+ return poly;
862
+ };
863
+ }
864
+ });
865
+
866
+ // node_modules/qrcode/lib/core/reed-solomon-encoder.js
867
+ var require_reed_solomon_encoder = __commonJS({
868
+ "node_modules/qrcode/lib/core/reed-solomon-encoder.js"(exports, module2) {
869
+ var Polynomial = require_polynomial();
870
+ function ReedSolomonEncoder(degree) {
871
+ this.genPoly = void 0;
872
+ this.degree = degree;
873
+ if (this.degree) this.initialize(this.degree);
874
+ }
875
+ ReedSolomonEncoder.prototype.initialize = function initialize(degree) {
876
+ this.degree = degree;
877
+ this.genPoly = Polynomial.generateECPolynomial(this.degree);
878
+ };
879
+ ReedSolomonEncoder.prototype.encode = function encode(data) {
880
+ if (!this.genPoly) {
881
+ throw new Error("Encoder not initialized");
882
+ }
883
+ const paddedData = new Uint8Array(data.length + this.degree);
884
+ paddedData.set(data);
885
+ const remainder = Polynomial.mod(paddedData, this.genPoly);
886
+ const start = this.degree - remainder.length;
887
+ if (start > 0) {
888
+ const buff = new Uint8Array(this.degree);
889
+ buff.set(remainder, start);
890
+ return buff;
891
+ }
892
+ return remainder;
893
+ };
894
+ module2.exports = ReedSolomonEncoder;
895
+ }
896
+ });
897
+
898
+ // node_modules/qrcode/lib/core/version-check.js
899
+ var require_version_check = __commonJS({
900
+ "node_modules/qrcode/lib/core/version-check.js"(exports) {
901
+ exports.isValid = function isValid(version) {
902
+ return !isNaN(version) && version >= 1 && version <= 40;
903
+ };
904
+ }
905
+ });
906
+
907
+ // node_modules/qrcode/lib/core/regex.js
908
+ var require_regex = __commonJS({
909
+ "node_modules/qrcode/lib/core/regex.js"(exports) {
910
+ var numeric = "[0-9]+";
911
+ var alphanumeric = "[A-Z $%*+\\-./:]+";
912
+ var kanji = "(?:[u3000-u303F]|[u3040-u309F]|[u30A0-u30FF]|[uFF00-uFFEF]|[u4E00-u9FAF]|[u2605-u2606]|[u2190-u2195]|u203B|[u2010u2015u2018u2019u2025u2026u201Cu201Du2225u2260]|[u0391-u0451]|[u00A7u00A8u00B1u00B4u00D7u00F7])+";
913
+ kanji = kanji.replace(/u/g, "\\u");
914
+ var byte = "(?:(?![A-Z0-9 $%*+\\-./:]|" + kanji + ")(?:.|[\r\n]))+";
915
+ exports.KANJI = new RegExp(kanji, "g");
916
+ exports.BYTE_KANJI = new RegExp("[^A-Z0-9 $%*+\\-./:]+", "g");
917
+ exports.BYTE = new RegExp(byte, "g");
918
+ exports.NUMERIC = new RegExp(numeric, "g");
919
+ exports.ALPHANUMERIC = new RegExp(alphanumeric, "g");
920
+ var TEST_KANJI = new RegExp("^" + kanji + "$");
921
+ var TEST_NUMERIC = new RegExp("^" + numeric + "$");
922
+ var TEST_ALPHANUMERIC = new RegExp("^[A-Z0-9 $%*+\\-./:]+$");
923
+ exports.testKanji = function testKanji(str) {
924
+ return TEST_KANJI.test(str);
925
+ };
926
+ exports.testNumeric = function testNumeric(str) {
927
+ return TEST_NUMERIC.test(str);
928
+ };
929
+ exports.testAlphanumeric = function testAlphanumeric(str) {
930
+ return TEST_ALPHANUMERIC.test(str);
931
+ };
932
+ }
933
+ });
934
+
935
+ // node_modules/qrcode/lib/core/mode.js
936
+ var require_mode = __commonJS({
937
+ "node_modules/qrcode/lib/core/mode.js"(exports) {
938
+ var VersionCheck = require_version_check();
939
+ var Regex = require_regex();
940
+ exports.NUMERIC = {
941
+ id: "Numeric",
942
+ bit: 1 << 0,
943
+ ccBits: [10, 12, 14]
944
+ };
945
+ exports.ALPHANUMERIC = {
946
+ id: "Alphanumeric",
947
+ bit: 1 << 1,
948
+ ccBits: [9, 11, 13]
949
+ };
950
+ exports.BYTE = {
951
+ id: "Byte",
952
+ bit: 1 << 2,
953
+ ccBits: [8, 16, 16]
954
+ };
955
+ exports.KANJI = {
956
+ id: "Kanji",
957
+ bit: 1 << 3,
958
+ ccBits: [8, 10, 12]
959
+ };
960
+ exports.MIXED = {
961
+ bit: -1
962
+ };
963
+ exports.getCharCountIndicator = function getCharCountIndicator(mode, version) {
964
+ if (!mode.ccBits) throw new Error("Invalid mode: " + mode);
965
+ if (!VersionCheck.isValid(version)) {
966
+ throw new Error("Invalid version: " + version);
967
+ }
968
+ if (version >= 1 && version < 10) return mode.ccBits[0];
969
+ else if (version < 27) return mode.ccBits[1];
970
+ return mode.ccBits[2];
971
+ };
972
+ exports.getBestModeForData = function getBestModeForData(dataStr) {
973
+ if (Regex.testNumeric(dataStr)) return exports.NUMERIC;
974
+ else if (Regex.testAlphanumeric(dataStr)) return exports.ALPHANUMERIC;
975
+ else if (Regex.testKanji(dataStr)) return exports.KANJI;
976
+ else return exports.BYTE;
977
+ };
978
+ exports.toString = function toString(mode) {
979
+ if (mode && mode.id) return mode.id;
980
+ throw new Error("Invalid mode");
981
+ };
982
+ exports.isValid = function isValid(mode) {
983
+ return mode && mode.bit && mode.ccBits;
984
+ };
985
+ function fromString(string) {
986
+ if (typeof string !== "string") {
987
+ throw new Error("Param is not a string");
988
+ }
989
+ const lcStr = string.toLowerCase();
990
+ switch (lcStr) {
991
+ case "numeric":
992
+ return exports.NUMERIC;
993
+ case "alphanumeric":
994
+ return exports.ALPHANUMERIC;
995
+ case "kanji":
996
+ return exports.KANJI;
997
+ case "byte":
998
+ return exports.BYTE;
999
+ default:
1000
+ throw new Error("Unknown mode: " + string);
1001
+ }
1002
+ }
1003
+ exports.from = function from(value, defaultValue) {
1004
+ if (exports.isValid(value)) {
1005
+ return value;
1006
+ }
1007
+ try {
1008
+ return fromString(value);
1009
+ } catch (e) {
1010
+ return defaultValue;
1011
+ }
1012
+ };
1013
+ }
1014
+ });
1015
+
1016
+ // node_modules/qrcode/lib/core/version.js
1017
+ var require_version = __commonJS({
1018
+ "node_modules/qrcode/lib/core/version.js"(exports) {
1019
+ var Utils = require_utils();
1020
+ var ECCode = require_error_correction_code();
1021
+ var ECLevel = require_error_correction_level();
1022
+ var Mode = require_mode();
1023
+ var VersionCheck = require_version_check();
1024
+ var G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0;
1025
+ var G18_BCH = Utils.getBCHDigit(G18);
1026
+ function getBestVersionForDataLength(mode, length, errorCorrectionLevel) {
1027
+ for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
1028
+ if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, mode)) {
1029
+ return currentVersion;
1030
+ }
1031
+ }
1032
+ return void 0;
1033
+ }
1034
+ function getReservedBitsCount(mode, version) {
1035
+ return Mode.getCharCountIndicator(mode, version) + 4;
1036
+ }
1037
+ function getTotalBitsFromDataArray(segments, version) {
1038
+ let totalBits = 0;
1039
+ segments.forEach(function(data) {
1040
+ const reservedBits = getReservedBitsCount(data.mode, version);
1041
+ totalBits += reservedBits + data.getBitsLength();
1042
+ });
1043
+ return totalBits;
1044
+ }
1045
+ function getBestVersionForMixedData(segments, errorCorrectionLevel) {
1046
+ for (let currentVersion = 1; currentVersion <= 40; currentVersion++) {
1047
+ const length = getTotalBitsFromDataArray(segments, currentVersion);
1048
+ if (length <= exports.getCapacity(currentVersion, errorCorrectionLevel, Mode.MIXED)) {
1049
+ return currentVersion;
1050
+ }
1051
+ }
1052
+ return void 0;
1053
+ }
1054
+ exports.from = function from(value, defaultValue) {
1055
+ if (VersionCheck.isValid(value)) {
1056
+ return parseInt(value, 10);
1057
+ }
1058
+ return defaultValue;
1059
+ };
1060
+ exports.getCapacity = function getCapacity(version, errorCorrectionLevel, mode) {
1061
+ if (!VersionCheck.isValid(version)) {
1062
+ throw new Error("Invalid QR Code version");
1063
+ }
1064
+ if (typeof mode === "undefined") mode = Mode.BYTE;
1065
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
1066
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
1067
+ const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
1068
+ if (mode === Mode.MIXED) return dataTotalCodewordsBits;
1069
+ const usableBits = dataTotalCodewordsBits - getReservedBitsCount(mode, version);
1070
+ switch (mode) {
1071
+ case Mode.NUMERIC:
1072
+ return Math.floor(usableBits / 10 * 3);
1073
+ case Mode.ALPHANUMERIC:
1074
+ return Math.floor(usableBits / 11 * 2);
1075
+ case Mode.KANJI:
1076
+ return Math.floor(usableBits / 13);
1077
+ case Mode.BYTE:
1078
+ default:
1079
+ return Math.floor(usableBits / 8);
1080
+ }
1081
+ };
1082
+ exports.getBestVersionForData = function getBestVersionForData(data, errorCorrectionLevel) {
1083
+ let seg;
1084
+ const ecl = ECLevel.from(errorCorrectionLevel, ECLevel.M);
1085
+ if (Array.isArray(data)) {
1086
+ if (data.length > 1) {
1087
+ return getBestVersionForMixedData(data, ecl);
1088
+ }
1089
+ if (data.length === 0) {
1090
+ return 1;
1091
+ }
1092
+ seg = data[0];
1093
+ } else {
1094
+ seg = data;
1095
+ }
1096
+ return getBestVersionForDataLength(seg.mode, seg.getLength(), ecl);
1097
+ };
1098
+ exports.getEncodedBits = function getEncodedBits(version) {
1099
+ if (!VersionCheck.isValid(version) || version < 7) {
1100
+ throw new Error("Invalid QR Code version");
1101
+ }
1102
+ let d = version << 12;
1103
+ while (Utils.getBCHDigit(d) - G18_BCH >= 0) {
1104
+ d ^= G18 << Utils.getBCHDigit(d) - G18_BCH;
1105
+ }
1106
+ return version << 12 | d;
1107
+ };
1108
+ }
1109
+ });
1110
+
1111
+ // node_modules/qrcode/lib/core/format-info.js
1112
+ var require_format_info = __commonJS({
1113
+ "node_modules/qrcode/lib/core/format-info.js"(exports) {
1114
+ var Utils = require_utils();
1115
+ var G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0;
1116
+ var G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1;
1117
+ var G15_BCH = Utils.getBCHDigit(G15);
1118
+ exports.getEncodedBits = function getEncodedBits(errorCorrectionLevel, mask) {
1119
+ const data = errorCorrectionLevel.bit << 3 | mask;
1120
+ let d = data << 10;
1121
+ while (Utils.getBCHDigit(d) - G15_BCH >= 0) {
1122
+ d ^= G15 << Utils.getBCHDigit(d) - G15_BCH;
1123
+ }
1124
+ return (data << 10 | d) ^ G15_MASK;
1125
+ };
1126
+ }
1127
+ });
1128
+
1129
+ // node_modules/qrcode/lib/core/numeric-data.js
1130
+ var require_numeric_data = __commonJS({
1131
+ "node_modules/qrcode/lib/core/numeric-data.js"(exports, module2) {
1132
+ var Mode = require_mode();
1133
+ function NumericData(data) {
1134
+ this.mode = Mode.NUMERIC;
1135
+ this.data = data.toString();
1136
+ }
1137
+ NumericData.getBitsLength = function getBitsLength(length) {
1138
+ return 10 * Math.floor(length / 3) + (length % 3 ? length % 3 * 3 + 1 : 0);
1139
+ };
1140
+ NumericData.prototype.getLength = function getLength() {
1141
+ return this.data.length;
1142
+ };
1143
+ NumericData.prototype.getBitsLength = function getBitsLength() {
1144
+ return NumericData.getBitsLength(this.data.length);
1145
+ };
1146
+ NumericData.prototype.write = function write(bitBuffer) {
1147
+ let i, group, value;
1148
+ for (i = 0; i + 3 <= this.data.length; i += 3) {
1149
+ group = this.data.substr(i, 3);
1150
+ value = parseInt(group, 10);
1151
+ bitBuffer.put(value, 10);
1152
+ }
1153
+ const remainingNum = this.data.length - i;
1154
+ if (remainingNum > 0) {
1155
+ group = this.data.substr(i);
1156
+ value = parseInt(group, 10);
1157
+ bitBuffer.put(value, remainingNum * 3 + 1);
1158
+ }
1159
+ };
1160
+ module2.exports = NumericData;
1161
+ }
1162
+ });
1163
+
1164
+ // node_modules/qrcode/lib/core/alphanumeric-data.js
1165
+ var require_alphanumeric_data = __commonJS({
1166
+ "node_modules/qrcode/lib/core/alphanumeric-data.js"(exports, module2) {
1167
+ var Mode = require_mode();
1168
+ var ALPHA_NUM_CHARS = [
1169
+ "0",
1170
+ "1",
1171
+ "2",
1172
+ "3",
1173
+ "4",
1174
+ "5",
1175
+ "6",
1176
+ "7",
1177
+ "8",
1178
+ "9",
1179
+ "A",
1180
+ "B",
1181
+ "C",
1182
+ "D",
1183
+ "E",
1184
+ "F",
1185
+ "G",
1186
+ "H",
1187
+ "I",
1188
+ "J",
1189
+ "K",
1190
+ "L",
1191
+ "M",
1192
+ "N",
1193
+ "O",
1194
+ "P",
1195
+ "Q",
1196
+ "R",
1197
+ "S",
1198
+ "T",
1199
+ "U",
1200
+ "V",
1201
+ "W",
1202
+ "X",
1203
+ "Y",
1204
+ "Z",
1205
+ " ",
1206
+ "$",
1207
+ "%",
1208
+ "*",
1209
+ "+",
1210
+ "-",
1211
+ ".",
1212
+ "/",
1213
+ ":"
1214
+ ];
1215
+ function AlphanumericData(data) {
1216
+ this.mode = Mode.ALPHANUMERIC;
1217
+ this.data = data;
1218
+ }
1219
+ AlphanumericData.getBitsLength = function getBitsLength(length) {
1220
+ return 11 * Math.floor(length / 2) + 6 * (length % 2);
1221
+ };
1222
+ AlphanumericData.prototype.getLength = function getLength() {
1223
+ return this.data.length;
1224
+ };
1225
+ AlphanumericData.prototype.getBitsLength = function getBitsLength() {
1226
+ return AlphanumericData.getBitsLength(this.data.length);
1227
+ };
1228
+ AlphanumericData.prototype.write = function write(bitBuffer) {
1229
+ let i;
1230
+ for (i = 0; i + 2 <= this.data.length; i += 2) {
1231
+ let value = ALPHA_NUM_CHARS.indexOf(this.data[i]) * 45;
1232
+ value += ALPHA_NUM_CHARS.indexOf(this.data[i + 1]);
1233
+ bitBuffer.put(value, 11);
1234
+ }
1235
+ if (this.data.length % 2) {
1236
+ bitBuffer.put(ALPHA_NUM_CHARS.indexOf(this.data[i]), 6);
1237
+ }
1238
+ };
1239
+ module2.exports = AlphanumericData;
1240
+ }
1241
+ });
1242
+
1243
+ // node_modules/qrcode/lib/core/byte-data.js
1244
+ var require_byte_data = __commonJS({
1245
+ "node_modules/qrcode/lib/core/byte-data.js"(exports, module2) {
1246
+ var Mode = require_mode();
1247
+ function ByteData(data) {
1248
+ this.mode = Mode.BYTE;
1249
+ if (typeof data === "string") {
1250
+ this.data = new TextEncoder().encode(data);
1251
+ } else {
1252
+ this.data = new Uint8Array(data);
1253
+ }
1254
+ }
1255
+ ByteData.getBitsLength = function getBitsLength(length) {
1256
+ return length * 8;
1257
+ };
1258
+ ByteData.prototype.getLength = function getLength() {
1259
+ return this.data.length;
1260
+ };
1261
+ ByteData.prototype.getBitsLength = function getBitsLength() {
1262
+ return ByteData.getBitsLength(this.data.length);
1263
+ };
1264
+ ByteData.prototype.write = function(bitBuffer) {
1265
+ for (let i = 0, l = this.data.length; i < l; i++) {
1266
+ bitBuffer.put(this.data[i], 8);
1267
+ }
1268
+ };
1269
+ module2.exports = ByteData;
1270
+ }
1271
+ });
1272
+
1273
+ // node_modules/qrcode/lib/core/kanji-data.js
1274
+ var require_kanji_data = __commonJS({
1275
+ "node_modules/qrcode/lib/core/kanji-data.js"(exports, module2) {
1276
+ var Mode = require_mode();
1277
+ var Utils = require_utils();
1278
+ function KanjiData(data) {
1279
+ this.mode = Mode.KANJI;
1280
+ this.data = data;
1281
+ }
1282
+ KanjiData.getBitsLength = function getBitsLength(length) {
1283
+ return length * 13;
1284
+ };
1285
+ KanjiData.prototype.getLength = function getLength() {
1286
+ return this.data.length;
1287
+ };
1288
+ KanjiData.prototype.getBitsLength = function getBitsLength() {
1289
+ return KanjiData.getBitsLength(this.data.length);
1290
+ };
1291
+ KanjiData.prototype.write = function(bitBuffer) {
1292
+ let i;
1293
+ for (i = 0; i < this.data.length; i++) {
1294
+ let value = Utils.toSJIS(this.data[i]);
1295
+ if (value >= 33088 && value <= 40956) {
1296
+ value -= 33088;
1297
+ } else if (value >= 57408 && value <= 60351) {
1298
+ value -= 49472;
1299
+ } else {
1300
+ throw new Error(
1301
+ "Invalid SJIS character: " + this.data[i] + "\nMake sure your charset is UTF-8"
1302
+ );
1303
+ }
1304
+ value = (value >>> 8 & 255) * 192 + (value & 255);
1305
+ bitBuffer.put(value, 13);
1306
+ }
1307
+ };
1308
+ module2.exports = KanjiData;
1309
+ }
1310
+ });
1311
+
1312
+ // node_modules/dijkstrajs/dijkstra.js
1313
+ var require_dijkstra = __commonJS({
1314
+ "node_modules/dijkstrajs/dijkstra.js"(exports, module2) {
1315
+ "use strict";
1316
+ var dijkstra = {
1317
+ single_source_shortest_paths: function(graph, s, d) {
1318
+ var predecessors = {};
1319
+ var costs = {};
1320
+ costs[s] = 0;
1321
+ var open = dijkstra.PriorityQueue.make();
1322
+ open.push(s, 0);
1323
+ var closest, u, v, cost_of_s_to_u, adjacent_nodes, cost_of_e, cost_of_s_to_u_plus_cost_of_e, cost_of_s_to_v, first_visit;
1324
+ while (!open.empty()) {
1325
+ closest = open.pop();
1326
+ u = closest.value;
1327
+ cost_of_s_to_u = closest.cost;
1328
+ adjacent_nodes = graph[u] || {};
1329
+ for (v in adjacent_nodes) {
1330
+ if (adjacent_nodes.hasOwnProperty(v)) {
1331
+ cost_of_e = adjacent_nodes[v];
1332
+ cost_of_s_to_u_plus_cost_of_e = cost_of_s_to_u + cost_of_e;
1333
+ cost_of_s_to_v = costs[v];
1334
+ first_visit = typeof costs[v] === "undefined";
1335
+ if (first_visit || cost_of_s_to_v > cost_of_s_to_u_plus_cost_of_e) {
1336
+ costs[v] = cost_of_s_to_u_plus_cost_of_e;
1337
+ open.push(v, cost_of_s_to_u_plus_cost_of_e);
1338
+ predecessors[v] = u;
1339
+ }
1340
+ }
1341
+ }
1342
+ }
1343
+ if (typeof d !== "undefined" && typeof costs[d] === "undefined") {
1344
+ var msg = ["Could not find a path from ", s, " to ", d, "."].join("");
1345
+ throw new Error(msg);
1346
+ }
1347
+ return predecessors;
1348
+ },
1349
+ extract_shortest_path_from_predecessor_list: function(predecessors, d) {
1350
+ var nodes = [];
1351
+ var u = d;
1352
+ var predecessor;
1353
+ while (u) {
1354
+ nodes.push(u);
1355
+ predecessor = predecessors[u];
1356
+ u = predecessors[u];
1357
+ }
1358
+ nodes.reverse();
1359
+ return nodes;
1360
+ },
1361
+ find_path: function(graph, s, d) {
1362
+ var predecessors = dijkstra.single_source_shortest_paths(graph, s, d);
1363
+ return dijkstra.extract_shortest_path_from_predecessor_list(
1364
+ predecessors,
1365
+ d
1366
+ );
1367
+ },
1368
+ /**
1369
+ * A very naive priority queue implementation.
1370
+ */
1371
+ PriorityQueue: {
1372
+ make: function(opts) {
1373
+ var T = dijkstra.PriorityQueue, t = {}, key;
1374
+ opts = opts || {};
1375
+ for (key in T) {
1376
+ if (T.hasOwnProperty(key)) {
1377
+ t[key] = T[key];
1378
+ }
1379
+ }
1380
+ t.queue = [];
1381
+ t.sorter = opts.sorter || T.default_sorter;
1382
+ return t;
1383
+ },
1384
+ default_sorter: function(a, b) {
1385
+ return a.cost - b.cost;
1386
+ },
1387
+ /**
1388
+ * Add a new item to the queue and ensure the highest priority element
1389
+ * is at the front of the queue.
1390
+ */
1391
+ push: function(value, cost) {
1392
+ var item = { value, cost };
1393
+ this.queue.push(item);
1394
+ this.queue.sort(this.sorter);
1395
+ },
1396
+ /**
1397
+ * Return the highest priority element in the queue.
1398
+ */
1399
+ pop: function() {
1400
+ return this.queue.shift();
1401
+ },
1402
+ empty: function() {
1403
+ return this.queue.length === 0;
1404
+ }
1405
+ }
1406
+ };
1407
+ if (typeof module2 !== "undefined") {
1408
+ module2.exports = dijkstra;
1409
+ }
1410
+ }
1411
+ });
1412
+
1413
+ // node_modules/qrcode/lib/core/segments.js
1414
+ var require_segments = __commonJS({
1415
+ "node_modules/qrcode/lib/core/segments.js"(exports) {
1416
+ var Mode = require_mode();
1417
+ var NumericData = require_numeric_data();
1418
+ var AlphanumericData = require_alphanumeric_data();
1419
+ var ByteData = require_byte_data();
1420
+ var KanjiData = require_kanji_data();
1421
+ var Regex = require_regex();
1422
+ var Utils = require_utils();
1423
+ var dijkstra = require_dijkstra();
1424
+ function getStringByteLength(str) {
1425
+ return unescape(encodeURIComponent(str)).length;
1426
+ }
1427
+ function getSegments(regex, mode, str) {
1428
+ const segments = [];
1429
+ let result;
1430
+ while ((result = regex.exec(str)) !== null) {
1431
+ segments.push({
1432
+ data: result[0],
1433
+ index: result.index,
1434
+ mode,
1435
+ length: result[0].length
1436
+ });
1437
+ }
1438
+ return segments;
1439
+ }
1440
+ function getSegmentsFromString(dataStr) {
1441
+ const numSegs = getSegments(Regex.NUMERIC, Mode.NUMERIC, dataStr);
1442
+ const alphaNumSegs = getSegments(Regex.ALPHANUMERIC, Mode.ALPHANUMERIC, dataStr);
1443
+ let byteSegs;
1444
+ let kanjiSegs;
1445
+ if (Utils.isKanjiModeEnabled()) {
1446
+ byteSegs = getSegments(Regex.BYTE, Mode.BYTE, dataStr);
1447
+ kanjiSegs = getSegments(Regex.KANJI, Mode.KANJI, dataStr);
1448
+ } else {
1449
+ byteSegs = getSegments(Regex.BYTE_KANJI, Mode.BYTE, dataStr);
1450
+ kanjiSegs = [];
1451
+ }
1452
+ const segs = numSegs.concat(alphaNumSegs, byteSegs, kanjiSegs);
1453
+ return segs.sort(function(s1, s2) {
1454
+ return s1.index - s2.index;
1455
+ }).map(function(obj) {
1456
+ return {
1457
+ data: obj.data,
1458
+ mode: obj.mode,
1459
+ length: obj.length
1460
+ };
1461
+ });
1462
+ }
1463
+ function getSegmentBitsLength(length, mode) {
1464
+ switch (mode) {
1465
+ case Mode.NUMERIC:
1466
+ return NumericData.getBitsLength(length);
1467
+ case Mode.ALPHANUMERIC:
1468
+ return AlphanumericData.getBitsLength(length);
1469
+ case Mode.KANJI:
1470
+ return KanjiData.getBitsLength(length);
1471
+ case Mode.BYTE:
1472
+ return ByteData.getBitsLength(length);
1473
+ }
1474
+ }
1475
+ function mergeSegments(segs) {
1476
+ return segs.reduce(function(acc, curr) {
1477
+ const prevSeg = acc.length - 1 >= 0 ? acc[acc.length - 1] : null;
1478
+ if (prevSeg && prevSeg.mode === curr.mode) {
1479
+ acc[acc.length - 1].data += curr.data;
1480
+ return acc;
1481
+ }
1482
+ acc.push(curr);
1483
+ return acc;
1484
+ }, []);
1485
+ }
1486
+ function buildNodes(segs) {
1487
+ const nodes = [];
1488
+ for (let i = 0; i < segs.length; i++) {
1489
+ const seg = segs[i];
1490
+ switch (seg.mode) {
1491
+ case Mode.NUMERIC:
1492
+ nodes.push([
1493
+ seg,
1494
+ { data: seg.data, mode: Mode.ALPHANUMERIC, length: seg.length },
1495
+ { data: seg.data, mode: Mode.BYTE, length: seg.length }
1496
+ ]);
1497
+ break;
1498
+ case Mode.ALPHANUMERIC:
1499
+ nodes.push([
1500
+ seg,
1501
+ { data: seg.data, mode: Mode.BYTE, length: seg.length }
1502
+ ]);
1503
+ break;
1504
+ case Mode.KANJI:
1505
+ nodes.push([
1506
+ seg,
1507
+ { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
1508
+ ]);
1509
+ break;
1510
+ case Mode.BYTE:
1511
+ nodes.push([
1512
+ { data: seg.data, mode: Mode.BYTE, length: getStringByteLength(seg.data) }
1513
+ ]);
1514
+ }
1515
+ }
1516
+ return nodes;
1517
+ }
1518
+ function buildGraph(nodes, version) {
1519
+ const table = {};
1520
+ const graph = { start: {} };
1521
+ let prevNodeIds = ["start"];
1522
+ for (let i = 0; i < nodes.length; i++) {
1523
+ const nodeGroup = nodes[i];
1524
+ const currentNodeIds = [];
1525
+ for (let j = 0; j < nodeGroup.length; j++) {
1526
+ const node = nodeGroup[j];
1527
+ const key = "" + i + j;
1528
+ currentNodeIds.push(key);
1529
+ table[key] = { node, lastCount: 0 };
1530
+ graph[key] = {};
1531
+ for (let n = 0; n < prevNodeIds.length; n++) {
1532
+ const prevNodeId = prevNodeIds[n];
1533
+ if (table[prevNodeId] && table[prevNodeId].node.mode === node.mode) {
1534
+ graph[prevNodeId][key] = getSegmentBitsLength(table[prevNodeId].lastCount + node.length, node.mode) - getSegmentBitsLength(table[prevNodeId].lastCount, node.mode);
1535
+ table[prevNodeId].lastCount += node.length;
1536
+ } else {
1537
+ if (table[prevNodeId]) table[prevNodeId].lastCount = node.length;
1538
+ graph[prevNodeId][key] = getSegmentBitsLength(node.length, node.mode) + 4 + Mode.getCharCountIndicator(node.mode, version);
1539
+ }
1540
+ }
1541
+ }
1542
+ prevNodeIds = currentNodeIds;
1543
+ }
1544
+ for (let n = 0; n < prevNodeIds.length; n++) {
1545
+ graph[prevNodeIds[n]].end = 0;
1546
+ }
1547
+ return { map: graph, table };
1548
+ }
1549
+ function buildSingleSegment(data, modesHint) {
1550
+ let mode;
1551
+ const bestMode = Mode.getBestModeForData(data);
1552
+ mode = Mode.from(modesHint, bestMode);
1553
+ if (mode !== Mode.BYTE && mode.bit < bestMode.bit) {
1554
+ throw new Error('"' + data + '" cannot be encoded with mode ' + Mode.toString(mode) + ".\n Suggested mode is: " + Mode.toString(bestMode));
1555
+ }
1556
+ if (mode === Mode.KANJI && !Utils.isKanjiModeEnabled()) {
1557
+ mode = Mode.BYTE;
1558
+ }
1559
+ switch (mode) {
1560
+ case Mode.NUMERIC:
1561
+ return new NumericData(data);
1562
+ case Mode.ALPHANUMERIC:
1563
+ return new AlphanumericData(data);
1564
+ case Mode.KANJI:
1565
+ return new KanjiData(data);
1566
+ case Mode.BYTE:
1567
+ return new ByteData(data);
1568
+ }
1569
+ }
1570
+ exports.fromArray = function fromArray(array) {
1571
+ return array.reduce(function(acc, seg) {
1572
+ if (typeof seg === "string") {
1573
+ acc.push(buildSingleSegment(seg, null));
1574
+ } else if (seg.data) {
1575
+ acc.push(buildSingleSegment(seg.data, seg.mode));
1576
+ }
1577
+ return acc;
1578
+ }, []);
1579
+ };
1580
+ exports.fromString = function fromString(data, version) {
1581
+ const segs = getSegmentsFromString(data, Utils.isKanjiModeEnabled());
1582
+ const nodes = buildNodes(segs);
1583
+ const graph = buildGraph(nodes, version);
1584
+ const path = dijkstra.find_path(graph.map, "start", "end");
1585
+ const optimizedSegs = [];
1586
+ for (let i = 1; i < path.length - 1; i++) {
1587
+ optimizedSegs.push(graph.table[path[i]].node);
1588
+ }
1589
+ return exports.fromArray(mergeSegments(optimizedSegs));
1590
+ };
1591
+ exports.rawSplit = function rawSplit(data) {
1592
+ return exports.fromArray(
1593
+ getSegmentsFromString(data, Utils.isKanjiModeEnabled())
1594
+ );
1595
+ };
1596
+ }
1597
+ });
1598
+
1599
+ // node_modules/qrcode/lib/core/qrcode.js
1600
+ var require_qrcode = __commonJS({
1601
+ "node_modules/qrcode/lib/core/qrcode.js"(exports) {
1602
+ var Utils = require_utils();
1603
+ var ECLevel = require_error_correction_level();
1604
+ var BitBuffer = require_bit_buffer();
1605
+ var BitMatrix = require_bit_matrix();
1606
+ var AlignmentPattern = require_alignment_pattern();
1607
+ var FinderPattern = require_finder_pattern();
1608
+ var MaskPattern = require_mask_pattern();
1609
+ var ECCode = require_error_correction_code();
1610
+ var ReedSolomonEncoder = require_reed_solomon_encoder();
1611
+ var Version = require_version();
1612
+ var FormatInfo = require_format_info();
1613
+ var Mode = require_mode();
1614
+ var Segments = require_segments();
1615
+ function setupFinderPattern(matrix, version) {
1616
+ const size = matrix.size;
1617
+ const pos = FinderPattern.getPositions(version);
1618
+ for (let i = 0; i < pos.length; i++) {
1619
+ const row = pos[i][0];
1620
+ const col = pos[i][1];
1621
+ for (let r = -1; r <= 7; r++) {
1622
+ if (row + r <= -1 || size <= row + r) continue;
1623
+ for (let c = -1; c <= 7; c++) {
1624
+ if (col + c <= -1 || size <= col + c) continue;
1625
+ if (r >= 0 && r <= 6 && (c === 0 || c === 6) || c >= 0 && c <= 6 && (r === 0 || r === 6) || r >= 2 && r <= 4 && c >= 2 && c <= 4) {
1626
+ matrix.set(row + r, col + c, true, true);
1627
+ } else {
1628
+ matrix.set(row + r, col + c, false, true);
1629
+ }
1630
+ }
1631
+ }
1632
+ }
1633
+ }
1634
+ function setupTimingPattern(matrix) {
1635
+ const size = matrix.size;
1636
+ for (let r = 8; r < size - 8; r++) {
1637
+ const value = r % 2 === 0;
1638
+ matrix.set(r, 6, value, true);
1639
+ matrix.set(6, r, value, true);
1640
+ }
1641
+ }
1642
+ function setupAlignmentPattern(matrix, version) {
1643
+ const pos = AlignmentPattern.getPositions(version);
1644
+ for (let i = 0; i < pos.length; i++) {
1645
+ const row = pos[i][0];
1646
+ const col = pos[i][1];
1647
+ for (let r = -2; r <= 2; r++) {
1648
+ for (let c = -2; c <= 2; c++) {
1649
+ if (r === -2 || r === 2 || c === -2 || c === 2 || r === 0 && c === 0) {
1650
+ matrix.set(row + r, col + c, true, true);
1651
+ } else {
1652
+ matrix.set(row + r, col + c, false, true);
1653
+ }
1654
+ }
1655
+ }
1656
+ }
1657
+ }
1658
+ function setupVersionInfo(matrix, version) {
1659
+ const size = matrix.size;
1660
+ const bits = Version.getEncodedBits(version);
1661
+ let row, col, mod;
1662
+ for (let i = 0; i < 18; i++) {
1663
+ row = Math.floor(i / 3);
1664
+ col = i % 3 + size - 8 - 3;
1665
+ mod = (bits >> i & 1) === 1;
1666
+ matrix.set(row, col, mod, true);
1667
+ matrix.set(col, row, mod, true);
1668
+ }
1669
+ }
1670
+ function setupFormatInfo(matrix, errorCorrectionLevel, maskPattern) {
1671
+ const size = matrix.size;
1672
+ const bits = FormatInfo.getEncodedBits(errorCorrectionLevel, maskPattern);
1673
+ let i, mod;
1674
+ for (i = 0; i < 15; i++) {
1675
+ mod = (bits >> i & 1) === 1;
1676
+ if (i < 6) {
1677
+ matrix.set(i, 8, mod, true);
1678
+ } else if (i < 8) {
1679
+ matrix.set(i + 1, 8, mod, true);
1680
+ } else {
1681
+ matrix.set(size - 15 + i, 8, mod, true);
1682
+ }
1683
+ if (i < 8) {
1684
+ matrix.set(8, size - i - 1, mod, true);
1685
+ } else if (i < 9) {
1686
+ matrix.set(8, 15 - i - 1 + 1, mod, true);
1687
+ } else {
1688
+ matrix.set(8, 15 - i - 1, mod, true);
1689
+ }
1690
+ }
1691
+ matrix.set(size - 8, 8, 1, true);
1692
+ }
1693
+ function setupData(matrix, data) {
1694
+ const size = matrix.size;
1695
+ let inc = -1;
1696
+ let row = size - 1;
1697
+ let bitIndex = 7;
1698
+ let byteIndex = 0;
1699
+ for (let col = size - 1; col > 0; col -= 2) {
1700
+ if (col === 6) col--;
1701
+ while (true) {
1702
+ for (let c = 0; c < 2; c++) {
1703
+ if (!matrix.isReserved(row, col - c)) {
1704
+ let dark = false;
1705
+ if (byteIndex < data.length) {
1706
+ dark = (data[byteIndex] >>> bitIndex & 1) === 1;
1707
+ }
1708
+ matrix.set(row, col - c, dark);
1709
+ bitIndex--;
1710
+ if (bitIndex === -1) {
1711
+ byteIndex++;
1712
+ bitIndex = 7;
1713
+ }
1714
+ }
1715
+ }
1716
+ row += inc;
1717
+ if (row < 0 || size <= row) {
1718
+ row -= inc;
1719
+ inc = -inc;
1720
+ break;
1721
+ }
1722
+ }
1723
+ }
1724
+ }
1725
+ function createData(version, errorCorrectionLevel, segments) {
1726
+ const buffer = new BitBuffer();
1727
+ segments.forEach(function(data) {
1728
+ buffer.put(data.mode.bit, 4);
1729
+ buffer.put(data.getLength(), Mode.getCharCountIndicator(data.mode, version));
1730
+ data.write(buffer);
1731
+ });
1732
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
1733
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
1734
+ const dataTotalCodewordsBits = (totalCodewords - ecTotalCodewords) * 8;
1735
+ if (buffer.getLengthInBits() + 4 <= dataTotalCodewordsBits) {
1736
+ buffer.put(0, 4);
1737
+ }
1738
+ while (buffer.getLengthInBits() % 8 !== 0) {
1739
+ buffer.putBit(0);
1740
+ }
1741
+ const remainingByte = (dataTotalCodewordsBits - buffer.getLengthInBits()) / 8;
1742
+ for (let i = 0; i < remainingByte; i++) {
1743
+ buffer.put(i % 2 ? 17 : 236, 8);
1744
+ }
1745
+ return createCodewords(buffer, version, errorCorrectionLevel);
1746
+ }
1747
+ function createCodewords(bitBuffer, version, errorCorrectionLevel) {
1748
+ const totalCodewords = Utils.getSymbolTotalCodewords(version);
1749
+ const ecTotalCodewords = ECCode.getTotalCodewordsCount(version, errorCorrectionLevel);
1750
+ const dataTotalCodewords = totalCodewords - ecTotalCodewords;
1751
+ const ecTotalBlocks = ECCode.getBlocksCount(version, errorCorrectionLevel);
1752
+ const blocksInGroup2 = totalCodewords % ecTotalBlocks;
1753
+ const blocksInGroup1 = ecTotalBlocks - blocksInGroup2;
1754
+ const totalCodewordsInGroup1 = Math.floor(totalCodewords / ecTotalBlocks);
1755
+ const dataCodewordsInGroup1 = Math.floor(dataTotalCodewords / ecTotalBlocks);
1756
+ const dataCodewordsInGroup2 = dataCodewordsInGroup1 + 1;
1757
+ const ecCount = totalCodewordsInGroup1 - dataCodewordsInGroup1;
1758
+ const rs = new ReedSolomonEncoder(ecCount);
1759
+ let offset = 0;
1760
+ const dcData = new Array(ecTotalBlocks);
1761
+ const ecData = new Array(ecTotalBlocks);
1762
+ let maxDataSize = 0;
1763
+ const buffer = new Uint8Array(bitBuffer.buffer);
1764
+ for (let b = 0; b < ecTotalBlocks; b++) {
1765
+ const dataSize = b < blocksInGroup1 ? dataCodewordsInGroup1 : dataCodewordsInGroup2;
1766
+ dcData[b] = buffer.slice(offset, offset + dataSize);
1767
+ ecData[b] = rs.encode(dcData[b]);
1768
+ offset += dataSize;
1769
+ maxDataSize = Math.max(maxDataSize, dataSize);
1770
+ }
1771
+ const data = new Uint8Array(totalCodewords);
1772
+ let index = 0;
1773
+ let i, r;
1774
+ for (i = 0; i < maxDataSize; i++) {
1775
+ for (r = 0; r < ecTotalBlocks; r++) {
1776
+ if (i < dcData[r].length) {
1777
+ data[index++] = dcData[r][i];
1778
+ }
1779
+ }
1780
+ }
1781
+ for (i = 0; i < ecCount; i++) {
1782
+ for (r = 0; r < ecTotalBlocks; r++) {
1783
+ data[index++] = ecData[r][i];
1784
+ }
1785
+ }
1786
+ return data;
1787
+ }
1788
+ function createSymbol(data, version, errorCorrectionLevel, maskPattern) {
1789
+ let segments;
1790
+ if (Array.isArray(data)) {
1791
+ segments = Segments.fromArray(data);
1792
+ } else if (typeof data === "string") {
1793
+ let estimatedVersion = version;
1794
+ if (!estimatedVersion) {
1795
+ const rawSegments = Segments.rawSplit(data);
1796
+ estimatedVersion = Version.getBestVersionForData(rawSegments, errorCorrectionLevel);
1797
+ }
1798
+ segments = Segments.fromString(data, estimatedVersion || 40);
1799
+ } else {
1800
+ throw new Error("Invalid data");
1801
+ }
1802
+ const bestVersion = Version.getBestVersionForData(segments, errorCorrectionLevel);
1803
+ if (!bestVersion) {
1804
+ throw new Error("The amount of data is too big to be stored in a QR Code");
1805
+ }
1806
+ if (!version) {
1807
+ version = bestVersion;
1808
+ } else if (version < bestVersion) {
1809
+ throw new Error(
1810
+ "\nThe chosen QR Code version cannot contain this amount of data.\nMinimum version required to store current data is: " + bestVersion + ".\n"
1811
+ );
1812
+ }
1813
+ const dataBits = createData(version, errorCorrectionLevel, segments);
1814
+ const moduleCount = Utils.getSymbolSize(version);
1815
+ const modules = new BitMatrix(moduleCount);
1816
+ setupFinderPattern(modules, version);
1817
+ setupTimingPattern(modules);
1818
+ setupAlignmentPattern(modules, version);
1819
+ setupFormatInfo(modules, errorCorrectionLevel, 0);
1820
+ if (version >= 7) {
1821
+ setupVersionInfo(modules, version);
1822
+ }
1823
+ setupData(modules, dataBits);
1824
+ if (isNaN(maskPattern)) {
1825
+ maskPattern = MaskPattern.getBestMask(
1826
+ modules,
1827
+ setupFormatInfo.bind(null, modules, errorCorrectionLevel)
1828
+ );
1829
+ }
1830
+ MaskPattern.applyMask(maskPattern, modules);
1831
+ setupFormatInfo(modules, errorCorrectionLevel, maskPattern);
1832
+ return {
1833
+ modules,
1834
+ version,
1835
+ errorCorrectionLevel,
1836
+ maskPattern,
1837
+ segments
1838
+ };
1839
+ }
1840
+ exports.create = function create(data, options) {
1841
+ if (typeof data === "undefined" || data === "") {
1842
+ throw new Error("No input text");
1843
+ }
1844
+ let errorCorrectionLevel = ECLevel.M;
1845
+ let version;
1846
+ let mask;
1847
+ if (typeof options !== "undefined") {
1848
+ errorCorrectionLevel = ECLevel.from(options.errorCorrectionLevel, ECLevel.M);
1849
+ version = Version.from(options.version);
1850
+ mask = MaskPattern.from(options.maskPattern);
1851
+ if (options.toSJISFunc) {
1852
+ Utils.setToSJISFunction(options.toSJISFunc);
1853
+ }
1854
+ }
1855
+ return createSymbol(data, version, errorCorrectionLevel, mask);
1856
+ };
1857
+ }
1858
+ });
1859
+
1860
+ // node_modules/qrcode/lib/renderer/utils.js
1861
+ var require_utils2 = __commonJS({
1862
+ "node_modules/qrcode/lib/renderer/utils.js"(exports) {
1863
+ function hex2rgba(hex) {
1864
+ if (typeof hex === "number") {
1865
+ hex = hex.toString();
1866
+ }
1867
+ if (typeof hex !== "string") {
1868
+ throw new Error("Color should be defined as hex string");
1869
+ }
1870
+ let hexCode = hex.slice().replace("#", "").split("");
1871
+ if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {
1872
+ throw new Error("Invalid hex color: " + hex);
1873
+ }
1874
+ if (hexCode.length === 3 || hexCode.length === 4) {
1875
+ hexCode = Array.prototype.concat.apply([], hexCode.map(function(c) {
1876
+ return [c, c];
1877
+ }));
1878
+ }
1879
+ if (hexCode.length === 6) hexCode.push("F", "F");
1880
+ const hexValue = parseInt(hexCode.join(""), 16);
1881
+ return {
1882
+ r: hexValue >> 24 & 255,
1883
+ g: hexValue >> 16 & 255,
1884
+ b: hexValue >> 8 & 255,
1885
+ a: hexValue & 255,
1886
+ hex: "#" + hexCode.slice(0, 6).join("")
1887
+ };
1888
+ }
1889
+ exports.getOptions = function getOptions(options) {
1890
+ if (!options) options = {};
1891
+ if (!options.color) options.color = {};
1892
+ const margin = typeof options.margin === "undefined" || options.margin === null || options.margin < 0 ? 4 : options.margin;
1893
+ const width = options.width && options.width >= 21 ? options.width : void 0;
1894
+ const scale = options.scale || 4;
1895
+ return {
1896
+ width,
1897
+ scale: width ? 4 : scale,
1898
+ margin,
1899
+ color: {
1900
+ dark: hex2rgba(options.color.dark || "#000000ff"),
1901
+ light: hex2rgba(options.color.light || "#ffffffff")
1902
+ },
1903
+ type: options.type,
1904
+ rendererOpts: options.rendererOpts || {}
1905
+ };
1906
+ };
1907
+ exports.getScale = function getScale(qrSize, opts) {
1908
+ return opts.width && opts.width >= qrSize + opts.margin * 2 ? opts.width / (qrSize + opts.margin * 2) : opts.scale;
1909
+ };
1910
+ exports.getImageWidth = function getImageWidth(qrSize, opts) {
1911
+ const scale = exports.getScale(qrSize, opts);
1912
+ return Math.floor((qrSize + opts.margin * 2) * scale);
1913
+ };
1914
+ exports.qrToImageData = function qrToImageData(imgData, qr, opts) {
1915
+ const size = qr.modules.size;
1916
+ const data = qr.modules.data;
1917
+ const scale = exports.getScale(size, opts);
1918
+ const symbolSize = Math.floor((size + opts.margin * 2) * scale);
1919
+ const scaledMargin = opts.margin * scale;
1920
+ const palette = [opts.color.light, opts.color.dark];
1921
+ for (let i = 0; i < symbolSize; i++) {
1922
+ for (let j = 0; j < symbolSize; j++) {
1923
+ let posDst = (i * symbolSize + j) * 4;
1924
+ let pxColor = opts.color.light;
1925
+ if (i >= scaledMargin && j >= scaledMargin && i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {
1926
+ const iSrc = Math.floor((i - scaledMargin) / scale);
1927
+ const jSrc = Math.floor((j - scaledMargin) / scale);
1928
+ pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0];
1929
+ }
1930
+ imgData[posDst++] = pxColor.r;
1931
+ imgData[posDst++] = pxColor.g;
1932
+ imgData[posDst++] = pxColor.b;
1933
+ imgData[posDst] = pxColor.a;
1934
+ }
1935
+ }
1936
+ };
1937
+ }
1938
+ });
1939
+
1940
+ // node_modules/qrcode/lib/renderer/canvas.js
1941
+ var require_canvas = __commonJS({
1942
+ "node_modules/qrcode/lib/renderer/canvas.js"(exports) {
1943
+ var Utils = require_utils2();
1944
+ function clearCanvas(ctx, canvas, size) {
1945
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
1946
+ if (!canvas.style) canvas.style = {};
1947
+ canvas.height = size;
1948
+ canvas.width = size;
1949
+ canvas.style.height = size + "px";
1950
+ canvas.style.width = size + "px";
1951
+ }
1952
+ function getCanvasElement() {
1953
+ try {
1954
+ return document.createElement("canvas");
1955
+ } catch (e) {
1956
+ throw new Error("You need to specify a canvas element");
1957
+ }
1958
+ }
1959
+ exports.render = function render(qrData, canvas, options) {
1960
+ let opts = options;
1961
+ let canvasEl = canvas;
1962
+ if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) {
1963
+ opts = canvas;
1964
+ canvas = void 0;
1965
+ }
1966
+ if (!canvas) {
1967
+ canvasEl = getCanvasElement();
1968
+ }
1969
+ opts = Utils.getOptions(opts);
1970
+ const size = Utils.getImageWidth(qrData.modules.size, opts);
1971
+ const ctx = canvasEl.getContext("2d");
1972
+ const image = ctx.createImageData(size, size);
1973
+ Utils.qrToImageData(image.data, qrData, opts);
1974
+ clearCanvas(ctx, canvasEl, size);
1975
+ ctx.putImageData(image, 0, 0);
1976
+ return canvasEl;
1977
+ };
1978
+ exports.renderToDataURL = function renderToDataURL(qrData, canvas, options) {
1979
+ let opts = options;
1980
+ if (typeof opts === "undefined" && (!canvas || !canvas.getContext)) {
1981
+ opts = canvas;
1982
+ canvas = void 0;
1983
+ }
1984
+ if (!opts) opts = {};
1985
+ const canvasEl = exports.render(qrData, canvas, opts);
1986
+ const type = opts.type || "image/png";
1987
+ const rendererOpts = opts.rendererOpts || {};
1988
+ return canvasEl.toDataURL(type, rendererOpts.quality);
1989
+ };
1990
+ }
1991
+ });
1992
+
1993
+ // node_modules/qrcode/lib/renderer/svg-tag.js
1994
+ var require_svg_tag = __commonJS({
1995
+ "node_modules/qrcode/lib/renderer/svg-tag.js"(exports) {
1996
+ var Utils = require_utils2();
1997
+ function getColorAttrib(color, attrib) {
1998
+ const alpha = color.a / 255;
1999
+ const str = attrib + '="' + color.hex + '"';
2000
+ return alpha < 1 ? str + " " + attrib + '-opacity="' + alpha.toFixed(2).slice(1) + '"' : str;
2001
+ }
2002
+ function svgCmd(cmd, x, y) {
2003
+ let str = cmd + x;
2004
+ if (typeof y !== "undefined") str += " " + y;
2005
+ return str;
2006
+ }
2007
+ function qrToPath(data, size, margin) {
2008
+ let path = "";
2009
+ let moveBy = 0;
2010
+ let newRow = false;
2011
+ let lineLength = 0;
2012
+ for (let i = 0; i < data.length; i++) {
2013
+ const col = Math.floor(i % size);
2014
+ const row = Math.floor(i / size);
2015
+ if (!col && !newRow) newRow = true;
2016
+ if (data[i]) {
2017
+ lineLength++;
2018
+ if (!(i > 0 && col > 0 && data[i - 1])) {
2019
+ path += newRow ? svgCmd("M", col + margin, 0.5 + row + margin) : svgCmd("m", moveBy, 0);
2020
+ moveBy = 0;
2021
+ newRow = false;
2022
+ }
2023
+ if (!(col + 1 < size && data[i + 1])) {
2024
+ path += svgCmd("h", lineLength);
2025
+ lineLength = 0;
2026
+ }
2027
+ } else {
2028
+ moveBy++;
2029
+ }
2030
+ }
2031
+ return path;
2032
+ }
2033
+ exports.render = function render(qrData, options, cb) {
2034
+ const opts = Utils.getOptions(options);
2035
+ const size = qrData.modules.size;
2036
+ const data = qrData.modules.data;
2037
+ const qrcodesize = size + opts.margin * 2;
2038
+ const bg = !opts.color.light.a ? "" : "<path " + getColorAttrib(opts.color.light, "fill") + ' d="M0 0h' + qrcodesize + "v" + qrcodesize + 'H0z"/>';
2039
+ const path = "<path " + getColorAttrib(opts.color.dark, "stroke") + ' d="' + qrToPath(data, size, opts.margin) + '"/>';
2040
+ const viewBox = 'viewBox="0 0 ' + qrcodesize + " " + qrcodesize + '"';
2041
+ const width = !opts.width ? "" : 'width="' + opts.width + '" height="' + opts.width + '" ';
2042
+ const svgTag = '<svg xmlns="http://www.w3.org/2000/svg" ' + width + viewBox + ' shape-rendering="crispEdges">' + bg + path + "</svg>\n";
2043
+ if (typeof cb === "function") {
2044
+ cb(null, svgTag);
2045
+ }
2046
+ return svgTag;
2047
+ };
2048
+ }
2049
+ });
2050
+
2051
+ // node_modules/qrcode/lib/browser.js
2052
+ var require_browser = __commonJS({
2053
+ "node_modules/qrcode/lib/browser.js"(exports) {
2054
+ var canPromise = require_can_promise();
2055
+ var QRCode2 = require_qrcode();
2056
+ var CanvasRenderer = require_canvas();
2057
+ var SvgRenderer = require_svg_tag();
2058
+ function renderCanvas(renderFunc, canvas, text, opts, cb) {
2059
+ const args = [].slice.call(arguments, 1);
2060
+ const argsNum = args.length;
2061
+ const isLastArgCb = typeof args[argsNum - 1] === "function";
2062
+ if (!isLastArgCb && !canPromise()) {
2063
+ throw new Error("Callback required as last argument");
2064
+ }
2065
+ if (isLastArgCb) {
2066
+ if (argsNum < 2) {
2067
+ throw new Error("Too few arguments provided");
2068
+ }
2069
+ if (argsNum === 2) {
2070
+ cb = text;
2071
+ text = canvas;
2072
+ canvas = opts = void 0;
2073
+ } else if (argsNum === 3) {
2074
+ if (canvas.getContext && typeof cb === "undefined") {
2075
+ cb = opts;
2076
+ opts = void 0;
2077
+ } else {
2078
+ cb = opts;
2079
+ opts = text;
2080
+ text = canvas;
2081
+ canvas = void 0;
2082
+ }
2083
+ }
2084
+ } else {
2085
+ if (argsNum < 1) {
2086
+ throw new Error("Too few arguments provided");
2087
+ }
2088
+ if (argsNum === 1) {
2089
+ text = canvas;
2090
+ canvas = opts = void 0;
2091
+ } else if (argsNum === 2 && !canvas.getContext) {
2092
+ opts = text;
2093
+ text = canvas;
2094
+ canvas = void 0;
2095
+ }
2096
+ return new Promise(function(resolve, reject) {
2097
+ try {
2098
+ const data = QRCode2.create(text, opts);
2099
+ resolve(renderFunc(data, canvas, opts));
2100
+ } catch (e) {
2101
+ reject(e);
2102
+ }
2103
+ });
2104
+ }
2105
+ try {
2106
+ const data = QRCode2.create(text, opts);
2107
+ cb(null, renderFunc(data, canvas, opts));
2108
+ } catch (e) {
2109
+ cb(e);
2110
+ }
2111
+ }
2112
+ exports.create = QRCode2.create;
2113
+ exports.toCanvas = renderCanvas.bind(null, CanvasRenderer.render);
2114
+ exports.toDataURL = renderCanvas.bind(null, CanvasRenderer.renderToDataURL);
2115
+ exports.toString = renderCanvas.bind(null, function(data, _, opts) {
2116
+ return SvgRenderer.render(data, opts);
2117
+ });
2118
+ }
2119
+ });
35
2120
 
36
2121
  // src/client.jsx
37
2122
  var client_exports = {};
@@ -41,7 +2126,7 @@ __export(client_exports, {
41
2126
  inject: () => inject
42
2127
  });
43
2128
  module.exports = __toCommonJS(client_exports);
44
- var import_react8 = __toESM(require("react"), 1);
2129
+ var import_react10 = __toESM(require("react"), 1);
45
2130
 
46
2131
  // src/shared.js
47
2132
  var import_react = __toESM(require("react"), 1);
@@ -722,7 +2807,7 @@ function TokenLogChip(props) {
722
2807
  }, [sid]);
723
2808
  if (!sid) return null;
724
2809
  const t = snap.totals;
725
- const label = snap.err && !t ? snap.err.includes("\u91CD\u542F") ? "\u7528\u91CF\xB7\u9700\u91CD\u542F\u5BBF\u4E3B" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 " + fmtCost(t.cost) : "") : "\u26C1 \u2026";
2810
+ const label = snap.err && !t ? snap.err.includes("\u91CD\u542F") ? "\u7528\u91CF\xB7\u9700\u91CD\u542F\u5BBF\u4E3B" : "\u7528\u91CF\xB7\u5931\u8D25" : t ? "\u26C1 " + fmtCompact(t.totalTokens) + (t.cost > 0 ? " \xB7 $" + t.cost.toFixed(2) : "") : "\u26C1 \u2026";
726
2811
  const title = t ? "\u672C\u4F1A\u8BDD " + fmtNum(t.calls) + " \u6B21\u8C03\u7528 \xB7 " + fmtNum(t.totalTokens) + " Token \xB7 " + fmtCost(t.cost) + "\uFF08\u4F30\u7B97\uFF09\n\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55" : (snap.err ? snap.err + "\n" : "") + "\u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u7528\u91CF\u8BB0\u5F55";
727
2812
  return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
728
2813
  "button",
@@ -768,8 +2853,8 @@ var modelsStore = {
768
2853
  },
769
2854
  load() {
770
2855
  if (this.snap.loading) return;
771
- this.set({ loading: true });
772
- fetch("/dsh-dock/models", { signal: AbortSignal.timeout(2e4) }).then((res) => res.ok ? res.json() : Promise.reject(new Error("\u6A21\u578B\u76EE\u5F55\u63A5\u53E3 HTTP " + res.status))).then((data) => this.set({ data, loading: false, error: null })).catch((e) => this.set({ loading: false, error: e && e.message || String(e) }));
2856
+ this.set({ loading: true, error: null });
2857
+ fetch("/dsh-dock/models", { cache: "no-store", signal: AbortSignal.timeout(2e4) }).then((res) => res.ok ? res.json() : Promise.reject(new Error("\u6A21\u578B\u76EE\u5F55\u63A5\u53E3 HTTP " + res.status))).then((data) => this.set({ data, loading: false, error: null })).catch((e) => this.set({ loading: false, error: e && e.message || String(e) }));
773
2858
  }
774
2859
  };
775
2860
  function useModels() {
@@ -826,6 +2911,14 @@ function ModelsView() {
826
2911
  const [vpDirty, setVpDirty] = import_react3.default.useState(false);
827
2912
  const [vpSaving, setVpSaving] = import_react3.default.useState(false);
828
2913
  const [vpMsg, setVpMsg] = import_react3.default.useState(null);
2914
+ const [vpDirectExpanded, setVpDirectExpanded] = import_react3.default.useState(false);
2915
+ import_react3.default.useEffect(() => {
2916
+ modelsStore.load();
2917
+ }, []);
2918
+ const refreshModels = () => {
2919
+ setBuiltKey(null);
2920
+ modelsStore.load();
2921
+ };
829
2922
  const cur = providers.length > 0 ? providers.find((p) => p.id === selId) || providers[0] : null;
830
2923
  const wantKey = cur ? cur.id + ":" + String(data && data.generatedAt || 0) : null;
831
2924
  if (cur && builtKey !== wantKey) {
@@ -944,7 +3037,7 @@ function ModelsView() {
944
3037
  {
945
3038
  key: v,
946
3039
  className: "dkm-check",
947
- title: v === "image" ? "\u52FE\u9009=\u7AEF\u70B9\u539F\u751F\u652F\u6301\u56FE\u7247\uFF08\u539F\u56FE\u76F4\u53D1\uFF0C\u56FE\u7247\u7406\u89E3\u4EE3\u7406\u8DF3\u8FC7\uFF09\uFF1B\u7EAF\u6587\u672C\u6A21\u578B\u52FF\u52FE\u2014\u2014\u6536\u56FE\u4F1A\u81EA\u52A8\u4EA4\u7ED9\u56FE\u7247\u7406\u89E3\u4EE3\u7406\u8BC6\u522B" : null
3040
+ title: v === "image" ? "\u7531\u4F60\u58F0\u660E\u8BE5\u7AEF\u70B9\u652F\u6301\u56FE\u7247\uFF1A\u4FDD\u5B58\u540E\u539F\u56FE\u76F4\u53D1\uFF0C\u5E76\u53EF\u4F5C\u4E3A\u89C6\u89C9\u6A21\u578B\u5019\u9009\u3002\u7CFB\u7EDF\u4E0D\u4F1A\u66FF\u4F60\u731C\u6D4B\uFF1B\u7AEF\u70B9\u5B9E\u9645\u4E0D\u652F\u6301\u65F6\u53D6\u6D88\u52FE\u9009\u5373\u53EF\u6062\u590D\u8D70\u56FE\u7247\u7406\u89E3\u4EE3\u7406" : null
948
3041
  },
949
3042
  import_react3.default.createElement("input", {
950
3043
  type: "checkbox",
@@ -1007,6 +3100,14 @@ function ModelsView() {
1007
3100
  )
1008
3101
  );
1009
3102
  const body = [];
3103
+ if (data) {
3104
+ body.push(import_react3.default.createElement(
3105
+ "div",
3106
+ { key: "refresh", className: "dkm-topbar" },
3107
+ import_react3.default.createElement("span", { className: "dkm-sub" }, "\u5DF2\u8F7D\u5165 " + providers.length + " \u4E2A Provider\uFF1B\u5728 DSH \u539F\u751F\u6A21\u578B\u8BBE\u7F6E\u4E2D\u65B0\u589E\u540E\uFF0C\u8FD4\u56DE\u672C\u9875\u4F1A\u81EA\u52A8\u66F4\u65B0"),
3108
+ import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: snap.loading || saving, onClick: refreshModels }, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u5237\u65B0\u6A21\u578B\u76EE\u5F55")
3109
+ ));
3110
+ }
1010
3111
  if (snap.error) {
1011
3112
  body.push(import_react3.default.createElement(
1012
3113
  "div",
@@ -1025,13 +3126,23 @@ function ModelsView() {
1025
3126
  ));
1026
3127
  }
1027
3128
  if (data && data.visionProxy !== void 0 && vpDraft) {
1028
- const effInput = (m) => (m.runtimeInput && m.runtimeInput.length > 0 ? m.runtimeInput : m.input) || [];
3129
+ const runtimeImage = (m) => Array.isArray(m.runtimeInput) && m.runtimeInput.indexOf("image") >= 0;
3130
+ const declaredImage = (m) => Array.isArray(m.input) && m.input.indexOf("image") >= 0;
1029
3131
  const vpDirect = [];
1030
3132
  const vpProxied = [];
1031
3133
  for (const p of providers) {
1032
3134
  for (const m of p.models || []) {
1033
- const item = { key: p.id + "/" + m.id, label: (p.displayName || p.id) + " / " + (m.name || m.id), model: m.name || m.id };
1034
- (effInput(m).indexOf("image") >= 0 ? vpDirect : vpProxied).push(item);
3135
+ const declared = declaredImage(m);
3136
+ const runtime = runtimeImage(m);
3137
+ const source = declared ? "\u4F60\u5DF2\u6807\u8BB0\u56FE\u7247" : runtime ? "\u8FD0\u884C\u65F6\u8BC6\u522B" : "\u672A\u6807\u8BB0\u56FE\u7247";
3138
+ const item = {
3139
+ key: p.id + "/" + m.id,
3140
+ label: (p.displayName || p.id) + " / " + (m.name || m.id) + "\uFF08" + source + "\uFF09",
3141
+ model: m.name || m.id,
3142
+ source,
3143
+ declared
3144
+ };
3145
+ (declared || runtime ? vpDirect : vpProxied).push(item);
1035
3146
  }
1036
3147
  }
1037
3148
  const vpCandidates = vpDirect.slice();
@@ -1086,23 +3197,37 @@ function ModelsView() {
1086
3197
  !vpKnown && vpDraft.provider ? import_react3.default.createElement("option", { value: vpKey }, vpDraft.provider + " / " + vpDraft.model + "\uFF08\u5F53\u524D\uFF09") : null,
1087
3198
  vpCandidates.map((c) => import_react3.default.createElement("option", { key: c.key, value: c.key }, c.label))
1088
3199
  ),
1089
- vpCandidates.length === 0 ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\u76EE\u5F55\u91CC\u6682\u65E0\u591A\u6A21\u6001\u6A21\u578B\u2014\u2014\u5148\u5728\u4E0B\u65B9\u7ED9\u771F\xB7\u591A\u6A21\u6001\u6A21\u578B\u52FE\u9009\u300C\u56FE\u7247\u300D\u8F93\u5165\u7C7B\u578B") : null
3200
+ vpCandidates.length === 0 ? import_react3.default.createElement("span", { className: "dkm-sub" }, "\u8FD8\u6CA1\u6709\u6807\u8BB0\u56FE\u7247\u80FD\u529B\u7684\u6A21\u578B\u2014\u2014\u5728\u4E0B\u65B9\u7ED9\u4F60\u786E\u8BA4\u652F\u6301\u56FE\u7247\u7684\u6A21\u578B\u52FE\u9009\u300C\u56FE\u7247\u300D\u5E76\u4FDD\u5B58") : null
1090
3201
  ),
1091
3202
  import_react3.default.createElement(
1092
3203
  "div",
1093
3204
  { className: "dkm-sub" },
1094
- "\u5224\u5B9A\u4E0E\u5B98\u65B9\u8FD0\u884C\u65F6\u540C\u6E90\uFF1A\u300C\u56FE\u7247\u300D\u52FE\u9009\uFF08\u6216\u76EE\u5F55\u9ED8\u8BA4\uFF09= \u7AEF\u70B9\u539F\u751F\u652F\u6301\u3001\u539F\u56FE\u76F4\u53D1\uFF1B\u5176\u4F59\u6A21\u578B\u6536\u56FE\u81EA\u52A8\u8D70\u89C6\u89C9\u6A21\u578B\u3002\u6CE8\u610F\uFF1A\u82E5\u7AEF\u70B9\u5B9E\u9645\u4E0D\u8BA4\u56FE\u5374\u52FE\u4E86\u300C\u56FE\u7247\u300D\uFF0C\u6A21\u578B\u4F1A\u770B\u4E0D\u89C1\u56FE\u7247\u3001\u8F6C\u800C\u7528\u5DE5\u5177\u778E\u6298\u817E\u2014\u2014\u4E0D\u786E\u5B9A\u5C31\u4E0D\u8981\u52FE\uFF0C\u4EA4\u7ED9\u4EE3\u7406\u3002"
3205
+ "\u4EE5\u4F60\u5728\u4E0B\u65B9\u52FE\u9009\u7684\u300C\u56FE\u7247\u300D\u4E3A\u51C6\uFF1B\u8FD0\u884C\u65F6\u8BC6\u522B\u53EA\u662F\u8F85\u52A9\u63D0\u793A\u3002\u5B83\u4E0D\u4EE3\u8868\u5DF2\u8054\u7F51\u5B9E\u6D4B\u53EF\u8C03\u7528\uFF0C\u5B9E\u9645\u53EF\u7528\u6027\u4ECD\u53D6\u51B3\u4E8E Provider \u51ED\u636E\u3001\u989D\u5EA6\u4E0E\u4E0A\u6E38\u670D\u52A1\u3002\u82E5\u7AEF\u70B9\u5B9E\u9645\u4E0D\u8BA4\u56FE\uFF0C\u53D6\u6D88\u8BE5\u6A21\u578B\u7684\u300C\u56FE\u7247\u300D\u52FE\u9009\u5373\u53EF\u6062\u590D\u8D70\u56FE\u7247\u7406\u89E3\u4EE3\u7406\u3002"
1095
3206
  ),
1096
3207
  vpDirect.length > 0 ? import_react3.default.createElement(
1097
3208
  "div",
1098
- { className: "dkm-checks" },
1099
- import_react3.default.createElement("span", { className: "dkm-label" }, "\u539F\u56FE\u76F4\u53D1\uFF08\u591A\u6A21\u6001\uFF0C" + vpDirect.length + "\uFF09\uFF1A"),
1100
- vpDirect.map((c) => import_react3.default.createElement("span", { key: c.key, className: "dkm-chip", title: c.key }, c.model))
3209
+ { className: "dkm-capabilities" },
3210
+ import_react3.default.createElement(
3211
+ "div",
3212
+ { className: "dkm-checks" },
3213
+ import_react3.default.createElement("span", { className: "dkm-label" }, "\u539F\u56FE\u76F4\u53D1\u5019\u9009\uFF08\u4F60\u7684\u6807\u8BB0\u4F18\u5148\uFF0C" + vpDirect.length + "\uFF09\uFF1A"),
3214
+ import_react3.default.createElement("button", {
3215
+ type: "button",
3216
+ className: "dkm-mini",
3217
+ "aria-expanded": vpDirectExpanded,
3218
+ onClick: () => setVpDirectExpanded(!vpDirectExpanded)
3219
+ }, vpDirectExpanded ? "\u6536\u8D77\u5217\u8868" : "\u5C55\u5F00\u5217\u8868")
3220
+ ),
3221
+ vpDirectExpanded ? import_react3.default.createElement(
3222
+ "div",
3223
+ { className: "dkm-checks dkm-capability-list" },
3224
+ vpDirect.map((c) => import_react3.default.createElement("span", { key: c.key, className: "dkm-chip", title: c.key + " \xB7 " + c.source }, c.model))
3225
+ ) : null
1101
3226
  ) : null,
1102
3227
  vpProxied.length > 0 ? import_react3.default.createElement(
1103
3228
  "div",
1104
3229
  { className: "dkm-checks" },
1105
- import_react3.default.createElement("span", { className: "dkm-label" }, "\u8D70\u89C6\u89C9\u4EE3\u7406\uFF08\u7EAF\u6587\u672C\uFF0C" + vpProxied.length + "\uFF09\uFF1A"),
3230
+ import_react3.default.createElement("span", { className: "dkm-label" }, "\u8D70\u89C6\u89C9\u4EE3\u7406\uFF08\u672A\u6807\u8BB0\u56FE\u7247\uFF0C" + vpProxied.length + "\uFF09\uFF1A"),
1106
3231
  import_react3.default.createElement("span", { className: "dkm-sub" }, vpProxied.map((c) => c.model).join("\u3001"))
1107
3232
  ) : null,
1108
3233
  import_react3.default.createElement(
@@ -1182,10 +3307,7 @@ function ModelsView() {
1182
3307
  { className: "dkm-savebar" },
1183
3308
  import_react3.default.createElement("span", { className: "dkm-msg" }, dirty ? "\u6709\u672A\u4FDD\u5B58\u7684\u4FEE\u6539" : "\u65E0\u672A\u4FDD\u5B58\u4FEE\u6539"),
1184
3309
  import_react3.default.createElement("button", { type: "button", className: "dkm-save", disabled: !dirty || saving, onClick: save }, saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58\u5199\u56DE\u5B98\u65B9\u914D\u7F6E"),
1185
- import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: saving, onClick: () => {
1186
- setBuiltKey(null);
1187
- modelsStore.load();
1188
- } }, "\u91CD\u65B0\u62C9\u53D6"),
3310
+ import_react3.default.createElement("button", { type: "button", className: "dkb-refresh", disabled: saving || snap.loading, onClick: refreshModels }, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u91CD\u65B0\u62C9\u53D6"),
1189
3311
  msg ? import_react3.default.createElement("span", { className: "dkm-msg " + (msg.ok ? "ok" : "err") }, msg.text) : null
1190
3312
  )
1191
3313
  ));
@@ -1244,6 +3366,9 @@ var feature2 = {
1244
3366
  ".dkm-msg.ok{color:var(--dsw-alias-state-success-primary);}",
1245
3367
  ".dkm-msg.err{color:var(--dsw-alias-state-error-primary);}",
1246
3368
  ".dkm-list{display:flex;flex-direction:column;gap:8px;}",
3369
+ ".dkm-topbar{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}",
3370
+ ".dkm-capabilities{display:flex;flex-direction:column;gap:6px;}",
3371
+ ".dkm-capability-list{max-height:168px;overflow:auto;padding:2px 0 2px 2px;}",
1247
3372
  ".dkm-ro{color:var(--dsw-alias-label-secondary);font-size:12px;}",
1248
3373
  ".dkm-mini{cursor:pointer;border:1px solid var(--dsw-alias-border-l2);background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:999px;padding:1px 8px;font-family:inherit;font-size:11px;flex:none;}",
1249
3374
  ".dkm-mini:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-secondary);}",
@@ -1286,40 +3411,64 @@ var feature3 = {
1286
3411
 
1287
3412
  // features/theme/view.js
1288
3413
  var import_react5 = __toESM(require("react"), 1);
1289
- function readThemeLabel(ctx) {
3414
+ var import_react6 = require("react");
3415
+ var PREFERENCE_LABELS = { light: "\u4EAE\u8272", dark: "\u6697\u8272", system: "\u8DDF\u968F\u7CFB\u7EDF" };
3416
+ var THEME_LABELS = { light: "\u4EAE\u8272", dark: "\u6697\u8272" };
3417
+ function readThemeInfo(ctx) {
1290
3418
  const theme = ctx && ctx.get ? ctx.get("theme") : void 0;
1291
- if (theme === void 0) return { err: "theme \u670D\u52A1\u4E0D\u53EF\u7528" };
3419
+ if (!theme || typeof theme.getTheme !== "function") return { err: "theme \u670D\u52A1\u4E0D\u53EF\u7528" };
1292
3420
  let snap = null;
1293
3421
  try {
1294
3422
  snap = theme.getTheme();
1295
3423
  } catch (err) {
1296
3424
  return { err: "\u8BFB\u53D6\u5931\u8D25\uFF1A" + String(err && err.message || err) };
1297
3425
  }
1298
- const label = snap && typeof snap.id === "string" ? snap.id : snap && typeof snap.name === "string" ? snap.name : "\u672A\u77E5";
3426
+ const preference = snap && typeof snap.preference === "string" ? snap.preference : "";
3427
+ const activeId = snap && snap.active && typeof snap.active.id === "string" ? snap.active.id : "";
3428
+ const label = (PREFERENCE_LABELS[preference] || preference || "\u672A\u77E5") + (activeId && activeId !== preference && THEME_LABELS[activeId] ? "\uFF08\u5B9E\u9645" + THEME_LABELS[activeId] + "\uFF09" : "");
1299
3429
  return { label };
1300
3430
  }
3431
+ function useThemeInfo(ctx) {
3432
+ const [info, setInfo] = (0, import_react6.useState)(() => readThemeInfo(ctx));
3433
+ (0, import_react6.useEffect)(() => {
3434
+ let off = null;
3435
+ try {
3436
+ if (ctx && typeof ctx.on === "function") {
3437
+ off = ctx.on("theme/change", () => setInfo(readThemeInfo(ctx)));
3438
+ }
3439
+ } catch {
3440
+ }
3441
+ return () => {
3442
+ try {
3443
+ if (typeof off === "function") off();
3444
+ } catch {
3445
+ }
3446
+ };
3447
+ }, [ctx]);
3448
+ return info;
3449
+ }
1301
3450
  function ThemeView(props) {
1302
- const r = readThemeLabel(props && props.ctx);
3451
+ const r = useThemeInfo(props && props.ctx);
1303
3452
  if (r.err) return import_react5.default.createElement("div", null, r.err);
1304
3453
  return import_react5.default.createElement("div", null, "\u5F53\u524D\u4E3B\u9898\uFF1A" + r.label);
1305
3454
  }
1306
3455
  function ThemeStat(props) {
1307
- const r = readThemeLabel(props && props.ctx);
3456
+ const r = useThemeInfo(props && props.ctx);
1308
3457
  if (r.err) return import_react5.default.createElement("span", null, r.err);
1309
- return import_react5.default.createElement("span", null, "\u5F53\u524D\u4E3B\u9898\uFF1A" + r.label);
3458
+ return import_react5.default.createElement("span", null, "\u4E3B\u9898\uFF1A" + r.label);
1310
3459
  }
1311
3460
  var feature4 = {
1312
3461
  id: "theme",
1313
3462
  name: "\u4E3B\u9898\u4FE1\u606F",
1314
3463
  order: 150,
1315
3464
  accent: "#a78bfa",
1316
- description: "\u793A\u4F8B\u529F\u80FD\uFF1A\u8BFB\u53D6\u5F53\u524D\u4E3B\u9898\u5FEB\u7167\uFF08\u7EAF Client\uFF09",
3465
+ description: "\u8BFB\u53D6\u5F53\u524D\u4E3B\u9898\u5FEB\u7167\uFF1A\u504F\u597D\u4E0E\u5B9E\u9645\u751F\u6548\u4E3B\u9898\uFF08\u7EAF Client\uFF0C\u4E3B\u9898\u5207\u6362\u5B9E\u65F6\u5237\u65B0\uFF09",
1317
3466
  View: ThemeView,
1318
3467
  HomeStat: ThemeStat
1319
3468
  };
1320
3469
 
1321
3470
  // features/balance/view.js
1322
- var import_react6 = __toESM(require("react"), 1);
3471
+ var import_react7 = __toESM(require("react"), 1);
1323
3472
  var ACCENT_PALETTE = ["#4d9fff", "#34d399", "#fbbf24", "#a78bfa", "#f472b6", "#38bdf8", "#fb923c", "#4ade80", "#e879f9", "#22d3ee"];
1324
3473
  var CURATED_ACCENTS = {
1325
3474
  "deepseek-official": "#4d9fff",
@@ -1361,8 +3510,8 @@ var balanceStore = {
1361
3510
  }
1362
3511
  };
1363
3512
  function useBalance(ctx) {
1364
- const [snap, setSnap] = import_react6.default.useState(balanceStore.snap);
1365
- import_react6.default.useEffect(() => {
3513
+ const [snap, setSnap] = import_react7.default.useState(balanceStore.snap);
3514
+ import_react7.default.useEffect(() => {
1366
3515
  const off = balanceStore.subscribe(() => setSnap(balanceStore.snap));
1367
3516
  if (!balanceStore.snap.data && !balanceStore.snap.loading) balanceStore.load();
1368
3517
  const disposer = ctx && typeof ctx.interval === "function" ? ctx.interval(() => balanceStore.load(), 5 * 60 * 1e3) : null;
@@ -1376,7 +3525,7 @@ function useBalance(ctx) {
1376
3525
  function BalanceView(props) {
1377
3526
  const snap = useBalance(props && props.ctx);
1378
3527
  const load = () => balanceStore.load();
1379
- import_react6.default.useEffect(() => {
3528
+ import_react7.default.useEffect(() => {
1380
3529
  const pid = props && props.params && props.params.provider;
1381
3530
  if (!pid || typeof document === "undefined") return;
1382
3531
  const t = setTimeout(() => {
@@ -1399,15 +3548,15 @@ function BalanceView(props) {
1399
3548
  const def = data && data.default ? data.default.provider : null;
1400
3549
  const body = [];
1401
3550
  if (snap.error) {
1402
- body.push(import_react6.default.createElement("div", { key: "err", className: "dkb-note dkb-error" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF1A" + snap.error));
3551
+ body.push(import_react7.default.createElement("div", { key: "err", className: "dkb-note dkb-error" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF1A" + snap.error));
1403
3552
  } else if (!data) {
1404
- body.push(import_react6.default.createElement("div", { key: "loading", className: "dkb-note" }, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u8FD8\u6CA1\u6709\u6570\u636E\uFF0C\u70B9\u51FB\u4E0B\u65B9\u5237\u65B0"));
3553
+ body.push(import_react7.default.createElement("div", { key: "loading", className: "dkb-note" }, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u8FD8\u6CA1\u6709\u6570\u636E\uFF0C\u70B9\u51FB\u4E0B\u65B9\u5237\u65B0"));
1405
3554
  } else if (providers.length === 0) {
1406
- body.push(import_react6.default.createElement("div", { key: "empty", className: "dkb-note" }, "\u6CA1\u6709\u627E\u5230\u5DF2\u914D\u7F6E\u7684\u6A21\u578B Provider"));
3555
+ body.push(import_react7.default.createElement("div", { key: "empty", className: "dkb-note" }, "\u6CA1\u6709\u627E\u5230\u5DF2\u914D\u7F6E\u7684\u6A21\u578B Provider"));
1407
3556
  } else {
1408
3557
  const rank = (p) => p.balance && p.balance.status === "ok" ? 0 : p.balance && p.balance.status === "login-required" ? 1 : 2;
1409
3558
  const sorted = providers.slice().sort((a, b) => rank(a) - rank(b));
1410
- body.push(import_react6.default.createElement(
3559
+ body.push(import_react7.default.createElement(
1411
3560
  "div",
1412
3561
  { key: "rows", className: "dkb-rows" },
1413
3562
  sorted.map((p) => {
@@ -1424,73 +3573,73 @@ function BalanceView(props) {
1424
3573
  let balBody = null;
1425
3574
  if (b && b.status === "ok" && b.kind === "quota") {
1426
3575
  const dims = Array.isArray(b.dims) ? b.dims : [];
1427
- balBody = import_react6.default.createElement(
1428
- import_react6.default.Fragment,
3576
+ balBody = import_react7.default.createElement(
3577
+ import_react7.default.Fragment,
1429
3578
  null,
1430
- import_react6.default.createElement(
3579
+ import_react7.default.createElement(
1431
3580
  "div",
1432
3581
  { className: "dkb-main" },
1433
- import_react6.default.createElement("span", { className: "dkb-main-label" }, "\u5269\u4F59\u989D\u5EA6"),
1434
- import_react6.default.createElement("span", { className: "dkb-main-value" }, fmt(b.remaining) + (b.unit ? " " + b.unit : "")),
1435
- import_react6.default.createElement(
3582
+ import_react7.default.createElement("span", { className: "dkb-main-label" }, "\u5269\u4F59\u989D\u5EA6"),
3583
+ import_react7.default.createElement("span", { className: "dkb-main-value" }, fmt(b.remaining) + (b.unit ? " " + b.unit : "")),
3584
+ import_react7.default.createElement(
1436
3585
  "span",
1437
3586
  { className: "dkb-main-part" },
1438
3587
  "\u5DF2\u7528 " + fmt(b.used) + " / \u603B " + fmt(b.limit),
1439
- b.resetTime ? import_react6.default.createElement("span", null, " \xB7 \u91CD\u7F6E " + String(b.resetTime).slice(0, 10)) : null
3588
+ b.resetTime ? import_react7.default.createElement("span", null, " \xB7 \u91CD\u7F6E " + String(b.resetTime).slice(0, 10)) : null
1440
3589
  )
1441
3590
  ),
1442
- dims.map((d, i) => import_react6.default.createElement(
3591
+ dims.map((d, i) => import_react7.default.createElement(
1443
3592
  "div",
1444
3593
  { key: "d" + i, className: "dkb-dim" },
1445
- import_react6.default.createElement("span", { className: "dkb-dim-label" }, d.window === "weekly" ? "\u5468\u989D\u5EA6" : "\u5C0F\u65F6\u989D\u5EA6"),
1446
- import_react6.default.createElement(
3594
+ import_react7.default.createElement("span", { className: "dkb-dim-label" }, d.window === "weekly" ? "\u5468\u989D\u5EA6" : "\u5C0F\u65F6\u989D\u5EA6"),
3595
+ import_react7.default.createElement(
1447
3596
  "span",
1448
3597
  { className: "dkb-dim-bar" },
1449
- import_react6.default.createElement("span", { className: "dkb-dim-fill", style: { width: (d.limit > 0 ? Math.min(100, Math.round(d.remaining / d.limit * 100)) : 0) + "%" } })
3598
+ import_react7.default.createElement("span", { className: "dkb-dim-fill", style: { width: (d.limit > 0 ? Math.min(100, Math.round(d.remaining / d.limit * 100)) : 0) + "%" } })
1450
3599
  ),
1451
- import_react6.default.createElement("span", { className: "dkb-dim-text" }, "\u5269 " + fmt(d.remaining) + " / " + fmt(d.limit))
3600
+ import_react7.default.createElement("span", { className: "dkb-dim-text" }, "\u5269 " + fmt(d.remaining) + " / " + fmt(d.limit))
1452
3601
  ))
1453
3602
  );
1454
3603
  } else if (b && b.status === "ok") {
1455
3604
  const infos = Array.isArray(b.infos) ? b.infos : [];
1456
- balBody = import_react6.default.createElement(
3605
+ balBody = import_react7.default.createElement(
1457
3606
  "div",
1458
3607
  { className: "dkb-mains" },
1459
- infos.map((i, idx) => import_react6.default.createElement(
3608
+ infos.map((i, idx) => import_react7.default.createElement(
1460
3609
  "div",
1461
3610
  { key: idx, className: "dkb-main" },
1462
- import_react6.default.createElement("span", { className: "dkb-main-label", style: { color: accent } }, i.currency),
1463
- import_react6.default.createElement("span", { className: "dkb-main-value" }, fmt(i.totalBalance)),
1464
- import_react6.default.createElement(
3611
+ import_react7.default.createElement("span", { className: "dkb-main-label", style: { color: accent } }, i.currency),
3612
+ import_react7.default.createElement("span", { className: "dkb-main-value" }, fmt(i.totalBalance)),
3613
+ import_react7.default.createElement(
1465
3614
  "span",
1466
3615
  { className: "dkb-main-parts" },
1467
- i.grantedBalance != null ? import_react6.default.createElement("span", { className: "dkb-main-part", style: { color: C_GRANTED } }, "\u8D60\u9001 " + fmt(i.grantedBalance)) : null,
1468
- i.toppedUpBalance != null ? import_react6.default.createElement("span", { className: "dkb-main-part", style: { color: C_TOPUP } }, "\u5145\u503C " + fmt(i.toppedUpBalance)) : null
3616
+ i.grantedBalance != null ? import_react7.default.createElement("span", { className: "dkb-main-part", style: { color: C_GRANTED } }, "\u8D60\u9001 " + fmt(i.grantedBalance)) : null,
3617
+ i.toppedUpBalance != null ? import_react7.default.createElement("span", { className: "dkb-main-part", style: { color: C_TOPUP } }, "\u5145\u503C " + fmt(i.toppedUpBalance)) : null
1469
3618
  )
1470
3619
  ))
1471
3620
  );
1472
3621
  } else if (b && b.status === "login-required" && b.consoleUrl) {
1473
- balBody = import_react6.default.createElement(
3622
+ balBody = import_react7.default.createElement(
1474
3623
  "div",
1475
3624
  { className: "dkb-main" },
1476
- import_react6.default.createElement("a", { href: b.consoleUrl, target: "_blank", rel: "noreferrer", className: "dkb-link", style: { color: accent } }, "\u53BB\u63A7\u5236\u53F0\u67E5\u770B\u4F59\u989D \u2192")
3625
+ import_react7.default.createElement("a", { href: b.consoleUrl, target: "_blank", rel: "noreferrer", className: "dkb-link", style: { color: accent } }, "\u53BB\u63A7\u5236\u53F0\u67E5\u770B\u4F59\u989D \u2192")
1477
3626
  );
1478
3627
  } else {
1479
- balBody = b && b.message ? import_react6.default.createElement("div", { className: "dkb-note" }, b.message) : import_react6.default.createElement("div", { className: "dkb-note" }, "\u8BE5 Provider \u6CA1\u6709\u5DF2\u77E5\u7684\u4F59\u989D\u67E5\u8BE2\u63A5\u53E3");
3628
+ balBody = b && b.message ? import_react7.default.createElement("div", { className: "dkb-note" }, b.message) : import_react7.default.createElement("div", { className: "dkb-note" }, "\u8BE5 Provider \u6CA1\u6709\u5DF2\u77E5\u7684\u4F59\u989D\u67E5\u8BE2\u63A5\u53E3");
1480
3629
  }
1481
3630
  const sub = ["ID " + p.id, p.api, p.baseURL ? p.baseURL.replace(/^https?:\/\//, "") : null].filter(Boolean).join(" \xB7 ");
1482
- return import_react6.default.createElement(
3631
+ return import_react7.default.createElement(
1483
3632
  "div",
1484
3633
  { key: p.id, className: "dkb-row", "data-dock-provider": p.id },
1485
- import_react6.default.createElement(
3634
+ import_react7.default.createElement(
1486
3635
  "div",
1487
3636
  { className: "dkb-row-head" },
1488
- import_react6.default.createElement("span", { className: "dkb-dot", style: { background: accent } }),
1489
- import_react6.default.createElement("span", { className: "dkb-name", style: { color: accent } }, p.displayName),
1490
- def === p.id ? import_react6.default.createElement("span", { className: "dkb-default" }, "\u9ED8\u8BA4") : null,
1491
- import_react6.default.createElement("span", { className: "dkb-badge" + (badge[1] ? " " + badge[1] : ""), style: badge[1] === "err" ? { color: C_ERR, borderColor: C_ERR } : null }, badge[0]),
3637
+ import_react7.default.createElement("span", { className: "dkb-dot", style: { background: accent } }),
3638
+ import_react7.default.createElement("span", { className: "dkb-name", style: { color: accent } }, p.displayName),
3639
+ def === p.id ? import_react7.default.createElement("span", { className: "dkb-default" }, "\u9ED8\u8BA4") : null,
3640
+ import_react7.default.createElement("span", { className: "dkb-badge" + (badge[1] ? " " + badge[1] : ""), style: badge[1] === "err" ? { color: C_ERR, borderColor: C_ERR } : null }, badge[0]),
1492
3641
  // 模型数折叠提示(点开展开 chips)
1493
- p.models && p.models.length > 0 ? import_react6.default.createElement("button", {
3642
+ p.models && p.models.length > 0 ? import_react7.default.createElement("button", {
1494
3643
  type: "button",
1495
3644
  className: "dkb-models-toggle",
1496
3645
  title: p.models.join(", "),
@@ -1500,13 +3649,13 @@ function BalanceView(props) {
1500
3649
  }
1501
3650
  }, p.models.length + " \u4E2A\u6A21\u578B \u25BE") : null
1502
3651
  ),
1503
- sub ? import_react6.default.createElement("div", { className: "dkb-sub" }, sub) : null,
1504
- p.apiKeyEnv ? import_react6.default.createElement("div", { className: "dkb-sub" }, "\u5BC6\u94A5: " + p.apiKeyEnv + (p.credentialConfigured ? " \u2713" : " \u2717")) : null,
1505
- p.models && p.models.length > 0 ? import_react6.default.createElement(
3652
+ sub ? import_react7.default.createElement("div", { className: "dkb-sub" }, sub) : null,
3653
+ p.apiKeyEnv ? import_react7.default.createElement("div", { className: "dkb-sub" }, "\u5BC6\u94A5: " + p.apiKeyEnv + (p.credentialConfigured ? " \u2713" : " \u2717")) : null,
3654
+ p.models && p.models.length > 0 ? import_react7.default.createElement(
1506
3655
  "div",
1507
3656
  { className: "dkb-chips" },
1508
- p.models.slice(0, 8).map((m) => import_react6.default.createElement("span", { key: m, className: "dkb-chip", style: { border: "1px solid " + accent, color: accent, background: accent + "1a" } }, m)),
1509
- p.models.length > 8 ? import_react6.default.createElement("span", { key: "more", className: "dkb-chip" }, "+" + (p.models.length - 8)) : null
3657
+ p.models.slice(0, 8).map((m) => import_react7.default.createElement("span", { key: m, className: "dkb-chip", style: { border: "1px solid " + accent, color: accent, background: accent + "1a" } }, m)),
3658
+ p.models.length > 8 ? import_react7.default.createElement("span", { key: "more", className: "dkb-chip" }, "+" + (p.models.length - 8)) : null
1510
3659
  ) : null,
1511
3660
  balBody
1512
3661
  );
@@ -1514,20 +3663,20 @@ function BalanceView(props) {
1514
3663
  ));
1515
3664
  }
1516
3665
  const now = new Date(data && data.generatedAt ? data.generatedAt : Date.now());
1517
- return import_react6.default.createElement(
3666
+ return import_react7.default.createElement(
1518
3667
  "div",
1519
3668
  { className: "dkb-rows" },
1520
- import_react6.default.createElement(
3669
+ import_react7.default.createElement(
1521
3670
  "div",
1522
3671
  { className: "dkb-note" },
1523
3672
  data && !snap.error && providers.length > 0 ? okCount + "/" + providers.length + " \u4E2A Provider \u53EF\u67E5\u4F59\u989D\uFF08\u53EF\u67E5\u7684\u6392\u524D\u9762\uFF09" : "\u6A21\u578B\u4F59\u989D \xB7 Host \u534A\u90E8\u5B9E\u65F6\u62C9\u53D6"
1524
3673
  ),
1525
3674
  body,
1526
- import_react6.default.createElement(
3675
+ import_react7.default.createElement(
1527
3676
  "div",
1528
3677
  { className: "dkb-foot" },
1529
- import_react6.default.createElement("span", null, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u66F4\u65B0\u4E8E " + now.toLocaleTimeString()),
1530
- import_react6.default.createElement("button", { type: "button", className: "dkb-refresh", onClick: load }, "\u5237\u65B0")
3678
+ import_react7.default.createElement("span", null, snap.loading ? "\u5237\u65B0\u4E2D\u2026" : "\u66F4\u65B0\u4E8E " + now.toLocaleTimeString()),
3679
+ import_react7.default.createElement("button", { type: "button", className: "dkb-refresh", onClick: load }, "\u5237\u65B0")
1531
3680
  )
1532
3681
  );
1533
3682
  }
@@ -1535,14 +3684,14 @@ function BalanceStat(props) {
1535
3684
  const snap = useBalance(props && props.ctx);
1536
3685
  const data = snap.data;
1537
3686
  const providers = data && Array.isArray(data.providers) ? data.providers : [];
1538
- if (snap.error) return import_react6.default.createElement("span", { className: "dockm-err" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF08\u70B9\u51FB\u8FDB\u5165\u67E5\u770B\u8BE6\u60C5\uFF09");
1539
- if (!data) return import_react6.default.createElement("span", null, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u7B49\u5F85\u62C9\u53D6\u4F59\u989D");
3687
+ if (snap.error) return import_react7.default.createElement("span", { className: "dockm-err" }, "\u4F59\u989D\u67E5\u8BE2\u5931\u8D25\uFF08\u70B9\u51FB\u8FDB\u5165\u67E5\u770B\u8BE6\u60C5\uFF09");
3688
+ if (!data) return import_react7.default.createElement("span", null, snap.loading ? "\u6B63\u5728\u62C9\u53D6\u4F59\u989D\u2026" : "\u7B49\u5F85\u62C9\u53D6\u4F59\u989D");
1540
3689
  const ok = providers.filter((p) => p.balance && p.balance.status === "ok").length;
1541
- return import_react6.default.createElement("span", null, providers.length + " \u4E2A Provider \xB7 " + ok + " \u4E2A\u53EF\u67E5\u4F59\u989D");
3690
+ return import_react7.default.createElement("span", null, providers.length + " \u4E2A Provider \xB7 " + ok + " \u4E2A\u53EF\u67E5\u4F59\u989D");
1542
3691
  }
1543
3692
  function useCurrentProvider(ctx, sessionId) {
1544
- const [cur, setCur] = import_react6.default.useState(null);
1545
- import_react6.default.useEffect(() => {
3693
+ const [cur, setCur] = import_react7.default.useState(null);
3694
+ import_react7.default.useEffect(() => {
1546
3695
  let alive = true, off = null;
1547
3696
  try {
1548
3697
  const models = ctx && ctx.get ? ctx.get("modelDirectories") : void 0;
@@ -1604,7 +3753,7 @@ function BalanceChip(props) {
1604
3753
  const text = snap.error ? "\u4F59\u989D\xB7\u5931\u8D25" : !data ? snap.loading ? "\u4F59\u989D \u2026" : "\u4F59\u989D \u2014" : cur ? chipBalanceText(cur) : "\u4F59\u989D \u2014";
1605
3754
  const selModel = sel && (sel.model || sel.selected && sel.selected.model) || null;
1606
3755
  const title = cur ? (cur.displayName || cur.id) + (selModel ? " \xB7 \u5F53\u524D\u6A21\u578B " + selModel : "") + " \xB7 \u70B9\u51FB\u5728\u529F\u80FD\u575E\u67E5\u770B\u4F59\u989D\u8BE6\u60C5" : "\u70B9\u51FB\u6253\u5F00\u529F\u80FD\u575E \xB7 \u6A21\u578B\u4F59\u989D";
1607
- return import_react6.default.createElement(
3756
+ return import_react7.default.createElement(
1608
3757
  "button",
1609
3758
  {
1610
3759
  type: "button",
@@ -1613,8 +3762,8 @@ function BalanceChip(props) {
1613
3762
  "aria-label": "\u6A21\u578B\u4F59\u989D",
1614
3763
  onClick: () => openPanel("balance", def ? { provider: def } : null)
1615
3764
  },
1616
- import_react6.default.createElement("span", { className: "dockchip-dot", style: { background: accent } }),
1617
- import_react6.default.createElement("span", null, text)
3765
+ import_react7.default.createElement("span", { className: "dockchip-dot", style: { background: accent } }),
3766
+ import_react7.default.createElement("span", null, text)
1618
3767
  );
1619
3768
  }
1620
3769
  var feature5 = {
@@ -1674,7 +3823,7 @@ var feature5 = {
1674
3823
  };
1675
3824
 
1676
3825
  // features/animation/view.jsx
1677
- var import_react7 = require("react");
3826
+ var import_react8 = require("react");
1678
3827
  var import_jsx_runtime2 = require("react/jsx-runtime");
1679
3828
  function rpcCall2(method, args) {
1680
3829
  return fetch("/dsh-dock/animation/" + method, {
@@ -1693,10 +3842,10 @@ function rpcCall2(method, args) {
1693
3842
  }
1694
3843
  var EFFECT_MODES = [
1695
3844
  { id: "flow", name: "\u6D41\u5149\u7EC6\u7EBF", desc: "\u9876\u90E8\u7EC6\u7EBF\u6D41\u5149\u5F80\u8FD4\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\u52A0\u5FEB" },
1696
- { id: "breathe", name: "\u547C\u5438\u5149\u70B9", desc: "\u72B6\u6001\u5FBD\u6807\u5706\u70B9\u547C\u5438\uFF0C\u8D8A\u5FD9\u547C\u5438\u8D8A\u5FEB" },
3845
+ { id: "breathe", name: "\u547C\u5438\u5149\u70B9", desc: "\u9192\u76EE\u547C\u5438\u5149\u70B9\u5E26\u6269\u6563\u5149\u6655\uFF1A\u989C\u8272\u968F\u4EFB\u52A1\u9636\u6BB5\uFF08\u601D\u8003\u84DD/\u8F93\u51FA\u7EFF/\u4EE3\u7801\u6A59/\u67E5\u8D44\u6599\u9752\uFF09\uFF0C\u547C\u5438\u968F\u541E\u5410\u52A0\u5FEB" },
1697
3846
  { id: "ring", name: "\u8F68\u9053\u5149\u73AF", desc: "\u7EC6\u73AF\u7ED5\u5706\u70B9\u65CB\u8F6C\uFF0C\u8F6C\u901F\u968F\u4EFB\u52A1\u901F\u5EA6" },
1698
3847
  { id: "orbit", name: "\u73AF\u5C4F\u5DE1\u822A", desc: "\u4E00\u9897\u5149\u70B9\u6CBF\u5C4F\u5E55\u8FB9\u7F18\u5DE1\u822A\u6574\u5708\uFF0C\u9192\u76EE\u4E0D\u906E\u6321" },
1699
- { id: "robot", name: "\u684C\u9762\u4F19\u4F34", desc: "\u66F4\u5177\u8C61\u7684\u4EBA\u7269\u5750\u9547\u56DB\u5C4F\u5DE5\u4F4D\uFF1A\u601D\u8003\u3001\u8F93\u51FA\u3001\u67E5\u8D44\u6599\u968F\u4EFB\u52A1\u9636\u6BB5\u5207\u6362" },
3848
+ { id: "robot", name: "\u684C\u9762\u4F19\u4F34", desc: "\u771F\u4EBA\u5316\u53CC\u5DE5\u4F4D\uFF1A\u67E5\u8D44\u6599\u770B\u5DE6\u5C4F\u3001\u5199\u5165/\u6539\u4EE3\u7801\u79FB\u5230\u53F3\u5C4F\uFF1B\u5EA7\u6905\u548C\u8F6C\u5934\u968F\u5B9E\u65F6\u4EFB\u52A1\u8282\u594F\u52A0\u901F" },
1700
3849
  { id: "matrix", name: "\u4EE3\u7801\u96E8", desc: "\u5B57\u7B26\u6CBF\u5C4F\u5E55\u7F13\u843D\u5982\u6570\u636E\u6D41\uFF0C\u901F\u5EA6\u968F\u4EFB\u52A1\u541E\u5410\uFF0C\u514B\u5236\u7684\u4F4E\u900F\u660E\u5EA6" },
1701
3850
  { id: "stars", name: "\u661F\u91CE", desc: "\u7EC6\u788E\u661F\u70B9\u7F13\u6162\u98D8\u79FB\u95EA\u70C1\uFF0C\u5B89\u9759\u8010\u770B\u7684\u80CC\u666F\u6C1B\u56F4" },
1702
3851
  { id: "aurora", name: "\u6781\u5149", desc: "\u5C4F\u5E55\u9876\u90E8\u67D4\u5149\u5E26\u7F13\u6162\u547C\u5438\u6D41\u52A8\uFF0C\u50CF\u6781\u5149\u62C2\u8FC7" }
@@ -1705,6 +3854,10 @@ var PHASE_LABELS = { think: "\u601D\u8003\u4E2D", write: "\u8F93\u51FA\u4E2D", c
1705
3854
  function phaseLabel(p) {
1706
3855
  return PHASE_LABELS[p] || "\u5DE5\u4F5C\u4E2D";
1707
3856
  }
3857
+ var PHASE_COLORS = { think: "#60a5fa", write: "#34d399", code: "#fbbf24", search: "#2dd4bf" };
3858
+ function phaseColor(p) {
3859
+ return PHASE_COLORS[p] || "#4d9fff";
3860
+ }
1708
3861
  var END_LABELS = {
1709
3862
  completed: { label: "\u5B8C\u6210", cls: "ok" },
1710
3863
  error: { label: "\u51FA\u9519", cls: "err" },
@@ -1783,13 +3936,13 @@ var animationStore = {
1783
3936
  }
1784
3937
  };
1785
3938
  function useAnimation() {
1786
- const [snap, setSnap] = (0, import_react7.useState)(animationStore.snap);
1787
- (0, import_react7.useEffect)(() => animationStore.subscribe(() => setSnap(animationStore.snap)), []);
3939
+ const [snap, setSnap] = (0, import_react8.useState)(animationStore.snap);
3940
+ (0, import_react8.useEffect)(() => animationStore.subscribe(() => setSnap(animationStore.snap)), []);
1788
3941
  return snap;
1789
3942
  }
1790
3943
  function useTicker(ctx, active) {
1791
- const [, bump] = (0, import_react7.useState)(0);
1792
- (0, import_react7.useEffect)(() => {
3944
+ const [, bump] = (0, import_react8.useState)(0);
3945
+ (0, import_react8.useEffect)(() => {
1793
3946
  if (!active) return;
1794
3947
  if (ctx && typeof ctx.interval === "function") return ctx.interval(bump, 1e3);
1795
3948
  const t = setInterval(bump, 1e3);
@@ -1824,6 +3977,7 @@ function Box3(props) {
1824
3977
  }
1825
3978
  function Monitor3(props) {
1826
3979
  const w = props.w, h = props.h;
3980
+ const searchScreen = props.mode === "search";
1827
3981
  const lines = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5];
1828
3982
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
1829
3983
  "span",
@@ -1832,7 +3986,10 @@ function Monitor3(props) {
1832
3986
  style: { left: props.x - w / 2, top: props.y - h / 2, width: w, height: h, transform: "translateZ(" + (props.z || -3) + "px) rotateY(" + (props.ry || 0) + "deg)" },
1833
3987
  children: [
1834
3988
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w, h, d: 5, cls: "dk3-frame", x: w / 2, y: h / 2 }),
1835
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-screen", style: { width: w - 4, height: h - 4, transform: "translate(-50%,-50%) translateZ(3.1px)" }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-code", children: [
3989
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-screen", style: { width: w - 4, height: h - 4, transform: "translate(-50%,-50%) translateZ(3.1px)" }, children: searchScreen ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-search-ui", children: [
3990
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-search-box", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("b", {}) }),
3991
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-search-results", children: lines.slice(0, 6).map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}, i)) })
3992
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-code", children: [
1836
3993
  lines.map((n, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}, i)),
1837
3994
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-cur" })
1838
3995
  ] }) })
@@ -1842,57 +3999,86 @@ function Monitor3(props) {
1842
3999
  }
1843
4000
  function RobotScene(props) {
1844
4001
  const phase = props && props.phase ? props.phase : "code";
1845
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-bot-scene", "data-phase": phase, "aria-hidden": "true", children: [
4002
+ const tasks = Array.isArray(props && props.tasks) ? props.tasks : null;
4003
+ const n = tasks ? Math.max(1, Math.min(3, tasks.length)) : 1;
4004
+ const station = phase === "search" ? "left" : phase === "write" || phase === "code" ? "right" : "center";
4005
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-bot-scene", "data-phase": phase, "data-station": station, "data-tasks": tasks ? String(n) : void 0, "aria-hidden": "true", children: [
1846
4006
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-world", children: [
1847
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 150, h: 7, d: 40, cls: "dk3-desk", x: 115, y: 78 }),
1848
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 26, d: 32, cls: "dk3-metal dk3-leg", x: 48, y: 94 }),
1849
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 26, d: 32, cls: "dk3-metal dk3-leg", x: 182, y: 94 }),
1850
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 34, h: 24, x: 140, y: 60, ry: 24, cls: "left" }),
1851
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 40, h: 30, x: 168, y: 58, ry: 0, cls: "center" }),
1852
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 28, h: 21, x: 188, y: 62, ry: -24, cls: "right" }),
1853
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 30, h: 20, x: 168, y: 28, ry: 0, cls: "top" }),
1854
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 126, y: 73, z: 14 }),
1855
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 5, d: 4, cls: "dk3-mug", x: 140, y: 71, z: 14 }),
4007
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 134, h: 7, d: 38, cls: "dk3-desk", x: 145, y: 76 }),
4008
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 24, d: 30, cls: "dk3-metal dk3-leg", x: 84, y: 89 }),
4009
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 24, d: 30, cls: "dk3-metal dk3-leg", x: 206, y: 89 }),
4010
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 34, h: 24, x: 140, y: 59, ry: 20, cls: "left", mode: "search" }),
4011
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 42, h: 30, x: 180, y: 57, ry: -16, cls: "right" }),
4012
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Monitor3, { w: 28, h: 18, x: 160, y: 31, ry: 0, cls: "top" }),
4013
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 130, y: 71, z: 14 }),
4014
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 2.5, d: 6, cls: "dk3-metal dk3-mouse3", x: 141, y: 71, z: 14 }),
4015
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 5, d: 4, cls: "dk3-mug", x: 154, y: 69, z: 14 }),
4016
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 16, h: 2.5, d: 9, cls: "dk3-metal dk3-kb3", x: 170, y: 71, z: 14 }),
4017
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 2.5, d: 6, cls: "dk3-metal dk3-mouse3", x: 181, y: 71, z: 14 }),
1856
4018
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-person", children: [
1857
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 30, d: 22, cls: "dk3-chairback", x: 2, y: 42 }),
1858
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 20, h: 4, d: 22, cls: "dk3-chairseat", x: 12, y: 58 }),
1859
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 12, d: 3, cls: "dk3-metal", x: 12, y: 68 }),
1860
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 14, h: 2, d: 14, cls: "dk3-metal", x: 12, y: 74 }),
1861
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 13, h: 5, d: 9, cls: "dk3-pants", x: 20, y: 54 }),
1862
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 12, d: 4, cls: "dk3-pants", x: 26, y: 62 }),
1863
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 6, h: 3, d: 5, cls: "dk3-shoe", x: 28, y: 73 }),
1864
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 15, h: 20, d: 11, cls: "dk3-hood dk3-torso", x: 12, y: 36 }),
1865
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 8, d: 9, cls: "dk3-hood dk3-hoodbump", x: 5, y: 30 }),
1866
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 3, d: 4, cls: "dk3-skin", x: 14, y: 25 }),
1867
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-head3", children: [
1868
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box3, { w: 13, h: 12, d: 12, cls: "dk3-skin dk3-headbox", x: 8, y: 10, children: [
1869
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-brows", style: { width: 10, height: 4, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.3px)" }, children: [
1870
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1871
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
4019
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 20, d: 20, cls: "dk3-chairback", x: 2, y: 47 }),
4020
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 18, h: 4, d: 20, cls: "dk3-chairseat", x: 12, y: 59 }),
4021
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 9, d: 3, cls: "dk3-metal", x: 12, y: 66 }),
4022
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 13, h: 2, d: 13, cls: "dk3-metal", x: 12, y: 71 }),
4023
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 3, d: 3, cls: "dk3-wheel", x: 6, y: 74 }),
4024
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3, h: 3, d: 3, cls: "dk3-wheel", x: 18, y: 74 }),
4025
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 5, d: 9, cls: "dk3-pants", x: 20, y: 54 }),
4026
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 10, d: 4, cls: "dk3-pants", x: 26, y: 62 }),
4027
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 6, h: 3, d: 5, cls: "dk3-shoe", x: 28, y: 70 }),
4028
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-upper3", children: [
4029
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 18, h: 5, d: 12, cls: "dk3-hood dk3-shoulders3", x: 13, y: 30 }),
4030
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 15, h: 14, d: 11, cls: "dk3-hood dk3-torso dk3-chest3", x: 12, y: 38 }),
4031
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 7, d: 10, cls: "dk3-hood dk3-torso dk3-waist3", x: 12, y: 47 }),
4032
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 8, d: 9, cls: "dk3-hood dk3-hoodbump", x: 5, y: 32 }),
4033
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 5, h: 7, d: 5, cls: "dk3-skin dk3-neck3", x: 14, y: 24 }),
4034
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 8, h: 3, d: 8, cls: "dk3-collar3", x: 14, y: 28 }),
4035
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-head3", children: [
4036
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(Box3, { w: 12, h: 11, d: 11, cls: "dk3-skin dk3-cranium", x: 8, y: 8, children: [
4037
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-brows", style: { width: 9, height: 4, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(5.8px)" }, children: [
4038
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
4039
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
4040
+ ] }),
4041
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-eyes", style: { width: 9, height: 6, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(5.7px)" }, children: [
4042
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
4043
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
4044
+ ] }),
4045
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-nose", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.1px)" } })
1872
4046
  ] }),
1873
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-eyes", style: { width: 10, height: 7, transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.2px)" }, children: [
4047
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 9, h: 7, d: 9, cls: "dk3-skin dk3-jaw3", x: 8.5, y: 14, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-mouth", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(4.7px)" } }) }),
4048
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 12, h: 5, d: 12, cls: "dk3-hair dk3-hair-crown", x: 8, y: 3.5 }),
4049
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 8, d: 11, cls: "dk3-hair dk3-hair-back", x: 3, y: 7.5 }),
4050
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fringe3", children: [
4051
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1874
4052
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
1875
4053
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
1876
4054
  ] }),
1877
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-nose", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.8px)" } }),
1878
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-mouth", style: { transform: "translate(-50%,-50%) rotateY(90deg) translateZ(6.2px)" } })
4055
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-ear" })
1879
4056
  ] }),
1880
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 14, h: 6, d: 13, cls: "dk3-hair", x: 8, y: 4 }),
1881
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 13, cls: "dk3-hair", x: 2, y: 9 }),
1882
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dk3-ear" })
1883
- ] }),
1884
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3", children: [
1885
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
1886
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
1887
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 11, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 6, y: 2 }),
1888
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 12.5, y: 2 })
1889
- ] })
1890
- ] }),
1891
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-far", children: [
1892
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
1893
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
1894
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 11, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 6, y: 2 }),
1895
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 12.5, y: 2 })
4057
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-near", children: [
4058
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
4059
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
4060
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 10, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 5.5, y: 2 }),
4061
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-wrist3", children: [
4062
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 2, y: 2 }),
4063
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fingers3", children: [
4064
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
4065
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
4066
+ ] })
4067
+ ] })
4068
+ ] })
4069
+ ] }),
4070
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-arm3 dk3-far", children: [
4071
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 4, h: 11, d: 4, cls: "dk3-hood dk3-uarm", x: 2, y: 6 }),
4072
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-elbow", children: [
4073
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 10, h: 3.5, d: 3.5, cls: "dk3-hood dk3-farm", x: 5.5, y: 2 }),
4074
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dk3-wrist3", children: [
4075
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Box3, { w: 3.5, h: 3, d: 3, cls: "dk3-skin dk3-hand", x: 2, y: 2 }),
4076
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dk3-fingers3", children: [
4077
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {}),
4078
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("i", {})
4079
+ ] })
4080
+ ] })
4081
+ ] })
1896
4082
  ] })
1897
4083
  ] })
1898
4084
  ] })
@@ -1950,16 +4136,16 @@ function previewSound(effect) {
1950
4136
  }
1951
4137
  function Toast(props) {
1952
4138
  const t = props.t;
1953
- const [closing, setClosing] = (0, import_react7.useState)(false);
1954
- const close = (0, import_react7.useCallback)(() => {
4139
+ const [closing, setClosing] = (0, import_react8.useState)(false);
4140
+ const close = (0, import_react8.useCallback)(() => {
1955
4141
  if (!closing) setClosing(true);
1956
4142
  }, [closing]);
1957
- (0, import_react7.useEffect)(() => {
4143
+ (0, import_react8.useEffect)(() => {
1958
4144
  if (!t.stayMs) return;
1959
4145
  const timer = setTimeout(close, t.stayMs);
1960
4146
  return () => clearTimeout(timer);
1961
4147
  }, []);
1962
- (0, import_react7.useEffect)(() => {
4148
+ (0, import_react8.useEffect)(() => {
1963
4149
  if (!closing) return;
1964
4150
  const timer = setTimeout(() => props.onClose(t.id), 240);
1965
4151
  return () => clearTimeout(timer);
@@ -2001,7 +4187,7 @@ var MATRIX_CHARS = "01</>;{}=+*#";
2001
4187
  function AmbientLayer(props) {
2002
4188
  const mode = props.mode;
2003
4189
  const speed = props.speed;
2004
- const matrix = (0, import_react7.useMemo)(() => makeBits(34, () => ({
4190
+ const matrix = (0, import_react8.useMemo)(() => makeBits(34, () => ({
2005
4191
  l: Math.random() * 100,
2006
4192
  d: 4 + Math.random() * 6,
2007
4193
  delay: -Math.random() * 8,
@@ -2009,7 +4195,7 @@ function AmbientLayer(props) {
2009
4195
  s: 11 + Math.round(Math.random() * 4),
2010
4196
  c: MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)] + MATRIX_CHARS[Math.floor(Math.random() * MATRIX_CHARS.length)]
2011
4197
  })), []);
2012
- const stars = (0, import_react7.useMemo)(() => makeBits(80, () => ({
4198
+ const stars = (0, import_react8.useMemo)(() => makeBits(80, () => ({
2013
4199
  l: Math.random() * 100,
2014
4200
  t: Math.random() * 100,
2015
4201
  sz: 1.5 + Math.random() * 2,
@@ -2042,17 +4228,17 @@ function AmbientLayer(props) {
2042
4228
  function AnimationOverlay(props) {
2043
4229
  const ctx = props && props.ctx;
2044
4230
  const snap = useAnimation();
2045
- const [toasts, setToasts] = (0, import_react7.useState)([]);
2046
- const [flourish, setFlourish] = (0, import_react7.useState)(null);
2047
- const [bursts, setBursts] = (0, import_react7.useState)([]);
2048
- const prevActiveRef = (0, import_react7.useRef)(null);
2049
- const burstIdRef = (0, import_react7.useRef)(0);
2050
- const pushBurst = (0, import_react7.useCallback)((type, x, y, bits) => {
4231
+ const [toasts, setToasts] = (0, import_react8.useState)([]);
4232
+ const [flourish, setFlourish] = (0, import_react8.useState)(null);
4233
+ const [bursts, setBursts] = (0, import_react8.useState)([]);
4234
+ const prevActiveRef = (0, import_react8.useRef)(null);
4235
+ const burstIdRef = (0, import_react8.useRef)(0);
4236
+ const pushBurst = (0, import_react8.useCallback)((type, x, y, bits) => {
2051
4237
  const id = ++burstIdRef.current;
2052
4238
  setBursts((prev) => prev.concat([{ id, type, x, y, bits }]).slice(-6));
2053
4239
  setTimeout(() => setBursts((prev) => prev.filter((b) => b.id !== id)), 2600);
2054
4240
  }, []);
2055
- (0, import_react7.useEffect)(() => {
4241
+ (0, import_react8.useEffect)(() => {
2056
4242
  if (typeof document === "undefined") return;
2057
4243
  const onClick = (e) => {
2058
4244
  const t = e.target;
@@ -2078,22 +4264,22 @@ function AnimationOverlay(props) {
2078
4264
  document.addEventListener("click", onClick, true);
2079
4265
  return () => document.removeEventListener("click", onClick, true);
2080
4266
  }, [pushBurst]);
2081
- const taskCountRef = (0, import_react7.useRef)(0);
2082
- (0, import_react7.useEffect)(() => {
4267
+ const taskCountRef = (0, import_react8.useRef)(0);
4268
+ (0, import_react8.useEffect)(() => {
2083
4269
  const st2 = snap.status;
2084
4270
  if (!st2 || !st2.active) return;
2085
4271
  const n = st2.active.length;
2086
4272
  if (n > taskCountRef.current) pushBurst("surge");
2087
4273
  taskCountRef.current = n;
2088
4274
  }, [snap.status, pushBurst]);
2089
- (0, import_react7.useEffect)(() => {
4275
+ (0, import_react8.useEffect)(() => {
2090
4276
  let stopped = false;
2091
4277
  let timer = null;
2092
4278
  const loop = async () => {
2093
4279
  await animationStore.refresh();
2094
4280
  if (stopped) return;
2095
4281
  const s = animationStore.snap;
2096
- timer = setTimeout(loop, s.error ? 15e3 : s.status && s.status.active && s.status.active.length > 0 ? 2e3 : 6e3);
4282
+ timer = setTimeout(loop, s.error ? 15e3 : s.status && s.status.active && s.status.active.length > 0 ? 850 : 6e3);
2097
4283
  };
2098
4284
  loop();
2099
4285
  const onVisible = () => {
@@ -2106,7 +4292,7 @@ function AnimationOverlay(props) {
2106
4292
  document.removeEventListener("visibilitychange", onVisible);
2107
4293
  };
2108
4294
  }, []);
2109
- (0, import_react7.useEffect)(() => {
4295
+ (0, import_react8.useEffect)(() => {
2110
4296
  const st2 = snap.status;
2111
4297
  if (!st2 || !st2.active) return;
2112
4298
  const prev = prevActiveRef.current;
@@ -2177,47 +4363,50 @@ function AnimationOverlay(props) {
2177
4363
  const active = st && st.active ? st.active : [];
2178
4364
  const animOn = !!(cfg && cfg.animationEnabled && active.length > 0);
2179
4365
  const mode = cfg && cfg.effectMode ? cfg.effectMode : "flow";
4366
+ const phase = active.length > 0 ? active.reduce((best, x) => !best || (x.phaseAt || 0) > (best.phaseAt || 0) ? x : best, null).phase : "think";
2180
4367
  useTicker(ctx, animOn);
2181
4368
  const now = Date.now();
2182
4369
  const elapsed = active.length > 0 ? fmtClock(now - Math.min(...active.map((x) => x.startTime || now))) : "";
2183
- const [panelOpen, setPanelOpen2] = (0, import_react7.useState)(false);
2184
- (0, import_react7.useEffect)(() => {
4370
+ const [panelOpen, setPanelOpen2] = (0, import_react8.useState)(false);
4371
+ (0, import_react8.useEffect)(() => {
2185
4372
  setPanelOpen2(panelNav.open);
2186
4373
  return subscribePanel(() => setPanelOpen2(panelNav.open));
2187
4374
  }, []);
2188
- const [speed, setSpeed] = (0, import_react7.useState)(1);
2189
- const speedRef = (0, import_react7.useRef)({ tokens: -1, at: 0 });
2190
- (0, import_react7.useEffect)(() => {
4375
+ const [speed, setSpeed] = (0, import_react8.useState)(1);
4376
+ const speedRef = (0, import_react8.useRef)({ ticks: -1, at: 0 });
4377
+ (0, import_react8.useEffect)(() => {
2191
4378
  if (!st || active.length === 0) {
2192
- speedRef.current = { tokens: -1, at: 0 };
4379
+ speedRef.current = { ticks: -1, at: 0 };
4380
+ setSpeed(1);
2193
4381
  return;
2194
4382
  }
2195
- const total = active.reduce((a, x) => a + (x.totalTokens || 0), 0);
4383
+ const ticks = active.reduce((a, x) => a + (x.motionTicks || 0), 0);
2196
4384
  const t = Date.now();
2197
4385
  const prev = speedRef.current;
2198
- if (prev.tokens < 0 || t - prev.at < 500) {
2199
- speedRef.current = { tokens: total, at: t };
4386
+ if (prev.ticks < 0 || t - prev.at < 300) {
4387
+ speedRef.current = { ticks, at: t };
2200
4388
  return;
2201
4389
  }
2202
- const rate = Math.max(0, (total - prev.tokens) / ((t - prev.at) / 1e3));
2203
- setSpeed(Math.max(0.7, Math.min(3, 0.7 + rate / 45)));
2204
- speedRef.current = { tokens: total, at: t };
4390
+ const rate = Math.max(0, (ticks - prev.ticks) / ((t - prev.at) / 1e3));
4391
+ const phaseBoost = phase === "write" || phase === "code" ? 0.28 : phase === "search" ? 0.18 : 0;
4392
+ const next = Math.max(0.9, Math.min(4, Number((0.9 + rate / 14 + phaseBoost).toFixed(2))));
4393
+ setSpeed((current) => Math.abs(current - next) < 0.03 ? current : next);
4394
+ speedRef.current = { ticks, at: t };
2205
4395
  }, [snap.status]);
2206
- const phase = active.length > 0 ? active.reduce((best, x) => !best || (x.phaseAt || 0) > (best.phaseAt || 0) ? x : best, null).phase : "think";
2207
4396
  const ambientOn = animOn && !panelOpen;
2208
4397
  const robotScaleFromConfig = Math.max(0.85, Math.min(2.2, Number(cfg && cfg.robotScale) || 1.35));
2209
4398
  const speedStyle = { "--dkan-speed": Number(speed).toFixed(2) };
2210
- const saveRobotScale = (0, import_react7.useCallback)((robotScale) => {
4399
+ const saveRobotScale = (0, import_react8.useCallback)((robotScale) => {
2211
4400
  rpcCall2("config", { robotScale }).then((d) => animationStore.applyConfig(d && d.config)).catch(() => {
2212
4401
  });
2213
4402
  }, []);
2214
- const [botPos, setBotPos] = (0, import_react7.useState)(null);
2215
- const botPosRef = (0, import_react7.useRef)(null);
2216
- const botDragRef = (0, import_react7.useRef)(null);
2217
- const botResizeRef = (0, import_react7.useRef)(null);
2218
- const [botScaleDraft, setBotScaleDraft] = (0, import_react7.useState)(null);
2219
- const botClickBlockRef = (0, import_react7.useRef)(false);
2220
- (0, import_react7.useEffect)(() => {
4403
+ const [botPos, setBotPos] = (0, import_react8.useState)(null);
4404
+ const botPosRef = (0, import_react8.useRef)(null);
4405
+ const botDragRef = (0, import_react8.useRef)(null);
4406
+ const botResizeRef = (0, import_react8.useRef)(null);
4407
+ const [botScaleDraft, setBotScaleDraft] = (0, import_react8.useState)(null);
4408
+ const botClickBlockRef = (0, import_react8.useRef)(false);
4409
+ (0, import_react8.useEffect)(() => {
2221
4410
  try {
2222
4411
  if (typeof localStorage === "undefined") return;
2223
4412
  const raw = localStorage.getItem("dsh-dock/anim/robot-pos/v1");
@@ -2340,7 +4529,7 @@ function AnimationOverlay(props) {
2340
4529
  }
2341
4530
  },
2342
4531
  children: [
2343
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase }),
4532
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase, tasks: active }),
2344
4533
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-bot-cap", children: [
2345
4534
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
2346
4535
  " \u4E2A\u4EFB\u52A1",
@@ -2376,19 +4565,22 @@ function AnimationOverlay(props) {
2376
4565
  "button",
2377
4566
  {
2378
4567
  type: "button",
2379
- className: "dkan-badge",
2380
- style: speedStyle,
2381
- title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
4568
+ className: "dkan-badge" + (mode === "breathe" ? " dkan-badge-breathe" : ""),
4569
+ style: Object.assign({}, speedStyle, { "--dkan-phase": phaseColor(phase) }),
4570
+ title: active.length + " \u4E2A\u4EFB\u52A1\u8FDB\u884C\u4E2D \xB7 " + phaseLabel(phase) + " \xB7 \u70B9\u51FB\u67E5\u770B\u4EFB\u52A1\u52A8\u753B\u9875",
2382
4571
  onClick: () => openPanel("animation"),
2383
4572
  children: [
2384
4573
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap", children: [
2385
4574
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
4575
+ mode === "breathe" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-halo" }) : null,
2386
4576
  mode === "ring" ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-ring" }) : null
2387
4577
  ] }),
2388
4578
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-badge-txt", children: [
2389
4579
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "n", children: active.length }),
2390
4580
  " \u4E2A\u4EFB\u52A1",
2391
- elapsed ? " \xB7 " + elapsed : ""
4581
+ elapsed ? " \xB7 " + elapsed : "",
4582
+ " \xB7 ",
4583
+ phaseLabel(phase)
2392
4584
  ] })
2393
4585
  ]
2394
4586
  }
@@ -2444,7 +4636,10 @@ function ModePreview({ id }) {
2444
4636
  if (id === "robot") {
2445
4637
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev dkan-prev-bot", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RobotScene, { phase: "code" }) });
2446
4638
  }
2447
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dotwrap dkan-breathe", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }) }) });
4639
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-prev", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-dotwrap dkan-breathe", children: [
4640
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-dot" }),
4641
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-halo" })
4642
+ ] }) });
2448
4643
  }
2449
4644
  function TaskRow(props) {
2450
4645
  const t = props.t;
@@ -2467,23 +4662,26 @@ function TaskRow(props) {
2467
4662
  function AnimationView(props) {
2468
4663
  const ctx = props && props.ctx;
2469
4664
  const snap = useAnimation(ctx);
2470
- const [cfg, setCfg] = (0, import_react7.useState)(null);
2471
- const [saveErr, setSaveErr] = (0, import_react7.useState)("");
2472
- const [testing, setTesting] = (0, import_react7.useState)(false);
2473
- const [testState, setTestState] = (0, import_react7.useState)(null);
2474
- const cfgRef = (0, import_react7.useRef)(null);
2475
- const pendingSavesRef = (0, import_react7.useRef)(0);
2476
- const editingWebhookRef = (0, import_react7.useRef)(false);
2477
- (0, import_react7.useEffect)(() => {
4665
+ const [cfg, setCfg] = (0, import_react8.useState)(null);
4666
+ const [saveErr, setSaveErr] = (0, import_react8.useState)("");
4667
+ const [testing, setTesting] = (0, import_react8.useState)(false);
4668
+ const [testState, setTestState] = (0, import_react8.useState)(null);
4669
+ const [feishuTestState, setFeishuTestState] = (0, import_react8.useState)(null);
4670
+ const [feishuTesting, setFeishuTesting] = (0, import_react8.useState)(false);
4671
+ const cfgRef = (0, import_react8.useRef)(null);
4672
+ const pendingSavesRef = (0, import_react8.useRef)(0);
4673
+ const editingWebhookRef = (0, import_react8.useRef)(false);
4674
+ const editingFeishuRef = (0, import_react8.useRef)(false);
4675
+ (0, import_react8.useEffect)(() => {
2478
4676
  const c = snap.status && snap.status.config;
2479
4677
  if (!c) return;
2480
- if (pendingSavesRef.current > 0 || editingWebhookRef.current) return;
4678
+ if (pendingSavesRef.current > 0 || editingWebhookRef.current || editingFeishuRef.current) return;
2481
4679
  if (c !== cfgRef.current) {
2482
4680
  cfgRef.current = c;
2483
4681
  setCfg(Object.assign({}, c));
2484
4682
  }
2485
4683
  }, [snap.status]);
2486
- (0, import_react7.useEffect)(() => {
4684
+ (0, import_react8.useEffect)(() => {
2487
4685
  if (!animationStore.snap.status) animationStore.refresh();
2488
4686
  }, []);
2489
4687
  const patch = (p) => {
@@ -2509,6 +4707,17 @@ function AnimationView(props) {
2509
4707
  setCfg(Object.assign({}, c));
2510
4708
  }
2511
4709
  };
4710
+ const saveFeishuWebhook = async () => {
4711
+ if (!editingFeishuRef.current) return;
4712
+ const hook = String(cfg.feishuWebhook || "").trim();
4713
+ await patch({ feishuWebhook: hook });
4714
+ editingFeishuRef.current = false;
4715
+ const c = animationStore.snap.status && animationStore.snap.status.config;
4716
+ if (c && c !== cfgRef.current) {
4717
+ cfgRef.current = c;
4718
+ setCfg(Object.assign({}, c));
4719
+ }
4720
+ };
2512
4721
  const runDingtalkTest = async () => {
2513
4722
  setTesting(true);
2514
4723
  setTestState(null);
@@ -2530,6 +4739,27 @@ function AnimationView(props) {
2530
4739
  setTesting(false);
2531
4740
  }
2532
4741
  };
4742
+ const runFeishuTest = async () => {
4743
+ setFeishuTesting(true);
4744
+ setFeishuTestState(null);
4745
+ try {
4746
+ if (editingFeishuRef.current) {
4747
+ const hook = String(cfg.feishuWebhook || "").trim();
4748
+ if (!hook) throw new Error("\u8BF7\u5148\u586B\u5199 Webhook \u5730\u5740");
4749
+ const d = await rpcCall2("config", { feishuWebhook: hook });
4750
+ animationStore.applyConfig(d && d.config);
4751
+ editingFeishuRef.current = false;
4752
+ cfgRef.current = d && d.config || cfgRef.current;
4753
+ setCfg(Object.assign({}, cfg, { feishuWebhook: hook }));
4754
+ }
4755
+ const r = await rpcCall2("test", { target: "feishu" });
4756
+ setFeishuTestState(r && r.sent ? { ok: true, msg: "\u6D4B\u8BD5\u6D88\u606F\u5DF2\u53D1\u9001\uFF0C\u53BB\u7FA4\u91CC\u770B\u770B" } : { ok: false, msg: r && r.error || "\u53D1\u9001\u5931\u8D25" });
4757
+ } catch (e) {
4758
+ setFeishuTestState({ ok: false, msg: e && e.message || String(e) });
4759
+ } finally {
4760
+ setFeishuTesting(false);
4761
+ }
4762
+ };
2533
4763
  const enableSystemNotify = async (next) => {
2534
4764
  if (next && typeof Notification !== "undefined" && Notification.permission !== "granted") {
2535
4765
  try {
@@ -2812,7 +5042,66 @@ function AnimationView(props) {
2812
5042
  ] }),
2813
5043
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u9489\u9489\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u667A\u80FD\u7FA4\u52A9\u624B \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\uFF08Webhook\uFF09\uFF0C \u5B89\u5168\u8BBE\u7F6E\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
2814
5044
  ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u9489\u9489\u3002" })
2815
- ] }, "dingtalk")
5045
+ ] }, "dingtalk"),
5046
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec", children: [
5047
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-sec-head", children: [
5048
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-title", children: "\u98DE\u4E66\u63A8\u9001" }),
5049
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-sub", children: "\u4EFB\u52A1\u7ED3\u675F\u63A8\u9001\u5230\u98DE\u4E66\u7FA4\u673A\u5668\u4EBA\uFF08\u5BBF\u4E3B\u76F4\u53D1\uFF0C\u6D4F\u89C8\u5668\u5173\u7740\u4E5F\u80FD\u63A8\uFF1B\u4E8B\u4EF6\u8DDF\u968F\u4E0A\u65B9\u5B8C\u6210/\u5F02\u5E38\u5F00\u5173\uFF09" }),
5050
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-sec-sw", children: [
5051
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-sec-swlabel" + (cfg.feishuEnabled ? " on" : ""), children: cfg.feishuEnabled ? "\u5DF2\u5F00\u542F" : "\u5DF2\u5173\u95ED" }),
5052
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5053
+ "button",
5054
+ {
5055
+ type: "button",
5056
+ className: "dock-sw" + (cfg.feishuEnabled ? " on" : ""),
5057
+ role: "switch",
5058
+ "aria-checked": cfg.feishuEnabled,
5059
+ "aria-label": "\u5F00\u5173\u98DE\u4E66\u63A8\u9001",
5060
+ title: cfg.feishuEnabled ? "\u5173\u95ED\u98DE\u4E66\u63A8\u9001" : "\u5F00\u542F\u98DE\u4E66\u63A8\u9001",
5061
+ onClick: () => patch({ feishuEnabled: !cfg.feishuEnabled })
5062
+ }
5063
+ )
5064
+ ] })
5065
+ ] }),
5066
+ cfg.feishuEnabled ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-rows-narrow", children: [
5067
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row dkan-row-webhook", children: [
5068
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "Webhook" }),
5069
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5070
+ "input",
5071
+ {
5072
+ type: "text",
5073
+ className: "dkan-input",
5074
+ spellCheck: false,
5075
+ value: cfg.feishuWebhook || "",
5076
+ placeholder: "https://open.feishu.cn/open-apis/bot/v2/hook/\u2026",
5077
+ onChange: (e) => {
5078
+ editingFeishuRef.current = true;
5079
+ setCfg(Object.assign({}, cfg, { feishuWebhook: e.target.value }));
5080
+ }
5081
+ }
5082
+ ),
5083
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
5084
+ "button",
5085
+ {
5086
+ type: "button",
5087
+ className: "dkan-btn",
5088
+ disabled: !editingFeishuRef.current,
5089
+ onClick: saveFeishuWebhook,
5090
+ children: editingFeishuRef.current ? "\u4FDD\u5B58" : "\u5DF2\u4FDD\u5B58"
5091
+ }
5092
+ )
5093
+ ] }),
5094
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "dkan-row", children: [
5095
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-label", children: "\u8FDE\u901A\u6D4B\u8BD5" }),
5096
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "dkan-btn", disabled: feishuTesting, onClick: runFeishuTest, children: feishuTesting ? "\u53D1\u9001\u4E2D\u2026" : "\u53D1\u9001\u6D4B\u8BD5\u6D88\u606F" }),
5097
+ feishuTestState ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "dkan-row-sub" + (feishuTestState.ok ? " dkan-ok" : " dkan-err"), children: [
5098
+ feishuTestState.ok ? "\u2713 " : "\u2717 ",
5099
+ feishuTestState.msg
5100
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "dkan-row-sub", children: "\u7528\u5F53\u524D\u4FDD\u5B58\u7684 Webhook \u53D1\u4E00\u6761\u6D4B\u8BD5\u6D88\u606F" })
5101
+ ] }),
5102
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u673A\u5668\u4EBA\u521B\u5EFA\uFF1A\u98DE\u4E66\u7FA4 \u2192 \u8BBE\u7F6E \u2192 \u7FA4\u673A\u5668\u4EBA \u2192 \u6DFB\u52A0\u673A\u5668\u4EBA \u2192 \u81EA\u5B9A\u4E49\u673A\u5668\u4EBA\uFF08\u83B7\u53D6 Webhook \u5730\u5740\uFF09\uFF1B \u5B89\u5168\u8BBE\u7F6E\u5982\u9009\u300C\u81EA\u5B9A\u4E49\u5173\u952E\u8BCD\u300D\u586B\u300C\u4EFB\u52A1\u300D\u6216\u300Cdsh\u300D\uFF08\u63A8\u9001\u6807\u9898\u542B\u300C\u4EFB\u52A1\u300D\u5373\u53EF\u547D\u4E2D\uFF09\u3002" })
5103
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note", children: "\u672A\u5F00\u542F\u2014\u2014\u4EFB\u52A1\u7ED3\u675F\u4E0D\u63A8\u9001\u98DE\u4E66\u3002" })
5104
+ ] }, "feishu")
2816
5105
  );
2817
5106
  }
2818
5107
  if (saveErr) rows.push(/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "dkan-note dkan-err", children: saveErr }, "err"));
@@ -2855,6 +5144,8 @@ var css2 = [
2855
5144
  "@keyframes dkan-orbit{0%{top:0;left:0}25%{top:0;left:calc(100vw - 12px)}50%{top:calc(100vh - 12px);left:calc(100vw - 12px)}75%{top:calc(100vh - 12px);left:0}100%{top:0;left:0}}",
2856
5145
  // ===== 氛围动效 =====
2857
5146
  ".dkan-amb{position:fixed;inset:0;z-index:9989;pointer-events:none;overflow:hidden;}",
5147
+ // pointer-events 不继承:全屏装饰层的子粒子(星点/流星/极光/火花/彩带)必须各自透明于点击
5148
+ ".dkan-amb *,.dkan-fxwrap *{pointer-events:none;}",
2858
5149
  // 代码雨:字符列缓落(提亮加大,速度随吞吐)
2859
5150
  ".dkan-matrix span{position:absolute;top:-12%;writing-mode:vertical-rl;font-family:var(--ds-font-family-code,monospace);color:var(--dsw-alias-accent,#4d9fff);text-shadow:0 0 6px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 60%,transparent);animation:dkan-fall linear infinite;will-change:transform;}",
2860
5151
  "@keyframes dkan-fall{to{transform:translateY(125vh)}}",
@@ -2901,10 +5192,16 @@ var css2 = [
2901
5192
  ".dkan-badge .n{color:var(--dsw-alias-label-primary);font-weight:600;}",
2902
5193
  "@keyframes dkan-rise{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}",
2903
5194
  // 徽标圆点与两种动效(呼吸 / 轨道环)
2904
- ".dkan-dotwrap{position:relative;width:16px;height:16px;flex:none;display:inline-flex;align-items:center;justify-content:center;}",
2905
- ".dkan-dot{width:9px;height:9px;border-radius:50%;background:var(--dsw-alias-accent,#4d9fff);box-shadow:0 0 8px color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 55%,transparent);}",
2906
- ".dkan-breathe .dkan-dot{animation:dkan-breathe calc(2.6s / var(--dkan-speed,1)) ease-in-out infinite;}",
2907
- "@keyframes dkan-breathe{0%,100%{transform:scale(1);opacity:.55}50%{transform:scale(1.6);opacity:1}}",
5195
+ ".dkan-dotwrap{position:relative;width:20px;height:20px;flex:none;display:inline-flex;align-items:center;justify-content:center;}",
5196
+ ".dkan-dot{width:12px;height:12px;border-radius:50%;background:var(--dkan-phase,var(--dsw-alias-accent,#4d9fff));box-shadow:0 0 10px color-mix(in srgb,var(--dkan-phase,var(--dsw-alias-accent,#4d9fff)) 70%,transparent);transition:background .4s var(--ds-ease-in-out),box-shadow .4s var(--ds-ease-in-out);}",
5197
+ ".dkan-breathe .dkan-dot{animation:dkan-breathe calc(2.2s / var(--dkan-speed,1)) ease-in-out infinite;}",
5198
+ "@keyframes dkan-breathe{0%,100%{transform:scale(1);opacity:.5}50%{transform:scale(1.7);opacity:1}}",
5199
+ // 呼吸光晕:向外扩散的波纹环,与圆点同频(颜色随阶段)
5200
+ ".dkan-halo{position:absolute;inset:0;border-radius:50%;border:2px solid var(--dkan-phase,var(--dsw-alias-accent,#4d9fff));animation:dkan-halo calc(2.2s / var(--dkan-speed,1)) ease-out infinite;}",
5201
+ "@keyframes dkan-halo{0%{transform:scale(.5);opacity:.9}70%{transform:scale(1.5);opacity:.25}100%{transform:scale(1.7);opacity:0}}",
5202
+ // breathe 模式徽标更醒目:阶段色描边 + 呼吸辉光
5203
+ ".dkan-badge-breathe{border-color:color-mix(in srgb,var(--dkan-phase,#4d9fff) 55%,transparent);animation:dkan-rise .3s var(--ds-ease-in-out),dkan-badge-breathe calc(2.2s / var(--dkan-speed,1)) ease-in-out infinite;}",
5204
+ "@keyframes dkan-badge-breathe{0%,100%{box-shadow:0 0 6px color-mix(in srgb,var(--dkan-phase,#4d9fff) 22%,transparent),0 6px 24px rgb(0 0 0 / .16)}50%{box-shadow:0 0 18px color-mix(in srgb,var(--dkan-phase,#4d9fff) 55%,transparent),0 6px 24px rgb(0 0 0 / .16)}}",
2908
5205
  ".dkan-ring{position:absolute;inset:0;border-radius:50%;background:conic-gradient(from 0deg,transparent 0 68%,var(--dsw-alias-accent,#4d9fff) 92%,#fff);-webkit-mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));mask:radial-gradient(farthest-side,transparent calc(100% - 2px),#000 calc(100% - 2px));animation:dkan-spin calc(2.2s / var(--dkan-speed,1)) linear infinite;opacity:.9;}",
2909
5206
  "@keyframes dkan-spin{to{transform:rotate(360deg)}}",
2910
5207
  // 通知卡片栈(右上角)
@@ -2979,7 +5276,7 @@ var css2 = [
2979
5276
  "@keyframes dkan-prev-aurora{0%{transform:translateX(-10%)}100%{transform:translateX(15%)}}",
2980
5277
  ".dkan-prev-bot{height:92px;justify-content:center;}",
2981
5278
  ".dkan-prev-bot .dkan-bot-scene{--dkan-bot-scale:1;transform:scale(.56);transform-origin:center;}",
2982
- // ===== 桌面伙伴:具象人物 + 四屏工位(尺寸可调,整卡可拖拽) =====
5279
+ // ===== 桌面伙伴:具象人物 + 紧凑双工位(尺寸可调,整卡可拖拽) =====
2983
5280
  // 卡片:玻璃拟态;默认停泊右下(dsh 输入卡上方),拖动后位置持久化、可放屏幕任意处
2984
5281
  ".dkan-botcard{--dkan-bot-scale:1.35;position:fixed;right:20px;bottom:calc(var(--dsh-composer-height,152px) + 20px);z-index:9990;display:flex;flex-direction:column;gap:6px;padding:10px 12px;border-radius:16px;cursor:grab;border:1px solid var(--dsw-alias-border-l1);background:color-mix(in srgb,var(--dsw-alias-bg-layer-2) 86%,transparent);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);box-shadow:0 12px 36px rgb(0 0 0 / .22);color:var(--dsw-alias-label-secondary);font-family:inherit;font-size:12px;pointer-events:auto;touch-action:none;user-select:none;animation:dkan-rise .3s var(--ds-ease-in-out);}",
2985
5282
  ".dkan-botcard:hover,.dkan-botcard:focus-visible{border-color:var(--dsw-alias-accent,#4d9fff);outline:none;}",
@@ -3014,9 +5311,24 @@ var css2 = [
3014
5311
  ".dk3-code i:nth-child(5n+4){width:72%;}",
3015
5312
  ".dk3-code i:nth-child(5n){width:54%;background:var(--dkan-code-a);}",
3016
5313
  ".dk3-cur{position:absolute;left:3px;bottom:2px;width:4px;height:2px;background:var(--dkan-code-b);animation:dkan-blink3 1s steps(1) infinite;}",
5314
+ // 左屏检索视图:搜索框、放大镜与结果条,和右侧代码编辑器明确区分
5315
+ ".dk3-search-ui{position:absolute;inset:3px;display:block;overflow:hidden;}",
5316
+ ".dk3-search-box{display:block;height:5px;margin:0 1px 3px;border:1px solid color-mix(in srgb,var(--dkan-code-a) 72%,#d7fff4);border-radius:2px;box-sizing:border-box;}",
5317
+ ".dk3-search-box b{display:block;width:2px;height:2px;margin:1px 0 0 2px;border:1px solid var(--dkan-code-a);border-radius:50%;position:relative;}",
5318
+ ".dk3-search-box b:after{content:'';position:absolute;width:2px;height:1px;background:var(--dkan-code-a);right:-2px;bottom:-1px;transform:rotate(45deg);transform-origin:left center;}",
5319
+ ".dk3-search-results{display:block;animation:dk3-search-scroll calc(2.1s / var(--dkan-speed,1)) linear infinite;}",
5320
+ ".dk3-search-results i{display:block;height:2px;margin:2px 1px 0;border-radius:1px;background:var(--dkan-code-a);opacity:.72;}",
5321
+ ".dk3-search-results i:nth-child(2n){width:74%;background:var(--dkan-code-b);}",
5322
+ ".dk3-search-results i:nth-child(3n){width:48%;background:var(--dkan-code-c);}",
5323
+ "@keyframes dk3-search-scroll{to{transform:translateY(-5px)}}",
3017
5324
  "@keyframes dk3-scroll{to{transform:translateY(-50%)}}",
3018
- // 人物组(坐在桌子中间近镜头侧 z=30,侧身面朝 +X 三屏;不会被桌体遮挡)
3019
- ".dk3-person{position:absolute;left:96px;top:14px;width:44px;height:64px;transform-style:preserve-3d;transform:translateZ(30px);}",
5325
+ // 人物与椅子始终正对桌面:工位切换只横移,不再旋转整个人和座椅。
5326
+ ".dk3-person{--dk3-seat-x:22px;position:absolute;left:98px;top:14px;width:44px;height:61px;transform-style:preserve-3d;transform:translateZ(30px) translateX(var(--dk3-seat-x));transition:transform max(.18s,calc(.38s / var(--dkan-speed,1))) cubic-bezier(.23,1,.32,1);will-change:transform;}",
5327
+ ".dkan-bot-scene[data-station=left] .dk3-person{--dk3-seat-x:0px;}",
5328
+ ".dkan-bot-scene[data-station=center] .dk3-person{--dk3-seat-x:22px;}",
5329
+ ".dkan-bot-scene[data-station=right] .dk3-person{--dk3-seat-x:44px;}",
5330
+ // 上身以髋部为旋转原点;只做前后倾,始终朝向桌面。
5331
+ ".dk3-upper3{position:absolute;inset:0;transform-style:preserve-3d;transform-origin:12px 52px;transform:translateZ(0);transition:transform .24s cubic-bezier(.77,0,.175,1);will-change:transform;}",
3020
5332
  // 动漫人物配色:皮肤/头发/卫衣/裤子
3021
5333
  ".dk3-skin .dk3-face{background:linear-gradient(180deg,#ffd9b8,#f3b98d);}",
3022
5334
  ".dk3-skin .dk3-face:nth-child(5){background:#ffe3c9;}",
@@ -3026,64 +5338,106 @@ var css2 = [
3026
5338
  ".dk3-hood .dk3-face:nth-child(5){background:#93a5ba;}",
3027
5339
  ".dk3-pants .dk3-face{background:linear-gradient(180deg,#3d4a5c,#2c3646);}",
3028
5340
  ".dk3-pants .dk3-face:nth-child(5){background:#4a5a70;}",
3029
- // 人物细节:圆角 + 鞋 + 咖啡杯 + 嘴
3030
- ".dk3-headbox .dk3-face{border-radius:3px;}",
3031
- ".dk3-torso .dk3-face{border-radius:3px;}",
5341
+ // 人物细节:收窄下颌、连续肩颈、短侧渐层发型
5342
+ ".dk3-cranium .dk3-face{border-radius:42% 46% 38% 36%;}",
5343
+ ".dk3-jaw3 .dk3-face{border-radius:30% 30% 48% 48%;}",
5344
+ ".dk3-neck3 .dk3-face{border-radius:2px;}",
5345
+ ".dk3-collar3 .dk3-face{background:linear-gradient(180deg,#516176,#374459);border-radius:3px;}",
5346
+ ".dk3-shoulders3 .dk3-face{border-radius:4px;}",
5347
+ ".dk3-chest3 .dk3-face{border-radius:4px;}",
5348
+ ".dk3-waist3 .dk3-face{border-radius:3px;}",
3032
5349
  ".dk3-hair .dk3-face{border-radius:2px;}",
5350
+ ".dk3-hair-crown .dk3-face{border-radius:48% 42% 28% 30%;}",
5351
+ ".dk3-hair-back .dk3-face{background:linear-gradient(180deg,#493727,#2f241b);border-radius:46% 24% 38% 44%;}",
3033
5352
  ".dk3-shoe .dk3-face{background:#20262f;border-radius:2px;}",
3034
5353
  ".dk3-mug .dk3-face{background:#c2703d;border-radius:1px;}",
3035
5354
  ".dk3-mug .dk3-face:nth-child(5){background:#e08a52;}",
3036
- ".dk3-mouth{position:absolute;left:50%;top:78%;width:5px;height:1.5px;border-radius:1px;background:#b5766a;}",
5355
+ ".dk3-mouth{position:absolute;left:50%;top:64%;width:3.5px;height:1px;border-radius:2px;background:#a9635c;}",
3037
5356
  // 椅子
3038
5357
  ".dk3-chairback .dk3-face{background:linear-gradient(180deg,#3f4c60,#2c3648);}",
3039
5358
  ".dk3-chairseat .dk3-face{background:#33415a;}",
3040
- // 头组(俯仰=rotateZ,左右看=rotateY);眼睛贴在 +X 面板上
3041
- ".dk3-head3{position:absolute;left:14px;top:2px;width:17px;height:20px;transform-style:preserve-3d;transform-origin:50% 85%;transition:transform .25s var(--ds-ease-in-out);}",
3042
- ".dk3-brows{position:absolute;left:50%;top:30%;display:flex;gap:3px;align-items:center;justify-content:center;}",
3043
- ".dk3-brows i{width:3px;height:1px;border-radius:2px;background:#4a3428;}",
3044
- ".dk3-eyes{position:absolute;left:50%;top:52%;display:flex;gap:3px;align-items:center;justify-content:center;}",
3045
- ".dk3-eyes i{width:3px;height:4px;border-radius:50%;background:radial-gradient(circle at 60% 35%,#fff 0 .5px,#2b3442 .8px);animation:dkan-blink3 4.6s infinite;}",
3046
- ".dk3-nose{position:absolute;left:50%;top:64%;width:2px;height:2px;border-radius:50%;background:#d99277;}",
3047
- ".dk3-ear{position:absolute;left:-1px;top:11px;width:3px;height:5px;border-radius:50%;background:#f3b98d;transform:translateZ(2px);}",
5359
+ // 头组与颈部中心均为 x=14;只让头部观察左右屏,身体和椅子不转向。
5360
+ ".dk3-head3{--dk3-head-turn:rotateY(0deg);position:absolute;left:6px;top:3px;width:17px;height:21px;transform-style:preserve-3d;transform-origin:8px 18px;transform:var(--dk3-head-turn);transition:transform max(.18s,calc(.22s / var(--dkan-speed,1))) cubic-bezier(.23,1,.32,1);will-change:transform;}",
5361
+ ".dkan-bot-scene[data-station=left] .dk3-head3{--dk3-head-turn:rotateY(-18deg);}",
5362
+ ".dkan-bot-scene[data-station=center] .dk3-head3{--dk3-head-turn:rotateY(0deg);}",
5363
+ ".dkan-bot-scene[data-station=right] .dk3-head3{--dk3-head-turn:rotateY(14deg);}",
5364
+ ".dk3-brows{position:absolute;left:50%;top:29%;display:flex;gap:2.5px;align-items:center;justify-content:center;}",
5365
+ ".dk3-brows i{width:3.5px;height:1px;border-radius:2px;background:#3a2a21;transform:rotate(-7deg);}",
5366
+ ".dk3-brows i+ i{transform:rotate(7deg);}",
5367
+ ".dk3-eyes{position:absolute;left:50%;top:51%;display:flex;gap:2.5px;align-items:center;justify-content:center;}",
5368
+ ".dk3-eyes i{width:3.5px;height:2.5px;border-radius:50%;background:radial-gradient(circle at 62% 30%,#fff 0 .5px,#263141 .8px 1.7px,#111827 1.9px);animation:dkan-blink3 4.8s infinite;}",
5369
+ ".dk3-nose{position:absolute;left:50%;top:66%;width:2px;height:3px;border-radius:60% 40% 55% 45%;background:linear-gradient(90deg,#e7a67e,#c77f67);}",
5370
+ ".dk3-ear{position:absolute;left:1px;top:10px;width:3px;height:5px;border-radius:52% 44% 48% 52%;background:linear-gradient(90deg,#edaa82,#ffd2ad);transform:translateZ(2px);}",
5371
+ ".dk3-fringe3{position:absolute;left:13px;top:4px;width:5px;height:7px;transform-style:preserve-3d;transform:rotateY(90deg) translateZ(5.8px);}",
5372
+ ".dk3-fringe3 i{position:absolute;top:0;width:2px;height:6px;border-radius:70% 25% 60% 30%;background:linear-gradient(180deg,#6b5239,#392b20);transform-origin:top center;}",
5373
+ ".dk3-fringe3 i:nth-child(1){left:0;transform:rotate(-18deg);height:5px;}",
5374
+ ".dk3-fringe3 i:nth-child(2){left:1.8px;transform:rotate(-6deg);height:6px;}",
5375
+ ".dk3-fringe3 i:nth-child(3){left:3.5px;transform:rotate(12deg);height:4px;}",
3048
5376
  "@keyframes dkan-blink3{0%,91%,100%{transform:scaleY(1)}94%{transform:scaleY(.15)}}",
3049
- // 手臂:肩组挂躯干前上,肘组在其下端(前臂+手伸向键盘);write/code 时肘部高频敲击
3050
- ".dk3-arm3{position:absolute;left:20px;top:30px;width:16px;height:16px;transform-style:preserve-3d;}",
3051
- ".dk3-elbow{position:absolute;left:0;top:10px;width:15px;height:5px;transform-style:preserve-3d;transform-origin:2px 2px;}",
3052
- ".dk3-far{transform:translateZ(-8px);filter:brightness(.62);}",
5377
+ // 手臂按肩→肘→腕分段,旋转原点位于真实关节连接处。
5378
+ ".dk3-arm3{position:absolute;left:20px;top:30px;width:16px;height:16px;transform-style:preserve-3d;transform-origin:2px 2px;will-change:transform;}",
5379
+ ".dk3-elbow{position:absolute;left:0;top:10px;width:15px;height:5px;transform-style:preserve-3d;transform-origin:1px 2px;will-change:transform;}",
5380
+ ".dk3-wrist3{position:absolute;left:9.5px;top:0;width:6px;height:5px;transform-style:preserve-3d;transform-origin:1px 2px;will-change:transform;}",
5381
+ ".dk3-fingers3{position:absolute;left:3px;top:1px;width:4px;height:3px;transform:translateZ(2px);}",
5382
+ ".dk3-fingers3 i{position:absolute;left:0;width:4px;height:.8px;border-radius:2px;background:#f2b58d;}",
5383
+ ".dk3-fingers3 i+ i{top:1.4px;width:3.5px;}",
5384
+ ".dk3-far{transform:translateZ(-7px);filter:brightness(.72);}",
3053
5385
  // 思考泡泡(贴镜头 2D 层,think 阶段显示)
3054
5386
  ".dkan-bubble{position:absolute;left:80px;top:4px;display:none;gap:3px;padding:4px 6px;border-radius:8px;background:var(--dsw-alias-bg-layer-2);border:1px solid var(--dsw-alias-border-l2);box-shadow:0 2px 6px rgb(0 0 0 / .15);z-index:3;}",
3055
5387
  ".dkan-bubble i{width:4px;height:4px;border-radius:50%;background:var(--dsw-alias-label-tertiary);animation:dkan-bubdot 1.2s ease-in-out infinite;}",
3056
5388
  ".dkan-bubble i:nth-child(2){animation-delay:.2s;}",
3057
5389
  ".dkan-bubble i:nth-child(3){animation-delay:.4s;}",
3058
5390
  "@keyframes dkan-bubdot{0%,100%{opacity:.25;transform:translateY(0)}50%{opacity:1;transform:translateY(-2px)}}",
5391
+ // ===== 多任务工位(data-tasks=活跃任务数,上限 3) =====
5392
+ // 椅子滚轮
5393
+ ".dk3-wheel .dk3-face{background:#1c232e;border-radius:50%;}",
5394
+ // 有活跃任务时,未轮到的侧工位稍暗;多任务则两个工位均保持可见。
5395
+ ".dkan-bot-scene[data-tasks] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks] .dk3-mon3.right .dk3-screen{opacity:.3;}",
5396
+ // 2 个及以上任务:左右工位同时点亮(各自带辉光、代码滚动加速)。
5397
+ '.dkan-bot-scene[data-tasks="2"] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks="2"] .dk3-mon3.right .dk3-screen,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 8px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 42%,transparent);}',
5398
+ '.dkan-bot-scene[data-tasks="2"] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-tasks="2"] .dk3-mon3.right .dk3-code,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-tasks="3"] .dk3-mon3.right .dk3-code{animation-duration:calc(2.6s / var(--dkan-speed,1));}',
5399
+ // 座椅移动期间滚轮跟随任务节奏转动;思考中停下,避免无意义的常驻运动。
5400
+ ".dkan-bot-scene[data-station=left] .dk3-wheel,.dkan-bot-scene[data-station=right] .dk3-wheel{animation:dkan-wheel calc(.46s / var(--dkan-speed,1)) linear infinite;transform-origin:center;}",
5401
+ "@keyframes dkan-wheel{to{transform:rotateZ(360deg)}}",
3059
5402
  // ===== 阶段驱动(data-phase 四态,host 由 chunk 流实时同步) =====
3060
- // think:屏幕调暗 + 仰头苦想 + 泡泡浮现
5403
+ // think:上身轻靠、近侧手托下巴、远侧手留在桌面;动作有停顿而不是机械往返。
3061
5404
  ".dkan-bot-scene[data-phase=think] .dk3-screen{opacity:.32;}",
3062
5405
  ".dkan-bot-scene[data-phase=think] .dkan-bubble{display:inline-flex;}",
3063
- ".dkan-bot-scene[data-phase=think] .dk3-head3{animation:dkan-think-head 1.8s ease-in-out infinite alternate;}",
3064
- ".dkan-bot-scene[data-phase=think] .dk3-arm3:not(.dk3-far){animation:dkan-think-arm 1.8s ease-in-out infinite alternate;}",
3065
- ".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-far{animation:dkan-think-arm-far 1.8s ease-in-out infinite alternate;}",
3066
- "@keyframes dkan-think-head{from{transform:rotateZ(-12deg) translateY(-1px)}to{transform:rotateZ(-22deg) translate(3px,-4px)}}",
3067
- "@keyframes dkan-think-arm{from{transform:rotateZ(-4deg)}to{transform:rotateZ(-34deg) translate(1px,-8px)}}",
3068
- "@keyframes dkan-think-arm-far{from{transform:translateZ(-8px) rotateZ(-2deg)}to{transform:translateZ(-8px) rotateZ(-24deg) translate(1px,-7px)}}",
3069
- // write/code:中屏高亮代码滚动 + 肘部高频敲击 + 低头专注
3070
- ".dkan-bot-scene[data-phase=write] .dk3-mon3.center .dk3-screen,.dkan-bot-scene[data-phase=code] .dk3-mon3.center .dk3-screen{opacity:1;box-shadow:0 0 10px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 45%,transparent);}",
3071
- ".dkan-bot-scene[data-phase=write] .dk3-mon3.center .dk3-code,.dkan-bot-scene[data-phase=code] .dk3-mon3.center .dk3-code{animation-duration:calc(2.2s / var(--dkan-speed,1));}",
3072
- ".dkan-bot-scene[data-phase=write] .dk3-arm3:not(.dk3-far),.dkan-bot-scene[data-phase=code] .dk3-arm3:not(.dk3-far){animation:dkan-output-arm calc(.46s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3073
- ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far{animation:dkan-output-arm-far calc(.46s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3074
- ".dkan-bot-scene[data-phase=write] .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-elbow{animation:dkan-type3 calc(.22s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3075
- ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far .dk3-elbow{animation-delay:.11s;}",
3076
- "@keyframes dkan-type3{from{transform:rotate(12deg) translateY(-1px)}to{transform:rotate(-14deg) translateY(2px)}}",
3077
- "@keyframes dkan-output-arm{from{transform:rotateZ(7deg) translateY(0)}to{transform:rotateZ(-13deg) translateY(4px)}}",
3078
- "@keyframes dkan-output-arm-far{from{transform:translateZ(-8px) rotateZ(5deg)}to{transform:translateZ(-8px) rotateZ(-11deg) translateY(4px)}}",
3079
- ".dkan-bot-scene[data-phase=write] .dk3-head3,.dkan-bot-scene[data-phase=code] .dk3-head3{animation:dkan-output-head calc(.8s / var(--dkan-speed,1)) ease-in-out infinite alternate;}",
3080
- "@keyframes dkan-output-head{from{transform:rotateZ(4deg) translateY(0)}to{transform:rotateZ(10deg) translate(2px,2px)}}",
3081
- // search:侧屏高亮 + 滚动加速 + 头部左右扫视(一会忙这个一会看那个)
3082
- ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-screen,.dkan-bot-scene[data-phase=search] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 8px color-mix(in srgb,var(--dkan-code-a,#4ade80) 40%,transparent);}",
3083
- ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-code,.dkan-bot-scene[data-phase=search] .dk3-mon3.right .dk3-code{animation-duration:calc(1.6s / var(--dkan-speed,1));}",
3084
- ".dkan-bot-scene[data-phase=search] .dk3-head3{animation:dkan-scan3 3.4s ease-in-out infinite;}",
3085
- "@keyframes dkan-scan3{0%,16%{transform:rotateZ(3deg) rotateY(-38deg)}30%,48%{transform:rotateZ(3deg) rotateY(6deg)}62%,80%{transform:rotateZ(3deg) rotateY(38deg)}100%{transform:rotateZ(3deg) rotateY(-38deg)}}",
3086
- "@media (prefers-reduced-motion:reduce){.dkan-botcard *{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important;}}",
5406
+ ".dkan-bot-scene[data-phase=think] .dk3-upper3{animation:dkan-think-upper max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5407
+ ".dkan-bot-scene[data-phase=think] .dk3-head3{animation:dkan-think-head max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5408
+ ".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-near{animation:dkan-think-near max(1.8s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5409
+ ".dkan-bot-scene[data-phase=think] .dk3-arm3.dk3-far{transform:translateZ(-7px) rotateZ(3deg);}",
5410
+ ".dkan-bot-scene[data-phase=think] .dk3-near .dk3-elbow{transform:rotateZ(-28deg) translateY(-1px);}",
5411
+ ".dkan-bot-scene[data-phase=think] .dk3-near .dk3-wrist3{transform:rotateZ(-18deg) translateY(-1px);}",
5412
+ "@keyframes dkan-think-upper{0%,44%{transform:rotateZ(-1deg) translateY(0)}62%,100%{transform:rotateZ(-1.8deg) translateY(-.5px)}}",
5413
+ "@keyframes dkan-think-head{0%,44%{transform:var(--dk3-head-turn) rotateZ(-3deg)}62%,100%{transform:var(--dk3-head-turn) rotateZ(-6deg) translateY(-.5px)}}",
5414
+ "@keyframes dkan-think-near{0%,44%{transform:rotateZ(-31deg) translate(-8px,-14.5px)}62%,100%{transform:rotateZ(-34deg) translate(-8.5px,-15px)}}",
5415
+ // write/code:身体仍面向桌面,仅轻微前倾;主要由手腕和手指敲击。
5416
+ ".dkan-bot-scene[data-phase=write] .dk3-mon3.right .dk3-screen,.dkan-bot-scene[data-phase=code] .dk3-mon3.right .dk3-screen{opacity:1;box-shadow:0 0 11px color-mix(in srgb,var(--dkan-code-b,#60a5fa) 52%,transparent);}",
5417
+ ".dkan-bot-scene[data-phase=write] .dk3-mon3.right .dk3-code,.dkan-bot-scene[data-phase=code] .dk3-mon3.right .dk3-code{animation-duration:calc(1.35s / var(--dkan-speed,1));}",
5418
+ ".dkan-bot-scene[data-phase=write] .dk3-upper3,.dkan-bot-scene[data-phase=code] .dk3-upper3{animation:dkan-code-upper max(1.2s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5419
+ ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-near,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-near{transform:rotateZ(3deg);}",
5420
+ ".dkan-bot-scene[data-phase=write] .dk3-arm3.dk3-far,.dkan-bot-scene[data-phase=code] .dk3-arm3.dk3-far{transform:translateZ(-7px) rotateZ(1deg);}",
5421
+ ".dkan-bot-scene[data-phase=write] .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-elbow{animation:dkan-type-elbow max(.28s,calc(.58s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5422
+ ".dkan-bot-scene[data-phase=write] .dk3-wrist3,.dkan-bot-scene[data-phase=code] .dk3-wrist3{animation:dkan-type-wrist max(.18s,calc(.29s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5423
+ ".dkan-bot-scene[data-phase=write] .dk3-far .dk3-elbow,.dkan-bot-scene[data-phase=code] .dk3-far .dk3-elbow{animation-delay:-.09s;animation-duration:max(.3s,calc(.63s / var(--dkan-speed,1)));}",
5424
+ ".dkan-bot-scene[data-phase=write] .dk3-far .dk3-wrist3,.dkan-bot-scene[data-phase=code] .dk3-far .dk3-wrist3{animation-delay:-.09s;animation-duration:max(.2s,calc(.33s / var(--dkan-speed,1)));}",
5425
+ ".dkan-bot-scene[data-phase=write] .dk3-head3,.dkan-bot-scene[data-phase=code] .dk3-head3{animation:dkan-output-head max(1.2s,calc(2.4s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5426
+ "@keyframes dkan-code-upper{0%,38%{transform:rotateZ(2deg) translate(1px,0)}62%,100%{transform:rotateZ(3deg) translate(1px,1px)}}",
5427
+ "@keyframes dkan-type-elbow{0%,38%{transform:rotateZ(-4deg)}62%,100%{transform:rotateZ(5deg) translateY(1px)}}",
5428
+ "@keyframes dkan-type-wrist{0%,34%{transform:rotateZ(-2deg) translateY(0)}62%,100%{transform:rotateZ(3deg) translateY(1.5px)}}",
5429
+ "@keyframes dkan-output-head{0%,46%,100%{transform:var(--dk3-head-turn) rotateZ(3deg)}58%{transform:var(--dk3-head-turn) rotateZ(5deg) translateY(1px)}}",
5430
+ // search:身体正对桌面,头看左屏,近侧手腕小幅操作鼠标。
5431
+ ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-screen{opacity:1;box-shadow:0 0 10px color-mix(in srgb,var(--dkan-code-a,#4ade80) 52%,transparent);}",
5432
+ ".dkan-bot-scene[data-phase=search] .dk3-mon3.left .dk3-search-results{animation-duration:calc(1.05s / var(--dkan-speed,1));}",
5433
+ ".dkan-bot-scene[data-phase=search] .dk3-upper3{transform:rotateZ(2deg) translateY(1px);}",
5434
+ ".dkan-bot-scene[data-phase=search] .dk3-head3{animation:dkan-search-head max(.72s,calc(1.15s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5435
+ ".dkan-bot-scene[data-phase=search] .dk3-near .dk3-wrist3{animation:dkan-search-wrist max(.45s,calc(.72s / var(--dkan-speed,1))) cubic-bezier(.77,0,.175,1) infinite;}",
5436
+ ".dkan-bot-scene[data-phase=search] .dk3-far{transform:translateZ(-7px) rotateZ(2deg);}",
5437
+ "@keyframes dkan-search-head{0%,28%{transform:var(--dk3-head-turn) rotateZ(1deg)}48%,68%{transform:var(--dk3-head-turn) rotateZ(6deg) translate(1px,1px)}88%,100%{transform:var(--dk3-head-turn) rotateZ(2deg)}}",
5438
+ "@keyframes dkan-search-wrist{0%,34%{transform:translateX(-1px)}62%,100%{transform:translateX(1.5px)}}",
5439
+ // 减少动态时停止空间位移,保留屏幕亮暗与思考状态的淡入反馈。
5440
+ "@media (prefers-reduced-motion:reduce){.dk3-person,.dk3-upper3,.dk3-head3,.dk3-arm3,.dk3-elbow,.dk3-wrist3,.dk3-wheel,.dk3-code,.dk3-search-results{animation:none!important;transition:none!important}.dk3-screen,.dkan-bubble{transition:opacity .2s cubic-bezier(.23,1,.32,1)!important}}",
3087
5441
  // 通知子选项行
3088
5442
  ".dkan-rows-narrow{display:flex;flex-direction:column;gap:6px;}",
3089
5443
  ".dkan-row{display:flex;align-items:center;gap:8px;font-size:12px;color:var(--dsw-alias-label-secondary);flex-wrap:wrap;}",
@@ -3135,9 +5489,459 @@ var feature6 = {
3135
5489
  Overlay: AnimationOverlay
3136
5490
  };
3137
5491
 
5492
+ // features/mobile-relay/view.jsx
5493
+ var import_react9 = require("react");
5494
+ var import_qrcode = __toESM(require_browser(), 1);
5495
+ var import_jsx_runtime3 = require("react/jsx-runtime");
5496
+ var DEVICE_KEY = "dsh-dock/mobile-relay/device/v1";
5497
+ var SESSION_KEY = "dsh-dock/mobile-relay/session/v1";
5498
+ var LAUNCH_KEY = "dsh-dock/mobile-relay/launch/v1";
5499
+ function rpc(method, payload) {
5500
+ return fetch("/dsh-dock/mobile-relay/" + method, {
5501
+ method: "POST",
5502
+ headers: { "content-type": "application/json" },
5503
+ body: JSON.stringify(payload || {})
5504
+ }).then(async (res) => {
5505
+ const body = await res.json().catch(() => ({}));
5506
+ if (res.ok && body && body.ok) return body.data;
5507
+ if (res.status === 404 || res.status === 405) throw new Error("\u5BBF\u4E3B\u8FDB\u7A0B\u4ECD\u662F\u65E7\u7248\u672C\uFF0C\u8BF7\u91CD\u542F dsh web \u540E\u518D\u5F00\u542F\u5C40\u57DF\u7F51\u8FDE\u63A5");
5508
+ throw new Error(body && body.error && body.error.message || "\u8BF7\u6C42\u5931\u8D25\uFF08" + res.status + "\uFF09");
5509
+ });
5510
+ }
5511
+ function deviceId() {
5512
+ let id = "";
5513
+ try {
5514
+ id = localStorage.getItem(DEVICE_KEY) || "";
5515
+ } catch {
5516
+ }
5517
+ if (!id) {
5518
+ id = globalThis.crypto && crypto.randomUUID ? crypto.randomUUID() : Math.random().toString(36).slice(2);
5519
+ try {
5520
+ localStorage.setItem(DEVICE_KEY, id);
5521
+ } catch {
5522
+ }
5523
+ }
5524
+ return id;
5525
+ }
5526
+ function readSession() {
5527
+ try {
5528
+ const raw = sessionStorage.getItem(SESSION_KEY);
5529
+ return raw ? JSON.parse(raw) : null;
5530
+ } catch {
5531
+ return null;
5532
+ }
5533
+ }
5534
+ function saveSession(value) {
5535
+ try {
5536
+ sessionStorage.setItem(SESSION_KEY, JSON.stringify(value));
5537
+ } catch {
5538
+ }
5539
+ }
5540
+ function clearSession() {
5541
+ try {
5542
+ sessionStorage.removeItem(SESSION_KEY);
5543
+ } catch {
5544
+ }
5545
+ }
5546
+ function fmtDuration2(ms) {
5547
+ const sec = Math.max(0, Math.floor((ms || 0) / 1e3));
5548
+ const min = Math.floor(sec / 60);
5549
+ const rest = sec % 60;
5550
+ return min > 0 ? min + " \u5206 " + String(rest).padStart(2, "0") + " \u79D2" : rest + " \u79D2";
5551
+ }
5552
+ function fmtTime3(value) {
5553
+ return value ? new Date(value).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" }) : "";
5554
+ }
5555
+ function phaseLabel2(phase) {
5556
+ return { think: "\u6B63\u5728\u601D\u8003", write: "\u6B63\u5728\u8F93\u51FA", code: "\u6B63\u5728\u5F00\u53D1", search: "\u6B63\u5728\u67E5\u8D44\u6599" }[phase] || "\u8FDB\u884C\u4E2D";
5557
+ }
5558
+ function copy(value) {
5559
+ if (navigator.clipboard && navigator.clipboard.writeText) return navigator.clipboard.writeText(value);
5560
+ return Promise.reject(new Error("\u5F53\u524D\u6D4F\u89C8\u5668\u4E0D\u652F\u6301\u590D\u5236\uFF0C\u8BF7\u957F\u6309\u6216\u624B\u52A8\u590D\u5236"));
5561
+ }
5562
+ function RelayIcon({ name, size = 18 }) {
5563
+ const common = { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.8, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": true };
5564
+ if (name === "phone") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...common, children: [
5565
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "7", y: "2.5", width: "10", height: "19", rx: "2.2" }),
5566
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M10 18.5h4" })
5567
+ ] });
5568
+ if (name === "link") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...common, children: [
5569
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M10.5 13.5a4 4 0 0 0 5.66.01l2-2a4 4 0 0 0-5.66-5.66l-1.15 1.14" }),
5570
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M13.5 10.5a4 4 0 0 0-5.66-.01l-2 2a4 4 0 0 0 5.66 5.66l1.15-1.14" })
5571
+ ] });
5572
+ if (name === "copy") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...common, children: [
5573
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("rect", { x: "8", y: "8", width: "11", height: "12", rx: "1.5" }),
5574
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M16 8V5.5A1.5 1.5 0 0 0 14.5 4h-9A1.5 1.5 0 0 0 4 5.5v9A1.5 1.5 0 0 0 5.5 16H8" })
5575
+ ] });
5576
+ if (name === "check") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...common, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m5 12 4.2 4.2L19 6.5" }) });
5577
+ if (name === "arrow") return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...common, children: [
5578
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M5 12h13" }),
5579
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m14 7 5 5-5 5" })
5580
+ ] });
5581
+ if (name === "close") return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("svg", { ...common, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "m6 6 12 12M18 6 6 18" }) });
5582
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("svg", { ...common, children: [
5583
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "8" }),
5584
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("path", { d: "M12 8v4l2.5 2" })
5585
+ ] });
5586
+ }
5587
+ function useCompact() {
5588
+ const [compact, setCompact] = (0, import_react9.useState)(() => typeof window !== "undefined" && window.matchMedia("(max-width: 680px)").matches);
5589
+ (0, import_react9.useEffect)(() => {
5590
+ const media = window.matchMedia("(max-width: 680px)");
5591
+ const update = () => setCompact(media.matches);
5592
+ update();
5593
+ media.addEventListener("change", update);
5594
+ return () => media.removeEventListener("change", update);
5595
+ }, []);
5596
+ return compact;
5597
+ }
5598
+ function MobileRelayView() {
5599
+ const compact = useCompact();
5600
+ const [session, setSession] = (0, import_react9.useState)(readSession);
5601
+ const [pair, setPair] = (0, import_react9.useState)(null);
5602
+ const [network, setNetwork] = (0, import_react9.useState)(null);
5603
+ const [port, setPort] = (0, import_react9.useState)(3081);
5604
+ const [selectedAddress, setSelectedAddress] = (0, import_react9.useState)("");
5605
+ const [qrDataUrl, setQrDataUrl] = (0, import_react9.useState)("");
5606
+ const [note, setNote] = (0, import_react9.useState)("");
5607
+ const [busy, setBusy] = (0, import_react9.useState)("");
5608
+ const [notice, setNotice] = (0, import_react9.useState)("");
5609
+ const [error, setError] = (0, import_react9.useState)("");
5610
+ const mobile = session && session.role === "mobile";
5611
+ const setCurrent = (0, import_react9.useCallback)((next) => {
5612
+ setSession(next);
5613
+ next ? saveSession(next) : clearSession();
5614
+ }, []);
5615
+ (0, import_react9.useEffect)(() => {
5616
+ if (session) return;
5617
+ rpc("network").then((data) => {
5618
+ setNetwork(data);
5619
+ if (data && data.defaultPort) setPort(data.defaultPort);
5620
+ const first = data && data.addresses && data.addresses[0];
5621
+ if (first) setSelectedAddress(first.address);
5622
+ }).catch((e) => setError(e && e.message ? e.message : String(e)));
5623
+ }, [session]);
5624
+ const refresh = (0, import_react9.useCallback)(async (candidate = session) => {
5625
+ if (!candidate) return;
5626
+ try {
5627
+ const result = await rpc("status", candidate);
5628
+ setPair(result.pair);
5629
+ setError("");
5630
+ } catch (e) {
5631
+ const message = e && e.message ? e.message : String(e);
5632
+ setError(message);
5633
+ if (/过期|未完成配对/.test(message)) setCurrent(null);
5634
+ }
5635
+ }, [session, setCurrent]);
5636
+ (0, import_react9.useEffect)(() => {
5637
+ if (session) refresh(session);
5638
+ }, [session, refresh]);
5639
+ (0, import_react9.useEffect)(() => {
5640
+ if (!session) return;
5641
+ const timer = setInterval(() => refresh(session), 2500);
5642
+ return () => clearInterval(timer);
5643
+ }, [session, refresh]);
5644
+ (0, import_react9.useEffect)(() => {
5645
+ if (session) return;
5646
+ let launch = "";
5647
+ try {
5648
+ launch = sessionStorage.getItem(LAUNCH_KEY) || "";
5649
+ } catch {
5650
+ }
5651
+ if (!launch) return;
5652
+ try {
5653
+ sessionStorage.removeItem(LAUNCH_KEY);
5654
+ } catch {
5655
+ }
5656
+ const [pairId, code] = launch.split(".");
5657
+ if (!pairId || !code) return;
5658
+ setBusy("join");
5659
+ rpc("join", { pairId, code, deviceId: deviceId(), label: "\u624B\u673A\u7AEF" }).then((data) => {
5660
+ setCurrent({ pairId, secret: data.secret, role: "mobile", deviceId: deviceId() });
5661
+ setPair(data.pair);
5662
+ setNotice("\u5DF2\u8FDE\u63A5\u5230\u7535\u8111\u7AEF\uFF0C\u4EFB\u52A1\u72B6\u6001\u4F1A\u6301\u7EED\u540C\u6B65\u3002");
5663
+ }).catch((e) => setError(e && e.message ? e.message : String(e))).finally(() => setBusy(""));
5664
+ }, [session, setCurrent]);
5665
+ const mobileLink = (0, import_react9.useMemo)(() => {
5666
+ if (!session || !session.gatewayToken || !session.gatewayAddress || !session.gatewayPort) return "";
5667
+ return "http://" + session.gatewayAddress + ":" + session.gatewayPort + "/__dsh_mobile/connect#" + session.gatewayToken;
5668
+ }, [session]);
5669
+ (0, import_react9.useEffect)(() => {
5670
+ let active = true;
5671
+ if (!mobileLink) {
5672
+ setQrDataUrl("");
5673
+ return () => {
5674
+ active = false;
5675
+ };
5676
+ }
5677
+ import_qrcode.default.toDataURL(mobileLink, {
5678
+ errorCorrectionLevel: "M",
5679
+ margin: 2,
5680
+ width: 260,
5681
+ color: { dark: "#111827", light: "#ffffff" }
5682
+ }).then((value) => {
5683
+ if (active) setQrDataUrl(value);
5684
+ }).catch((e) => {
5685
+ if (active) setError("\u4E8C\u7EF4\u7801\u751F\u6210\u5931\u8D25\uFF1A" + (e && e.message ? e.message : String(e)));
5686
+ });
5687
+ return () => {
5688
+ active = false;
5689
+ };
5690
+ }, [mobileLink]);
5691
+ async function start() {
5692
+ setError("");
5693
+ setNotice("");
5694
+ const numericPort = Number(port);
5695
+ if (!selectedAddress) {
5696
+ setError("\u6CA1\u6709\u68C0\u6D4B\u5230\u53EF\u7528\u7684\u5C40\u57DF\u7F51 IPv4 \u5730\u5740\uFF0C\u8BF7\u5148\u8FDE\u63A5 Wi-Fi \u6216\u6709\u7EBF\u7F51\u7EDC\u3002");
5697
+ return;
5698
+ }
5699
+ if (!Number.isInteger(numericPort) || numericPort < 1024 || numericPort > 65535) {
5700
+ setError("\u5C40\u57DF\u7F51\u7AEF\u53E3\u9700\u4E3A 1024 \u5230 65535 \u4E4B\u95F4\u7684\u6574\u6570\u3002");
5701
+ return;
5702
+ }
5703
+ setBusy("start");
5704
+ try {
5705
+ const data = await rpc("start", { deviceId: deviceId(), port: numericPort });
5706
+ const next = {
5707
+ pairId: data.pairId,
5708
+ secret: data.secret,
5709
+ code: data.code,
5710
+ role: "desktop",
5711
+ deviceId: deviceId(),
5712
+ gatewayToken: data.gatewayToken,
5713
+ gatewayPort: data.gateway.port,
5714
+ gatewayAddress: selectedAddress
5715
+ };
5716
+ setCurrent(next);
5717
+ setPair(data.pair);
5718
+ setNotice("\u53D7\u4FDD\u62A4\u7684\u5C40\u57DF\u7F51\u53CD\u5411\u4EE3\u7406\u5DF2\u5F00\u542F\u3002\u624B\u673A\u626B\u7801\u5373\u53EF\u8FDB\u5165\u540C\u4E00 DSH\u3002");
5719
+ } catch (e) {
5720
+ setError(e && e.message ? e.message : String(e));
5721
+ } finally {
5722
+ setBusy("");
5723
+ }
5724
+ }
5725
+ async function sendNote(event) {
5726
+ event.preventDefault();
5727
+ if (!session || !note.trim()) return;
5728
+ setBusy("note");
5729
+ setError("");
5730
+ try {
5731
+ const data = await rpc("note", Object.assign({}, session, { note }));
5732
+ setPair(data.pair);
5733
+ setNote("");
5734
+ setNotice("\u63A5\u529B\u5907\u6CE8\u5DF2\u540C\u6B65\u3002");
5735
+ } catch (e) {
5736
+ setError(e && e.message ? e.message : String(e));
5737
+ } finally {
5738
+ setBusy("");
5739
+ }
5740
+ }
5741
+ async function end() {
5742
+ if (!session) return;
5743
+ setBusy("end");
5744
+ try {
5745
+ await rpc("end", session);
5746
+ setCurrent(null);
5747
+ setPair(null);
5748
+ setNotice("\u624B\u673A\u8FDE\u63A5\u5DF2\u5173\u95ED\u3002");
5749
+ } catch (e) {
5750
+ setError(e && e.message ? e.message : String(e));
5751
+ } finally {
5752
+ setBusy("");
5753
+ }
5754
+ }
5755
+ function copyLink() {
5756
+ copy(mobileLink).then(() => setNotice("\u8FDE\u63A5\u94FE\u63A5\u5DF2\u590D\u5236\u3002")).catch((e) => setError(e.message));
5757
+ }
5758
+ if (!session) return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "dmr " + (compact ? "dmr-compact" : ""), children: [
5759
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-hero", children: [
5760
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dmr-hero-icon", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RelayIcon, { name: "phone", size: 22 }) }),
5761
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
5762
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: "\u628A\u5F00\u53D1\u4EFB\u52A1\u63A5\u5230\u624B\u673A" }),
5763
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u4E3B DSH \u7EE7\u7EED\u4EC5\u9650\u672C\u673A\uFF1B\u5F00\u542F\u5C40\u57DF\u7F51\u53CD\u5411\u4EE3\u7406\u540E\uFF0C\u901A\u8FC7\u4E00\u6B21\u6027\u4E8C\u7EF4\u7801\u5B89\u5168\u63A5\u5165\u3002" })
5764
+ ] })
5765
+ ] }),
5766
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("ol", { className: "dmr-steps", children: [
5767
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
5768
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "1" }),
5769
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
5770
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "\u786E\u8BA4 IP \u4E0E\u7AEF\u53E3" }),
5771
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: "\u81EA\u52A8\u8BC6\u522B\u7535\u8111\u5C40\u57DF\u7F51 IPv4\uFF0C\u9ED8\u8BA4\u4F7F\u7528\u72EC\u7ACB\u7AEF\u53E3 3081\u3002" })
5772
+ ] })
5773
+ ] }),
5774
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
5775
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "2" }),
5776
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
5777
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "\u5F00\u542F\u53CD\u5411\u4EE3\u7406" }),
5778
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: "\u4EE3\u7406 HTTP \u4E0E WebSocket\uFF0C\u672A\u8BA4\u8BC1\u8BBE\u5907\u65E0\u6CD5\u8BBF\u95EE\u3002" })
5779
+ ] })
5780
+ ] }),
5781
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("li", { children: [
5782
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "3" }),
5783
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
5784
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "\u624B\u673A\u626B\u7801\u63A5\u529B" }),
5785
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: "\u626B\u7801\u8FDB\u5165\u539F\u4F1A\u8BDD\uFF0C\u7535\u8111\u7AEF\u540C\u6B65\u770B\u5230\u5F00\u53D1\u8FDB\u5EA6\u3002" })
5786
+ ] })
5787
+ ] })
5788
+ ] }),
5789
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-network-grid", children: [
5790
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "dmr-field", children: [
5791
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u5C40\u57DF\u7F51 IP" }),
5792
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("select", { value: selectedAddress, onChange: (e) => setSelectedAddress(e.target.value), disabled: !network || !network.addresses || !network.addresses.length, children: network && network.addresses && network.addresses.length ? network.addresses.map((item) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("option", { value: item.address, children: [
5793
+ item.address,
5794
+ " \xB7 ",
5795
+ item.interface
5796
+ ] }, item.interface + item.address)) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: "", children: network ? "\u672A\u68C0\u6D4B\u5230\u5730\u5740" : "\u6B63\u5728\u68C0\u6D4B\u7F51\u7EDC\u2026" }) }),
5797
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: "\u624B\u673A\u9700\u4E0E\u7535\u8111\u4F4D\u4E8E\u53EF\u4E92\u8BBF\u7684\u540C\u4E00\u5C40\u57DF\u7F51\u3002" })
5798
+ ] }),
5799
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { className: "dmr-field", children: [
5800
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u76D1\u542C\u7AEF\u53E3" }),
5801
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("input", { value: port, onChange: (e) => setPort(e.target.value), inputMode: "numeric", type: "number", min: "1024", max: "65535", "aria-describedby": "dmr-port-help" }),
5802
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { id: "dmr-port-help", children: "\u4E3B\u670D\u52A1\u4ECD\u4E3A 127.0.0.1:3080\uFF1B\u624B\u673A\u5165\u53E3\u5EFA\u8BAE\u4F7F\u7528 3081\u3002" })
5803
+ ] })
5804
+ ] }),
5805
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-security", children: [
5806
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "\u5B89\u5168\u8BF4\u660E" }),
5807
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u94FE\u63A5\u76F8\u5F53\u4E8E\u4E34\u65F6\u767B\u5F55\u51ED\u636E\uFF0C\u53EA\u53D1\u7ED9\u81EA\u5DF1\u7684\u624B\u673A\u3002\u9A8C\u8BC1\u4EE4\u724C 10 \u5206\u949F\u540E\u5931\u6548\uFF1B\u5173\u95ED\u8FDE\u63A5\u4F1A\u7ACB\u5373\u64A4\u9500\u624B\u673A\u4F1A\u8BDD\u5E76\u505C\u6B62\u7AEF\u53E3\u76D1\u542C\u3002" })
5808
+ ] }),
5809
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dmr-primary", onClick: start, disabled: busy === "start" || !selectedAddress, children: busy === "start" ? "\u6B63\u5728\u5F00\u542F\u53CD\u5411\u4EE3\u7406\u2026" : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
5810
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RelayIcon, { name: "link" }),
5811
+ "\u5F00\u542F\u53CD\u5411\u4EE3\u7406\u5E76\u751F\u6210\u4E8C\u7EF4\u7801"
5812
+ ] }) }),
5813
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-message error", role: "alert", children: error }),
5814
+ notice && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-message success", "aria-live": "polite", children: [
5815
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RelayIcon, { name: "check" }),
5816
+ notice
5817
+ ] })
5818
+ ] });
5819
+ const onlineMobiles = pair && pair.devices ? pair.devices.filter((device) => device.role === "mobile") : [];
5820
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("section", { className: "dmr " + (compact ? "dmr-compact" : ""), children: [
5821
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-status-head", children: [
5822
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
5823
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dmr-eyebrow", children: [
5824
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", {}),
5825
+ " ",
5826
+ mobile ? "\u5DF2\u8FDE\u63A5\u5230\u7535\u8111" : "\u624B\u673A\u8FDE\u63A5\u5DF2\u5F00\u542F"
5827
+ ] }),
5828
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h3", { children: mobile ? "\u53EF\u4EE5\u5728\u8FD9\u91CC\u7EE7\u7EED\u5F00\u53D1" : "\u7B49\u5F85\u624B\u673A\u63A5\u5165" }),
5829
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: mobile ? "\u4EFB\u52A1\u72B6\u6001\u548C\u63A5\u529B\u5907\u6CE8\u4F1A\u81EA\u52A8\u540C\u6B65\u3002\u7EE7\u7EED\u5F00\u53D1\u8BF7\u56DE\u5230\u5F53\u524D DSH \u4F1A\u8BDD\u8F93\u5165\u533A\u3002" : "\u5C06\u4E0B\u9762\u7684\u5B89\u5168\u94FE\u63A5\u53D1\u5230\u624B\u673A\uFF1B\u8FDE\u63A5\u5728 " + fmtTime3(pair && pair.expiresAt) + " \u524D\u6709\u6548\u3002" })
5830
+ ] }),
5831
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dmr-icon-button", onClick: end, disabled: busy === "end", title: "\u5173\u95ED\u624B\u673A\u8FDE\u63A5", "aria-label": "\u5173\u95ED\u624B\u673A\u8FDE\u63A5", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RelayIcon, { name: "close" }) })
5832
+ ] }),
5833
+ !mobile && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-share", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-share-layout", children: [
5834
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-qr-card", children: [
5835
+ qrDataUrl ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("img", { src: qrDataUrl, alt: "\u624B\u673A\u63A5\u529B\u4E00\u6B21\u6027\u8FDE\u63A5\u4E8C\u7EF4\u7801", width: "260", height: "260" }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-qr-loading", "aria-live": "polite", children: "\u6B63\u5728\u751F\u6210\u4E8C\u7EF4\u7801\u2026" }),
5836
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: "\u4F7F\u7528\u624B\u673A\u76F8\u673A\u626B\u7801" }),
5837
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: "\u624B\u673A\u4E0E\u7535\u8111\u9700\u5728\u540C\u4E00\u5C40\u57DF\u7F51" })
5838
+ ] }),
5839
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-share-detail", children: [
5840
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
5841
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: "dmr-eyebrow", children: [
5842
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("i", {}),
5843
+ " \u53CD\u5411\u4EE3\u7406\u5DF2\u8FD0\u884C"
5844
+ ] }),
5845
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("h4", { children: [
5846
+ session.gatewayAddress,
5847
+ ":",
5848
+ session.gatewayPort,
5849
+ " \u2192 127.0.0.1:3080"
5850
+ ] })
5851
+ ] }),
5852
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-link", title: mobileLink, children: mobileLink || "\u5C40\u57DF\u7F51\u5165\u53E3\u672A\u5C31\u7EEA" }),
5853
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-share-actions", children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("button", { type: "button", className: "dmr-primary", onClick: copyLink, disabled: !mobileLink, children: [
5854
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RelayIcon, { name: "copy" }),
5855
+ "\u590D\u5236\u8FDE\u63A5\u94FE\u63A5"
5856
+ ] }) }),
5857
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: "\u4E8C\u7EF4\u7801\u548C\u94FE\u63A5\u53EA\u53EF\u6210\u529F\u9A8C\u8BC1\u4E00\u6B21\uFF0C10 \u5206\u949F\u540E\u5931\u6548\u3002\u5982\u9700\u53E6\u4E00\u53F0\u624B\u673A\uFF0C\u8BF7\u5173\u95ED\u540E\u91CD\u65B0\u5F00\u542F\u3002" })
5858
+ ] })
5859
+ ] }) }),
5860
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-overview", children: [
5861
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-overview-card", children: [
5862
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u8BBE\u5907\u72B6\u6001" }),
5863
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: mobile ? "\u624B\u673A\u5DF2\u63A5\u529B" : onlineMobiles.length ? onlineMobiles.length + " \u53F0\u624B\u673A\u5728\u7EBF" : "\u7B49\u5F85\u624B\u673A" }),
5864
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: mobile ? "\u4FDD\u6301\u6B64\u9875\u9762\u6253\u5F00\u5373\u53EF\u540C\u6B65\u72B6\u6001" : onlineMobiles.length ? "\u72B6\u6001\u6BCF 2.5 \u79D2\u5237\u65B0" : "\u8FDE\u63A5\u7801\u4EC5\u5728\u5F53\u524D\u914D\u5BF9\u7A97\u53E3\u6709\u6548" })
5865
+ ] }),
5866
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-overview-card", children: [
5867
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: "\u8FDB\u884C\u4E2D\u7684\u4EFB\u52A1" }),
5868
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: pair && pair.tasks ? pair.tasks.length : "\u2014" }),
5869
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("small", { children: pair && pair.tasks && pair.tasks.length ? "\u4E0E DSH \u5F53\u524D\u4F1A\u8BDD\u5171\u7528\u540C\u4E00\u4EFB\u52A1" : "\u5F00\u59CB\u4EFB\u52A1\u540E\u4F1A\u81EA\u52A8\u663E\u793A\u5728\u8FD9\u91CC" })
5870
+ ] })
5871
+ ] }),
5872
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-section", children: [
5873
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-section-head", children: [
5874
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h4", { children: "\u5B9E\u65F6\u4EFB\u52A1" }),
5875
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { type: "button", className: "dmr-text-button", onClick: () => refresh(), disabled: busy, children: "\u5237\u65B0" })
5876
+ ] }),
5877
+ pair && pair.tasks && pair.tasks.length ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-task-list", children: pair.tasks.map((task) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("article", { className: "dmr-task", children: [
5878
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "dmr-phase " + task.phase, children: phaseLabel2(task.phase) }),
5879
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { children: [
5880
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("strong", { children: task.title }),
5881
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("small", { children: [
5882
+ "\u5DF2\u8FD0\u884C ",
5883
+ fmtDuration2(task.elapsed),
5884
+ " \xB7 \u6700\u8FD1\u6D3B\u52A8 ",
5885
+ fmtTime3(task.lastActivityAt)
5886
+ ] })
5887
+ ] })
5888
+ ] }, task.sessionId)) }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-empty", children: "\u5F53\u524D\u6CA1\u6709\u6B63\u5728\u8FD0\u884C\u7684\u4EFB\u52A1\u3002\u542F\u52A8\u4EFB\u52A1\u540E\uFF0C\u624B\u673A\u548C\u7535\u8111\u90FD\u4F1A\u770B\u5230\u540C\u4E00\u4EFD\u72B6\u6001\u3002" })
5889
+ ] }),
5890
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("form", { className: "dmr-note", onSubmit: sendNote, children: [
5891
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-section-head", children: [
5892
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("h4", { children: "\u63A5\u529B\u5907\u6CE8" }),
5893
+ pair && pair.noteAt ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("small", { children: [
5894
+ pair.noteFrom,
5895
+ " \xB7 ",
5896
+ fmtTime3(pair.noteAt)
5897
+ ] }) : null
5898
+ ] }),
5899
+ pair && pair.note ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("blockquote", { children: pair.note }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { children: "\u628A\u5F53\u524D\u8FDB\u5EA6\u3001\u4E0B\u4E00\u6B65\u6216\u9700\u8981\u6CE8\u610F\u7684\u4E8B\u9879\u7559\u7ED9\u53E6\u4E00\u53F0\u8BBE\u5907\u3002" }),
5900
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("label", { children: [
5901
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "sr-only", children: "\u63A5\u529B\u5907\u6CE8" }),
5902
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("textarea", { value: note, onChange: (e) => setNote(e.target.value), maxLength: "1200", placeholder: mobile ? "\u4F8B\u5982\uFF1A\u6211\u5DF2\u5728\u624B\u673A\u67E5\u770B\u5230\u6784\u5EFA\u9519\u8BEF\uFF0C\u4E0B\u4E00\u6B65\u8BF7\u5728\u7535\u8111\u8FD0\u884C\u6D4B\u8BD5\u3002" : "\u4F8B\u5982\uFF1A\u5DF2\u7ECF\u5B8C\u6210\u63A5\u53E3\u4FEE\u6539\uFF0C\u624B\u673A\u7AEF\u7EE7\u7EED\u68C0\u67E5\u9875\u9762\u4EA4\u4E92\u3002" })
5903
+ ] }),
5904
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "dmr-secondary", disabled: !note.trim() || busy === "note", children: busy === "note" ? "\u6B63\u5728\u540C\u6B65\u2026" : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
5905
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RelayIcon, { name: "arrow" }),
5906
+ "\u540C\u6B65\u5907\u6CE8"
5907
+ ] }) })
5908
+ ] }),
5909
+ error && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "dmr-message error", role: "alert", children: error }),
5910
+ notice && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "dmr-message success", "aria-live": "polite", children: [
5911
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(RelayIcon, { name: "check" }),
5912
+ notice
5913
+ ] })
5914
+ ] });
5915
+ }
5916
+ function MobileRelayHomeStat() {
5917
+ const [summary, setSummary] = (0, import_react9.useState)("\u53EF\u5728\u624B\u673A\u7EE7\u7EED\u5F53\u524D\u4EFB\u52A1");
5918
+ (0, import_react9.useEffect)(() => {
5919
+ const session = readSession();
5920
+ if (!session) return;
5921
+ rpc("status", session).then((data) => {
5922
+ const p = data.pair;
5923
+ setSummary((p.tasks || []).length ? p.tasks.length + " \u4E2A\u4EFB\u52A1\u540C\u6B65\u4E2D" : "\u624B\u673A\u5DF2\u8FDE\u63A5\uFF0C\u7B49\u5F85\u4EFB\u52A1");
5924
+ }).catch(() => setSummary("\u8FDE\u63A5\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u914D\u5BF9"));
5925
+ }, []);
5926
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { children: summary });
5927
+ }
5928
+ var feature7 = {
5929
+ id: "mobile-relay",
5930
+ name: "\u624B\u673A\u63A5\u529B",
5931
+ order: 80,
5932
+ accent: "#38bdf8",
5933
+ description: "\u5B89\u5168\u53CD\u5411\u4EE3\u7406\u4E0E\u626B\u7801\u63A5\u529B\uFF0C\u540C\u6B65\u5F53\u524D\u4EFB\u52A1\u72B6\u6001\u548C\u5907\u6CE8",
5934
+ defaultEnabled: true,
5935
+ css: `
5936
+ .dmr{--dmr-accent:#38bdf8;--dmr-accent-soft:color-mix(in srgb,var(--dmr-accent) 13%,transparent);display:flex;flex-direction:column;gap:16px;max-width:720px;color:var(--dsw-alias-label-primary);font-size:13px;line-height:1.5}.dmr h3,.dmr h4,.dmr p{margin:0}.dmr h3{font-size:17px;line-height:1.25;letter-spacing:-.01em}.dmr h4{font-size:13px}.dmr-hero,.dmr-status-head{display:flex;align-items:flex-start;gap:12px}.dmr-hero>div,.dmr-status-head>div{min-width:0;display:flex;flex-direction:column;gap:4px}.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.55}.dmr-hero-icon{width:42px;height:42px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:14px;background:var(--dmr-accent-soft);color:var(--dmr-accent);border:1px solid color-mix(in srgb,var(--dmr-accent) 35%,var(--dsw-alias-border-l1))}.dmr-steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:0;padding:0;list-style:none}.dmr-steps li{display:flex;gap:9px;padding:11px;border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);border-radius:12px}.dmr-steps li>span{width:21px;height:21px;display:inline-flex;align-items:center;justify-content:center;flex:none;border-radius:50%;font-size:11px;font-weight:700;color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-steps div{display:flex;flex-direction:column;gap:3px;min-width:0}.dmr-steps strong{font-size:12px}.dmr-steps small{font-size:11px;color:var(--dsw-alias-label-secondary);line-height:1.45}.dmr-field{display:flex;flex-direction:column;gap:6px;font-weight:600}.dmr-field input,.dmr-field select,.dmr-note textarea{box-sizing:border-box;width:100%;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:10px;padding:10px 12px;min-height:44px;font:inherit;outline:none;transition:border-color .18s ease,box-shadow .18s ease}.dmr-field input:focus,.dmr-field select:focus,.dmr-note textarea:focus{border-color:var(--dmr-accent);box-shadow:0 0 0 3px var(--dmr-accent-soft)}.dmr-field small{font-weight:400}.dmr-network-grid{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(150px,.6fr);gap:12px}.dmr-security{padding:12px 13px;border:1px solid color-mix(in srgb,#f59e0b 38%,var(--dsw-alias-border-l1));border-radius:12px;background:color-mix(in srgb,#f59e0b 8%,transparent)}.dmr-security strong{display:block;margin-bottom:4px;color:#f59e0b;font-size:12px}.dmr-security p{font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.55}.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button{font:inherit;touch-action:manipulation;cursor:pointer;transition:transform .15s ease,background .18s ease,border-color .18s ease,opacity .18s ease}.dmr-primary,.dmr-secondary{min-height:44px;display:inline-flex;align-items:center;justify-content:center;gap:8px;border-radius:10px;padding:9px 13px;font-weight:600}.dmr-primary{align-self:flex-start;border:1px solid var(--dmr-accent);background:var(--dmr-accent);color:#062238}.dmr-primary:hover{filter:brightness(1.05)}.dmr-secondary{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.dmr-secondary:hover{border-color:var(--dmr-accent);background:var(--dmr-accent-soft)}.dmr-primary:active,.dmr-secondary:active,.dmr-icon-button:active{transform:scale(.98)}.dmr-primary:disabled,.dmr-secondary:disabled,.dmr-text-button:disabled,.dmr-icon-button:disabled{cursor:not-allowed;opacity:.5}.dmr-message{display:flex;align-items:flex-start;gap:7px;padding:10px 12px;border-radius:10px;font-size:12px}.dmr-message.success{color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb,var(--dsw-alias-state-success-primary) 10%,transparent)}.dmr-message.error{color:var(--dsw-alias-state-error-primary);background:color-mix(in srgb,var(--dsw-alias-state-error-primary) 10%,transparent)}.dmr-status-head{justify-content:space-between}.dmr-eyebrow{display:inline-flex;align-items:center;gap:6px;font-size:11px;font-weight:600;color:var(--dmr-accent)}.dmr-eyebrow i{width:7px;height:7px;border-radius:50%;background:currentColor;box-shadow:0 0 0 4px var(--dmr-accent-soft)}.dmr-icon-button{display:inline-flex;align-items:center;justify-content:center;flex:none;width:44px;height:44px;border:1px solid var(--dsw-alias-border-l2);border-radius:10px;background:transparent;color:var(--dsw-alias-label-secondary)}.dmr-icon-button:hover{color:var(--dsw-alias-state-error-primary);border-color:currentColor}.dmr-share{display:flex;flex-direction:column;gap:9px;padding:13px;border:1px solid color-mix(in srgb,var(--dmr-accent) 32%,var(--dsw-alias-border-l1));border-radius:13px;background:var(--dmr-accent-soft)}.dmr-share-layout{display:grid;grid-template-columns:196px minmax(0,1fr);gap:16px;align-items:center}.dmr-qr-card{box-sizing:border-box;display:flex;flex-direction:column;align-items:center;gap:5px;padding:10px;border-radius:12px;background:#fff;color:#111827;text-align:center}.dmr-qr-card img{display:block;width:176px;height:176px;max-width:100%;object-fit:contain}.dmr-qr-card strong{font-size:12px}.dmr-qr-card small{color:#4b5563;font-size:10px}.dmr-qr-loading{display:grid;place-items:center;width:176px;height:176px;color:#64748b;font-size:12px}.dmr-share-detail{min-width:0;display:flex;flex-direction:column;gap:10px}.dmr-share-detail>div:first-child{display:flex;flex-direction:column;gap:4px}.dmr-link{padding:10px 11px;border-radius:8px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);font:12px/1.4 ui-monospace,SFMono-Regular,Menlo,monospace;word-break:break-all;color:var(--dsw-alias-label-secondary)}.dmr-share-actions{display:flex;gap:8px;flex-wrap:wrap}.dmr-share-actions .dmr-primary{align-self:auto}.dmr-overview{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.dmr-overview-card{display:flex;flex-direction:column;gap:3px;padding:12px;border:1px solid var(--dsw-alias-border-l1);border-radius:12px;background:var(--dsw-alias-bg-layer-1)}.dmr-overview-card>span{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-overview-card strong{font-size:16px;letter-spacing:-.01em}.dmr-section{display:flex;flex-direction:column;gap:9px}.dmr-section-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.dmr-section-head small{font-size:11px;color:var(--dsw-alias-label-tertiary)}.dmr-text-button{border:0;background:transparent;color:var(--dmr-accent);padding:8px;min-height:36px;font-weight:600}.dmr-task-list{display:flex;flex-direction:column;gap:8px}.dmr-task{display:flex;align-items:flex-start;gap:9px;padding:10px 11px;border:1px solid var(--dsw-alias-border-l1);border-radius:10px;background:var(--dsw-alias-bg-layer-1)}.dmr-task>div{display:flex;min-width:0;flex:1;flex-direction:column;gap:2px}.dmr-task strong{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dmr-phase{flex:none;border-radius:999px;padding:3px 8px;font-size:11px;background:var(--dmr-accent-soft);color:var(--dmr-accent)}.dmr-phase.write{color:var(--dsw-alias-state-success-primary)}.dmr-phase.code{color:#f59e0b}.dmr-phase.search{color:#14b8a6}.dmr-empty{padding:18px 12px;text-align:center;border:1px dashed var(--dsw-alias-border-l2);border-radius:10px;color:var(--dsw-alias-label-secondary);font-size:12px}.dmr-note{display:flex;flex-direction:column;gap:9px;padding-top:2px}.dmr-note blockquote{margin:0;padding:10px 12px;border-left:3px solid var(--dmr-accent);border-radius:0 9px 9px 0;background:var(--dmr-accent-soft);white-space:pre-wrap;font-size:12px}.dmr-note textarea{min-height:88px;resize:vertical;line-height:1.5}.dmr-note .dmr-secondary{align-self:flex-start}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}@media (max-width:680px){.dmr{gap:14px;font-size:14px}.dmr h3{font-size:18px}.dmr-steps{grid-template-columns:1fr;gap:8px}.dmr-steps li{padding:10px}.dmr-steps small,.dmr-hero p,.dmr-status-head p,.dmr-field small,.dmr-share small,.dmr-overview-card small,.dmr-task small,.dmr-note p{font-size:12px}.dmr-network-grid{grid-template-columns:1fr;gap:10px}.dmr-field input,.dmr-field select{font-size:16px}.dmr-primary,.dmr-secondary{width:100%;font-size:14px}.dmr-share-layout{grid-template-columns:1fr;gap:12px}.dmr-qr-card{width:min(240px,100%);margin:0 auto}.dmr-qr-card img,.dmr-qr-loading{width:210px;height:210px}.dmr-share-actions{flex-direction:column}.dmr-share-actions .dmr-primary{width:100%}.dmr-overview{gap:8px}.dmr-overview-card{padding:11px}.dmr-status-head{gap:8px}.dmr-link{font-size:11px}.dmr-note textarea{font-size:16px;min-height:104px}.dmr-note .dmr-secondary{align-self:stretch}.dmr-compact .dmr-hero-icon{width:40px;height:40px;border-radius:13px}}@media (prefers-reduced-motion:reduce){.dmr-primary,.dmr-secondary,.dmr-text-button,.dmr-icon-button,.dmr-field input,.dmr-field select,.dmr-note textarea{transition:none}}
5937
+ `,
5938
+ View: MobileRelayView,
5939
+ HomeStat: MobileRelayHomeStat
5940
+ };
5941
+
3138
5942
  // src/client.jsx
3139
- var DOCK_VERSION = "0.5.0";
3140
- var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6];
5943
+ var DOCK_VERSION = "0.7.0";
5944
+ var BUILTIN_FEATURES = [feature, feature2, feature3, feature4, feature5, feature6, feature7];
3141
5945
  var PLANNED_FEATURES = [];
3142
5946
  var PLANNED_NOTES = {};
3143
5947
  var externalDefs = [];
@@ -3201,9 +6005,13 @@ var SHELL_CSS = [
3201
6005
  ".dock-badge{flex:none;border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);border-radius:999px;padding:3px 10px;font-size:12px;}",
3202
6006
  ".dock-body{border-top:1px solid var(--dsw-alias-border-l1);padding-top:8px;color:var(--dsw-alias-label-secondary);display:flex;flex-direction:column;gap:4px;}",
3203
6007
  // 侧栏入口按钮(docke2- 前缀)+ 功能坞弹出面板(dockm- 前缀,仿 dsh 设置的居中模态:遮罩 + 对话框,左导航 + 右内容)
3204
- ".docke2-btn{box-sizing:border-box;cursor:pointer;display:inline-flex;align-items:center;gap:6px;border:none;background:transparent;color:var(--dsw-alias-label-secondary);border-radius:10px;height:32px;font-family:inherit;font-size:13px;line-height:32px;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
3205
- ".docke2-btn:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
6008
+ // 侧栏入口按钮(docke2- 前缀):与 dsh 设置按钮(.VOzbGW_trigger)几何逐条对齐——
6009
+ // 宽栏同为整宽左对齐行按钮(高 42、margin 4/-2、padding 0 10px 0 8px、圆角 12),窄栏同为 36 圆钮居中,
6010
+ // 使两按钮上下成列、左右边缘完全对齐(此前右对齐/叠放都会错位)。
6011
+ ".docke2-btn{box-sizing:border-box;cursor:pointer;display:flex;align-items:center;gap:8px;border:none;background:transparent;color:var(--dsw-alias-label-primary);border-radius:12px;width:calc(100% + 4px);height:42px;margin:4px -2px;padding:0 10px 0 8px;font-family:inherit;font-size:14px;line-height:22px;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
6012
+ ".docke2-btn:hover{background:var(--dsw-alias-interactive-bg-hover);}",
3206
6013
  ".docke2-btn.docke2-on{color:var(--dsw-alias-accent,#4d9fff);background:var(--dsw-alias-accent-soft,color-mix(in srgb,var(--dsw-alias-accent,#4d9fff) 12%,transparent));}",
6014
+ ".docke2-btn.docke2-rail{width:36px;height:36px;margin:8px 0 10px;padding:0;border-radius:50%;justify-content:center;gap:0;}",
3207
6015
  ".docke2-label{white-space:nowrap;overflow:hidden;}",
3208
6016
  ".dockm-backdrop{position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;background:color-mix(in srgb,var(--dsw-alias-bg-layer-1) 55%,transparent);backdrop-filter:blur(4px);pointer-events:auto;animation:dockm-fade .15s var(--ds-ease-in-out);}",
3209
6017
  "@keyframes dockm-fade{from{opacity:0}to{opacity:1}}",
@@ -3263,13 +6071,24 @@ var SHELL_CSS = [
3263
6071
  ".dockm-foot-sw{margin-left:auto;flex:none;display:inline-flex;align-items:center;gap:8px;}",
3264
6072
  ".dockm-foot-swlabel{font-size:11px;color:var(--dsw-alias-label-tertiary);}",
3265
6073
  ".dockm-foot-swlabel.on{color:var(--dsw-alias-state-success-primary);}",
6074
+ // 窄屏:功能坞是一级工作台而不是被压扁的桌面弹窗。全屏承接安全区,导航改横向,
6075
+ // 禁用桌面拖拽/缩放,所有导航和关闭动作保持至少 44px 的可点击面积。
6076
+ "@media (max-width:680px){.dockm-backdrop{align-items:stretch;justify-content:stretch;background:var(--dsw-alias-bg-layer-2);backdrop-filter:none}.dockm-dialog,.dockm-dialog.dockm-max{position:fixed!important;left:0!important;top:0!important;right:auto!important;bottom:auto!important;width:100dvw!important;height:100dvh!important;min-height:100dvh;border:0;border-radius:0;box-shadow:none}.dockm-dialog.dockm-min .dockm-body{display:flex}.dockm-head{min-height:60px;box-sizing:border-box;padding:calc(env(safe-area-inset-top) + 8px) 12px 8px;cursor:default;touch-action:manipulation}.dockm-sub,.dockm-win,.dockm-resize{display:none}.dockm-title{font-size:16px}.dockm-close{width:44px;height:44px;font-size:17px}.dockm-body{flex-direction:column;min-height:0}.dockm-nav{box-sizing:border-box;width:auto;max-width:100%;min-height:56px;flex-direction:row;gap:6px;padding:6px 10px;overflow-x:auto;overflow-y:hidden;border-right:0;border-bottom:1px solid var(--dsw-alias-border-l1);scrollbar-width:none;overscroll-behavior-x:contain}.dockm-nav::-webkit-scrollbar{display:none}.dockm-nav-item{flex:none;min-height:44px;padding:0 12px;font-size:13px;touch-action:manipulation}.dockm-nav-item .dockm-badge{display:none}.dockm-content{padding:16px max(16px,env(safe-area-inset-right)) calc(20px + env(safe-area-inset-bottom)) max(16px,env(safe-area-inset-left));gap:14px;overscroll-behavior:contain}.dockm-content-head{gap:5px}.dockm-name{font-size:16px}.dockm-desc{font-size:13px;line-height:1.55}.dockm-foot{padding-top:12px;font-size:11px}.dockm-foot-sw{width:100%;margin-left:0;justify-content:space-between}.dock-sw{width:44px;height:26px}.dock-sw::after{top:3px;left:3px;width:18px;height:18px}.dock-sw.on::after{transform:translateX(18px)}.dockh-grid{grid-template-columns:1fr;gap:10px}.dockh-card{padding:12px}.dockh-desc{font-size:13px}.dockh-go{font-size:12px}}",
6077
+ "@media (prefers-reduced-motion:reduce){.dockm-backdrop,.dockm-dialog{animation:none}.dockm-nav-item,.dockm-close,.dockm-win,.dock-sw{transition:none}}",
3266
6078
  ".dockh-desc{color:var(--dsw-alias-label-secondary);font-size:12px;line-height:1.5;}",
3267
6079
  ".dockh-stat{color:var(--dsw-alias-label-tertiary);font-size:12px;border-top:1px solid var(--dsw-alias-border-l1);padding-top:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}",
3268
6080
  ".dockh-foot{display:flex;align-items:center;gap:8px;}",
3269
6081
  ".dockh-go{color:var(--dsw-alias-label-tertiary);font-size:11px;}",
3270
6082
  // 会话输入区工具行 chips(dockchip- 前缀):余额/用量随身小控件,挂在模型选择器左侧
3271
- ".dockchip-row{display:inline-flex;align-items:center;gap:4px;min-width:0;}",
3272
- ".dockchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:2px 8px;font-family:inherit;font-size:11px;line-height:18px;white-space:nowrap;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
6083
+ // 溢出兼容(两层防护,缺一不可):
6084
+ // 1) 宽度上限:宿主 .row 是 flex-wrap:wrap 且换行优先于收缩,chips 一长 tools 整行变宽,
6085
+ // 右侧模型选择器/发送键被挤到第二行(左右错位)。宿主 .row 带 container-type:inline-size,
6086
+ // 用容器单位 cqw 让上限随输入卡宽度自适应(窄卡少占、宽卡多占);不支持 cqw 的老内核退回固定 280px。
6087
+ // 2) 截断:超限部分用省略号截断(完整数值在 title 悬浮提示里),防 chips 凸出输入卡圆角(悬空)。
6088
+ ".dockchip-row{display:inline-flex;align-items:center;gap:4px;min-width:0;flex:0 1 auto;overflow:hidden;max-width:280px;}",
6089
+ "@supports (width:1cqw){.dockchip-row{max-width:min(280px,36cqw);}}",
6090
+ ".dockchip{display:inline-flex;align-items:center;gap:5px;cursor:pointer;border:none;background:transparent;color:var(--dsw-alias-label-tertiary);border-radius:8px;padding:2px 8px;font-family:inherit;font-size:11px;line-height:18px;white-space:nowrap;min-width:0;overflow:hidden;transition:background .15s var(--ds-ease-in-out),color .15s var(--ds-ease-in-out);}",
6091
+ ".dockchip > span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;min-width:0;}",
3273
6092
  ".dockchip:hover{background:var(--dsw-alias-interactive-bg-hover);color:var(--dsw-alias-label-primary);}",
3274
6093
  ".dockchip .dockchip-dot{width:6px;height:6px;border-radius:50%;flex:none;}",
3275
6094
  ".dockchip.err{color:var(--dsw-alias-state-error-primary);}"
@@ -3299,8 +6118,8 @@ function ensureCss() {
3299
6118
  }
3300
6119
  }
3301
6120
  function useExternalVersion() {
3302
- const [, bump] = import_react8.default.useReducer((n) => n + 1, 0);
3303
- import_react8.default.useEffect(() => {
6121
+ const [, bump] = import_react10.default.useReducer((n) => n + 1, 0);
6122
+ import_react10.default.useEffect(() => {
3304
6123
  externalListeners.add(bump);
3305
6124
  return () => {
3306
6125
  externalListeners.delete(bump);
@@ -3308,42 +6127,42 @@ function useExternalVersion() {
3308
6127
  }, []);
3309
6128
  }
3310
6129
  var lastGeom = { x: null, y: null, w: null, h: null };
3311
- function DockIcon() {
3312
- return import_react8.default.createElement(
6130
+ function DockIcon(props) {
6131
+ const size = props && props.size || 16;
6132
+ return import_react10.default.createElement(
3313
6133
  "svg",
3314
- { width: 16, height: 16, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
3315
- import_react8.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
3316
- import_react8.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
3317
- import_react8.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
3318
- import_react8.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
6134
+ { width: size, height: size, viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: 1.3, "aria-hidden": true },
6135
+ import_react10.default.createElement("rect", { x: 2.5, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
6136
+ import_react10.default.createElement("rect", { x: 9, y: 2.5, width: 4.4, height: 4.4, rx: 1.2 }),
6137
+ import_react10.default.createElement("rect", { x: 2.5, y: 9, width: 4.4, height: 4.4, rx: 1.2 }),
6138
+ import_react10.default.createElement("rect", { x: 9, y: 9, width: 4.4, height: 4.4, rx: 1.2 })
3319
6139
  );
3320
6140
  }
3321
6141
  function DockEntry(props) {
3322
6142
  const wide = !!props.wide;
3323
- const [open, setOpen] = import_react8.default.useState(panelNav.open);
3324
- import_react8.default.useEffect(() => subscribePanel(() => setOpen(panelNav.open)), []);
3325
- return import_react8.default.createElement("button", {
6143
+ const [open, setOpen] = import_react10.default.useState(panelNav.open);
6144
+ import_react10.default.useEffect(() => subscribePanel(() => setOpen(panelNav.open)), []);
6145
+ return import_react10.default.createElement("button", {
3326
6146
  type: "button",
3327
- className: "docke2-btn" + (open ? " docke2-on" : ""),
3328
- style: wide ? { marginLeft: "auto", transform: "translateY(46px)", zIndex: 1, height: 42, lineHeight: "42px", padding: "0 12px" } : { transform: "translateY(44px)", zIndex: 1, width: 36, height: 36, justifyContent: "center", padding: 0 },
6147
+ className: "docke2-btn" + (open ? " docke2-on" : "") + (wide ? "" : " docke2-rail"),
3329
6148
  title: "\u529F\u80FD\u575E",
3330
6149
  "aria-label": "\u529F\u80FD\u575E",
3331
6150
  "aria-expanded": open,
3332
6151
  onClick: () => setPanelOpen(!open)
3333
- }, import_react8.default.createElement(DockIcon, null), wide ? import_react8.default.createElement("span", { className: "docke2-label" }, "\u529F\u80FD\u575E") : null);
6152
+ }, import_react10.default.createElement(DockIcon, { size: wide ? 16 : 18 }), wide ? import_react10.default.createElement("span", { className: "docke2-label" }, "\u529F\u80FD\u575E") : null);
3334
6153
  }
3335
6154
  function DockModal() {
3336
- const [nav, setNav] = import_react8.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
3337
- import_react8.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
6155
+ const [nav, setNav] = import_react10.default.useState({ open: panelNav.open, active: panelNav.active, params: panelNav.params });
6156
+ import_react10.default.useEffect(() => subscribePanel(() => setNav({ open: panelNav.open, active: panelNav.active, params: panelNav.params })), []);
3338
6157
  const open = nav.open || typeof document === "undefined";
3339
6158
  const active = nav.active;
3340
6159
  const setActive = navigatePanel;
3341
6160
  const navParams = nav.params;
3342
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
6161
+ const [, force] = import_react10.default.useReducer((n) => n + 1, 0);
3343
6162
  useExternalVersion();
3344
- const [win, setWin] = import_react8.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
3345
- const dlgRef = import_react8.default.useRef(null);
3346
- import_react8.default.useEffect(() => {
6163
+ const [win, setWin] = import_react10.default.useState(() => ({ mode: "normal", x: null, y: null, w: null, h: null }));
6164
+ const dlgRef = import_react10.default.useRef(null);
6165
+ import_react10.default.useEffect(() => {
3347
6166
  if (lastGeom.w) setWin({ mode: "normal", x: lastGeom.x, y: lastGeom.y, w: lastGeom.w, h: lastGeom.h });
3348
6167
  }, []);
3349
6168
  function beginDrag(e, type) {
@@ -3381,13 +6200,13 @@ function DockModal() {
3381
6200
  const mod = isHome ? null : MODULES.find((m) => m.id === active) || MODULES[0];
3382
6201
  const st = mod ? stateOf(mod.id) : null;
3383
6202
  const View = mod ? mod.View : null;
3384
- const viewNode = mod && View ? import_react8.default.createElement(
6203
+ const viewNode = mod && View ? import_react10.default.createElement(
3385
6204
  "div",
3386
6205
  { className: "dockm-view" },
3387
- import_react8.default.createElement(
3388
- mod.external ? FeatureBoundary : import_react8.default.Fragment,
6206
+ import_react10.default.createElement(
6207
+ mod.external ? FeatureBoundary : import_react10.default.Fragment,
3389
6208
  null,
3390
- import_react8.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
6209
+ import_react10.default.createElement(View, { ctx: ctxRef.current, feature: mod, params: navParams })
3391
6210
  )
3392
6211
  ) : null;
3393
6212
  const enabledCount = MODULES.filter((m) => {
@@ -3401,10 +6220,10 @@ function DockModal() {
3401
6220
  width: win.w != null ? win.w : void 0,
3402
6221
  height: win.mode === "min" ? "auto" : win.h != null ? win.h : void 0
3403
6222
  } : null;
3404
- return import_react8.default.createElement(
6223
+ return import_react10.default.createElement(
3405
6224
  "div",
3406
6225
  { className: "dockm-backdrop", onClick: () => setPanelOpen(false) },
3407
- import_react8.default.createElement(
6226
+ import_react10.default.createElement(
3408
6227
  "div",
3409
6228
  {
3410
6229
  className: "dockm-dialog" + (win.mode === "max" ? " dockm-max" : "") + (win.mode === "min" ? " dockm-min" : ""),
@@ -3412,41 +6231,41 @@ function DockModal() {
3412
6231
  ref: dlgRef,
3413
6232
  onClick: (e) => e.stopPropagation()
3414
6233
  },
3415
- import_react8.default.createElement(
6234
+ import_react10.default.createElement(
3416
6235
  "div",
3417
6236
  {
3418
6237
  className: "dockm-head",
3419
6238
  onPointerDown: (e) => beginDrag(e, "move"),
3420
6239
  onDoubleClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
3421
6240
  },
3422
- import_react8.default.createElement(DockIcon, null),
3423
- import_react8.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
3424
- import_react8.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
3425
- import_react8.default.createElement(
6241
+ import_react10.default.createElement(DockIcon, null),
6242
+ import_react10.default.createElement("span", { className: "dockm-title" }, "\u529F\u80FD\u575E"),
6243
+ import_react10.default.createElement("span", { className: "dockm-sub" }, "dsh-dock \xB7 \u4E5F\u53EF\u5728 \u8BBE\u7F6E \u2192 \u529F\u80FD\u575E \u6253\u5F00\u7BA1\u7406\u9875"),
6244
+ import_react10.default.createElement(
3426
6245
  "span",
3427
6246
  { className: "dockm-ctrls" },
3428
- import_react8.default.createElement("button", {
6247
+ import_react10.default.createElement("button", {
3429
6248
  type: "button",
3430
6249
  className: "dockm-win",
3431
6250
  title: win.mode === "min" ? "\u8FD8\u539F" : "\u6700\u5C0F\u5316",
3432
6251
  onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "min" ? "normal" : "min" }))
3433
6252
  }, "\u2581"),
3434
- import_react8.default.createElement("button", {
6253
+ import_react10.default.createElement("button", {
3435
6254
  type: "button",
3436
6255
  className: "dockm-win",
3437
6256
  title: win.mode === "max" ? "\u8FD8\u539F" : "\u6700\u5927\u5316",
3438
6257
  onClick: () => setWin((s) => Object.assign({}, s, { mode: s.mode === "max" ? "normal" : "max" }))
3439
6258
  }, win.mode === "max" ? "\u2750" : "\u25A2"),
3440
- import_react8.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
6259
+ import_react10.default.createElement("button", { type: "button", className: "dockm-close", "aria-label": "\u5173\u95ED", title: "\u5173\u95ED", onClick: () => setPanelOpen(false) }, "\u2715")
3441
6260
  )
3442
6261
  ),
3443
- import_react8.default.createElement(
6262
+ import_react10.default.createElement(
3444
6263
  "div",
3445
6264
  { className: "dockm-body" },
3446
- import_react8.default.createElement(
6265
+ import_react10.default.createElement(
3447
6266
  "nav",
3448
6267
  { className: "dockm-nav", "aria-label": "\u529F\u80FD\u6A21\u5757" },
3449
- import_react8.default.createElement(
6268
+ import_react10.default.createElement(
3450
6269
  "button",
3451
6270
  {
3452
6271
  type: "button",
@@ -3454,10 +6273,10 @@ function DockModal() {
3454
6273
  className: "dockm-nav-item" + (isHome ? " on" : ""),
3455
6274
  onClick: () => setActive("home")
3456
6275
  },
3457
- import_react8.default.createElement("span", { className: "dockm-navhome" }, import_react8.default.createElement(DockIcon, null)),
3458
- import_react8.default.createElement("span", null, "\u9996\u9875")
6276
+ import_react10.default.createElement("span", { className: "dockm-navhome" }, import_react10.default.createElement(DockIcon, null)),
6277
+ import_react10.default.createElement("span", null, "\u9996\u9875")
3459
6278
  ),
3460
- MODULES.map((m) => import_react8.default.createElement(
6279
+ MODULES.map((m) => import_react10.default.createElement(
3461
6280
  "button",
3462
6281
  {
3463
6282
  type: "button",
@@ -3465,42 +6284,42 @@ function DockModal() {
3465
6284
  className: "dockm-nav-item" + (m.id === active ? " on" : ""),
3466
6285
  onClick: () => setActive(m.id)
3467
6286
  },
3468
- import_react8.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
3469
- import_react8.default.createElement("span", null, m.name),
3470
- m.planned ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
3471
- m.external ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
6287
+ import_react10.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
6288
+ import_react10.default.createElement("span", null, m.name),
6289
+ m.planned ? import_react10.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
6290
+ m.external ? import_react10.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8") : null
3472
6291
  ))
3473
6292
  ),
3474
- import_react8.default.createElement(
6293
+ import_react10.default.createElement(
3475
6294
  "div",
3476
6295
  { className: "dockm-content" },
3477
- import_react8.default.createElement(
6296
+ import_react10.default.createElement(
3478
6297
  "div",
3479
6298
  { className: "dockm-content-head" },
3480
- import_react8.default.createElement(
6299
+ import_react10.default.createElement(
3481
6300
  "div",
3482
6301
  { className: "dockm-name" },
3483
- isHome ? import_react8.default.createElement("span", { className: "dockm-navhome" }, import_react8.default.createElement(DockIcon, null)) : import_react8.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
6302
+ isHome ? import_react10.default.createElement("span", { className: "dockm-navhome" }, import_react10.default.createElement(DockIcon, null)) : import_react10.default.createElement("span", { className: "dockm-dot", style: { background: mod.accent } }),
3484
6303
  isHome ? "\u9996\u9875" : mod.name,
3485
- !isHome && mod.planned ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
3486
- !isHome && mod.external ? import_react8.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
6304
+ !isHome && mod.planned ? import_react10.default.createElement("span", { className: "dockm-badge" }, "\u89C4\u5212\u4E2D") : null,
6305
+ !isHome && mod.external ? import_react10.default.createElement("span", { className: "dockm-badge" }, "\u5916\u90E8\u5305" + (mod.package ? " \xB7 " + mod.package : "")) : null
3487
6306
  ),
3488
- import_react8.default.createElement(
6307
+ import_react10.default.createElement(
3489
6308
  "div",
3490
6309
  { className: "dockm-desc" },
3491
6310
  isHome ? "\u6240\u6709\u5B50\u529F\u80FD\u603B\u63FD\uFF1A\u8FD0\u884C\u72B6\u6001\u3001\u6982\u8981\u4E0E\u5FEB\u6377\u5F00\u5173\uFF0C\u70B9\u51FB\u5361\u7247\u8FDB\u5165\u5BF9\u5E94\u529F\u80FD\u9875\u3002" : mod.description
3492
6311
  )
3493
6312
  ),
3494
- isHome ? import_react8.default.createElement("div", { className: "dockm-view" }, import_react8.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react8.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react8.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react8.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
3495
- import_react8.default.createElement(
6313
+ isHome ? import_react10.default.createElement("div", { className: "dockm-view" }, import_react10.default.createElement(HomeView, { ctx: ctxRef.current, onOpen: setActive, onToggle: force })) : mod.planned ? import_react10.default.createElement("div", { className: "dockm-note" }, PLANNED_NOTES[mod.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st && st.enabled && viewNode ? viewNode : st && st.error ? import_react10.default.createElement("div", { className: "dockm-note dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : import_react10.default.createElement("div", { className: "dockm-note" }, "\u8BE5\u529F\u80FD\u5F53\u524D\u4E3A\u505C\u7528\u72B6\u6001\uFF08\u5F00\u5173\u5DF2\u6301\u4E45\u5316\uFF0C\u91CD\u542F\u540E\u4FDD\u6301\uFF09"),
6314
+ import_react10.default.createElement(
3496
6315
  "div",
3497
6316
  { className: "dockm-foot" },
3498
- import_react8.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
3499
- !isHome && mod && !mod.planned && st ? import_react8.default.createElement(
6317
+ import_react10.default.createElement("span", null, isHome ? "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u5171 " + MODULES.length + " \u4E2A\u529F\u80FD\u6A21\u5757\uFF0C" + enabledCount + " \u4E2A\u5DF2\u542F\u7528" : "\u529F\u80FD\u575E v" + DOCK_VERSION + " \xB7 \u65B0\u529F\u80FD\u6309\u8DEF\u7EBF\u56FE\u8FFD\u52A0"),
6318
+ !isHome && mod && !mod.planned && st ? import_react10.default.createElement(
3500
6319
  "span",
3501
6320
  { className: "dockm-foot-sw" },
3502
- import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
3503
- import_react8.default.createElement("button", {
6321
+ import_react10.default.createElement("span", { className: "dockm-foot-swlabel" + (st.enabled ? " on" : "") }, st.enabled ? "\u5DF2\u542F\u7528" : "\u5DF2\u505C\u7528"),
6322
+ import_react10.default.createElement("button", {
3504
6323
  type: "button",
3505
6324
  className: "dock-sw" + (st.enabled ? " on" : ""),
3506
6325
  role: "switch",
@@ -3513,11 +6332,11 @@ function DockModal() {
3513
6332
  }
3514
6333
  })
3515
6334
  ) : null,
3516
- !isHome && mod && typeof mod.Chip === "function" ? import_react8.default.createElement(
6335
+ !isHome && mod && typeof mod.Chip === "function" ? import_react10.default.createElement(
3517
6336
  "span",
3518
6337
  { className: "dockm-foot-sw" },
3519
- import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
3520
- import_react8.default.createElement("button", {
6338
+ import_react10.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(mod.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
6339
+ import_react10.default.createElement("button", {
3521
6340
  type: "button",
3522
6341
  className: "dock-sw" + (chipShown(mod.id) ? " on" : ""),
3523
6342
  role: "switch",
@@ -3533,30 +6352,30 @@ function DockModal() {
3533
6352
  )
3534
6353
  )
3535
6354
  ),
3536
- win.mode === "normal" ? import_react8.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
6355
+ win.mode === "normal" ? import_react10.default.createElement("div", { className: "dockm-resize", onPointerDown: (e) => beginDrag(e, "size") }) : null
3537
6356
  )
3538
6357
  );
3539
6358
  }
3540
6359
  function HomeView(props) {
3541
6360
  const ctx = props && props.ctx;
3542
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
6361
+ const [, force] = import_react10.default.useReducer((n) => n + 1, 0);
3543
6362
  useExternalVersion();
3544
6363
  const open = (id) => {
3545
6364
  if (props && typeof props.onOpen === "function") props.onOpen(id);
3546
6365
  };
3547
- return import_react8.default.createElement(
6366
+ return import_react10.default.createElement(
3548
6367
  "div",
3549
6368
  { className: "dockh-grid" },
3550
6369
  allModules().map((m) => {
3551
6370
  const st = stateOf(m.id);
3552
6371
  const enabled = !!(st && st.enabled);
3553
6372
  const Stat = m.HomeStat;
3554
- const statNode = m.planned ? import_react8.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react8.default.createElement(
3555
- m.external ? FeatureBoundary : import_react8.default.Fragment,
6373
+ const statNode = m.planned ? import_react10.default.createElement("span", null, PLANNED_NOTES[m.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : enabled && Stat ? import_react10.default.createElement(
6374
+ m.external ? FeatureBoundary : import_react10.default.Fragment,
3556
6375
  null,
3557
- import_react8.default.createElement(Stat, { ctx })
3558
- ) : import_react8.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
3559
- return import_react8.default.createElement(
6376
+ import_react10.default.createElement(Stat, { ctx })
6377
+ ) : import_react10.default.createElement("span", null, "\u5DF2\u505C\u7528\uFF0C\u542F\u7528\u540E\u5728\u6B64\u5C55\u793A\u8FD0\u884C\u6982\u8981");
6378
+ return import_react10.default.createElement(
3560
6379
  "div",
3561
6380
  {
3562
6381
  key: m.id,
@@ -3571,21 +6390,21 @@ function HomeView(props) {
3571
6390
  }
3572
6391
  }
3573
6392
  },
3574
- import_react8.default.createElement(
6393
+ import_react10.default.createElement(
3575
6394
  "div",
3576
6395
  { className: "dockh-head" },
3577
- import_react8.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
3578
- import_react8.default.createElement("span", { className: "dockh-name" }, m.name),
3579
- m.external ? import_react8.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
6396
+ import_react10.default.createElement("span", { className: "dockm-dot", style: { background: m.accent } }),
6397
+ import_react10.default.createElement("span", { className: "dockh-name" }, m.name),
6398
+ m.external ? import_react10.default.createElement("span", { className: "dockh-badge", title: m.package || void 0 }, "\u5916\u90E8") : null,
3580
6399
  // 状态标识:圆点 + 文字(纯展示,与开关视觉区分)
3581
- import_react8.default.createElement(
6400
+ import_react10.default.createElement(
3582
6401
  "span",
3583
6402
  { className: "dockh-status" + (m.planned ? " plan" : enabled ? "" : " off") },
3584
- import_react8.default.createElement("span", { className: "dockh-sdot" }),
3585
- import_react8.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
6403
+ import_react10.default.createElement("span", { className: "dockh-sdot" }),
6404
+ import_react10.default.createElement("span", null, m.planned ? "\u89C4\u5212\u4E2D" : enabled ? "\u8FD0\u884C\u4E2D" : "\u5DF2\u505C\u7528")
3586
6405
  ),
3587
6406
  // 启停开关(规划中的功能不显示)
3588
- m.planned ? null : import_react8.default.createElement("button", {
6407
+ m.planned ? null : import_react10.default.createElement("button", {
3589
6408
  type: "button",
3590
6409
  className: "dock-sw" + (enabled ? " on" : ""),
3591
6410
  role: "switch",
@@ -3600,12 +6419,12 @@ function HomeView(props) {
3600
6419
  }
3601
6420
  })
3602
6421
  ),
3603
- import_react8.default.createElement("div", { className: "dockh-desc" }, m.description),
3604
- import_react8.default.createElement("div", { className: "dockh-stat" }, statNode),
3605
- import_react8.default.createElement(
6422
+ import_react10.default.createElement("div", { className: "dockh-desc" }, m.description),
6423
+ import_react10.default.createElement("div", { className: "dockh-stat" }, statNode),
6424
+ import_react10.default.createElement(
3606
6425
  "div",
3607
6426
  { className: "dockh-foot" },
3608
- import_react8.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
6427
+ import_react10.default.createElement("span", { className: "dockh-go" }, "\u67E5\u770B\u8BE6\u60C5 \u2192")
3609
6428
  )
3610
6429
  );
3611
6430
  })
@@ -3613,16 +6432,16 @@ function HomeView(props) {
3613
6432
  }
3614
6433
  function DockPanel() {
3615
6434
  const ctx = ctxRef.current;
3616
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
6435
+ const [, force] = import_react10.default.useReducer((n) => n + 1, 0);
3617
6436
  useExternalVersion();
3618
6437
  const toggle = (id) => {
3619
6438
  toggleFeature(id);
3620
6439
  force();
3621
6440
  };
3622
- return import_react8.default.createElement(
6441
+ return import_react10.default.createElement(
3623
6442
  "div",
3624
6443
  { className: "dock-root" },
3625
- import_react8.default.createElement(
6444
+ import_react10.default.createElement(
3626
6445
  "div",
3627
6446
  { className: "dock-intro" },
3628
6447
  "\u529F\u80FD\u575E\uFF08dsh-dock\uFF09\xB7 \u6240\u6709\u5C0F\u529F\u80FD\u96C6\u4E2D\u5728\u8FD9\u4E00\u4E2A\u9762\u677F\u91CC\u7BA1\u7406\u3002v0.4.0 \u8D77\u6BCF\u4E2A\u529F\u80FD\u662F\u72EC\u7ACB\u6A21\u5757\uFF08features/<id>/\uFF09\uFF0C",
@@ -3631,25 +6450,25 @@ function DockPanel() {
3631
6450
  allModules().map((f) => {
3632
6451
  const st = stateOf(f.id);
3633
6452
  const View = f.View;
3634
- const viewNode = !f.planned && st.enabled && View ? import_react8.default.createElement(
6453
+ const viewNode = !f.planned && st.enabled && View ? import_react10.default.createElement(
3635
6454
  "div",
3636
6455
  { className: "dock-body" },
3637
- import_react8.default.createElement(
3638
- f.external ? FeatureBoundary : import_react8.default.Fragment,
6456
+ import_react10.default.createElement(
6457
+ f.external ? FeatureBoundary : import_react10.default.Fragment,
3639
6458
  null,
3640
- import_react8.default.createElement(View, { ctx, feature: f })
6459
+ import_react10.default.createElement(View, { ctx, feature: f })
3641
6460
  )
3642
6461
  ) : null;
3643
- return import_react8.default.createElement(
6462
+ return import_react10.default.createElement(
3644
6463
  "div",
3645
6464
  { className: "dock-card", key: f.id },
3646
- import_react8.default.createElement(
6465
+ import_react10.default.createElement(
3647
6466
  "div",
3648
6467
  { className: "dock-card-head" },
3649
- import_react8.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
3650
- import_react8.default.createElement("span", { className: "dock-name" }, f.name),
3651
- import_react8.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
3652
- f.planned ? import_react8.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react8.default.createElement("button", {
6468
+ import_react10.default.createElement("span", { className: "dock-dot" + (st.error ? " err" : st.enabled ? " on" : "") }),
6469
+ import_react10.default.createElement("span", { className: "dock-name" }, f.name),
6470
+ import_react10.default.createElement("span", { className: "dock-desc" }, f.description + (f.external ? "\uFF08\u6765\u81EA\u5916\u90E8\u5305" + (f.package ? " " + f.package : "") + "\uFF09" : "")),
6471
+ f.planned ? import_react10.default.createElement("span", { className: "dock-badge" }, "\u89C4\u5212\u4E2D") : import_react10.default.createElement("button", {
3653
6472
  type: "button",
3654
6473
  className: "dock-sw" + (st.enabled ? " on" : ""),
3655
6474
  role: "switch",
@@ -3658,11 +6477,11 @@ function DockPanel() {
3658
6477
  title: st.enabled ? "\u505C\u7528\u300C" + f.name + "\u300D" : "\u542F\u7528\u300C" + f.name + "\u300D",
3659
6478
  onClick: () => toggle(f.id)
3660
6479
  }),
3661
- !f.planned && typeof f.Chip === "function" ? import_react8.default.createElement(
6480
+ !f.planned && typeof f.Chip === "function" ? import_react10.default.createElement(
3662
6481
  "span",
3663
6482
  { className: "dockm-foot-sw" },
3664
- import_react8.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
3665
- import_react8.default.createElement("button", {
6483
+ import_react10.default.createElement("span", { className: "dockm-foot-swlabel" + (chipShown(f.id) ? " on" : "") }, "\u4F1A\u8BDD\u9875\u5C0F\u63A7\u4EF6"),
6484
+ import_react10.default.createElement("button", {
3666
6485
  type: "button",
3667
6486
  className: "dock-sw" + (chipShown(f.id) ? " on" : ""),
3668
6487
  role: "switch",
@@ -3676,19 +6495,19 @@ function DockPanel() {
3676
6495
  })
3677
6496
  ) : null
3678
6497
  ),
3679
- f.planned ? import_react8.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react8.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
6498
+ f.planned ? import_react10.default.createElement("div", { className: "dock-body" }, PLANNED_NOTES[f.id] || "\u5F85\u63A5\u5165\uFF1A\u89C1 README \u8DEF\u7EBF\u56FE") : st.error ? import_react10.default.createElement("div", { className: "dock-body dockm-err" }, "\u529F\u80FD\u51FA\u9519\uFF1A" + st.error) : null,
3680
6499
  viewNode
3681
6500
  );
3682
6501
  })
3683
6502
  );
3684
6503
  }
3685
6504
  function DockChips(props) {
3686
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
3687
- import_react8.default.useEffect(() => subscribeFeatureState(() => force()), []);
6505
+ const [, force] = import_react10.default.useReducer((n) => n + 1, 0);
6506
+ import_react10.default.useEffect(() => subscribeFeatureState(() => force()), []);
3688
6507
  const items = [];
3689
6508
  for (const f of allModules()) {
3690
6509
  if (f.planned || !stateOf(f.id).enabled || !chipShown(f.id) || typeof f.Chip !== "function") continue;
3691
- items.push(import_react8.default.createElement(f.Chip, {
6510
+ items.push(import_react10.default.createElement(f.Chip, {
3692
6511
  key: f.id,
3693
6512
  ctx: props.ctx,
3694
6513
  feature: f,
@@ -3698,23 +6517,23 @@ function DockChips(props) {
3698
6517
  }));
3699
6518
  }
3700
6519
  if (items.length === 0) return null;
3701
- return import_react8.default.createElement("div", { className: "dockchip-row" }, items);
6520
+ return import_react10.default.createElement("div", { className: "dockchip-row" }, items);
3702
6521
  }
3703
6522
  function FeatureOverlays() {
3704
- const [, force] = import_react8.default.useReducer((n) => n + 1, 0);
6523
+ const [, force] = import_react10.default.useReducer((n) => n + 1, 0);
3705
6524
  useExternalVersion();
3706
- import_react8.default.useEffect(() => subscribeFeatureState(() => force()), []);
6525
+ import_react10.default.useEffect(() => subscribeFeatureState(() => force()), []);
3707
6526
  const items = [];
3708
6527
  for (const f of allModules()) {
3709
6528
  if (f.planned || !stateOf(f.id).enabled || typeof f.Overlay !== "function") continue;
3710
- items.push(import_react8.default.createElement(
6529
+ items.push(import_react10.default.createElement(
3711
6530
  FeatureBoundary,
3712
6531
  { key: f.id },
3713
- import_react8.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
6532
+ import_react10.default.createElement(f.Overlay, { ctx: ctxRef.current, feature: f })
3714
6533
  ));
3715
6534
  }
3716
6535
  if (items.length === 0) return null;
3717
- return import_react8.default.createElement(import_react8.default.Fragment, null, items);
6536
+ return import_react10.default.createElement(import_react10.default.Fragment, null, items);
3718
6537
  }
3719
6538
  var ctxRef = { current: null };
3720
6539
  function apply(ctx) {
@@ -3725,24 +6544,38 @@ function apply(ctx) {
3725
6544
  if (slots === void 0) return;
3726
6545
  slots.inject("sidebar.footer.action", () => slots.register(
3727
6546
  { name: "sidebar.footer.action", id: "dsh-dock", order: 1, label: "\u529F\u80FD\u575E" },
3728
- (props) => import_react8.default.createElement(DockEntry, props)
6547
+ (props) => import_react10.default.createElement(DockEntry, props)
3729
6548
  ));
3730
6549
  slots.inject("shell.overlay", () => slots.register(
3731
6550
  { name: "shell.overlay", id: "dsh-dock-panel", order: 21, label: "\u529F\u80FD\u575E\u9762\u677F" },
3732
- () => import_react8.default.createElement(DockModal, null)
6551
+ () => import_react10.default.createElement(DockModal, null)
3733
6552
  ));
3734
6553
  slots.inject("shell.overlay", () => slots.register(
3735
6554
  { name: "shell.overlay", id: "dsh-dock-feature-overlays", order: 22, label: "\u529F\u80FD\u575E\u5168\u5C40\u6D6E\u5C42" },
3736
- () => import_react8.default.createElement(FeatureOverlays, null)
6555
+ () => import_react10.default.createElement(FeatureOverlays, null)
3737
6556
  ));
3738
6557
  slots.inject("settings.section", () => slots.register(
3739
6558
  { name: "settings.section", id: "dsh-dock", order: 90, label: "\u529F\u80FD\u575E" },
3740
- () => import_react8.default.createElement(DockPanel, null)
6559
+ () => import_react10.default.createElement(DockPanel, null)
3741
6560
  ));
3742
6561
  slots.inject("conversation.input.left", () => slots.register(
3743
6562
  { name: "conversation.input.left", id: "dsh-dock-chips", order: 10, label: "\u529F\u80FD\u575E" },
3744
- (zone) => import_react8.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
6563
+ (zone) => import_react10.default.createElement(DockChips, Object.assign({}, zone, { ctx: ctxRef.current }))
3745
6564
  ));
6565
+ try {
6566
+ if (typeof window !== "undefined") {
6567
+ const match = window.location.hash.match(/(?:^#|&)dsh-mobile-relay=([^&]+)/);
6568
+ if (match) {
6569
+ const launch = decodeURIComponent(match[1]);
6570
+ if (/^[A-Za-z0-9_-]+\.[A-F0-9]{10}$/i.test(launch)) {
6571
+ sessionStorage.setItem("dsh-dock/mobile-relay/launch/v1", launch);
6572
+ window.history.replaceState(null, "", window.location.pathname + window.location.search);
6573
+ setTimeout(() => openPanel("mobile-relay"), 0);
6574
+ }
6575
+ }
6576
+ }
6577
+ } catch {
6578
+ }
3746
6579
  }
3747
6580
  var inject = ["timer"];
3748
6581