@leon___/dsh-client-liang-intensity-skin 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -7
- package/lib/client.js +357 -275
- package/lib/client.js.map +4 -4
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -56,20 +56,21 @@ dsh plugin --profile web add 'github:kingOfSoySauce/dsh-liang-skin'
|
|
|
56
56
|
|
|
57
57
|
## 外观开关
|
|
58
58
|
|
|
59
|
-
入口位于 `设置 → 通用设置 →
|
|
59
|
+
入口位于 `设置 → 通用设置 → 外观`:
|
|
60
60
|
|
|
61
61
|
- `滑动变祖`:显示滑块并启用人物、背景和自适应配色。
|
|
62
|
-
-
|
|
62
|
+
- 点击原生的 `浅色`、`深色` 或 `跟随系统`:移除背景层、皮肤变量和滑块,切回对应的 Harness 原生外观。
|
|
63
|
+
- `滑动变祖绑定思考等级`:使用 DSH 原生开关,关闭后滑块只切换人物和配色,不修改模型的推理等级;仅点击开关切换,标题文字不触发切换。
|
|
63
64
|
|
|
64
65
|
皮肤保持启用时,人物与背景配色由滑块档位决定;切换 DSH 原生深浅主题不会改变当前档位的背景。
|
|
65
66
|
|
|
66
|
-
|
|
67
|
+
绑定开关保存在当前浏览器本地。切回原生外观只对本次客户端激活有效;刷新页面或重新激活插件后默认开启皮肤。外观选择的跨刷新记忆暂未实现。绑定开启时,滑块会提交模型的推理档位;关闭绑定后只改变外观。
|
|
67
68
|
|
|
68
69
|
<a id="cli-install"></a>
|
|
69
70
|
|
|
70
71
|
## 命令安装
|
|
71
72
|
|
|
72
|
-
需要先安装 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
73
|
+
需要先安装 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness);本轮已在 DSH Web `0.1.7-rc.2` 检查原生控件,macOS Desktop 由用户试用;Windows Desktop 仍需更新后的实机反馈。安装本身可以在 DSH 运行时执行(只改动磁盘配置),重启后生效。三种方式任选其一:
|
|
73
74
|
|
|
74
75
|
> 安装前请确保已关闭其他皮肤插件,避免冲突。
|
|
75
76
|
|
|
@@ -82,10 +83,10 @@ dsh --profile web --dump-config | grep -B1 -A2 liang-intensity
|
|
|
82
83
|
|
|
83
84
|
### 方式二:从 GitHub Release tarball 安装
|
|
84
85
|
|
|
85
|
-
从本仓库 [Releases](https://github.com/kingOfSoySauce/dsh-liang-skin/releases) 页面下载 `dsh-client-liang-intensity-skin-0.1.
|
|
86
|
+
从本仓库 [Releases](https://github.com/kingOfSoySauce/dsh-liang-skin/releases) 页面下载 `leon___-dsh-client-liang-intensity-skin-0.1.11.tgz`(包内已包含构建好的 `lib/client.js`,安装时不需要执行任何 prepare 脚本),然后:
|
|
86
87
|
|
|
87
88
|
```sh
|
|
88
|
-
dsh plugin --profile web add ./dsh-client-liang-intensity-skin-0.1.
|
|
89
|
+
dsh plugin --profile web add ./leon___-dsh-client-liang-intensity-skin-0.1.11.tgz
|
|
89
90
|
```
|
|
90
91
|
|
|
91
92
|
|
|
@@ -116,7 +117,7 @@ dsh plugin --profile web add .
|
|
|
116
117
|
### 卸载
|
|
117
118
|
|
|
118
119
|
```sh
|
|
119
|
-
dsh plugin --profile web remove dsh-client-liang-intensity-skin
|
|
120
|
+
dsh plugin --profile web remove @leon___/dsh-client-liang-intensity-skin
|
|
120
121
|
```
|
|
121
122
|
|
|
122
123
|
`remove` 会自动把插件从 `dsh.profile.bundles` 中摘除;重启后设置入口完全移除。
|
|
@@ -134,10 +135,13 @@ dsh plugin --profile web remove dsh-client-liang-intensity-skin
|
|
|
134
135
|
npm install
|
|
135
136
|
npm test
|
|
136
137
|
npm run build
|
|
138
|
+
npm run test:compatibility
|
|
137
139
|
```
|
|
138
140
|
|
|
139
141
|
修改 client 源码后需要运行 `npm run build`,并一起提交更新后的 `lib/client.js` 和 source map。
|
|
140
142
|
|
|
143
|
+
浏览器兼容性回归使用本机 Chrome / Chromium;可通过 `CHROME_PATH` 指定浏览器可执行文件,不会自动下载浏览器。测试使用宿主布局夹具,不能代替官方 Desktop 真机验收。本轮兼容性修复的验证步骤见 [兼容性验证说明](docs/compatibility-validation.md)。
|
|
144
|
+
|
|
141
145
|
## 灵感与素材来源
|
|
142
146
|
|
|
143
147
|
本插件的“滑动变祖”视觉概念与人物图片素材源自
|
package/lib/client.js
CHANGED
|
@@ -25,11 +25,12 @@ __export(index_exports, {
|
|
|
25
25
|
});
|
|
26
26
|
module.exports = __toCommonJS(index_exports);
|
|
27
27
|
var import_react = require("react");
|
|
28
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
28
29
|
|
|
29
30
|
// src/client/skin.css
|
|
30
31
|
var skin_default = `.liang-skin-backdrop {
|
|
31
32
|
position: fixed;
|
|
32
|
-
z-index:
|
|
33
|
+
z-index: -1;
|
|
33
34
|
inset: 0;
|
|
34
35
|
overflow: hidden;
|
|
35
36
|
pointer-events: none;
|
|
@@ -48,7 +49,7 @@ body[data-liang-skin="on"] .liang-skin-backdrop {
|
|
|
48
49
|
right: 0;
|
|
49
50
|
display: block;
|
|
50
51
|
width: min(42vw, 720px);
|
|
51
|
-
height:
|
|
52
|
+
height: 100%;
|
|
52
53
|
object-fit: cover;
|
|
53
54
|
object-position: 50% 42%;
|
|
54
55
|
opacity: var(--liang-portrait-opacity, 0.45);
|
|
@@ -75,11 +76,16 @@ body[data-liang-skin="on"] .liang-skin-backdrop {
|
|
|
75
76
|
position: absolute;
|
|
76
77
|
inset: 0;
|
|
77
78
|
content: "";
|
|
78
|
-
background:
|
|
79
|
+
background:
|
|
80
|
+
linear-gradient(90deg, var(--liang-page, transparent) 0 28%, transparent 57% 100%),
|
|
81
|
+
linear-gradient(var(--liang-bg-base, transparent), var(--liang-bg-base, transparent));
|
|
79
82
|
}
|
|
80
83
|
|
|
81
84
|
body[data-liang-skin="on"] {
|
|
82
|
-
|
|
85
|
+
/* Keep the backdrop above the canvas but below content and native portals.
|
|
86
|
+
The host owns root positioning, dimensions, and its own stacking order. */
|
|
87
|
+
isolation: isolate;
|
|
88
|
+
--dsw-alias-bg-base: transparent !important;
|
|
83
89
|
--dsw-alias-bg-layer-1: var(--liang-layer-1) !important;
|
|
84
90
|
--dsw-alias-bg-layer-2: var(--liang-layer-2) !important;
|
|
85
91
|
--dsw-alias-bg-layer-3: var(--liang-layer-3) !important;
|
|
@@ -239,11 +245,16 @@ body[data-liang-skin="on"]:is(
|
|
|
239
245
|
}
|
|
240
246
|
|
|
241
247
|
body[data-liang-skin="on"] > #root {
|
|
242
|
-
position: relative;
|
|
243
|
-
z-index: 1;
|
|
244
248
|
background: transparent !important;
|
|
245
249
|
}
|
|
246
250
|
|
|
251
|
+
body[data-liang-skin="on"]:is(
|
|
252
|
+
[data-dsh-desktop-mode="compatibility"],
|
|
253
|
+
[data-dsh-desktop-mode="extended"]
|
|
254
|
+
) .liang-skin-backdrop {
|
|
255
|
+
top: var(--dsh-desktop-frame-height, 0px);
|
|
256
|
+
}
|
|
257
|
+
|
|
247
258
|
/* Windows paints the sidebar fill across the host frame, covering the portrait.
|
|
248
259
|
Match macOS's transparent frame while keeping the sidebar, caption, and
|
|
249
260
|
conversation surfaces painted by their own host rules. */
|
|
@@ -480,7 +491,7 @@ body[data-liang-skin="on"] .liang-effort-control__range::-webkit-slider-thumb {
|
|
|
480
491
|
display: flex;
|
|
481
492
|
}
|
|
482
493
|
|
|
483
|
-
[class*="
|
|
494
|
+
[class*="_cubeRow"]:has(.liang-appearance-choice) {
|
|
484
495
|
display: grid;
|
|
485
496
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
486
497
|
}
|
|
@@ -516,90 +527,14 @@ body[data-liang-skin="on"] .liang-effort-control__range::-webkit-slider-thumb {
|
|
|
516
527
|
}
|
|
517
528
|
|
|
518
529
|
.liang-appearance-binding {
|
|
519
|
-
box-sizing: border-box;
|
|
520
530
|
display: flex;
|
|
521
|
-
width: 100%;
|
|
522
|
-
min-height: 28px;
|
|
523
531
|
align-items: center;
|
|
524
532
|
justify-content: space-between;
|
|
525
|
-
gap:
|
|
526
|
-
padding:
|
|
527
|
-
|
|
528
|
-
font: inherit;
|
|
533
|
+
gap: 24px;
|
|
534
|
+
padding: 16px 0;
|
|
535
|
+
border-bottom: 0.5px solid var(--dsw-alias-border-l2);
|
|
529
536
|
font-size: 14px;
|
|
530
|
-
line-height:
|
|
531
|
-
cursor: pointer;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
.liang-appearance-binding__label {
|
|
535
|
-
display: block;
|
|
536
|
-
min-width: 0;
|
|
537
|
-
overflow: hidden;
|
|
538
|
-
text-overflow: ellipsis;
|
|
539
|
-
white-space: nowrap;
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
.liang-appearance-binding__copy {
|
|
543
|
-
display: flex;
|
|
544
|
-
min-width: 0;
|
|
545
|
-
flex-direction: column;
|
|
546
|
-
gap: 1px;
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
.liang-appearance-binding__description {
|
|
550
|
-
display: block;
|
|
551
|
-
overflow: hidden;
|
|
552
|
-
color: var(--dsw-alias-label-secondary);
|
|
553
|
-
font-size: 12px;
|
|
554
|
-
line-height: 18px;
|
|
555
|
-
text-overflow: ellipsis;
|
|
556
|
-
white-space: nowrap;
|
|
557
|
-
}
|
|
558
|
-
|
|
559
|
-
.liang-appearance-binding__input {
|
|
560
|
-
position: relative;
|
|
561
|
-
flex: 0 0 36px;
|
|
562
|
-
width: 36px;
|
|
563
|
-
height: 20px;
|
|
564
|
-
margin: 0;
|
|
565
|
-
border: 1px solid var(--dsw-alias-border-l2);
|
|
566
|
-
border-radius: 999px;
|
|
567
|
-
outline: none;
|
|
568
|
-
cursor: pointer;
|
|
569
|
-
appearance: none;
|
|
570
|
-
background: var(--dsw-alias-interactive-bg-hover, var(--dsw-alias-bg-module-platform));
|
|
571
|
-
}
|
|
572
|
-
|
|
573
|
-
.liang-appearance-binding__input::before {
|
|
574
|
-
position: absolute;
|
|
575
|
-
top: 2px;
|
|
576
|
-
left: 2px;
|
|
577
|
-
width: 14px;
|
|
578
|
-
height: 14px;
|
|
579
|
-
border-radius: 50%;
|
|
580
|
-
content: "";
|
|
581
|
-
background: var(--dsw-alias-label-primary);
|
|
582
|
-
box-shadow: 0 1px 3px rgb(0 0 0 / 18%);
|
|
583
|
-
transition: transform 160ms ease, background-color 160ms ease;
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
.liang-appearance-binding__input:checked {
|
|
587
|
-
border-color: var(--dsw-static-neutral-bluish-400);
|
|
588
|
-
background: var(--dsw-static-neutral-bluish-400);
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
.liang-appearance-binding__input:checked::before {
|
|
592
|
-
background: var(--dsw-alias-bg-layer-1, #fff);
|
|
593
|
-
transform: translateX(16px);
|
|
594
|
-
}
|
|
595
|
-
|
|
596
|
-
.liang-appearance-binding__input:focus-visible {
|
|
597
|
-
box-shadow: 0 0 0 2px var(--dsw-alias-interactive-bg-hover);
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
.liang-appearance-binding__input:disabled {
|
|
601
|
-
cursor: progress;
|
|
602
|
-
opacity: 0.7;
|
|
537
|
+
line-height: 20px;
|
|
603
538
|
}
|
|
604
539
|
|
|
605
540
|
@media (max-width: 760px) {
|
|
@@ -626,6 +561,278 @@ body[data-liang-skin="on"] .liang-effort-control__range::-webkit-slider-thumb {
|
|
|
626
561
|
}
|
|
627
562
|
`;
|
|
628
563
|
|
|
564
|
+
// src/client/appearance.ts
|
|
565
|
+
var NATIVE_APPEARANCE_ROW = '[class*="_cubeRow"]';
|
|
566
|
+
var LIANG_APPEARANCE_BUTTON = "liang-appearance-choice";
|
|
567
|
+
function hasClassSuffix(node, suffix) {
|
|
568
|
+
return [...node.classList].some((name) => name.endsWith(suffix));
|
|
569
|
+
}
|
|
570
|
+
function findAppearanceRow() {
|
|
571
|
+
for (const row of document.querySelectorAll(NATIVE_APPEARANCE_ROW)) {
|
|
572
|
+
if (!hasClassSuffix(row, "_cubeRow")) continue;
|
|
573
|
+
const nativeButtons = [...row.children].filter(
|
|
574
|
+
(node) => node instanceof HTMLButtonElement && hasClassSuffix(node, "_themeCube")
|
|
575
|
+
);
|
|
576
|
+
if (nativeButtons.length < 3) continue;
|
|
577
|
+
let group = row.parentElement;
|
|
578
|
+
while (group !== null && !hasClassSuffix(group, "_group")) {
|
|
579
|
+
group = group.parentElement;
|
|
580
|
+
}
|
|
581
|
+
group ??= row.parentElement;
|
|
582
|
+
if (group !== null) return { row, group, nativeButtons };
|
|
583
|
+
}
|
|
584
|
+
return null;
|
|
585
|
+
}
|
|
586
|
+
function installLiangAppearanceButton(scope, presenter, packageId) {
|
|
587
|
+
let pending = false;
|
|
588
|
+
let disposed = false;
|
|
589
|
+
let mounted = null;
|
|
590
|
+
const nativeClickHandlers = /* @__PURE__ */ new Map();
|
|
591
|
+
const unmount = () => {
|
|
592
|
+
for (const [button, handler] of nativeClickHandlers) {
|
|
593
|
+
button.removeEventListener("click", handler, { capture: true });
|
|
594
|
+
}
|
|
595
|
+
nativeClickHandlers.clear();
|
|
596
|
+
if (mounted === null) return;
|
|
597
|
+
mounted.button.removeEventListener("click", mounted.handleCustomClick);
|
|
598
|
+
mounted.button.remove();
|
|
599
|
+
mounted = null;
|
|
600
|
+
};
|
|
601
|
+
const choose = async (enabled) => {
|
|
602
|
+
if (disposed || pending || scope.getSnapshot().enabled === enabled) return;
|
|
603
|
+
pending = true;
|
|
604
|
+
sync();
|
|
605
|
+
try {
|
|
606
|
+
await presenter.choose(enabled);
|
|
607
|
+
} catch {
|
|
608
|
+
} finally {
|
|
609
|
+
pending = false;
|
|
610
|
+
if (!disposed) sync();
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
const createMount = (row, group) => {
|
|
614
|
+
const english = document.documentElement.lang.toLowerCase().startsWith("en");
|
|
615
|
+
const button = document.createElement("button");
|
|
616
|
+
button.className = LIANG_APPEARANCE_BUTTON;
|
|
617
|
+
button.type = "button";
|
|
618
|
+
button.dataset.plugin = packageId;
|
|
619
|
+
button.setAttribute("aria-label", "\u6ED1\u52A8\u53D8\u7956");
|
|
620
|
+
const icon = document.createElement("span");
|
|
621
|
+
icon.className = "liang-appearance-choice__icon";
|
|
622
|
+
icon.setAttribute("aria-hidden", "true");
|
|
623
|
+
icon.textContent = "\u25C8";
|
|
624
|
+
const label = document.createElement("span");
|
|
625
|
+
label.className = "liang-appearance-choice__label";
|
|
626
|
+
label.textContent = english ? "Slider" : "\u6ED1\u52A8\u53D8\u7956";
|
|
627
|
+
button.append(icon, label);
|
|
628
|
+
const handleCustomClick = () => {
|
|
629
|
+
void choose(true);
|
|
630
|
+
};
|
|
631
|
+
button.addEventListener("click", handleCustomClick);
|
|
632
|
+
return { row, group, button, handleCustomClick };
|
|
633
|
+
};
|
|
634
|
+
const sync = () => {
|
|
635
|
+
if (disposed) return;
|
|
636
|
+
const target = findAppearanceRow();
|
|
637
|
+
if (target === null) {
|
|
638
|
+
unmount();
|
|
639
|
+
return;
|
|
640
|
+
}
|
|
641
|
+
if (mounted !== null && (mounted.row !== target.row || mounted.group !== target.group)) {
|
|
642
|
+
unmount();
|
|
643
|
+
}
|
|
644
|
+
mounted ??= createMount(target.row, target.group);
|
|
645
|
+
const { row, button } = mounted;
|
|
646
|
+
if (button.parentElement !== row) row.append(button);
|
|
647
|
+
const snapshot = scope.getSnapshot();
|
|
648
|
+
button.disabled = pending;
|
|
649
|
+
button.setAttribute("aria-pressed", String(snapshot.enabled));
|
|
650
|
+
for (const [nativeButton, handler] of nativeClickHandlers) {
|
|
651
|
+
if (target.nativeButtons.includes(nativeButton)) continue;
|
|
652
|
+
nativeButton.removeEventListener("click", handler, { capture: true });
|
|
653
|
+
nativeClickHandlers.delete(nativeButton);
|
|
654
|
+
}
|
|
655
|
+
for (const nativeButton of target.nativeButtons) {
|
|
656
|
+
if (nativeClickHandlers.has(nativeButton)) continue;
|
|
657
|
+
const handleNativeClick = () => {
|
|
658
|
+
void choose(false);
|
|
659
|
+
};
|
|
660
|
+
nativeClickHandlers.set(nativeButton, handleNativeClick);
|
|
661
|
+
nativeButton.addEventListener("click", handleNativeClick, { capture: true });
|
|
662
|
+
}
|
|
663
|
+
};
|
|
664
|
+
const observer = new MutationObserver(sync);
|
|
665
|
+
observer.observe(document.body, { childList: true, subtree: true });
|
|
666
|
+
const unsubscribe = scope.subscribe(sync);
|
|
667
|
+
sync();
|
|
668
|
+
return () => {
|
|
669
|
+
if (disposed) return;
|
|
670
|
+
disposed = true;
|
|
671
|
+
observer.disconnect();
|
|
672
|
+
unsubscribe();
|
|
673
|
+
unmount();
|
|
674
|
+
};
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
// src/client/portrait-loader.ts
|
|
678
|
+
var RETRY_DELAYS = [500, 1500, 3e3];
|
|
679
|
+
function retryUrl(source, retry) {
|
|
680
|
+
if (retry === 0) return source;
|
|
681
|
+
const hashIndex = source.indexOf("#");
|
|
682
|
+
const hash = hashIndex < 0 ? "" : source.slice(hashIndex);
|
|
683
|
+
const base = hashIndex < 0 ? source : source.slice(0, hashIndex);
|
|
684
|
+
const queryIndex = base.indexOf("?");
|
|
685
|
+
const path = queryIndex < 0 ? base : base.slice(0, queryIndex);
|
|
686
|
+
const query = new URLSearchParams(queryIndex < 0 ? "" : base.slice(queryIndex + 1));
|
|
687
|
+
query.set("retry", String(retry));
|
|
688
|
+
return `${path}?${query}${hash}`;
|
|
689
|
+
}
|
|
690
|
+
function createPortraitLoader(options) {
|
|
691
|
+
const sources = options.sources.map((source) => ({ ...source }));
|
|
692
|
+
const assets = /* @__PURE__ */ new Map();
|
|
693
|
+
for (const { url } of sources) {
|
|
694
|
+
if (!assets.has(url)) {
|
|
695
|
+
assets.set(url, {
|
|
696
|
+
url,
|
|
697
|
+
status: "idle",
|
|
698
|
+
loadedUrl: null,
|
|
699
|
+
retries: 0,
|
|
700
|
+
image: null,
|
|
701
|
+
timer: null,
|
|
702
|
+
detach: null
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
const createImage = options.createImage ?? (() => new Image());
|
|
707
|
+
let onChange = options.onChange;
|
|
708
|
+
let active = false;
|
|
709
|
+
let disposed = false;
|
|
710
|
+
let generation = 0;
|
|
711
|
+
let targetLevel = sources[0]?.level ?? 0;
|
|
712
|
+
let displayedIndex = null;
|
|
713
|
+
let lastState = null;
|
|
714
|
+
const isCurrent = (run) => active && !disposed && generation === run;
|
|
715
|
+
const nearestIndex = (available) => {
|
|
716
|
+
let nearest = null;
|
|
717
|
+
for (let index = 0; index < sources.length; index += 1) {
|
|
718
|
+
if (!available(index)) continue;
|
|
719
|
+
const distance = Math.abs(sources[index].level - targetLevel);
|
|
720
|
+
const previous = nearest === null ? Infinity : Math.abs(sources[nearest].level - targetLevel);
|
|
721
|
+
if (nearest === null || distance < previous || distance === previous && sources[index].level > sources[nearest].level) {
|
|
722
|
+
nearest = index;
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
return nearest;
|
|
726
|
+
};
|
|
727
|
+
const isReady = (index) => assets.get(sources[index].url)?.status === "ready";
|
|
728
|
+
const emit = (state) => {
|
|
729
|
+
if (lastState?.index === state.index && lastState.url === state.url && lastState.status === state.status) return;
|
|
730
|
+
lastState = state;
|
|
731
|
+
onChange?.(state);
|
|
732
|
+
};
|
|
733
|
+
const reconcile = () => {
|
|
734
|
+
if (!active || disposed) return;
|
|
735
|
+
const target = nearestIndex(() => true);
|
|
736
|
+
if (target !== null && isReady(target)) displayedIndex = target;
|
|
737
|
+
else if (displayedIndex === null) displayedIndex = nearestIndex(isReady);
|
|
738
|
+
if (displayedIndex !== null) {
|
|
739
|
+
const asset = assets.get(sources[displayedIndex].url);
|
|
740
|
+
emit({ index: displayedIndex, url: asset.loadedUrl, image: asset.image, status: "ready" });
|
|
741
|
+
} else {
|
|
742
|
+
const exhausted = [...assets.values()].every((asset) => asset.status === "failed");
|
|
743
|
+
emit({ index: null, url: null, image: null, status: exhausted ? "failed" : "loading" });
|
|
744
|
+
}
|
|
745
|
+
};
|
|
746
|
+
const request = (asset, run) => {
|
|
747
|
+
if (!isCurrent(run)) return;
|
|
748
|
+
asset.status = "loading";
|
|
749
|
+
const image = createImage();
|
|
750
|
+
asset.image = image;
|
|
751
|
+
image.loading = "eager";
|
|
752
|
+
image.decoding = "async";
|
|
753
|
+
const url = retryUrl(asset.url, asset.retries);
|
|
754
|
+
let settled = false;
|
|
755
|
+
let decoding = false;
|
|
756
|
+
const current = () => !settled && isCurrent(run) && asset.image === image;
|
|
757
|
+
const detach = () => {
|
|
758
|
+
image.removeEventListener("load", handleLoad);
|
|
759
|
+
image.removeEventListener("error", handleError);
|
|
760
|
+
asset.detach = null;
|
|
761
|
+
};
|
|
762
|
+
const handleError = () => {
|
|
763
|
+
if (!current()) return;
|
|
764
|
+
settled = true;
|
|
765
|
+
detach();
|
|
766
|
+
image.removeAttribute("src");
|
|
767
|
+
asset.image = null;
|
|
768
|
+
if (asset.retries < RETRY_DELAYS.length) {
|
|
769
|
+
const delay = RETRY_DELAYS[asset.retries];
|
|
770
|
+
asset.retries += 1;
|
|
771
|
+
asset.timer = setTimeout(() => {
|
|
772
|
+
if (!isCurrent(run)) return;
|
|
773
|
+
asset.timer = null;
|
|
774
|
+
request(asset, run);
|
|
775
|
+
}, delay);
|
|
776
|
+
} else {
|
|
777
|
+
asset.status = "failed";
|
|
778
|
+
reconcile();
|
|
779
|
+
}
|
|
780
|
+
};
|
|
781
|
+
const handleLoad = () => {
|
|
782
|
+
if (!current() || decoding) return;
|
|
783
|
+
decoding = true;
|
|
784
|
+
void image.decode().then(() => {
|
|
785
|
+
if (!current()) return;
|
|
786
|
+
settled = true;
|
|
787
|
+
detach();
|
|
788
|
+
asset.loadedUrl = url;
|
|
789
|
+
asset.status = "ready";
|
|
790
|
+
reconcile();
|
|
791
|
+
}, handleError);
|
|
792
|
+
};
|
|
793
|
+
asset.detach = detach;
|
|
794
|
+
image.addEventListener("load", handleLoad);
|
|
795
|
+
image.addEventListener("error", handleError);
|
|
796
|
+
image.src = url;
|
|
797
|
+
};
|
|
798
|
+
const stop = () => {
|
|
799
|
+
active = false;
|
|
800
|
+
generation += 1;
|
|
801
|
+
for (const asset of assets.values()) {
|
|
802
|
+
if (asset.timer !== null) clearTimeout(asset.timer);
|
|
803
|
+
asset.timer = null;
|
|
804
|
+
asset.detach?.();
|
|
805
|
+
asset.image?.removeAttribute("src");
|
|
806
|
+
asset.image = null;
|
|
807
|
+
asset.status = "idle";
|
|
808
|
+
asset.loadedUrl = null;
|
|
809
|
+
asset.retries = 0;
|
|
810
|
+
}
|
|
811
|
+
displayedIndex = null;
|
|
812
|
+
lastState = null;
|
|
813
|
+
};
|
|
814
|
+
return {
|
|
815
|
+
start() {
|
|
816
|
+
if (disposed || active) return;
|
|
817
|
+
active = true;
|
|
818
|
+
const run = ++generation;
|
|
819
|
+
reconcile();
|
|
820
|
+
for (const asset of assets.values()) request(asset, run);
|
|
821
|
+
},
|
|
822
|
+
select(level) {
|
|
823
|
+
if (disposed || !Number.isFinite(level)) return;
|
|
824
|
+
targetLevel = level;
|
|
825
|
+
reconcile();
|
|
826
|
+
},
|
|
827
|
+
stop,
|
|
828
|
+
dispose() {
|
|
829
|
+
stop();
|
|
830
|
+
disposed = true;
|
|
831
|
+
onChange = null;
|
|
832
|
+
}
|
|
833
|
+
};
|
|
834
|
+
}
|
|
835
|
+
|
|
629
836
|
// src/client/logic.ts
|
|
630
837
|
var PREVIEW_MAX_FRAME = 240;
|
|
631
838
|
var MAX_LEVEL = 30;
|
|
@@ -665,19 +872,6 @@ function selectedEffortIndex(efforts, selectedId, defaultId) {
|
|
|
665
872
|
const id = selectedId ?? defaultId;
|
|
666
873
|
return id === void 0 ? -1 : efforts.findIndex((effort) => effort.id === id);
|
|
667
874
|
}
|
|
668
|
-
function portraitBlendForLevel(level, anchors) {
|
|
669
|
-
if (anchors.length === 0) return { lowerIndex: -1, upperIndex: -1, mix: 0 };
|
|
670
|
-
const safeLevel = Number.isFinite(level) ? Math.min(anchors[anchors.length - 1], Math.max(anchors[0], level)) : anchors[0];
|
|
671
|
-
let upperIndex = anchors.findIndex((anchor) => anchor >= safeLevel);
|
|
672
|
-
if (upperIndex < 0) upperIndex = anchors.length - 1;
|
|
673
|
-
const lowerIndex = Math.max(0, upperIndex - (anchors[upperIndex] > safeLevel ? 1 : 0));
|
|
674
|
-
const span = anchors[upperIndex] - anchors[lowerIndex];
|
|
675
|
-
return {
|
|
676
|
-
lowerIndex,
|
|
677
|
-
upperIndex,
|
|
678
|
-
mix: span === 0 ? 0 : (safeLevel - anchors[lowerIndex]) / span
|
|
679
|
-
};
|
|
680
|
-
}
|
|
681
875
|
function liangRankForFrame(rawFrame) {
|
|
682
876
|
const level = clampFrame(rawFrame) / PREVIEW_MAX_FRAME * MAX_LEVEL;
|
|
683
877
|
const index = level >= MAX_LEVEL ? LIANG_RANKS.length - 1 : Math.floor(level / 6);
|
|
@@ -750,7 +944,6 @@ var import_jsx_runtime = require("react/jsx-runtime");
|
|
|
750
944
|
var PACKAGE_ID = "dsh-client-liang-intensity-skin";
|
|
751
945
|
var LOCALE_NAMESPACE = "liang.skin";
|
|
752
946
|
var ASSET_PREFIX = `/plugins/${PACKAGE_ID}/assets`;
|
|
753
|
-
var FIRST_PORTRAIT_FILE = "portrait-source-v2/stage-00.webp";
|
|
754
947
|
var BIND_EFFORT_KEY = "dsh-liang-intensity-skin.bind-effort";
|
|
755
948
|
var PORTRAIT_ANCHORS = [
|
|
756
949
|
{ level: 0, file: "stage-00.webp" },
|
|
@@ -778,7 +971,6 @@ var PORTRAIT_ANCHORS = [
|
|
|
778
971
|
{ level: 29, file: "level-29.webp" },
|
|
779
972
|
{ level: 30, file: "stage-30.webp" }
|
|
780
973
|
];
|
|
781
|
-
var ANCHOR_LEVELS = PORTRAIT_ANCHORS.map((anchor) => anchor.level);
|
|
782
974
|
var cssVariables = [
|
|
783
975
|
"--liang-strength",
|
|
784
976
|
"--liang-page",
|
|
@@ -800,9 +992,7 @@ var SkinPresenter = class {
|
|
|
800
992
|
scope;
|
|
801
993
|
theme;
|
|
802
994
|
root;
|
|
803
|
-
|
|
804
|
-
preloads;
|
|
805
|
-
portraitReady = false;
|
|
995
|
+
portraits;
|
|
806
996
|
enabled = true;
|
|
807
997
|
// Default to the max frame so the first paint after load is the dark shell;
|
|
808
998
|
// starting at 0 flashed the light palette before the directory resolved.
|
|
@@ -817,46 +1007,31 @@ var SkinPresenter = class {
|
|
|
817
1007
|
this.root = document.createElement("div");
|
|
818
1008
|
this.root.className = "liang-skin-backdrop";
|
|
819
1009
|
this.root.dataset.plugin = PACKAGE_ID;
|
|
820
|
-
this.root.dataset.media = "
|
|
1010
|
+
this.root.dataset.media = "color";
|
|
821
1011
|
this.root.setAttribute("aria-hidden", "true");
|
|
822
|
-
this.
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
if (this.
|
|
839
|
-
this.portraitReady = true;
|
|
1012
|
+
this.portraits = createPortraitLoader({
|
|
1013
|
+
sources: PORTRAIT_ANCHORS.map(({ level, file }) => ({
|
|
1014
|
+
level,
|
|
1015
|
+
url: `${ASSET_PREFIX}/portrait-source-v2/${file}`
|
|
1016
|
+
})),
|
|
1017
|
+
onChange: ({ image }) => {
|
|
1018
|
+
if (this.disposed || !this.enabled) return;
|
|
1019
|
+
if (image === null) {
|
|
1020
|
+
this.root.dataset.media = "color";
|
|
1021
|
+
this.root.replaceChildren();
|
|
1022
|
+
return;
|
|
1023
|
+
}
|
|
1024
|
+
const portrait = image;
|
|
1025
|
+
portrait.className = "liang-skin-sequence-frame";
|
|
1026
|
+
portrait.alt = "";
|
|
1027
|
+
portrait.draggable = false;
|
|
1028
|
+
if (this.root.firstChild !== portrait) this.root.replaceChildren(portrait);
|
|
840
1029
|
this.root.dataset.media = "sequence";
|
|
841
|
-
this.updatePortrait(paletteForFrame(this.frame).level);
|
|
842
|
-
},
|
|
843
|
-
() => {
|
|
844
1030
|
}
|
|
845
|
-
);
|
|
846
|
-
this.root.append(this.portrait);
|
|
847
|
-
document.body.prepend(this.root);
|
|
1031
|
+
});
|
|
848
1032
|
this.unsubscribe = scope.subscribe(() => this.syncSettings());
|
|
849
1033
|
this.syncSettings();
|
|
850
1034
|
}
|
|
851
|
-
handleSequenceError = () => {
|
|
852
|
-
if (this.portrait.src.endsWith(FIRST_PORTRAIT_FILE)) {
|
|
853
|
-
this.root.dataset.media = "color";
|
|
854
|
-
return;
|
|
855
|
-
}
|
|
856
|
-
this.portraitReady = false;
|
|
857
|
-
this.portrait.src = `${ASSET_PREFIX}/${FIRST_PORTRAIT_FILE}`;
|
|
858
|
-
this.root.dataset.media = "sequence";
|
|
859
|
-
};
|
|
860
1035
|
syncSettings() {
|
|
861
1036
|
this.setEnabled(this.scope.getSnapshot().enabled);
|
|
862
1037
|
}
|
|
@@ -867,19 +1042,27 @@ var SkinPresenter = class {
|
|
|
867
1042
|
return this.frame;
|
|
868
1043
|
}
|
|
869
1044
|
setEnabled(enabled) {
|
|
1045
|
+
if (this.disposed) return;
|
|
870
1046
|
this.enabled = enabled;
|
|
871
1047
|
if (enabled) {
|
|
872
1048
|
if (!this.root.isConnected) document.body.prepend(this.root);
|
|
873
1049
|
document.body.dataset.liangSkin = "on";
|
|
874
1050
|
this.applyFrame();
|
|
1051
|
+
this.portraits.start();
|
|
875
1052
|
} else {
|
|
1053
|
+
if (this.raf !== 0) cancelAnimationFrame(this.raf);
|
|
1054
|
+
this.raf = 0;
|
|
876
1055
|
this.root.remove();
|
|
1056
|
+
this.portraits.stop();
|
|
1057
|
+
this.root.replaceChildren();
|
|
1058
|
+
this.root.dataset.media = "color";
|
|
877
1059
|
delete document.body.dataset.liangSkin;
|
|
878
1060
|
delete document.body.dataset.liangStage;
|
|
879
1061
|
for (const name of cssVariables) document.body.style.removeProperty(name);
|
|
880
1062
|
}
|
|
881
1063
|
}
|
|
882
1064
|
setFrame(frame) {
|
|
1065
|
+
if (this.disposed) return;
|
|
883
1066
|
this.pendingFrame = Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(frame)));
|
|
884
1067
|
this.frame = this.pendingFrame;
|
|
885
1068
|
if (!this.enabled) return;
|
|
@@ -891,6 +1074,7 @@ var SkinPresenter = class {
|
|
|
891
1074
|
});
|
|
892
1075
|
}
|
|
893
1076
|
applyFrame() {
|
|
1077
|
+
if (this.disposed || !this.enabled) return;
|
|
894
1078
|
const palette = paletteForFrame(this.frame);
|
|
895
1079
|
const body = document.body;
|
|
896
1080
|
this.syncNativeTheme(palette.stage === 5 ? "dark" : "light");
|
|
@@ -917,16 +1101,7 @@ var SkinPresenter = class {
|
|
|
917
1101
|
this.theme.setTheme(theme);
|
|
918
1102
|
}
|
|
919
1103
|
updatePortrait(level) {
|
|
920
|
-
|
|
921
|
-
const { lowerIndex, upperIndex, mix: mix2 } = portraitBlendForLevel(
|
|
922
|
-
level,
|
|
923
|
-
ANCHOR_LEVELS
|
|
924
|
-
);
|
|
925
|
-
const lower = PORTRAIT_ANCHORS[lowerIndex];
|
|
926
|
-
const upper = PORTRAIT_ANCHORS[upperIndex];
|
|
927
|
-
const selected = mix2 >= 0.5 ? upper : lower;
|
|
928
|
-
const source = `${ASSET_PREFIX}/portrait-source-v2/${selected.file}`;
|
|
929
|
-
if (this.portrait.getAttribute("src") !== source) this.portrait.src = source;
|
|
1104
|
+
this.portraits.select(level);
|
|
930
1105
|
}
|
|
931
1106
|
async choose(enabled) {
|
|
932
1107
|
this.setEnabled(enabled);
|
|
@@ -942,8 +1117,7 @@ var SkinPresenter = class {
|
|
|
942
1117
|
this.disposed = true;
|
|
943
1118
|
this.unsubscribe();
|
|
944
1119
|
if (this.raf !== 0) cancelAnimationFrame(this.raf);
|
|
945
|
-
this.
|
|
946
|
-
for (const image of this.preloads) image.src = "";
|
|
1120
|
+
this.portraits.dispose();
|
|
947
1121
|
this.root.remove();
|
|
948
1122
|
document.body.removeAttribute("data-liang-skin");
|
|
949
1123
|
delete document.body.dataset.liangStage;
|
|
@@ -1110,116 +1284,29 @@ function LiangEffortSlider({ directory, load, select, presenter, scope }) {
|
|
|
1110
1284
|
}
|
|
1111
1285
|
);
|
|
1112
1286
|
}
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
const icon = document.createElement("span");
|
|
1134
|
-
icon.className = "liang-appearance-choice__icon";
|
|
1135
|
-
icon.setAttribute("aria-hidden", "true");
|
|
1136
|
-
icon.textContent = "\u25C8";
|
|
1137
|
-
const label = document.createElement("span");
|
|
1138
|
-
label.className = "liang-appearance-choice__label";
|
|
1139
|
-
label.textContent = document.documentElement.lang.toLowerCase().startsWith("en") ? "Slider" : "\u6ED1\u52A8\u53D8\u7956";
|
|
1140
|
-
customButton.append(icon, label);
|
|
1141
|
-
customButton.addEventListener("click", () => {
|
|
1142
|
-
if (pending || scope.getSnapshot().enabled) return;
|
|
1143
|
-
pending = true;
|
|
1144
|
-
sync();
|
|
1145
|
-
void presenter.choose(true).finally(() => {
|
|
1146
|
-
pending = false;
|
|
1147
|
-
sync();
|
|
1148
|
-
});
|
|
1149
|
-
});
|
|
1150
|
-
}
|
|
1151
|
-
if (customButton.parentElement !== row) row.append(customButton);
|
|
1152
|
-
const snapshot = scope.getSnapshot();
|
|
1153
|
-
customButton.disabled = pending;
|
|
1154
|
-
customButton.setAttribute("aria-pressed", String(snapshot.enabled));
|
|
1155
|
-
let bindingControl = group.querySelector(`.${LIANG_BINDING_CONTROL}`);
|
|
1156
|
-
if (!snapshot.enabled) {
|
|
1157
|
-
bindingControl?.remove();
|
|
1158
|
-
bindingControl = null;
|
|
1159
|
-
} else if (bindingControl === null) {
|
|
1160
|
-
bindingControl = document.createElement("label");
|
|
1161
|
-
bindingControl.className = LIANG_BINDING_CONTROL;
|
|
1162
|
-
bindingControl.dataset.plugin = PACKAGE_ID;
|
|
1163
|
-
const bindingCopy = document.createElement("span");
|
|
1164
|
-
bindingCopy.className = "liang-appearance-binding__copy";
|
|
1165
|
-
const bindingLabel = document.createElement("span");
|
|
1166
|
-
bindingLabel.className = "liang-appearance-binding__label";
|
|
1167
|
-
const bindingText = document.documentElement.lang.toLowerCase().startsWith("en") ? "Bind slider to reasoning level" : "\u6ED1\u52A8\u53D8\u7956\u7ED1\u5B9A\u601D\u8003\u7B49\u7EA7";
|
|
1168
|
-
bindingLabel.textContent = bindingText;
|
|
1169
|
-
const bindingDescription = document.createElement("span");
|
|
1170
|
-
bindingDescription.className = "liang-appearance-binding__description";
|
|
1171
|
-
bindingDescription.id = "liang-appearance-binding-description";
|
|
1172
|
-
bindingDescription.textContent = document.documentElement.lang.toLowerCase().startsWith("en") ? "When off, the slider does not change the reasoning level." : "\u5173\u95ED\u4E4B\u540E\u6ED1\u5757\u4E0D\u8054\u52A8\u601D\u8003\u7B49\u7EA7";
|
|
1173
|
-
bindingCopy.append(bindingLabel, bindingDescription);
|
|
1174
|
-
const bindingInput = document.createElement("input");
|
|
1175
|
-
bindingInput.className = LIANG_BINDING_INPUT;
|
|
1176
|
-
bindingInput.type = "checkbox";
|
|
1177
|
-
bindingInput.setAttribute("role", "switch");
|
|
1178
|
-
bindingInput.setAttribute("aria-label", bindingText);
|
|
1179
|
-
bindingInput.setAttribute("aria-describedby", bindingDescription.id);
|
|
1180
|
-
bindingInput.addEventListener("change", () => {
|
|
1181
|
-
void scope.setBindEffort(bindingInput.checked).catch(() => sync());
|
|
1182
|
-
});
|
|
1183
|
-
bindingControl.append(bindingCopy, bindingInput);
|
|
1184
|
-
group.append(bindingControl);
|
|
1185
|
-
}
|
|
1186
|
-
if (bindingControl !== null) {
|
|
1187
|
-
const bindingInput = bindingControl.querySelector(`.${LIANG_BINDING_INPUT}`);
|
|
1188
|
-
if (bindingInput !== null) {
|
|
1189
|
-
bindingInput.checked = snapshot.bindEffort;
|
|
1190
|
-
bindingInput.setAttribute("aria-checked", String(snapshot.bindEffort));
|
|
1191
|
-
bindingInput.disabled = pending;
|
|
1287
|
+
function EffortBindingRow({ scope, t }) {
|
|
1288
|
+
const snapshot = (0, import_react.useSyncExternalStore)(
|
|
1289
|
+
(listener) => scope.subscribe(listener),
|
|
1290
|
+
() => scope.getSnapshot()
|
|
1291
|
+
);
|
|
1292
|
+
const [pending, setPending] = (0, import_react.useState)(false);
|
|
1293
|
+
if (!snapshot.enabled) return null;
|
|
1294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "liang-appearance-binding", "data-plugin": PACKAGE_ID, children: [
|
|
1295
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: t("effort.binding") }),
|
|
1296
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
1297
|
+
import_dsh_client_ui_primitives.Switch,
|
|
1298
|
+
{
|
|
1299
|
+
checked: snapshot.bindEffort,
|
|
1300
|
+
disabled: pending,
|
|
1301
|
+
label: t("effort.binding"),
|
|
1302
|
+
onChange: (next) => {
|
|
1303
|
+
if (pending) return;
|
|
1304
|
+
setPending(true);
|
|
1305
|
+
void scope.setBindEffort(next).catch(() => void 0).finally(() => setPending(false));
|
|
1306
|
+
}
|
|
1192
1307
|
}
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
if (hookedNativeButtons.has(nativeButton)) continue;
|
|
1196
|
-
hookedNativeButtons.add(nativeButton);
|
|
1197
|
-
const handleNativeClick = () => {
|
|
1198
|
-
if (pending || !scope.getSnapshot().enabled) return;
|
|
1199
|
-
pending = true;
|
|
1200
|
-
sync();
|
|
1201
|
-
void presenter.choose(false).finally(() => {
|
|
1202
|
-
pending = false;
|
|
1203
|
-
sync();
|
|
1204
|
-
});
|
|
1205
|
-
};
|
|
1206
|
-
nativeClickHandlers.set(nativeButton, handleNativeClick);
|
|
1207
|
-
nativeButton.addEventListener("click", handleNativeClick, { capture: true });
|
|
1208
|
-
}
|
|
1209
|
-
};
|
|
1210
|
-
const observer = new MutationObserver(sync);
|
|
1211
|
-
observer.observe(document.body, { childList: true, subtree: true });
|
|
1212
|
-
const unsubscribe = scope.subscribe(sync);
|
|
1213
|
-
sync();
|
|
1214
|
-
return () => {
|
|
1215
|
-
observer.disconnect();
|
|
1216
|
-
unsubscribe();
|
|
1217
|
-
for (const [nativeButton, handleNativeClick] of nativeClickHandlers) {
|
|
1218
|
-
nativeButton.removeEventListener("click", handleNativeClick, { capture: true });
|
|
1219
|
-
}
|
|
1220
|
-
document.querySelectorAll(`.${LIANG_APPEARANCE_BUTTON}`).forEach((button) => button.remove());
|
|
1221
|
-
document.querySelectorAll(`.${LIANG_BINDING_CONTROL}`).forEach((control) => control.remove());
|
|
1222
|
-
};
|
|
1308
|
+
)
|
|
1309
|
+
] });
|
|
1223
1310
|
}
|
|
1224
1311
|
var inject = [
|
|
1225
1312
|
"slots",
|
|
@@ -1284,28 +1371,23 @@ function apply(ctx) {
|
|
|
1284
1371
|
const presenter = new SkinPresenter(scope, theme);
|
|
1285
1372
|
ctx.effect(() => () => presenter.dispose(), "liang-intensity-skin: backdrop presenter");
|
|
1286
1373
|
ctx.effect(
|
|
1287
|
-
() => installLiangAppearanceButton(scope, presenter),
|
|
1374
|
+
() => installLiangAppearanceButton(scope, presenter, PACKAGE_ID),
|
|
1288
1375
|
"liang-intensity-skin: native appearance extension"
|
|
1289
1376
|
);
|
|
1290
1377
|
ctx.effect(
|
|
1291
1378
|
() => ctx.locale.register(LOCALE_NAMESPACE, {
|
|
1292
|
-
zh: {
|
|
1293
|
-
|
|
1294
|
-
"appearance.light": "\u6D45\u8272",
|
|
1295
|
-
"appearance.dark": "\u6DF1\u8272",
|
|
1296
|
-
"appearance.system": "\u8DDF\u968F\u7CFB\u7EDF",
|
|
1297
|
-
"appearance.liang": "\u6ED1\u52A8\u53D8\u7956"
|
|
1298
|
-
},
|
|
1299
|
-
en: {
|
|
1300
|
-
"appearance.title": "Appearance",
|
|
1301
|
-
"appearance.light": "Light",
|
|
1302
|
-
"appearance.dark": "Dark",
|
|
1303
|
-
"appearance.system": "System",
|
|
1304
|
-
"appearance.liang": "Slider"
|
|
1305
|
-
}
|
|
1379
|
+
zh: { "effort.binding": "\u6ED1\u52A8\u53D8\u7956\u7ED1\u5B9A\u601D\u8003\u7B49\u7EA7" },
|
|
1380
|
+
en: { "effort.binding": "Bind slider to reasoning level" }
|
|
1306
1381
|
}),
|
|
1307
1382
|
"liang-intensity-skin: settings locale"
|
|
1308
1383
|
);
|
|
1384
|
+
ctx.slots.inject("settings.general.item", () => ctx.slots.register({
|
|
1385
|
+
name: "settings.general.item",
|
|
1386
|
+
id: "liang-effort-binding",
|
|
1387
|
+
order: 10.5,
|
|
1388
|
+
locale: LOCALE_NAMESPACE,
|
|
1389
|
+
inject: () => ({ scope })
|
|
1390
|
+
}, EffortBindingRow));
|
|
1309
1391
|
ctx.slots.inject("conversation.input.right", () => ctx.slots.register({
|
|
1310
1392
|
name: "conversation.input.right",
|
|
1311
1393
|
id: "liang-intensity-control",
|
package/lib/client.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/client/index.tsx", "../src/client/skin.css", "../src/client/logic.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport type { Context as ClientContext } from \"@deepseek-ai/cordis\";\nimport type { SnapshotStore } from \"@deepseek-ai/dsh-client-store\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-settings/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-model-selection/client\";\nimport styles from \"./skin.css\";\nimport {\n PREVIEW_MAX_FRAME,\n frameForEffort,\n indicatorLabel,\n nearestEffortIndex,\n paletteForFrame,\n portraitBlendForLevel,\n selectedEffortIndex,\n type EffortLike,\n} from \"./logic\";\n\nconst PACKAGE_ID = \"dsh-client-liang-intensity-skin\";\nconst LOCALE_NAMESPACE = \"liang.skin\";\nconst ASSET_PREFIX = `/plugins/${PACKAGE_ID}/assets`;\nconst FIRST_PORTRAIT_FILE = \"portrait-source-v2/stage-00.webp\";\nconst BIND_EFFORT_KEY = \"dsh-liang-intensity-skin.bind-effort\";\n\nconst PORTRAIT_ANCHORS = [\n { level: 0, file: \"stage-00.webp\" },\n { level: 1, file: \"level-01.webp\" },\n { level: 3, file: \"level-03.webp\" },\n { level: 4, file: \"level-04.webp\" },\n { level: 6, file: \"stage-06.webp\" },\n { level: 7, file: \"level-07.webp\" },\n { level: 9, file: \"level-09.webp\" },\n { level: 10, file: \"level-10.webp\" },\n { level: 12, file: \"stage-12.webp\" },\n { level: 13, file: \"level-13.webp\" },\n { level: 14, file: \"level-14.webp\" },\n { level: 15, file: \"bridge-15.webp\" },\n { level: 16, file: \"level-16.webp\" },\n { level: 17, file: \"level-17.webp\" },\n { level: 18, file: \"stage-18.webp\" },\n { level: 19, file: \"level-19.webp\" },\n { level: 21, file: \"level-21.webp\" },\n { level: 22, file: \"level-22.webp\" },\n { level: 24, file: \"stage-24.webp\" },\n { level: 25, file: \"level-25.webp\" },\n { level: 27, file: \"bridge-27.webp\" },\n { level: 28, file: \"level-28.webp\" },\n { level: 29, file: \"level-29.webp\" },\n { level: 30, file: \"stage-30.webp\" },\n] as const;\n\nconst ANCHOR_LEVELS = PORTRAIT_ANCHORS.map((anchor) => anchor.level);\n\ninterface SkinSettings {\n enabled: boolean;\n bindEffort: boolean;\n}\n\ninterface PreferenceStore {\n getSnapshot(): SkinSettings;\n subscribe(listener: () => void): () => void;\n set(enabled: boolean): Promise<void>;\n setBindEffort(enabled: boolean): Promise<void>;\n dispose(): void;\n}\n\ntype NativeThemeId = \"light\" | \"dark\";\n\ninterface ThemeService {\n getTheme(): { preference: string };\n setTheme(id: NativeThemeId | \"system\"): void;\n}\n\ninterface ModelSelection {\n provider: string;\n model: string;\n reasoningEffort?: string;\n}\n\ninterface CatalogModel {\n id: string;\n reasoning?: {\n efforts: EffortLike[];\n defaultEffort?: string;\n };\n}\n\ninterface ModelDirectoryState {\n current: ModelSelection | null;\n groups: readonly { id: string; models: CatalogModel[] }[];\n status: \"idle\" | \"loading\" | \"ready\" | \"selecting\" | \"error\";\n error: string | null;\n}\n\ninterface ModelDirectory {\n store: SnapshotStore<ModelDirectoryState>;\n load(): Promise<unknown>;\n select(selection: ModelSelection): Promise<{ ok: boolean }>;\n}\n\ninterface SliderProps {\n directory: SnapshotStore<ModelDirectoryState>;\n load: () => void;\n select: (selection: ModelSelection) => Promise<boolean>;\n presenter: SkinPresenter;\n scope: PreferenceStore;\n}\n\ninterface SettingsRowProps {\n scope: PreferenceStore;\n presenter: SkinPresenter;\n theme: ThemeService;\n subscribeTheme: (listener: () => void) => () => void;\n t: (key: string) => string;\n}\n\nconst cssVariables = [\n \"--liang-strength\",\n \"--liang-page\",\n \"--liang-bg-base\",\n \"--liang-layer-1\",\n \"--liang-layer-2\",\n \"--liang-layer-3\",\n \"--liang-sidebar\",\n \"--liang-ink\",\n \"--liang-secondary\",\n \"--liang-tertiary\",\n \"--liang-border\",\n \"--liang-accent\",\n \"--liang-accent-hover\",\n \"--liang-hover\",\n \"--liang-portrait-opacity\",\n] as const;\n\nclass SkinPresenter {\n private readonly scope: PreferenceStore;\n private readonly theme: ThemeService;\n private readonly root: HTMLDivElement;\n private readonly portrait: HTMLImageElement;\n private readonly preloads: HTMLImageElement[];\n private portraitReady = false;\n private enabled = true;\n // Default to the max frame so the first paint after load is the dark shell;\n // starting at 0 flashed the light palette before the directory resolved.\n private frame = PREVIEW_MAX_FRAME;\n private pendingFrame = PREVIEW_MAX_FRAME;\n private raf = 0;\n private disposed = false;\n private unsubscribe: () => void;\n\n constructor(scope: PreferenceStore, theme: ThemeService) {\n this.scope = scope;\n this.theme = theme;\n this.root = document.createElement(\"div\");\n this.root.className = \"liang-skin-backdrop\";\n this.root.dataset.plugin = PACKAGE_ID;\n // Show the first half-body frame immediately while the remaining frames\n // are fetched and decoded. A request being complete does not mean the\n // bitmap is ready for a tear-free first swap.\n this.root.dataset.media = \"sequence\";\n this.root.setAttribute(\"aria-hidden\", \"true\");\n\n this.portrait = document.createElement(\"img\");\n this.portrait.className = \"liang-skin-sequence-frame\";\n this.portrait.alt = \"\";\n this.portrait.draggable = false;\n this.portrait.decoding = \"async\";\n this.portrait.src = `${ASSET_PREFIX}/${FIRST_PORTRAIT_FILE}`;\n this.portrait.addEventListener(\"error\", this.handleSequenceError);\n\n this.preloads = PORTRAIT_ANCHORS.map(({ file }) => {\n const image = new Image();\n image.loading = \"eager\";\n image.decoding = \"async\";\n image.src = `${ASSET_PREFIX}/portrait-source-v2/${file}`;\n return image;\n });\n\n // `new Image()` starts the requests, but the browser may still defer\n // decoding until the image is attached to the document. Wait for all\n // frames up front so the first slider interaction never reveals a blank\n // or half-painted frame.\n void Promise.all(this.preloads.map((image) => image.decode())).then(\n () => {\n if (this.disposed) return;\n this.portraitReady = true;\n this.root.dataset.media = \"sequence\";\n this.updatePortrait(paletteForFrame(this.frame).level);\n },\n () => {\n // Keep the already-visible first half-body frame if another optional\n // frame cannot be decoded. It is still a valid skin fallback.\n },\n );\n\n this.root.append(this.portrait);\n document.body.prepend(this.root);\n\n this.unsubscribe = scope.subscribe(() => this.syncSettings());\n this.syncSettings();\n }\n\n private readonly handleSequenceError = () => {\n if (this.portrait.src.endsWith(FIRST_PORTRAIT_FILE)) {\n this.root.dataset.media = \"color\";\n return;\n }\n this.portraitReady = false;\n this.portrait.src = `${ASSET_PREFIX}/${FIRST_PORTRAIT_FILE}`;\n this.root.dataset.media = \"sequence\";\n };\n\n private syncSettings() {\n this.setEnabled(this.scope.getSnapshot().enabled);\n }\n\n isEnabled() {\n return this.enabled;\n }\n\n getFrame() {\n return this.frame;\n }\n\n setEnabled(enabled: boolean) {\n this.enabled = enabled;\n if (enabled) {\n if (!this.root.isConnected) document.body.prepend(this.root);\n document.body.dataset.liangSkin = \"on\";\n this.applyFrame();\n } else {\n this.root.remove();\n delete document.body.dataset.liangSkin;\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n }\n\n setFrame(frame: number) {\n this.pendingFrame = Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(frame)));\n this.frame = this.pendingFrame;\n if (!this.enabled) return;\n if (this.raf !== 0) return;\n this.raf = requestAnimationFrame(() => {\n this.raf = 0;\n this.frame = this.pendingFrame;\n this.applyFrame();\n });\n }\n\n private applyFrame() {\n const palette = paletteForFrame(this.frame);\n const body = document.body;\n this.syncNativeTheme(palette.stage === 5 ? \"dark\" : \"light\");\n body.dataset.liangStage = String(palette.stage);\n body.style.setProperty(\"--liang-strength\", String(palette.strength));\n body.style.setProperty(\"--liang-page\", palette.page);\n body.style.setProperty(\"--liang-bg-base\", palette.base);\n body.style.setProperty(\"--liang-layer-1\", palette.layer1);\n body.style.setProperty(\"--liang-layer-2\", palette.layer2);\n body.style.setProperty(\"--liang-layer-3\", palette.layer3);\n body.style.setProperty(\"--liang-sidebar\", palette.sidebar);\n body.style.setProperty(\"--liang-ink\", palette.ink);\n body.style.setProperty(\"--liang-secondary\", palette.secondary);\n body.style.setProperty(\"--liang-tertiary\", palette.tertiary);\n body.style.setProperty(\"--liang-border\", palette.border);\n body.style.setProperty(\"--liang-accent\", palette.accent);\n body.style.setProperty(\"--liang-accent-hover\", palette.accentHover);\n body.style.setProperty(\"--liang-hover\", palette.hover);\n body.style.setProperty(\"--liang-portrait-opacity\", palette.portraitOpacity);\n this.updatePortrait(palette.level);\n }\n\n syncNativeTheme(theme: NativeThemeId = paletteForFrame(this.frame).stage === 5 ? \"dark\" : \"light\") {\n if (!this.enabled || this.theme.getTheme().preference === theme) return;\n this.theme.setTheme(theme);\n }\n\n private updatePortrait(level: number) {\n if (!this.portraitReady) return;\n const { lowerIndex, upperIndex, mix } = portraitBlendForLevel(\n level,\n ANCHOR_LEVELS,\n );\n const lower = PORTRAIT_ANCHORS[lowerIndex];\n const upper = PORTRAIT_ANCHORS[upperIndex];\n const selected = mix >= 0.5 ? upper : lower;\n const source = `${ASSET_PREFIX}/portrait-source-v2/${selected.file}`;\n if (this.portrait.getAttribute(\"src\") !== source) this.portrait.src = source;\n }\n\n async choose(enabled: boolean) {\n this.setEnabled(enabled);\n try {\n await this.scope.set(enabled);\n } catch (error) {\n this.syncSettings();\n throw error;\n }\n }\n\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.unsubscribe();\n if (this.raf !== 0) cancelAnimationFrame(this.raf);\n this.portrait.removeEventListener(\"error\", this.handleSequenceError);\n for (const image of this.preloads) image.src = \"\";\n this.root.remove();\n document.body.removeAttribute(\"data-liang-skin\");\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n}\n\nfunction modelReasoning(state: ModelDirectoryState) {\n const current = state.current;\n if (current === null) return null;\n const group = state.groups.find((item) => item.id === current.provider);\n const model = group?.models.find((item) => item.id === current.model);\n if (model?.reasoning === undefined) return null;\n return {\n selection: current,\n efforts: model.reasoning.efforts,\n defaultEffort: model.reasoning.defaultEffort,\n };\n}\n\nfunction LiangEffortSlider({ directory, load, select, presenter, scope }: SliderProps) {\n const state = useSyncExternalStore(\n (listener) => directory.subscribe(listener),\n () => directory.getSnapshot(),\n );\n const skin = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const reasoning = useMemo(() => modelReasoning(state), [state]);\n const efforts = reasoning?.efforts ?? [];\n const committedIndex = selectedEffortIndex(\n efforts,\n reasoning?.selection.reasoningEffort,\n reasoning?.defaultEffort,\n );\n // An unknown committed effort defaults to the max frame: a fresh\n // conversation paints the dark shell immediately instead of flashing the\n // light palette until the directory load resolves the real effort.\n const committedFrame = committedIndex < 0\n ? PREVIEW_MAX_FRAME\n : frameForEffort(committedIndex, efforts.length);\n const bindEffort = skin.bindEffort;\n const [frame, setFrame] = useState(() => bindEffort ? committedFrame : presenter.getFrame());\n const [pending, setPending] = useState(false);\n const [failed, setFailed] = useState(false);\n const [interacting, setInteracting] = useState(false);\n const dragging = useRef(false);\n const dragStartFrame = useRef(frame);\n const enabled = skin.enabled;\n\n useEffect(() => {\n if (enabled) load();\n }, [enabled, load]);\n\n useEffect(() => {\n if (!bindEffort || dragging.current || pending) return;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }, [bindEffort, committedFrame, pending, presenter]);\n\n if (!enabled) return null;\n if (bindEffort && (reasoning === null || efforts.length < 2)) return null;\n\n const previewIndex = nearestEffortIndex(frame, efforts);\n const previewEffort = efforts[previewIndex];\n const progressRatio = frame / PREVIEW_MAX_FRAME;\n const tooltipLabel = indicatorLabel(frame, bindEffort ? efforts : []);\n\n const commit = async (rawFrame: number) => {\n if (!bindEffort) {\n dragging.current = false;\n setFrame(rawFrame);\n presenter.setFrame(rawFrame);\n return;\n }\n const targetIndex = nearestEffortIndex(rawFrame, efforts);\n const target = efforts[targetIndex];\n if (target === undefined) return;\n const targetFrame = frameForEffort(targetIndex, efforts.length);\n dragging.current = false;\n setFrame(targetFrame);\n presenter.setFrame(targetFrame);\n if (targetIndex === committedIndex || pending) return;\n setPending(true);\n setFailed(false);\n const accepted = await select({\n provider: reasoning.selection.provider,\n model: reasoning.selection.model,\n reasoningEffort: target.id,\n });\n setPending(false);\n if (!accepted) {\n setFailed(true);\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }\n };\n\n return (\n <div\n className=\"liang-effort-control\"\n data-plugin={PACKAGE_ID}\n data-state={failed ? \"error\" : pending ? \"pending\" : \"ready\"}\n title={bindEffort ? previewEffort?.name : undefined}\n >\n {interacting && (\n <output\n className=\"liang-effort-control__tooltip\"\n style={{ \"--liang-slider-ratio\": progressRatio } as React.CSSProperties}\n >\n {tooltipLabel}\n </output>\n )}\n <div className=\"liang-effort-control__ticks\" aria-hidden=\"true\">\n {efforts.map((effort, index) => (\n <i\n className=\"liang-effort-control__tick\"\n key={effort.id}\n style={{ left: `${(frameForEffort(index, efforts.length) / PREVIEW_MAX_FRAME) * 100}%` }}\n />\n ))}\n </div>\n <input\n className=\"liang-effort-control__range\"\n type=\"range\"\n min={0}\n max={PREVIEW_MAX_FRAME}\n step={1}\n value={frame}\n disabled={pending || state.status === \"selecting\"}\n aria-label={bindEffort ? \"\u601D\u8003\u7B49\u7EA7\" : \"\u76AE\u80A4\u8FDB\u5EA6\"}\n aria-valuetext={bindEffort ? previewEffort?.name ?? \"\" : tooltipLabel}\n onPointerDown={() => {\n dragging.current = true;\n dragStartFrame.current = frame;\n setInteracting(true);\n }}\n onInput={(event) => {\n dragging.current = true;\n const next = Number(event.currentTarget.value);\n setFrame(next);\n presenter.setFrame(next);\n }}\n onPointerUp={(event) => {\n setInteracting(false);\n void commit(Number(event.currentTarget.value));\n }}\n onPointerCancel={() => {\n setInteracting(false);\n dragging.current = false;\n setFrame(dragStartFrame.current);\n presenter.setFrame(dragStartFrame.current);\n }}\n onKeyUp={(event) => {\n setInteracting(false);\n if (event.key !== \"Escape\") void commit(Number(event.currentTarget.value));\n }}\n onBlur={(event) => {\n setInteracting(false);\n if (dragging.current) void commit(Number(event.currentTarget.value));\n }}\n onKeyDown={(event) => {\n setInteracting(true);\n if (event.key === \"Escape\" && !pending) {\n setInteracting(false);\n dragging.current = false;\n setFrame(dragStartFrame.current);\n presenter.setFrame(dragStartFrame.current);\n }\n }}\n />\n </div>\n );\n}\n\ntype AppearanceChoice = NativeThemeId | \"system\" | \"liang\";\n\nconst APPEARANCE_CHOICES: readonly { id: AppearanceChoice; labelKey: string }[] = [\n { id: \"light\", labelKey: \"appearance.light\" },\n { id: \"dark\", labelKey: \"appearance.dark\" },\n { id: \"system\", labelKey: \"appearance.system\" },\n { id: \"liang\", labelKey: \"appearance.liang\" },\n];\n\nfunction NativeAppearanceIcon({ id }: { id: Exclude<AppearanceChoice, \"liang\"> }) {\n if (id === \"light\") {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M11.3496 8C11.3496 6.14985 9.85015 4.65039 8 4.65039C6.14985 4.65039 4.65039 6.14985 4.65039 8C4.65039 9.85015 6.14985 11.3496 8 11.3496C9.85015 11.3496 11.3496 9.85015 11.3496 8ZM12.6504 8C12.6504 10.5681 10.5681 12.6504 8 12.6504C5.43188 12.6504 3.34961 10.5681 3.34961 8C3.34961 5.43188 5.43188 3.34961 8 3.34961C10.5681 3.34961 12.6504 5.43188 12.6504 8Z\" fill=\"currentColor\" />\n <path d=\"M8.65039 0.5V2.5H7.34961V0.5H8.65039Z\" fill=\"currentColor\" />\n <path d=\"M8.65039 13.5V15.5H7.34961V13.5H8.65039Z\" fill=\"currentColor\" />\n <path d=\"M3.15808 2.24035L4.57229 3.65456L3.6525 4.57435L2.23829 3.16014L3.15808 2.24035Z\" fill=\"currentColor\" />\n <path d=\"M12.3505 11.4327L13.7647 12.8469L12.8449 13.7667L11.4307 12.3525L12.3505 11.4327Z\" fill=\"currentColor\" />\n <path d=\"M2.24537 12.8469L3.65958 11.4327L4.57937 12.3525L3.16516 13.7667L2.24537 12.8469Z\" fill=\"currentColor\" />\n <path d=\"M11.4377 3.65455L12.852 2.24033L13.7718 3.16012L12.3575 4.57434L11.4377 3.65455Z\" fill=\"currentColor\" />\n <path d=\"M0.5 7.35461H2.5V8.6554H0.5L0.5 7.35461Z\" fill=\"currentColor\" />\n <path d=\"M13.5 7.35461H15.5V8.6554H13.5V7.35461Z\" fill=\"currentColor\" />\n </svg>\n );\n }\n\n if (id === \"dark\") {\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M13.2764 9.52324C12.5607 9.97754 11.7177 10.242 10.7812 10.242C8.11386 10.2419 5.95042 8.07997 5.9502 5.41289C5.9502 4.48128 6.21453 3.61071 6.67188 2.87285C4.30332 3.4658 2.54992 5.60845 2.5498 8.16093C2.5498 11.1712 4.99103 13.6102 8 13.6102C10.5383 13.6102 12.6709 11.8724 13.2764 9.52324ZM7.05078 5.41289C7.051 7.47224 8.72116 9.1423 10.7812 9.14238C11.9248 9.14238 12.887 8.63397 13.5781 7.8084C13.7266 7.63106 13.9701 7.56547 14.1875 7.64433C14.4049 7.72329 14.5497 7.9297 14.5498 8.16093C14.5498 11.7766 11.6161 14.7098 8 14.7098C4.38402 14.7098 1.4502 11.7792 1.4502 8.16093C1.45033 4.54322 4.3812 1.61015 8 1.61015C8.23027 1.61015 8.43585 1.75352 8.51562 1.96953C8.59536 2.18554 8.53241 2.42829 8.35742 2.57793C7.55573 3.26311 7.05078 4.27876 7.05078 5.41289Z\" fill=\"currentColor\" />\n </svg>\n );\n }\n\n return (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\" aria-hidden=\"true\">\n <path d=\"M12.1665 13.5811V14.7803H3.66651V13.5811H12.1665Z\" fill=\"currentColor\" />\n <path d=\"M13.4453 7.02379C13.4453 6.04702 13.4452 5.3616 13.3887 4.83434C13.3333 4.31828 13.2302 4.02378 13.0723 3.80309C12.9446 3.62475 12.7877 3.46883 12.6094 3.34117C12.3887 3.18328 12.0942 3.08007 11.5781 3.02477C11.0508 2.96829 10.3655 2.96715 9.38867 2.96715H6.61035C5.63359 2.96715 4.94816 2.96827 4.4209 3.02477C3.90486 3.0801 3.61034 3.18321 3.38965 3.34117C3.21143 3.46878 3.05534 3.62487 2.92774 3.80309C2.76977 4.02377 2.66667 4.3183 2.61133 4.83434C2.55483 5.3616 2.55371 6.04702 2.55371 7.02379C2.55371 8.0006 2.55485 8.68596 2.61133 9.21324C2.66663 9.72936 2.76983 10.0238 2.92774 10.2445C3.0554 10.4228 3.21131 10.5797 3.38965 10.7074C3.61034 10.8654 3.90484 10.9685 4.4209 11.0238C4.94816 11.0803 5.63359 11.0804 6.61035 11.0804H9.38867C10.3654 11.0804 11.0508 11.0803 11.5781 11.0238C12.0941 10.9685 12.3887 10.8652 12.6094 10.7074C12.7877 10.5797 12.9446 10.4229 13.0723 10.2445C13.2301 10.0238 13.3334 9.72927 13.3887 9.21324C13.4452 8.68596 13.4453 8.00058 13.4453 7.02379ZM14.6455 7.02379C14.6455 7.97428 14.646 8.73509 14.5811 9.34117C14.5149 9.95828 14.3756 10.4858 14.0479 10.9437C13.8436 11.229 13.5938 11.4788 13.3086 11.683C12.8507 12.0108 12.3232 12.15 11.7061 12.2162C11.1 12.2811 10.3391 12.2806 9.38867 12.2806H6.61035C5.66018 12.2806 4.89991 12.2811 4.29395 12.2162C3.67684 12.15 3.14935 12.0108 2.69141 11.683C2.40613 11.4788 2.15639 11.229 1.95215 10.9437C1.62436 10.4858 1.4841 9.95828 1.41797 9.34117C1.35305 8.73511 1.35449 7.97424 1.35449 7.02379C1.35449 6.07366 1.35308 5.31333 1.41797 4.70738C1.4841 4.09028 1.62436 3.56279 1.95215 3.10485C2.15638 2.81956 2.40613 2.56982 2.69141 2.36559C3.14935 2.03779 3.67684 1.89753 4.29395 1.83141C4.8999 1.76652 5.66022 1.76793 6.61035 1.76793H9.38867C10.3391 1.76793 11.1 1.76649 11.7061 1.83141C12.3232 1.89753 12.8507 2.03779 13.3086 2.36559C13.5939 2.56982 13.8436 2.81957 14.0479 3.10485C14.3756 3.56279 14.5149 4.09028 14.5811 4.70738C14.646 5.31335 14.6455 6.07362 14.6455 7.02379Z\" fill=\"currentColor\" />\n </svg>\n );\n}\n\nfunction AppearanceSkinRow({ scope, presenter, theme, subscribeTheme, t }: SettingsRowProps) {\n const snapshot = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const preference = useSyncExternalStore(\n subscribeTheme,\n () => theme.getTheme().preference,\n );\n const selected = snapshot.enabled\n ? \"liang\"\n : preference === \"light\" || preference === \"dark\" || preference === \"system\"\n ? preference\n : \"system\";\n const [pending, setPending] = useState(false);\n\n const choose = async (next: AppearanceChoice) => {\n if (next === selected || pending) return;\n setPending(true);\n try {\n if (next === \"liang\") {\n await presenter.choose(true);\n } else {\n // Disable the custom skin first. This is intentionally unconditional:\n // it makes the native choice the only writer after this click, even if\n // the external preference store is one render behind.\n await presenter.choose(false);\n theme.setTheme(next);\n }\n } finally {\n setPending(false);\n }\n };\n\n return (\n <div className=\"liang-settings-row\" data-plugin={PACKAGE_ID}>\n <span className=\"liang-settings-row__title\">{t(\"appearance.title\")}</span>\n <div className=\"liang-settings-row__choices\">\n {APPEARANCE_CHOICES.map(({ id, labelKey }) => (\n <button\n className={`liang-settings-row__choice${id === \"liang\" ? \" liang-settings-row__choice--liang\" : \"\"}`}\n type=\"button\"\n aria-pressed={selected === id}\n disabled={pending}\n onClick={() => void choose(id)}\n key={id}\n >\n {id === \"liang\" ? (\n <span className=\"liang-settings-row__liang-icon\" aria-hidden=\"true\">\u25C8</span>\n ) : (\n <NativeAppearanceIcon id={id} />\n )}\n {t(labelKey)}\n </button>\n ))}\n </div>\n </div>\n );\n}\n\nconst NATIVE_APPEARANCE_GROUP = '[class*=\"_8HJdBW_group\"]';\nconst NATIVE_APPEARANCE_ROW = '[class*=\"_8HJdBW_cubeRow\"]';\nconst LIANG_APPEARANCE_BUTTON = \"liang-appearance-choice\";\nconst LIANG_BINDING_CONTROL = \"liang-appearance-binding\";\nconst LIANG_BINDING_INPUT = \"liang-appearance-binding__input\";\n\nfunction installLiangAppearanceButton(scope: PreferenceStore, presenter: SkinPresenter) {\n let pending = false;\n const hookedNativeButtons = new Set<HTMLButtonElement>();\n const nativeClickHandlers = new Map<HTMLButtonElement, () => void>();\n\n const sync = () => {\n const group = [...document.querySelectorAll<HTMLElement>(NATIVE_APPEARANCE_GROUP)]\n .find((node) => node.querySelector('[class*=\"_8HJdBW_themeCube\"]'));\n const row = group?.querySelector<HTMLElement>(NATIVE_APPEARANCE_ROW);\n if (row === undefined || row === null) return;\n\n let customButton = row.querySelector<HTMLButtonElement>(`.${LIANG_APPEARANCE_BUTTON}`);\n if (customButton === null) {\n customButton = document.createElement(\"button\");\n customButton.className = LIANG_APPEARANCE_BUTTON;\n customButton.type = \"button\";\n customButton.dataset.plugin = PACKAGE_ID;\n customButton.setAttribute(\"aria-label\", \"\u6ED1\u52A8\u53D8\u7956\");\n\n const icon = document.createElement(\"span\");\n icon.className = \"liang-appearance-choice__icon\";\n icon.setAttribute(\"aria-hidden\", \"true\");\n icon.textContent = \"\u25C8\";\n\n const label = document.createElement(\"span\");\n label.className = \"liang-appearance-choice__label\";\n label.textContent = document.documentElement.lang.toLowerCase().startsWith(\"en\")\n ? \"Slider\"\n : \"\u6ED1\u52A8\u53D8\u7956\";\n customButton.append(icon, label);\n customButton.addEventListener(\"click\", () => {\n if (pending || scope.getSnapshot().enabled) return;\n pending = true;\n sync();\n void presenter.choose(true).finally(() => {\n pending = false;\n sync();\n });\n });\n }\n\n if (customButton.parentElement !== row) row.append(customButton);\n const snapshot = scope.getSnapshot();\n customButton.disabled = pending;\n customButton.setAttribute(\"aria-pressed\", String(snapshot.enabled));\n\n let bindingControl = group.querySelector<HTMLElement>(`.${LIANG_BINDING_CONTROL}`);\n if (!snapshot.enabled) {\n bindingControl?.remove();\n bindingControl = null;\n } else if (bindingControl === null) {\n bindingControl = document.createElement(\"label\");\n bindingControl.className = LIANG_BINDING_CONTROL;\n bindingControl.dataset.plugin = PACKAGE_ID;\n\n const bindingCopy = document.createElement(\"span\");\n bindingCopy.className = \"liang-appearance-binding__copy\";\n\n const bindingLabel = document.createElement(\"span\");\n bindingLabel.className = \"liang-appearance-binding__label\";\n const bindingText = document.documentElement.lang.toLowerCase().startsWith(\"en\")\n ? \"Bind slider to reasoning level\"\n : \"\u6ED1\u52A8\u53D8\u7956\u7ED1\u5B9A\u601D\u8003\u7B49\u7EA7\";\n bindingLabel.textContent = bindingText;\n\n const bindingDescription = document.createElement(\"span\");\n bindingDescription.className = \"liang-appearance-binding__description\";\n bindingDescription.id = \"liang-appearance-binding-description\";\n bindingDescription.textContent = document.documentElement.lang.toLowerCase().startsWith(\"en\")\n ? \"When off, the slider does not change the reasoning level.\"\n : \"\u5173\u95ED\u4E4B\u540E\u6ED1\u5757\u4E0D\u8054\u52A8\u601D\u8003\u7B49\u7EA7\";\n bindingCopy.append(bindingLabel, bindingDescription);\n\n const bindingInput = document.createElement(\"input\");\n bindingInput.className = LIANG_BINDING_INPUT;\n bindingInput.type = \"checkbox\";\n bindingInput.setAttribute(\"role\", \"switch\");\n bindingInput.setAttribute(\"aria-label\", bindingText);\n bindingInput.setAttribute(\"aria-describedby\", bindingDescription.id);\n bindingInput.addEventListener(\"change\", () => {\n void scope.setBindEffort(bindingInput.checked).catch(() => sync());\n });\n\n bindingControl.append(bindingCopy, bindingInput);\n group.append(bindingControl);\n }\n\n if (bindingControl !== null) {\n const bindingInput = bindingControl.querySelector<HTMLInputElement>(`.${LIANG_BINDING_INPUT}`);\n if (bindingInput !== null) {\n bindingInput.checked = snapshot.bindEffort;\n bindingInput.setAttribute(\"aria-checked\", String(snapshot.bindEffort));\n bindingInput.disabled = pending;\n }\n }\n\n for (const nativeButton of row.querySelectorAll<HTMLButtonElement>('[class*=\"_8HJdBW_themeCube\"]')) {\n if (hookedNativeButtons.has(nativeButton)) continue;\n hookedNativeButtons.add(nativeButton);\n const handleNativeClick = () => {\n if (pending || !scope.getSnapshot().enabled) return;\n pending = true;\n sync();\n void presenter.choose(false).finally(() => {\n pending = false;\n sync();\n });\n };\n nativeClickHandlers.set(nativeButton, handleNativeClick);\n nativeButton.addEventListener(\"click\", handleNativeClick, { capture: true });\n }\n };\n\n const observer = new MutationObserver(sync);\n observer.observe(document.body, { childList: true, subtree: true });\n const unsubscribe = scope.subscribe(sync);\n sync();\n\n return () => {\n observer.disconnect();\n unsubscribe();\n for (const [nativeButton, handleNativeClick] of nativeClickHandlers) {\n nativeButton.removeEventListener(\"click\", handleNativeClick, { capture: true });\n }\n document.querySelectorAll(`.${LIANG_APPEARANCE_BUTTON}`).forEach((button) => button.remove());\n document.querySelectorAll(`.${LIANG_BINDING_CONTROL}`).forEach((control) => control.remove());\n };\n}\n\nexport const inject = [\n \"slots\",\n \"sessions\",\n \"modelDirectories\",\n \"locale\",\n \"theme\",\n];\n\nfunction createPreferenceStore(): PreferenceStore {\n // The market's active skin is the source of truth for whether this client\n // should be visible. The appearance switch is therefore scoped to this\n // client activation and must not survive switching away and back.\n try {\n localStorage.removeItem(\"dsh-liang-intensity-skin.enabled\");\n } catch {\n // Storage may be unavailable; the in-memory default still enables Liang.\n }\n let snapshot: SkinSettings = {\n enabled: true,\n bindEffort: localStorage.getItem(BIND_EFFORT_KEY) !== \"0\",\n };\n const listeners = new Set<() => void>();\n const onStorage = (event: StorageEvent) => {\n if (event.key !== BIND_EFFORT_KEY) return;\n const next = {\n enabled: snapshot.enabled,\n bindEffort: event.newValue !== \"0\",\n };\n if (next.enabled === snapshot.enabled && next.bindEffort === snapshot.bindEffort) return;\n snapshot = next;\n for (const listener of listeners) listener();\n };\n window.addEventListener(\"storage\", onStorage);\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n async set(enabled) {\n if (enabled === snapshot.enabled) return;\n snapshot = { ...snapshot, enabled };\n for (const listener of listeners) listener();\n },\n async setBindEffort(bindEffort) {\n if (bindEffort === snapshot.bindEffort) return;\n localStorage.setItem(BIND_EFFORT_KEY, bindEffort ? \"1\" : \"0\");\n snapshot = { ...snapshot, bindEffort };\n for (const listener of listeners) listener();\n },\n dispose() {\n window.removeEventListener(\"storage\", onStorage);\n listeners.clear();\n },\n };\n}\n\nexport function apply(ctx: ClientContext) {\n const style = document.createElement(\"style\");\n style.dataset.plugin = PACKAGE_ID;\n style.textContent = styles;\n document.head.append(style);\n ctx.effect(() => () => style.remove(), \"liang-intensity-skin: scoped styles\");\n\n const scope = createPreferenceStore();\n ctx.effect(() => () => scope.dispose(), \"liang-intensity-skin: appearance preference\");\n const theme = ctx.get(\"theme\") as ThemeService;\n const presenter = new SkinPresenter(scope, theme);\n ctx.effect(() => () => presenter.dispose(), \"liang-intensity-skin: backdrop presenter\");\n ctx.effect(\n () => installLiangAppearanceButton(scope, presenter),\n \"liang-intensity-skin: native appearance extension\",\n );\n ctx.effect(\n () => ctx.locale.register(LOCALE_NAMESPACE, {\n zh: {\n \"appearance.title\": \"\u5916\u89C2\",\n \"appearance.light\": \"\u6D45\u8272\",\n \"appearance.dark\": \"\u6DF1\u8272\",\n \"appearance.system\": \"\u8DDF\u968F\u7CFB\u7EDF\",\n \"appearance.liang\": \"\u6ED1\u52A8\u53D8\u7956\",\n },\n en: {\n \"appearance.title\": \"Appearance\",\n \"appearance.light\": \"Light\",\n \"appearance.dark\": \"Dark\",\n \"appearance.system\": \"System\",\n \"appearance.liang\": \"Slider\",\n },\n }), \"liang-intensity-skin: settings locale\");\n\n ctx.slots.inject(\"conversation.input.right\", () => ctx.slots.register({\n name: \"conversation.input.right\",\n id: \"liang-intensity-control\",\n order: 10,\n inject: (sessionId: string) => {\n const available = ctx.sessions.subagentAddress(sessionId) === undefined;\n const directory = ctx.modelDirectories.directoryFor(sessionId) as ModelDirectory;\n return {\n directory: directory.store,\n presenter,\n scope,\n load: () => {\n if (available) void directory.load().catch(() => undefined);\n },\n select: (selection: ModelSelection) => available\n ? directory.select(selection).then((result) => result.ok, () => false)\n : Promise.resolve(false),\n };\n },\n }, LiangEffortSlider));\n}\n", ".liang-skin-backdrop {\n position: fixed;\n z-index: 0;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n background: var(--liang-page, transparent);\n opacity: 0;\n transition: opacity 220ms ease, background-color 180ms linear;\n}\n\nbody[data-liang-skin=\"on\"] .liang-skin-backdrop {\n opacity: 1;\n}\n\n.liang-skin-backdrop img {\n position: absolute;\n top: 50%;\n right: 0;\n display: block;\n width: min(42vw, 720px);\n height: 100vh;\n object-fit: cover;\n object-position: 50% 42%;\n opacity: var(--liang-portrait-opacity, 0.45);\n transform: translateY(-50%);\n filter: none;\n mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 20%) 10%, black 30%, black 100%);\n transition: filter 180ms linear;\n}\n\n.liang-skin-backdrop img {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"sequence\"] .liang-skin-sequence-frame {\n display: block;\n opacity: var(--liang-portrait-opacity, 0.82);\n}\n\n.liang-skin-backdrop[data-media=\"color\"] img {\n display: none;\n}\n\n.liang-skin-backdrop::after {\n position: absolute;\n inset: 0;\n content: \"\";\n background: linear-gradient(90deg, var(--liang-page, transparent) 0 28%, transparent 57% 100%);\n}\n\nbody[data-liang-skin=\"on\"] {\n --dsw-alias-bg-base: var(--liang-bg-base) !important;\n --dsw-alias-bg-layer-1: var(--liang-layer-1) !important;\n --dsw-alias-bg-layer-2: var(--liang-layer-2) !important;\n --dsw-alias-bg-layer-3: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-fill: var(--liang-sidebar) !important;\n --dsw-alias-label-primary: var(--liang-ink) !important;\n --dsw-alias-label-primary-dimmed: var(--liang-ink) !important;\n --dsw-alias-label-secondary: var(--liang-secondary) !important;\n --dsw-alias-label-tertiary: var(--liang-tertiary) !important;\n --dsw-alias-label-caption: var(--liang-tertiary) !important;\n --dsw-alias-border-l1: var(--liang-border) !important;\n --dsw-alias-border-l2-darkmode-thin: var(--liang-border) !important;\n --dsw-alias-border-l2: var(--liang-border) !important;\n --dsw-alias-border-l3: var(--liang-border) !important;\n --dsw-alias-button-primary-fill: var(--liang-accent) !important;\n --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important;\n --dsw-alias-button-info-fill: var(--liang-accent) !important;\n --dsw-alias-button-info-hover: var(--liang-accent-hover) !important;\n --dsw-alias-state-business-primary: var(--liang-accent) !important;\n --dsw-alias-interactive-bg-hover: var(--liang-hover) !important;\n --dsw-alias-interactive-bg-active: var(--liang-hover) !important;\n --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important;\n --dsw-alias-button-floating-fill: var(--liang-layer-2) !important;\n --dsw-alias-button-floating-hover: var(--liang-layer-3) !important;\n --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important;\n --dsw-specific-bubble: var(--liang-layer-2) !important;\n --dsw-specific-input-major: var(--liang-layer-1) !important;\n --dsw-specific-menu: var(--liang-layer-3) !important;\n --dsw-specific-selector: var(--liang-layer-2) !important;\n --dsw-alias-markdown-citation: var(--liang-layer-2) !important;\n --dsw-alias-markdown-code-block-banner: var(--liang-layer-1) !important;\n --dsw-alias-markdown-code-block: var(--liang-layer-1) !important;\n --dsw-alias-markdown-code-segment-selected: var(--liang-layer-2) !important;\n --dsw-alias-markdown-code-segment-unselected: var(--liang-layer-1) !important;\n --dsw-alias-markdown-inline-code: var(--liang-layer-2) !important;\n --dsw-alias-markdown-placeholder: var(--liang-layer-1) !important;\n --dsw-alias-markdown-tag: var(--liang-layer-2) !important;\n background: var(--liang-page) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) {\n --dsw-alias-brand-primary-new-colorprimary-new-color: rgb(65 118 230) !important;\n --dsw-alias-brand-primary: rgb(15 17 21) !important;\n --dsw-alias-brand-text: rgb(15 17 21) !important;\n --dsw-alias-button-primary-fill: rgb(15 17 21) !important;\n --dsw-alias-button-primary-hover: rgb(53 54 56) !important;\n --dsw-alias-button-info-fill: rgb(65 118 230) !important;\n --dsw-alias-button-info-hover: rgb(103 158 254) !important;\n --dsw-alias-state-business-primary: rgb(65 118 230) !important;\n --dsw-alias-label-primary-inverted: rgb(249 250 251) !important;\n --dsw-alias-button-elevated-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-hover: rgb(241 243 245) !important;\n --dsw-alias-interactive-bg-hover-solid: rgb(241 243 245) !important;\n --dsw-specific-bubble: rgb(237 243 254) !important;\n --dsw-specific-input-major: rgb(255 255 255) !important;\n --dsw-specific-menu: rgb(255 255 255) !important;\n --dsw-specific-selector: rgb(245 246 247) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] {\n --dsw-alias-brand-primary-new-colorprimary-new-color: #c19a49 !important;\n --dsw-alias-brand-primary: #c19a49 !important;\n --dsw-alias-brand-text: #d5b56e !important;\n --dsw-alias-button-info-fill: #c19a49 !important;\n --dsw-alias-button-info-hover: #d5b56e !important;\n --dsw-alias-state-business-primary: #c19a49 !important;\n --dsw-alias-bg-module-platform: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-nav-item-active: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-nav-item-hover: var(--liang-hover) !important;\n}\n\n/* The host renders the running-turn label as a clipped blue text gradient.\n Retarget only that gradient's color tokens in the custom dark skin; keep\n the host's text clipping and shimmer behavior, and leave light mode alone. */\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"_turnStatus\"] {\n --dsw-static-deepseek-500: #c19a49 !important;\n --dsw-static-deepseek-200: #d5b56e !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"_turnStatusClock\"] {\n color: #c19a49 !important;\n -webkit-text-fill-color: #c19a49 !important;\n}\n\n/* Preserve the wordmark badge contrast in the low-intensity shell. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: rgb(15 17 21) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: rgb(249 250 251) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [aria-label^=\"\u9009\u62E9\u6A21\u578B\"] > span:nth-of-type(2) {\n color: #d5b56e !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"heroGlow\"] ellipse {\n fill: #c19a49 !important;\n fill-opacity: 0.16 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] span[class*=\"_previewBadge\"] {\n color: #171816 !important;\n background: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n opacity: 0.62;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #fff !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n color: rgb(255 255 255 / 92%) !important;\n background: rgb(65 118 230 / 42%) !important;\n opacity: 1;\n}\n\nbody[data-liang-skin=\"on\"] > #root {\n position: relative;\n z-index: 1;\n background: transparent !important;\n}\n\n/* Windows paints the sidebar fill across the host frame, covering the portrait.\n Match macOS's transparent frame while keeping the sidebar, caption, and\n conversation surfaces painted by their own host rules. */\nhtml[data-windows-titlebar] body[data-liang-skin=\"on\"] #root [class*=\"_frame\"]:has(> [class*=\"_centerCol\"]) {\n background: transparent !important;\n}\n\n/* macOS adds different translucent sidebar materials for native light/dark.\n While Liang is active, the effort palette owns the sidebar fill. */\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_frame\"]:has(> [class*=\"_centerCol\"]) > [class*=\"_sidebarCol\"] {\n background: var(--liang-sidebar) !important;\n}\n\n/* Keep the host's expanded new-session surface on the same palette. The\n collapsed icon keeps its native transparent surface and hover behavior. */\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"]:has(> [class*=\"_logoRow\"]):not([class*=\"_collapsed\"]) button[class*=\"_newSession\"] {\n background: var(--dsw-alias-button-elevated-fill) !important;\n}\n\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"]:has(> [class*=\"_logoRow\"]):not([class*=\"_collapsed\"]) button[class*=\"_newSession\"]:hover {\n background: var(--dsw-alias-button-floating-hover) !important;\n}\n\n/* The native dark rule also outranks the collapsed icon's transparent fill. */\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"][class*=\"_collapsed\"]:has(> [class*=\"_logoRow\"]) button[class*=\"_newSession\"] {\n background: transparent !important;\n}\n\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"][class*=\"_collapsed\"]:has(> [class*=\"_logoRow\"]) button[class*=\"_newSession\"]:hover {\n background: var(--dsw-alias-interactive-bg-hover) !important;\n}\n\nbody[data-liang-skin=\"on\"] button,\nbody[data-liang-skin=\"on\"] input,\nbody[data-liang-skin=\"on\"] textarea {\n transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear;\n}\n\n/* The composer card has a native theme-mode fill, so keep its surface and\n readable ink aligned with the active Liang palette. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] {\n border-color: var(--liang-border) !important;\n color: var(--liang-ink) !important;\n background: var(--liang-layer-1) !important;\n box-shadow: 0 8px 28px rgb(20 22 20 / 8%);\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] :is(textarea, button, [data-input-mirror=\"true\"]) {\n color: var(--liang-ink) !important;\n caret-color: var(--liang-accent) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] textarea::placeholder {\n color: var(--liang-tertiary) !important;\n opacity: 1;\n}\n\n.liang-effort-control {\n --liang-control-accent: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n --liang-control-rail: var(--dsw-alias-border-l3, rgb(0 0 0 / 16%));\n position: relative;\n display: flex;\n width: 124px;\n height: 28px;\n align-items: center;\n margin: 0 3px;\n overflow: visible;\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control {\n --liang-control-accent: var(--liang-secondary);\n --liang-control-rail: color-mix(in srgb, var(--liang-secondary) 28%, transparent);\n}\n\n.liang-effort-control__ticks {\n position: absolute;\n z-index: 0;\n inset: 0 10px;\n pointer-events: none;\n}\n\n.liang-effort-control__ticks::before {\n position: absolute;\n top: 50%;\n right: 0;\n left: 0;\n height: 1px;\n content: \"\";\n background: var(--liang-control-rail);\n transform: translateY(-50%);\n}\n\n.liang-effort-control__tooltip {\n position: absolute;\n z-index: 4;\n bottom: calc(100% + 7px);\n left: calc(10px + (100% - 20px) * var(--liang-slider-ratio));\n min-width: max-content;\n padding: 5px 8px;\n border: 1px solid var(--liang-border, rgb(0 0 0 / 12%));\n border-radius: 7px;\n color: var(--liang-ink, #171816);\n background: var(--liang-layer-1, #fff);\n box-shadow: 0 5px 16px rgb(0 0 0 / 16%);\n font-size: 11px;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0.01em;\n pointer-events: none;\n transform: translateX(-50%);\n white-space: nowrap;\n}\n\n.liang-effort-control__tooltip::after {\n position: absolute;\n top: 100%;\n left: 50%;\n width: 7px;\n height: 7px;\n content: \"\";\n background: inherit;\n transform: translate(-50%, -4px) rotate(45deg);\n}\n\n.liang-effort-control__tick {\n position: absolute;\n top: 50%;\n width: 1px;\n height: 7px;\n background: var(--liang-control-accent);\n opacity: 0.42;\n transform: translate(-50%, -50%);\n}\n\n.liang-effort-control__range {\n position: relative;\n z-index: 1;\n width: calc(100% - 7px);\n height: 28px;\n margin: 0 3.5px;\n cursor: ew-resize;\n appearance: none;\n background: transparent;\n touch-action: pan-y;\n}\n\n.liang-effort-control__range:disabled {\n cursor: progress;\n opacity: 0.58;\n}\n\n.liang-effort-control__range::-webkit-slider-runnable-track {\n height: 1px;\n border-radius: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n appearance: none;\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--dsw-alias-bg-layer-1, #fff)) 2.5px);\n box-shadow: 0 1px 4px rgb(0 0 0 / 14%);\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border-color: color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--liang-layer-1)) 2.5px);\n}\n\n.liang-effort-control__range::-moz-range-track {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-progress {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-thumb {\n width: 11px;\n height: 11px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n background: color-mix(in srgb, var(--liang-control-accent) 24%, var(--dsw-alias-bg-layer-1, #fff));\n}\n\n.liang-effort-control__range:focus-visible {\n outline: none;\n}\n\n.liang-effort-control[data-state=\"error\"] {\n --liang-control-accent: var(--dsw-alias-state-error-primary, #e43c3c);\n}\n\n.liang-appearance-choice {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n flex: 180px;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 4px;\n padding: 20px 32px;\n border-radius: 16px;\n font: inherit;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n background: transparent;\n font-size: 14px;\n line-height: 22px;\n display: flex;\n}\n\n[class*=\"_8HJdBW_cubeRow\"]:has(.liang-appearance-choice) {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n}\n\n.liang-appearance-choice:hover:not([aria-pressed=\"true\"]) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.liang-appearance-choice[aria-pressed=\"true\"] {\n border-color: var(--dsw-static-neutral-bluish-400);\n background: var(--dsw-alias-bg-module-platform);\n}\n\n.liang-appearance-choice__icon {\n display: block;\n flex: 0 0 16px;\n width: 16px;\n height: 16px;\n color: currentColor;\n font-size: 16px;\n line-height: 16px;\n}\n\n.liang-appearance-choice__label {\n display: block;\n}\n\n/* Keep the host's three theme cubes untouched. These rules only style the\n fourth button that is appended to the host cube row. */\n.liang-appearance-choice:disabled {\n cursor: progress;\n opacity: 0.7;\n}\n\n.liang-appearance-binding {\n box-sizing: border-box;\n display: flex;\n width: 100%;\n min-height: 28px;\n align-items: center;\n justify-content: space-between;\n gap: 16px;\n padding: 4px 0 0;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n cursor: pointer;\n}\n\n.liang-appearance-binding__label {\n display: block;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.liang-appearance-binding__copy {\n display: flex;\n min-width: 0;\n flex-direction: column;\n gap: 1px;\n}\n\n.liang-appearance-binding__description {\n display: block;\n overflow: hidden;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 18px;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.liang-appearance-binding__input {\n position: relative;\n flex: 0 0 36px;\n width: 36px;\n height: 20px;\n margin: 0;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n outline: none;\n cursor: pointer;\n appearance: none;\n background: var(--dsw-alias-interactive-bg-hover, var(--dsw-alias-bg-module-platform));\n}\n\n.liang-appearance-binding__input::before {\n position: absolute;\n top: 2px;\n left: 2px;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n content: \"\";\n background: var(--dsw-alias-label-primary);\n box-shadow: 0 1px 3px rgb(0 0 0 / 18%);\n transition: transform 160ms ease, background-color 160ms ease;\n}\n\n.liang-appearance-binding__input:checked {\n border-color: var(--dsw-static-neutral-bluish-400);\n background: var(--dsw-static-neutral-bluish-400);\n}\n\n.liang-appearance-binding__input:checked::before {\n background: var(--dsw-alias-bg-layer-1, #fff);\n transform: translateX(16px);\n}\n\n.liang-appearance-binding__input:focus-visible {\n box-shadow: 0 0 0 2px var(--dsw-alias-interactive-bg-hover);\n}\n\n.liang-appearance-binding__input:disabled {\n cursor: progress;\n opacity: 0.7;\n}\n\n@media (max-width: 760px) {\n .liang-effort-control {\n width: 92px;\n }\n\n .liang-skin-backdrop img {\n right: -18vw;\n width: 92vw;\n opacity: calc(var(--liang-portrait-opacity, 0.45) * 0.72);\n }\n\n}\n\n@media (prefers-reduced-motion: reduce) {\n .liang-skin-backdrop,\n .liang-skin-backdrop img,\n body[data-liang-skin=\"on\"] button,\n body[data-liang-skin=\"on\"] input,\n body[data-liang-skin=\"on\"] textarea {\n transition: none;\n }\n}\n", "export const PREVIEW_MAX_FRAME = 240;\nexport const MAX_LEVEL = 30;\n\nconst LIANG_RANKS = [\"\u5C0F\u96BE\u6881\", \"\u7262\u6881\", \"\u6881\u5B50\", \"\u6881\u5723\", \"\u6881\u795E\", \"\u6881\u7956\"] as const;\n\nexport interface EffortLike {\n id: string;\n name: string;\n description?: string;\n}\n\nexport interface Palette {\n level: number;\n stage: number;\n strength: number;\n page: string;\n base: string;\n layer1: string;\n layer2: string;\n layer3: string;\n sidebar: string;\n ink: string;\n secondary: string;\n tertiary: string;\n border: string;\n accent: string;\n accentHover: string;\n hover: string;\n portraitOpacity: string;\n}\n\ntype Rgb = readonly [number, number, number];\n\ninterface PaletteStop {\n at: number;\n page: Rgb;\n surface: Rgb;\n surface2: Rgb;\n ink: Rgb;\n secondary: Rgb;\n accent: Rgb;\n portraitOpacity: number;\n}\n\n// These are the original calibrator's six stage anchors: pale neutral at the\n// low end, progressively smoked surfaces, then charcoal and antique gold.\nconst STOPS: readonly PaletteStop[] = [\n { at: 0, page: [232, 233, 229], surface: [248, 248, 245], surface2: [238, 239, 235], ink: [23, 24, 22], secondary: [112, 116, 111], accent: [181, 43, 36], portraitOpacity: 0.92 },\n { at: 6, page: [211, 211, 206], surface: [239, 239, 234], surface2: [224, 224, 218], ink: [26, 26, 24], secondary: [101, 101, 96], accent: [181, 43, 36], portraitOpacity: 0.93 },\n { at: 12, page: [171, 168, 162], surface: [211, 208, 201], surface2: [190, 186, 179], ink: [27, 26, 24], secondary: [83, 79, 74], accent: [166, 54, 42], portraitOpacity: 0.94 },\n { at: 18, page: [117, 112, 106], surface: [154, 148, 140], surface2: [128, 122, 115], ink: [24, 22, 20], secondary: [65, 61, 56], accent: [154, 56, 42], portraitOpacity: 0.94 },\n { at: 24, page: [43, 39, 37], surface: [48, 43, 40], surface2: [58, 51, 46], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [181, 92, 54], portraitOpacity: 0.94 },\n { at: 30, page: [17, 17, 17], surface: [30, 27, 25], surface2: [41, 35, 30], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [193, 154, 73], portraitOpacity: 0.94 },\n];\n\nexport function clampFrame(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(value)));\n}\n\nexport function frameForEffort(index: number, count: number): number {\n if (count <= 1 || !Number.isFinite(index)) return 0;\n const safe = Math.min(count - 1, Math.max(0, Math.round(index)));\n return Math.round((safe / (count - 1)) * PREVIEW_MAX_FRAME);\n}\n\nexport function nearestEffortIndex(frame: number, efforts: readonly EffortLike[]): number {\n if (efforts.length === 0) return -1;\n const safe = clampFrame(frame);\n let best = 0;\n let distance = Math.abs(safe - frameForEffort(0, efforts.length));\n for (let index = 1; index < efforts.length; index += 1) {\n const next = Math.abs(safe - frameForEffort(index, efforts.length));\n if (next < distance) {\n best = index;\n distance = next;\n }\n }\n return best;\n}\n\nexport function selectedEffortIndex(\n efforts: readonly EffortLike[],\n selectedId?: string,\n defaultId?: string,\n): number {\n const id = selectedId ?? defaultId;\n return id === undefined ? -1 : efforts.findIndex((effort) => effort.id === id);\n}\n\nexport function portraitBlendForLevel(level: number, anchors: readonly number[]) {\n if (anchors.length === 0) return { lowerIndex: -1, upperIndex: -1, mix: 0 };\n const safeLevel = Number.isFinite(level)\n ? Math.min(anchors[anchors.length - 1], Math.max(anchors[0], level))\n : anchors[0];\n let upperIndex = anchors.findIndex((anchor) => anchor >= safeLevel);\n if (upperIndex < 0) upperIndex = anchors.length - 1;\n const lowerIndex = Math.max(0, upperIndex - (anchors[upperIndex] > safeLevel ? 1 : 0));\n const span = anchors[upperIndex] - anchors[lowerIndex];\n return {\n lowerIndex,\n upperIndex,\n mix: span === 0 ? 0 : (safeLevel - anchors[lowerIndex]) / span,\n };\n}\n\nexport function liangRankForFrame(rawFrame: number): string {\n const level = (clampFrame(rawFrame) / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const index = level >= MAX_LEVEL ? LIANG_RANKS.length - 1 : Math.floor(level / 6);\n return LIANG_RANKS[Math.min(LIANG_RANKS.length - 1, Math.max(0, index))];\n}\n\nexport function indicatorLabel(rawFrame: number, efforts: readonly EffortLike[]): string {\n const effort = efforts[nearestEffortIndex(rawFrame, efforts)];\n return effort === undefined\n ? liangRankForFrame(rawFrame)\n : `${liangRankForFrame(rawFrame)} \u00B7 ${effort.name}`;\n}\n\nfunction lerp(a: number, b: number, amount: number): number {\n return a + (b - a) * amount;\n}\n\nfunction mix(a: Rgb, b: Rgb, amount: number): Rgb {\n return [\n Math.round(lerp(a[0], b[0], amount)),\n Math.round(lerp(a[1], b[1], amount)),\n Math.round(lerp(a[2], b[2], amount)),\n ];\n}\n\nfunction rgb(value: Rgb, alpha = 1): string {\n return alpha === 1\n ? `rgb(${value[0]} ${value[1]} ${value[2]})`\n : `rgb(${value[0]} ${value[1]} ${value[2]} / ${alpha})`;\n}\n\nexport function paletteForFrame(rawFrame: number): Palette {\n const frame = clampFrame(rawFrame);\n const level = (frame / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const portraitStage = Math.min(5, Math.floor(level / 6));\n const portraitFrom = STOPS[portraitStage];\n const portraitTo = STOPS[Math.min(5, portraitStage + 1)];\n const portraitAmount = portraitFrom === portraitTo\n ? 0\n : (level - portraitFrom.at) / (portraitTo.at - portraitFrom.at);\n\n // The UI itself is intentionally binary: levels 0\u201323 keep the native light\n // shell; entering the original \u6881\u795E/\u6881\u7956 region at level 24 switches black/gold.\n const dark = level >= 24;\n const stage = dark ? 5 : 0;\n const ui = dark ? STOPS[5] : STOPS[0];\n const page = ui.page;\n const surface = ui.surface;\n const surface2 = ui.surface2;\n const sidebar = mix(page, surface2, 0.25);\n const ink = ui.ink;\n const secondary = ui.secondary;\n // Keep Harness' native blue in the light shell. The original calibrator's\n // antique gold only becomes the product accent once the dark region begins.\n const accent: Rgb = dark ? [193, 154, 73] : [65, 118, 230];\n const accentHover = mix(accent, ink, 0.13);\n\n return {\n level,\n stage,\n strength: level / MAX_LEVEL,\n page: rgb(page),\n // Keep the shell readable while allowing the right-side portrait to remain\n // visibly present. Dense controls use the opaque layer tokens below.\n base: rgb(page, dark ? 0.42 : 0.28),\n layer1: rgb(surface, 0.94),\n layer2: rgb(surface2, 0.96),\n layer3: rgb(surface2, 0.99),\n sidebar: rgb(sidebar, 0.96),\n ink: rgb(ink),\n secondary: rgb(secondary),\n tertiary: rgb(mix(secondary, page, 0.28)),\n border: rgb(ink, dark ? 0.15 : 0.12),\n accent: rgb(accent),\n accentHover: rgb(accentHover),\n hover: rgb(ink, dark ? 0.09 : 0.07),\n portraitOpacity: String(lerp(\n portraitFrom.portraitOpacity,\n portraitTo.portraitOpacity,\n portraitAmount,\n )),\n };\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;;;ACNP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AA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",
|
|
6
|
-
"names": [
|
|
3
|
+
"sources": ["../src/client/index.tsx", "../src/client/skin.css", "../src/client/appearance.ts", "../src/client/portrait-loader.ts", "../src/client/logic.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n useEffect,\n useMemo,\n useRef,\n useState,\n useSyncExternalStore,\n} from \"react\";\nimport { Switch } from \"@deepseek-ai/dsh-client-ui-primitives\";\nimport type { Context as ClientContext } from \"@deepseek-ai/cordis\";\nimport type { SnapshotStore } from \"@deepseek-ai/dsh-client-store\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-conversation/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-settings/client\";\nimport type {} from \"@deepseek-ai/dsh-client-ui-model-selection/client\";\nimport styles from \"./skin.css\";\nimport { installLiangAppearanceButton } from \"./appearance\";\nimport { createPortraitLoader } from \"./portrait-loader\";\nimport {\n PREVIEW_MAX_FRAME,\n frameForEffort,\n indicatorLabel,\n nearestEffortIndex,\n paletteForFrame,\n selectedEffortIndex,\n type EffortLike,\n} from \"./logic\";\n\nconst PACKAGE_ID = \"dsh-client-liang-intensity-skin\";\nconst LOCALE_NAMESPACE = \"liang.skin\";\nconst ASSET_PREFIX = `/plugins/${PACKAGE_ID}/assets`;\nconst BIND_EFFORT_KEY = \"dsh-liang-intensity-skin.bind-effort\";\n\nconst PORTRAIT_ANCHORS = [\n { level: 0, file: \"stage-00.webp\" },\n { level: 1, file: \"level-01.webp\" },\n { level: 3, file: \"level-03.webp\" },\n { level: 4, file: \"level-04.webp\" },\n { level: 6, file: \"stage-06.webp\" },\n { level: 7, file: \"level-07.webp\" },\n { level: 9, file: \"level-09.webp\" },\n { level: 10, file: \"level-10.webp\" },\n { level: 12, file: \"stage-12.webp\" },\n { level: 13, file: \"level-13.webp\" },\n { level: 14, file: \"level-14.webp\" },\n { level: 15, file: \"bridge-15.webp\" },\n { level: 16, file: \"level-16.webp\" },\n { level: 17, file: \"level-17.webp\" },\n { level: 18, file: \"stage-18.webp\" },\n { level: 19, file: \"level-19.webp\" },\n { level: 21, file: \"level-21.webp\" },\n { level: 22, file: \"level-22.webp\" },\n { level: 24, file: \"stage-24.webp\" },\n { level: 25, file: \"level-25.webp\" },\n { level: 27, file: \"bridge-27.webp\" },\n { level: 28, file: \"level-28.webp\" },\n { level: 29, file: \"level-29.webp\" },\n { level: 30, file: \"stage-30.webp\" },\n] as const;\n\ninterface SkinSettings {\n enabled: boolean;\n bindEffort: boolean;\n}\n\ninterface PreferenceStore {\n getSnapshot(): SkinSettings;\n subscribe(listener: () => void): () => void;\n set(enabled: boolean): Promise<void>;\n setBindEffort(enabled: boolean): Promise<void>;\n dispose(): void;\n}\n\ntype NativeThemeId = \"light\" | \"dark\";\n\ninterface ThemeService {\n getTheme(): { preference: string };\n setTheme(id: NativeThemeId | \"system\"): void;\n}\n\ninterface ModelSelection {\n provider: string;\n model: string;\n reasoningEffort?: string;\n}\n\ninterface CatalogModel {\n id: string;\n reasoning?: {\n efforts: EffortLike[];\n defaultEffort?: string;\n };\n}\n\ninterface ModelDirectoryState {\n current: ModelSelection | null;\n groups: readonly { id: string; models: CatalogModel[] }[];\n status: \"idle\" | \"loading\" | \"ready\" | \"selecting\" | \"error\";\n error: string | null;\n}\n\ninterface ModelDirectory {\n store: SnapshotStore<ModelDirectoryState>;\n load(): Promise<unknown>;\n select(selection: ModelSelection): Promise<{ ok: boolean }>;\n}\n\ninterface SliderProps {\n directory: SnapshotStore<ModelDirectoryState>;\n load: () => void;\n select: (selection: ModelSelection) => Promise<boolean>;\n presenter: SkinPresenter;\n scope: PreferenceStore;\n}\n\ninterface EffortBindingRowProps {\n scope: PreferenceStore;\n t: (key: string) => string;\n}\n\nconst cssVariables = [\n \"--liang-strength\",\n \"--liang-page\",\n \"--liang-bg-base\",\n \"--liang-layer-1\",\n \"--liang-layer-2\",\n \"--liang-layer-3\",\n \"--liang-sidebar\",\n \"--liang-ink\",\n \"--liang-secondary\",\n \"--liang-tertiary\",\n \"--liang-border\",\n \"--liang-accent\",\n \"--liang-accent-hover\",\n \"--liang-hover\",\n \"--liang-portrait-opacity\",\n] as const;\n\nclass SkinPresenter {\n private readonly scope: PreferenceStore;\n private readonly theme: ThemeService;\n private readonly root: HTMLDivElement;\n private readonly portraits: ReturnType<typeof createPortraitLoader>;\n private enabled = true;\n // Default to the max frame so the first paint after load is the dark shell;\n // starting at 0 flashed the light palette before the directory resolved.\n private frame = PREVIEW_MAX_FRAME;\n private pendingFrame = PREVIEW_MAX_FRAME;\n private raf = 0;\n private disposed = false;\n private unsubscribe: () => void;\n\n constructor(scope: PreferenceStore, theme: ThemeService) {\n this.scope = scope;\n this.theme = theme;\n this.root = document.createElement(\"div\");\n this.root.className = \"liang-skin-backdrop\";\n this.root.dataset.plugin = PACKAGE_ID;\n this.root.dataset.media = \"color\";\n this.root.setAttribute(\"aria-hidden\", \"true\");\n this.portraits = createPortraitLoader({\n sources: PORTRAIT_ANCHORS.map(({ level, file }) => ({\n level,\n url: `${ASSET_PREFIX}/portrait-source-v2/${file}`,\n })),\n onChange: ({ image }) => {\n if (this.disposed || !this.enabled) return;\n if (image === null) {\n this.root.dataset.media = \"color\";\n this.root.replaceChildren();\n return;\n }\n // Reuse the decoded node so a frame swap cannot start a second fetch.\n const portrait = image as HTMLImageElement;\n portrait.className = \"liang-skin-sequence-frame\";\n portrait.alt = \"\";\n portrait.draggable = false;\n if (this.root.firstChild !== portrait) this.root.replaceChildren(portrait);\n this.root.dataset.media = \"sequence\";\n },\n });\n\n this.unsubscribe = scope.subscribe(() => this.syncSettings());\n this.syncSettings();\n }\n\n private syncSettings() {\n this.setEnabled(this.scope.getSnapshot().enabled);\n }\n\n isEnabled() {\n return this.enabled;\n }\n\n getFrame() {\n return this.frame;\n }\n\n setEnabled(enabled: boolean) {\n if (this.disposed) return;\n this.enabled = enabled;\n if (enabled) {\n if (!this.root.isConnected) document.body.prepend(this.root);\n document.body.dataset.liangSkin = \"on\";\n this.applyFrame();\n this.portraits.start();\n } else {\n if (this.raf !== 0) cancelAnimationFrame(this.raf);\n this.raf = 0;\n this.root.remove();\n this.portraits.stop();\n this.root.replaceChildren();\n this.root.dataset.media = \"color\";\n delete document.body.dataset.liangSkin;\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n }\n\n setFrame(frame: number) {\n if (this.disposed) return;\n this.pendingFrame = Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(frame)));\n this.frame = this.pendingFrame;\n if (!this.enabled) return;\n if (this.raf !== 0) return;\n this.raf = requestAnimationFrame(() => {\n this.raf = 0;\n this.frame = this.pendingFrame;\n this.applyFrame();\n });\n }\n\n private applyFrame() {\n if (this.disposed || !this.enabled) return;\n const palette = paletteForFrame(this.frame);\n const body = document.body;\n this.syncNativeTheme(palette.stage === 5 ? \"dark\" : \"light\");\n body.dataset.liangStage = String(palette.stage);\n body.style.setProperty(\"--liang-strength\", String(palette.strength));\n body.style.setProperty(\"--liang-page\", palette.page);\n body.style.setProperty(\"--liang-bg-base\", palette.base);\n body.style.setProperty(\"--liang-layer-1\", palette.layer1);\n body.style.setProperty(\"--liang-layer-2\", palette.layer2);\n body.style.setProperty(\"--liang-layer-3\", palette.layer3);\n body.style.setProperty(\"--liang-sidebar\", palette.sidebar);\n body.style.setProperty(\"--liang-ink\", palette.ink);\n body.style.setProperty(\"--liang-secondary\", palette.secondary);\n body.style.setProperty(\"--liang-tertiary\", palette.tertiary);\n body.style.setProperty(\"--liang-border\", palette.border);\n body.style.setProperty(\"--liang-accent\", palette.accent);\n body.style.setProperty(\"--liang-accent-hover\", palette.accentHover);\n body.style.setProperty(\"--liang-hover\", palette.hover);\n body.style.setProperty(\"--liang-portrait-opacity\", palette.portraitOpacity);\n this.updatePortrait(palette.level);\n }\n\n syncNativeTheme(theme: NativeThemeId = paletteForFrame(this.frame).stage === 5 ? \"dark\" : \"light\") {\n if (!this.enabled || this.theme.getTheme().preference === theme) return;\n this.theme.setTheme(theme);\n }\n\n private updatePortrait(level: number) {\n this.portraits.select(level);\n }\n\n async choose(enabled: boolean) {\n this.setEnabled(enabled);\n try {\n await this.scope.set(enabled);\n } catch (error) {\n this.syncSettings();\n throw error;\n }\n }\n\n dispose() {\n if (this.disposed) return;\n this.disposed = true;\n this.unsubscribe();\n if (this.raf !== 0) cancelAnimationFrame(this.raf);\n this.portraits.dispose();\n this.root.remove();\n document.body.removeAttribute(\"data-liang-skin\");\n delete document.body.dataset.liangStage;\n for (const name of cssVariables) document.body.style.removeProperty(name);\n }\n}\n\nfunction modelReasoning(state: ModelDirectoryState) {\n const current = state.current;\n if (current === null) return null;\n const group = state.groups.find((item) => item.id === current.provider);\n const model = group?.models.find((item) => item.id === current.model);\n if (model?.reasoning === undefined) return null;\n return {\n selection: current,\n efforts: model.reasoning.efforts,\n defaultEffort: model.reasoning.defaultEffort,\n };\n}\n\nfunction LiangEffortSlider({ directory, load, select, presenter, scope }: SliderProps) {\n const state = useSyncExternalStore(\n (listener) => directory.subscribe(listener),\n () => directory.getSnapshot(),\n );\n const skin = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const reasoning = useMemo(() => modelReasoning(state), [state]);\n const efforts = reasoning?.efforts ?? [];\n const committedIndex = selectedEffortIndex(\n efforts,\n reasoning?.selection.reasoningEffort,\n reasoning?.defaultEffort,\n );\n // An unknown committed effort defaults to the max frame: a fresh\n // conversation paints the dark shell immediately instead of flashing the\n // light palette until the directory load resolves the real effort.\n const committedFrame = committedIndex < 0\n ? PREVIEW_MAX_FRAME\n : frameForEffort(committedIndex, efforts.length);\n const bindEffort = skin.bindEffort;\n const [frame, setFrame] = useState(() => bindEffort ? committedFrame : presenter.getFrame());\n const [pending, setPending] = useState(false);\n const [failed, setFailed] = useState(false);\n const [interacting, setInteracting] = useState(false);\n const dragging = useRef(false);\n const dragStartFrame = useRef(frame);\n const enabled = skin.enabled;\n\n useEffect(() => {\n if (enabled) load();\n }, [enabled, load]);\n\n useEffect(() => {\n if (!bindEffort || dragging.current || pending) return;\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }, [bindEffort, committedFrame, pending, presenter]);\n\n if (!enabled) return null;\n if (bindEffort && (reasoning === null || efforts.length < 2)) return null;\n\n const previewIndex = nearestEffortIndex(frame, efforts);\n const previewEffort = efforts[previewIndex];\n const progressRatio = frame / PREVIEW_MAX_FRAME;\n const tooltipLabel = indicatorLabel(frame, bindEffort ? efforts : []);\n\n const commit = async (rawFrame: number) => {\n if (!bindEffort) {\n dragging.current = false;\n setFrame(rawFrame);\n presenter.setFrame(rawFrame);\n return;\n }\n const targetIndex = nearestEffortIndex(rawFrame, efforts);\n const target = efforts[targetIndex];\n if (target === undefined) return;\n const targetFrame = frameForEffort(targetIndex, efforts.length);\n dragging.current = false;\n setFrame(targetFrame);\n presenter.setFrame(targetFrame);\n if (targetIndex === committedIndex || pending) return;\n setPending(true);\n setFailed(false);\n const accepted = await select({\n provider: reasoning.selection.provider,\n model: reasoning.selection.model,\n reasoningEffort: target.id,\n });\n setPending(false);\n if (!accepted) {\n setFailed(true);\n setFrame(committedFrame);\n presenter.setFrame(committedFrame);\n }\n };\n\n return (\n <div\n className=\"liang-effort-control\"\n data-plugin={PACKAGE_ID}\n data-state={failed ? \"error\" : pending ? \"pending\" : \"ready\"}\n title={bindEffort ? previewEffort?.name : undefined}\n >\n {interacting && (\n <output\n className=\"liang-effort-control__tooltip\"\n style={{ \"--liang-slider-ratio\": progressRatio } as React.CSSProperties}\n >\n {tooltipLabel}\n </output>\n )}\n <div className=\"liang-effort-control__ticks\" aria-hidden=\"true\">\n {efforts.map((effort, index) => (\n <i\n className=\"liang-effort-control__tick\"\n key={effort.id}\n style={{ left: `${(frameForEffort(index, efforts.length) / PREVIEW_MAX_FRAME) * 100}%` }}\n />\n ))}\n </div>\n <input\n className=\"liang-effort-control__range\"\n type=\"range\"\n min={0}\n max={PREVIEW_MAX_FRAME}\n step={1}\n value={frame}\n disabled={pending || state.status === \"selecting\"}\n aria-label={bindEffort ? \"\u601D\u8003\u7B49\u7EA7\" : \"\u76AE\u80A4\u8FDB\u5EA6\"}\n aria-valuetext={bindEffort ? previewEffort?.name ?? \"\" : tooltipLabel}\n onPointerDown={() => {\n dragging.current = true;\n dragStartFrame.current = frame;\n setInteracting(true);\n }}\n onInput={(event) => {\n dragging.current = true;\n const next = Number(event.currentTarget.value);\n setFrame(next);\n presenter.setFrame(next);\n }}\n onPointerUp={(event) => {\n setInteracting(false);\n void commit(Number(event.currentTarget.value));\n }}\n onPointerCancel={() => {\n setInteracting(false);\n dragging.current = false;\n setFrame(dragStartFrame.current);\n presenter.setFrame(dragStartFrame.current);\n }}\n onKeyUp={(event) => {\n setInteracting(false);\n if (event.key !== \"Escape\") void commit(Number(event.currentTarget.value));\n }}\n onBlur={(event) => {\n setInteracting(false);\n if (dragging.current) void commit(Number(event.currentTarget.value));\n }}\n onKeyDown={(event) => {\n setInteracting(true);\n if (event.key === \"Escape\" && !pending) {\n setInteracting(false);\n dragging.current = false;\n setFrame(dragStartFrame.current);\n presenter.setFrame(dragStartFrame.current);\n }\n }}\n />\n </div>\n );\n}\n\nfunction EffortBindingRow({ scope, t }: EffortBindingRowProps) {\n const snapshot = useSyncExternalStore(\n (listener) => scope.subscribe(listener),\n () => scope.getSnapshot(),\n );\n const [pending, setPending] = useState(false);\n if (!snapshot.enabled) return null;\n\n return (\n <div className=\"liang-appearance-binding\" data-plugin={PACKAGE_ID}>\n <span>{t(\"effort.binding\")}</span>\n <Switch\n checked={snapshot.bindEffort}\n disabled={pending}\n label={t(\"effort.binding\")}\n onChange={(next) => {\n if (pending) return;\n setPending(true);\n void scope.setBindEffort(next).catch(() => undefined).finally(() => setPending(false));\n }}\n />\n </div>\n );\n}\n\nexport const inject = [\n \"slots\",\n \"sessions\",\n \"modelDirectories\",\n \"locale\",\n \"theme\",\n];\n\nfunction createPreferenceStore(): PreferenceStore {\n // The market's active skin is the source of truth for whether this client\n // should be visible. The appearance switch is therefore scoped to this\n // client activation and must not survive switching away and back.\n try {\n localStorage.removeItem(\"dsh-liang-intensity-skin.enabled\");\n } catch {\n // Storage may be unavailable; the in-memory default still enables Liang.\n }\n let snapshot: SkinSettings = {\n enabled: true,\n bindEffort: localStorage.getItem(BIND_EFFORT_KEY) !== \"0\",\n };\n const listeners = new Set<() => void>();\n const onStorage = (event: StorageEvent) => {\n if (event.key !== BIND_EFFORT_KEY) return;\n const next = {\n enabled: snapshot.enabled,\n bindEffort: event.newValue !== \"0\",\n };\n if (next.enabled === snapshot.enabled && next.bindEffort === snapshot.bindEffort) return;\n snapshot = next;\n for (const listener of listeners) listener();\n };\n window.addEventListener(\"storage\", onStorage);\n return {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => listeners.delete(listener);\n },\n async set(enabled) {\n if (enabled === snapshot.enabled) return;\n snapshot = { ...snapshot, enabled };\n for (const listener of listeners) listener();\n },\n async setBindEffort(bindEffort) {\n if (bindEffort === snapshot.bindEffort) return;\n localStorage.setItem(BIND_EFFORT_KEY, bindEffort ? \"1\" : \"0\");\n snapshot = { ...snapshot, bindEffort };\n for (const listener of listeners) listener();\n },\n dispose() {\n window.removeEventListener(\"storage\", onStorage);\n listeners.clear();\n },\n };\n}\n\nexport function apply(ctx: ClientContext) {\n const style = document.createElement(\"style\");\n style.dataset.plugin = PACKAGE_ID;\n style.textContent = styles;\n document.head.append(style);\n ctx.effect(() => () => style.remove(), \"liang-intensity-skin: scoped styles\");\n\n const scope = createPreferenceStore();\n ctx.effect(() => () => scope.dispose(), \"liang-intensity-skin: appearance preference\");\n const theme = ctx.get(\"theme\") as ThemeService;\n const presenter = new SkinPresenter(scope, theme);\n ctx.effect(() => () => presenter.dispose(), \"liang-intensity-skin: backdrop presenter\");\n ctx.effect(\n () => installLiangAppearanceButton(scope, presenter, PACKAGE_ID),\n \"liang-intensity-skin: native appearance extension\",\n );\n ctx.effect(\n () => ctx.locale.register(LOCALE_NAMESPACE, {\n zh: { \"effort.binding\": \"\u6ED1\u52A8\u53D8\u7956\u7ED1\u5B9A\u601D\u8003\u7B49\u7EA7\" },\n en: { \"effort.binding\": \"Bind slider to reasoning level\" },\n }), \"liang-intensity-skin: settings locale\");\n\n ctx.slots.inject(\"settings.general.item\", () => ctx.slots.register({\n name: \"settings.general.item\",\n id: \"liang-effort-binding\",\n order: 10.5,\n locale: LOCALE_NAMESPACE,\n inject: () => ({ scope }),\n }, EffortBindingRow));\n\n ctx.slots.inject(\"conversation.input.right\", () => ctx.slots.register({\n name: \"conversation.input.right\",\n id: \"liang-intensity-control\",\n order: 10,\n inject: (sessionId: string) => {\n const available = ctx.sessions.subagentAddress(sessionId) === undefined;\n const directory = ctx.modelDirectories.directoryFor(sessionId) as ModelDirectory;\n return {\n directory: directory.store,\n presenter,\n scope,\n load: () => {\n if (available) void directory.load().catch(() => undefined);\n },\n select: (selection: ModelSelection) => available\n ? directory.select(selection).then((result) => result.ok, () => false)\n : Promise.resolve(false),\n };\n },\n }, LiangEffortSlider));\n}\n", ".liang-skin-backdrop {\n position: fixed;\n z-index: -1;\n inset: 0;\n overflow: hidden;\n pointer-events: none;\n background: var(--liang-page, transparent);\n opacity: 0;\n transition: opacity 220ms ease, background-color 180ms linear;\n}\n\nbody[data-liang-skin=\"on\"] .liang-skin-backdrop {\n opacity: 1;\n}\n\n.liang-skin-backdrop img {\n position: absolute;\n top: 50%;\n right: 0;\n display: block;\n width: min(42vw, 720px);\n height: 100%;\n object-fit: cover;\n object-position: 50% 42%;\n opacity: var(--liang-portrait-opacity, 0.45);\n transform: translateY(-50%);\n filter: none;\n mask-image: linear-gradient(90deg, transparent 0%, rgb(0 0 0 / 20%) 10%, black 30%, black 100%);\n transition: filter 180ms linear;\n}\n\n.liang-skin-backdrop img {\n display: none;\n}\n\n.liang-skin-backdrop[data-media=\"sequence\"] .liang-skin-sequence-frame {\n display: block;\n opacity: var(--liang-portrait-opacity, 0.82);\n}\n\n.liang-skin-backdrop[data-media=\"color\"] img {\n display: none;\n}\n\n.liang-skin-backdrop::after {\n position: absolute;\n inset: 0;\n content: \"\";\n background:\n linear-gradient(90deg, var(--liang-page, transparent) 0 28%, transparent 57% 100%),\n linear-gradient(var(--liang-bg-base, transparent), var(--liang-bg-base, transparent));\n}\n\nbody[data-liang-skin=\"on\"] {\n /* Keep the backdrop above the canvas but below content and native portals.\n The host owns root positioning, dimensions, and its own stacking order. */\n isolation: isolate;\n --dsw-alias-bg-base: transparent !important;\n --dsw-alias-bg-layer-1: var(--liang-layer-1) !important;\n --dsw-alias-bg-layer-2: var(--liang-layer-2) !important;\n --dsw-alias-bg-layer-3: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-fill: var(--liang-sidebar) !important;\n --dsw-alias-label-primary: var(--liang-ink) !important;\n --dsw-alias-label-primary-dimmed: var(--liang-ink) !important;\n --dsw-alias-label-secondary: var(--liang-secondary) !important;\n --dsw-alias-label-tertiary: var(--liang-tertiary) !important;\n --dsw-alias-label-caption: var(--liang-tertiary) !important;\n --dsw-alias-border-l1: var(--liang-border) !important;\n --dsw-alias-border-l2-darkmode-thin: var(--liang-border) !important;\n --dsw-alias-border-l2: var(--liang-border) !important;\n --dsw-alias-border-l3: var(--liang-border) !important;\n --dsw-alias-button-primary-fill: var(--liang-accent) !important;\n --dsw-alias-button-primary-hover: var(--liang-accent-hover) !important;\n --dsw-alias-button-info-fill: var(--liang-accent) !important;\n --dsw-alias-button-info-hover: var(--liang-accent-hover) !important;\n --dsw-alias-state-business-primary: var(--liang-accent) !important;\n --dsw-alias-interactive-bg-hover: var(--liang-hover) !important;\n --dsw-alias-interactive-bg-active: var(--liang-hover) !important;\n --dsw-alias-button-elevated-fill: var(--liang-layer-1) !important;\n --dsw-alias-button-floating-fill: var(--liang-layer-2) !important;\n --dsw-alias-button-floating-hover: var(--liang-layer-3) !important;\n --dsw-alias-interactive-bg-hover-solid: var(--liang-layer-2) !important;\n --dsw-specific-bubble: var(--liang-layer-2) !important;\n --dsw-specific-input-major: var(--liang-layer-1) !important;\n --dsw-specific-menu: var(--liang-layer-3) !important;\n --dsw-specific-selector: var(--liang-layer-2) !important;\n --dsw-alias-markdown-citation: var(--liang-layer-2) !important;\n --dsw-alias-markdown-code-block-banner: var(--liang-layer-1) !important;\n --dsw-alias-markdown-code-block: var(--liang-layer-1) !important;\n --dsw-alias-markdown-code-segment-selected: var(--liang-layer-2) !important;\n --dsw-alias-markdown-code-segment-unselected: var(--liang-layer-1) !important;\n --dsw-alias-markdown-inline-code: var(--liang-layer-2) !important;\n --dsw-alias-markdown-placeholder: var(--liang-layer-1) !important;\n --dsw-alias-markdown-tag: var(--liang-layer-2) !important;\n background: var(--liang-page) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) {\n --dsw-alias-brand-primary-new-colorprimary-new-color: rgb(65 118 230) !important;\n --dsw-alias-brand-primary: rgb(15 17 21) !important;\n --dsw-alias-brand-text: rgb(15 17 21) !important;\n --dsw-alias-button-primary-fill: rgb(15 17 21) !important;\n --dsw-alias-button-primary-hover: rgb(53 54 56) !important;\n --dsw-alias-button-info-fill: rgb(65 118 230) !important;\n --dsw-alias-button-info-hover: rgb(103 158 254) !important;\n --dsw-alias-state-business-primary: rgb(65 118 230) !important;\n --dsw-alias-label-primary-inverted: rgb(249 250 251) !important;\n --dsw-alias-button-elevated-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-fill: rgb(255 255 255) !important;\n --dsw-alias-button-floating-hover: rgb(241 243 245) !important;\n --dsw-alias-interactive-bg-hover-solid: rgb(241 243 245) !important;\n --dsw-specific-bubble: rgb(237 243 254) !important;\n --dsw-specific-input-major: rgb(255 255 255) !important;\n --dsw-specific-menu: rgb(255 255 255) !important;\n --dsw-specific-selector: rgb(245 246 247) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] {\n --dsw-alias-brand-primary-new-colorprimary-new-color: #c19a49 !important;\n --dsw-alias-brand-primary: #c19a49 !important;\n --dsw-alias-brand-text: #d5b56e !important;\n --dsw-alias-button-info-fill: #c19a49 !important;\n --dsw-alias-button-info-hover: #d5b56e !important;\n --dsw-alias-state-business-primary: #c19a49 !important;\n --dsw-alias-bg-module-platform: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-nav-item-active: var(--liang-layer-3) !important;\n --dsw-specific-sidebar-nav-item-hover: var(--liang-hover) !important;\n}\n\n/* The host renders the running-turn label as a clipped blue text gradient.\n Retarget only that gradient's color tokens in the custom dark skin; keep\n the host's text clipping and shimmer behavior, and leave light mode alone. */\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"_turnStatus\"] {\n --dsw-static-deepseek-500: #c19a49 !important;\n --dsw-static-deepseek-200: #d5b56e !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"_turnStatusClock\"] {\n color: #c19a49 !important;\n -webkit-text-fill-color: #c19a49 !important;\n}\n\n/* Preserve the wordmark badge contrast in the low-intensity shell. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: rgb(15 17 21) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: rgb(249 250 251) !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > rect[width=\"52\"] {\n fill: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u65B0\u5EFA\u4F1A\u8BDD\"] svg[viewBox=\"0 0 182 24\"] > g[clip-path*=\"badge\"] path {\n fill: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [aria-label^=\"\u9009\u62E9\u6A21\u578B\"] > span:nth-of-type(2) {\n color: #d5b56e !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] [class*=\"heroGlow\"] ellipse {\n fill: #c19a49 !important;\n fill-opacity: 0.16 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] span[class*=\"_previewBadge\"] {\n color: #171816 !important;\n background: #c19a49 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #171816 !important;\n}\n\nbody[data-liang-skin=\"on\"][data-liang-stage=\"5\"] button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n opacity: 0.62;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"] {\n color: #fff !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) button[aria-label=\"\u53D1\u9001\u6D88\u606F\"]:disabled {\n color: rgb(255 255 255 / 92%) !important;\n background: rgb(65 118 230 / 42%) !important;\n opacity: 1;\n}\n\nbody[data-liang-skin=\"on\"] > #root {\n background: transparent !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-dsh-desktop-mode=\"compatibility\"],\n [data-dsh-desktop-mode=\"extended\"]\n) .liang-skin-backdrop {\n top: var(--dsh-desktop-frame-height, 0px);\n}\n\n/* Windows paints the sidebar fill across the host frame, covering the portrait.\n Match macOS's transparent frame while keeping the sidebar, caption, and\n conversation surfaces painted by their own host rules. */\nhtml[data-windows-titlebar] body[data-liang-skin=\"on\"] #root [class*=\"_frame\"]:has(> [class*=\"_centerCol\"]) {\n background: transparent !important;\n}\n\n/* macOS adds different translucent sidebar materials for native light/dark.\n While Liang is active, the effort palette owns the sidebar fill. */\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_frame\"]:has(> [class*=\"_centerCol\"]) > [class*=\"_sidebarCol\"] {\n background: var(--liang-sidebar) !important;\n}\n\n/* Keep the host's expanded new-session surface on the same palette. The\n collapsed icon keeps its native transparent surface and hover behavior. */\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"]:has(> [class*=\"_logoRow\"]):not([class*=\"_collapsed\"]) button[class*=\"_newSession\"] {\n background: var(--dsw-alias-button-elevated-fill) !important;\n}\n\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"]:has(> [class*=\"_logoRow\"]):not([class*=\"_collapsed\"]) button[class*=\"_newSession\"]:hover {\n background: var(--dsw-alias-button-floating-hover) !important;\n}\n\n/* The native dark rule also outranks the collapsed icon's transparent fill. */\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"][class*=\"_collapsed\"]:has(> [class*=\"_logoRow\"]) button[class*=\"_newSession\"] {\n background: transparent !important;\n}\n\nhtml[data-platform=\"darwin\"] body[data-liang-skin=\"on\"] #root [class*=\"_sidebarCol\"] [class*=\"_root\"][class*=\"_collapsed\"]:has(> [class*=\"_logoRow\"]) button[class*=\"_newSession\"]:hover {\n background: var(--dsw-alias-interactive-bg-hover) !important;\n}\n\nbody[data-liang-skin=\"on\"] button,\nbody[data-liang-skin=\"on\"] input,\nbody[data-liang-skin=\"on\"] textarea {\n transition: color 160ms linear, background-color 160ms linear, border-color 160ms linear;\n}\n\n/* The composer card has a native theme-mode fill, so keep its surface and\n readable ink aligned with the active Liang palette. */\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] {\n border-color: var(--liang-border) !important;\n color: var(--liang-ink) !important;\n background: var(--liang-layer-1) !important;\n box-shadow: 0 8px 28px rgb(20 22 20 / 8%);\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] :is(textarea, button, [data-input-mirror=\"true\"]) {\n color: var(--liang-ink) !important;\n caret-color: var(--liang-accent) !important;\n}\n\nbody[data-liang-skin=\"on\"]:is(\n [data-liang-stage=\"0\"],\n [data-liang-stage=\"1\"],\n [data-liang-stage=\"2\"],\n [data-liang-stage=\"3\"]\n) [data-composer-card=\"true\"] textarea::placeholder {\n color: var(--liang-tertiary) !important;\n opacity: 1;\n}\n\n.liang-effort-control {\n --liang-control-accent: var(--dsw-alias-brand-primary-new-colorprimary-new-color, #4176e6);\n --liang-control-rail: var(--dsw-alias-border-l3, rgb(0 0 0 / 16%));\n position: relative;\n display: flex;\n width: 124px;\n height: 28px;\n align-items: center;\n margin: 0 3px;\n overflow: visible;\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control {\n --liang-control-accent: var(--liang-secondary);\n --liang-control-rail: color-mix(in srgb, var(--liang-secondary) 28%, transparent);\n}\n\n.liang-effort-control__ticks {\n position: absolute;\n z-index: 0;\n inset: 0 10px;\n pointer-events: none;\n}\n\n.liang-effort-control__ticks::before {\n position: absolute;\n top: 50%;\n right: 0;\n left: 0;\n height: 1px;\n content: \"\";\n background: var(--liang-control-rail);\n transform: translateY(-50%);\n}\n\n.liang-effort-control__tooltip {\n position: absolute;\n z-index: 4;\n bottom: calc(100% + 7px);\n left: calc(10px + (100% - 20px) * var(--liang-slider-ratio));\n min-width: max-content;\n padding: 5px 8px;\n border: 1px solid var(--liang-border, rgb(0 0 0 / 12%));\n border-radius: 7px;\n color: var(--liang-ink, #171816);\n background: var(--liang-layer-1, #fff);\n box-shadow: 0 5px 16px rgb(0 0 0 / 16%);\n font-size: 11px;\n font-weight: 600;\n line-height: 16px;\n letter-spacing: 0.01em;\n pointer-events: none;\n transform: translateX(-50%);\n white-space: nowrap;\n}\n\n.liang-effort-control__tooltip::after {\n position: absolute;\n top: 100%;\n left: 50%;\n width: 7px;\n height: 7px;\n content: \"\";\n background: inherit;\n transform: translate(-50%, -4px) rotate(45deg);\n}\n\n.liang-effort-control__tick {\n position: absolute;\n top: 50%;\n width: 1px;\n height: 7px;\n background: var(--liang-control-accent);\n opacity: 0.42;\n transform: translate(-50%, -50%);\n}\n\n.liang-effort-control__range {\n position: relative;\n z-index: 1;\n width: calc(100% - 7px);\n height: 28px;\n margin: 0 3.5px;\n cursor: ew-resize;\n appearance: none;\n background: transparent;\n touch-action: pan-y;\n}\n\n.liang-effort-control__range:disabled {\n cursor: progress;\n opacity: 0.58;\n}\n\n.liang-effort-control__range::-webkit-slider-runnable-track {\n height: 1px;\n border-radius: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n appearance: none;\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--dsw-alias-bg-layer-1, #fff)) 2.5px);\n box-shadow: 0 1px 4px rgb(0 0 0 / 14%);\n}\n\nbody[data-liang-skin=\"on\"] .liang-effort-control__range::-webkit-slider-thumb {\n width: 13px;\n height: 13px;\n margin-top: -6px;\n border-color: color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n background: radial-gradient(circle, var(--liang-control-accent) 0 2px, color-mix(in srgb, var(--liang-control-accent) 22%, var(--liang-layer-1)) 2.5px);\n}\n\n.liang-effort-control__range::-moz-range-track {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-progress {\n height: 1px;\n background: transparent;\n}\n\n.liang-effort-control__range::-moz-range-thumb {\n width: 11px;\n height: 11px;\n border: 1.5px solid color-mix(in srgb, var(--liang-control-accent) 72%, transparent);\n border-radius: 50%;\n background: color-mix(in srgb, var(--liang-control-accent) 24%, var(--dsw-alias-bg-layer-1, #fff));\n}\n\n.liang-effort-control__range:focus-visible {\n outline: none;\n}\n\n.liang-effort-control[data-state=\"error\"] {\n --liang-control-accent: var(--dsw-alias-state-error-primary, #e43c3c);\n}\n\n.liang-appearance-choice {\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n flex: 180px;\n flex-direction: column;\n justify-content: center;\n align-items: center;\n gap: 4px;\n padding: 20px 32px;\n border-radius: 16px;\n font: inherit;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n background: transparent;\n font-size: 14px;\n line-height: 22px;\n display: flex;\n}\n\n[class*=\"_cubeRow\"]:has(.liang-appearance-choice) {\n display: grid;\n grid-template-columns: repeat(4, minmax(0, 1fr));\n}\n\n.liang-appearance-choice:hover:not([aria-pressed=\"true\"]) {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.liang-appearance-choice[aria-pressed=\"true\"] {\n border-color: var(--dsw-static-neutral-bluish-400);\n background: var(--dsw-alias-bg-module-platform);\n}\n\n.liang-appearance-choice__icon {\n display: block;\n flex: 0 0 16px;\n width: 16px;\n height: 16px;\n color: currentColor;\n font-size: 16px;\n line-height: 16px;\n}\n\n.liang-appearance-choice__label {\n display: block;\n}\n\n/* Keep the host's three theme cubes untouched. These rules only style the\n fourth button that is appended to the host cube row. */\n.liang-appearance-choice:disabled {\n cursor: progress;\n opacity: 0.7;\n}\n\n.liang-appearance-binding {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 24px;\n padding: 16px 0;\n border-bottom: 0.5px solid var(--dsw-alias-border-l2);\n font-size: 14px;\n line-height: 20px;\n}\n\n@media (max-width: 760px) {\n .liang-effort-control {\n width: 92px;\n }\n\n .liang-skin-backdrop img {\n right: -18vw;\n width: 92vw;\n opacity: calc(var(--liang-portrait-opacity, 0.45) * 0.72);\n }\n\n}\n\n@media (prefers-reduced-motion: reduce) {\n .liang-skin-backdrop,\n .liang-skin-backdrop img,\n body[data-liang-skin=\"on\"] button,\n body[data-liang-skin=\"on\"] input,\n body[data-liang-skin=\"on\"] textarea {\n transition: none;\n }\n}\n", "export interface AppearanceSnapshot {\n enabled: boolean;\n}\n\nexport interface AppearanceScope {\n getSnapshot(): AppearanceSnapshot;\n subscribe(listener: () => void): () => void;\n}\n\nexport interface AppearancePresenter {\n choose(enabled: boolean): Promise<void>;\n}\n\nconst NATIVE_APPEARANCE_ROW = '[class*=\"_cubeRow\"]';\nconst LIANG_APPEARANCE_BUTTON = \"liang-appearance-choice\";\n\nfunction hasClassSuffix(node: Element, suffix: string) {\n return [...node.classList].some((name) => name.endsWith(suffix));\n}\n\nfunction findAppearanceRow() {\n for (const row of document.querySelectorAll<HTMLElement>(NATIVE_APPEARANCE_ROW)) {\n if (!hasClassSuffix(row, \"_cubeRow\")) continue;\n // All three native appearance choices are direct button children. Validate\n // the structure as well as the suffix so unrelated cube rows stay alone.\n const nativeButtons = [...row.children].filter(\n (node): node is HTMLButtonElement => node instanceof HTMLButtonElement\n && hasClassSuffix(node, \"_themeCube\"),\n );\n if (nativeButtons.length < 3) continue;\n\n let group = row.parentElement;\n while (group !== null && !hasClassSuffix(group, \"_group\")) {\n group = group.parentElement;\n }\n group ??= row.parentElement;\n if (group !== null) return { row, group, nativeButtons };\n }\n return null;\n}\n\ninterface MountedAppearance {\n row: HTMLElement;\n group: HTMLElement;\n button: HTMLButtonElement;\n handleCustomClick: () => void;\n}\n\nexport function installLiangAppearanceButton(\n scope: AppearanceScope,\n presenter: AppearancePresenter,\n packageId: string,\n): () => void {\n let pending = false;\n let disposed = false;\n let mounted: MountedAppearance | null = null;\n const nativeClickHandlers = new Map<HTMLButtonElement, () => void>();\n\n const unmount = () => {\n for (const [button, handler] of nativeClickHandlers) {\n button.removeEventListener(\"click\", handler, { capture: true });\n }\n nativeClickHandlers.clear();\n if (mounted === null) return;\n mounted.button.removeEventListener(\"click\", mounted.handleCustomClick);\n mounted.button.remove();\n mounted = null;\n };\n\n const choose = async (enabled: boolean) => {\n if (disposed || pending || scope.getSnapshot().enabled === enabled) return;\n pending = true;\n sync();\n try {\n await presenter.choose(enabled);\n } catch {\n // The preference store remains the source of truth after a failed choice.\n } finally {\n pending = false;\n if (!disposed) sync();\n }\n };\n\n const createMount = (row: HTMLElement, group: HTMLElement): MountedAppearance => {\n const english = document.documentElement.lang.toLowerCase().startsWith(\"en\");\n const button = document.createElement(\"button\");\n button.className = LIANG_APPEARANCE_BUTTON;\n button.type = \"button\";\n button.dataset.plugin = packageId;\n button.setAttribute(\"aria-label\", \"\u6ED1\u52A8\u53D8\u7956\");\n\n const icon = document.createElement(\"span\");\n icon.className = \"liang-appearance-choice__icon\";\n icon.setAttribute(\"aria-hidden\", \"true\");\n icon.textContent = \"\u25C8\";\n\n const label = document.createElement(\"span\");\n label.className = \"liang-appearance-choice__label\";\n label.textContent = english ? \"Slider\" : \"\u6ED1\u52A8\u53D8\u7956\";\n button.append(icon, label);\n const handleCustomClick = () => { void choose(true); };\n button.addEventListener(\"click\", handleCustomClick);\n\n return { row, group, button, handleCustomClick };\n };\n\n const sync = () => {\n if (disposed) return;\n const target = findAppearanceRow();\n if (target === null) {\n unmount();\n return;\n }\n if (mounted !== null && (mounted.row !== target.row || mounted.group !== target.group)) {\n unmount();\n }\n mounted ??= createMount(target.row, target.group);\n const { row, button } = mounted;\n if (button.parentElement !== row) row.append(button);\n\n const snapshot = scope.getSnapshot();\n button.disabled = pending;\n button.setAttribute(\"aria-pressed\", String(snapshot.enabled));\n\n for (const [nativeButton, handler] of nativeClickHandlers) {\n if (target.nativeButtons.includes(nativeButton)) continue;\n nativeButton.removeEventListener(\"click\", handler, { capture: true });\n nativeClickHandlers.delete(nativeButton);\n }\n for (const nativeButton of target.nativeButtons) {\n if (nativeClickHandlers.has(nativeButton)) continue;\n const handleNativeClick = () => { void choose(false); };\n nativeClickHandlers.set(nativeButton, handleNativeClick);\n nativeButton.addEventListener(\"click\", handleNativeClick, { capture: true });\n }\n };\n\n const observer = new MutationObserver(sync);\n observer.observe(document.body, { childList: true, subtree: true });\n const unsubscribe = scope.subscribe(sync);\n sync();\n\n return () => {\n if (disposed) return;\n // Mark disposal first: outstanding choices and queued observer callbacks\n // must never attach new controls after the client has been deactivated.\n disposed = true;\n observer.disconnect();\n unsubscribe();\n unmount();\n };\n}\n", "export interface PortraitSource {\n level: number;\n url: string;\n}\n\nexport interface PortraitState {\n index: number | null;\n url: string | null;\n status: \"loading\" | \"ready\" | \"failed\";\n image: PortraitImage | null;\n}\n\nexport interface PortraitImage {\n src: string;\n loading: \"eager\" | \"lazy\";\n decoding: \"async\" | \"sync\" | \"auto\";\n decode(): Promise<void>;\n addEventListener(type: \"load\" | \"error\", listener: () => void): void;\n removeEventListener(type: \"load\" | \"error\", listener: () => void): void;\n removeAttribute(name: string): void;\n}\n\nexport interface PortraitLoaderOptions {\n sources: readonly PortraitSource[];\n onChange: (state: PortraitState) => void;\n createImage?: () => PortraitImage;\n}\n\ninterface Asset {\n url: string;\n status: \"idle\" | \"loading\" | \"ready\" | \"failed\";\n loadedUrl: string | null;\n retries: number;\n image: PortraitImage | null;\n timer: ReturnType<typeof setTimeout> | null;\n detach: (() => void) | null;\n}\n\nconst RETRY_DELAYS = [500, 1500, 3000] as const;\n\nfunction retryUrl(source: string, retry: number) {\n if (retry === 0) return source;\n const hashIndex = source.indexOf(\"#\");\n const hash = hashIndex < 0 ? \"\" : source.slice(hashIndex);\n const base = hashIndex < 0 ? source : source.slice(0, hashIndex);\n const queryIndex = base.indexOf(\"?\");\n const path = queryIndex < 0 ? base : base.slice(0, queryIndex);\n const query = new URLSearchParams(queryIndex < 0 ? \"\" : base.slice(queryIndex + 1));\n query.set(\"retry\", String(retry));\n return `${path}?${query}${hash}`;\n}\n\n/**\n * Decode frames independently and return the decoded image itself for display.\n * start() resumes after stop(); stop() silently releases every request/image.\n * dispose() is permanent. select() also accepts a target before start().\n */\nexport function createPortraitLoader(options: PortraitLoaderOptions) {\n const sources = options.sources.map((source) => ({ ...source }));\n const assets = new Map<string, Asset>();\n for (const { url } of sources) {\n if (!assets.has(url)) {\n assets.set(url, {\n url, status: \"idle\", loadedUrl: null, retries: 0,\n image: null, timer: null, detach: null,\n });\n }\n }\n const createImage = options.createImage ?? (() => new Image());\n let onChange: PortraitLoaderOptions[\"onChange\"] | null = options.onChange;\n let active = false;\n let disposed = false;\n let generation = 0;\n let targetLevel = sources[0]?.level ?? 0;\n let displayedIndex: number | null = null;\n let lastState: PortraitState | null = null;\n\n const isCurrent = (run: number) => active && !disposed && generation === run;\n const nearestIndex = (available: (index: number) => boolean) => {\n let nearest: number | null = null;\n for (let index = 0; index < sources.length; index += 1) {\n if (!available(index)) continue;\n const distance = Math.abs(sources[index].level - targetLevel);\n const previous = nearest === null ? Infinity : Math.abs(sources[nearest].level - targetLevel);\n if (nearest === null || distance < previous || (distance === previous && sources[index].level > sources[nearest].level)) {\n nearest = index;\n }\n }\n return nearest;\n };\n const isReady = (index: number) => assets.get(sources[index].url)?.status === \"ready\";\n const emit = (state: PortraitState) => {\n if (lastState?.index === state.index && lastState.url === state.url && lastState.status === state.status) return;\n lastState = state;\n onChange?.(state);\n };\n const reconcile = () => {\n if (!active || disposed) return;\n const target = nearestIndex(() => true);\n if (target !== null && isReady(target)) displayedIndex = target;\n else if (displayedIndex === null) displayedIndex = nearestIndex(isReady);\n if (displayedIndex !== null) {\n const asset = assets.get(sources[displayedIndex].url)!;\n emit({ index: displayedIndex, url: asset.loadedUrl, image: asset.image, status: \"ready\" });\n } else {\n const exhausted = [...assets.values()].every((asset) => asset.status === \"failed\");\n emit({ index: null, url: null, image: null, status: exhausted ? \"failed\" : \"loading\" });\n }\n };\n\n const request = (asset: Asset, run: number) => {\n if (!isCurrent(run)) return;\n asset.status = \"loading\";\n const image = createImage();\n asset.image = image;\n image.loading = \"eager\";\n image.decoding = \"async\";\n const url = retryUrl(asset.url, asset.retries);\n let settled = false;\n let decoding = false;\n const current = () => !settled && isCurrent(run) && asset.image === image;\n const detach = () => {\n image.removeEventListener(\"load\", handleLoad);\n image.removeEventListener(\"error\", handleError);\n asset.detach = null;\n };\n const handleError = () => {\n if (!current()) return;\n settled = true;\n detach();\n image.removeAttribute(\"src\");\n asset.image = null;\n if (asset.retries < RETRY_DELAYS.length) {\n const delay = RETRY_DELAYS[asset.retries];\n asset.retries += 1;\n asset.timer = setTimeout(() => {\n if (!isCurrent(run)) return;\n asset.timer = null;\n request(asset, run);\n }, delay);\n } else {\n asset.status = \"failed\";\n reconcile();\n }\n };\n const handleLoad = () => {\n if (!current() || decoding) return;\n decoding = true;\n void image.decode().then(() => {\n if (!current()) return;\n settled = true;\n detach();\n asset.loadedUrl = url;\n asset.status = \"ready\";\n reconcile();\n }, handleError);\n };\n asset.detach = detach;\n image.addEventListener(\"load\", handleLoad);\n image.addEventListener(\"error\", handleError);\n image.src = url;\n };\n\n const stop = () => {\n active = false;\n generation += 1;\n for (const asset of assets.values()) {\n if (asset.timer !== null) clearTimeout(asset.timer);\n asset.timer = null;\n asset.detach?.();\n asset.image?.removeAttribute(\"src\");\n asset.image = null;\n asset.status = \"idle\";\n asset.loadedUrl = null;\n asset.retries = 0;\n }\n displayedIndex = null;\n lastState = null;\n };\n\n return {\n start() {\n if (disposed || active) return;\n active = true;\n const run = ++generation;\n reconcile();\n for (const asset of assets.values()) request(asset, run);\n },\n select(level: number) {\n if (disposed || !Number.isFinite(level)) return;\n targetLevel = level;\n reconcile();\n },\n stop,\n dispose() {\n stop();\n disposed = true;\n onChange = null;\n },\n };\n}\n", "export const PREVIEW_MAX_FRAME = 240;\nexport const MAX_LEVEL = 30;\n\nconst LIANG_RANKS = [\"\u5C0F\u96BE\u6881\", \"\u7262\u6881\", \"\u6881\u5B50\", \"\u6881\u5723\", \"\u6881\u795E\", \"\u6881\u7956\"] as const;\n\nexport interface EffortLike {\n id: string;\n name: string;\n description?: string;\n}\n\nexport interface Palette {\n level: number;\n stage: number;\n strength: number;\n page: string;\n base: string;\n layer1: string;\n layer2: string;\n layer3: string;\n sidebar: string;\n ink: string;\n secondary: string;\n tertiary: string;\n border: string;\n accent: string;\n accentHover: string;\n hover: string;\n portraitOpacity: string;\n}\n\ntype Rgb = readonly [number, number, number];\n\ninterface PaletteStop {\n at: number;\n page: Rgb;\n surface: Rgb;\n surface2: Rgb;\n ink: Rgb;\n secondary: Rgb;\n accent: Rgb;\n portraitOpacity: number;\n}\n\n// These are the original calibrator's six stage anchors: pale neutral at the\n// low end, progressively smoked surfaces, then charcoal and antique gold.\nconst STOPS: readonly PaletteStop[] = [\n { at: 0, page: [232, 233, 229], surface: [248, 248, 245], surface2: [238, 239, 235], ink: [23, 24, 22], secondary: [112, 116, 111], accent: [181, 43, 36], portraitOpacity: 0.92 },\n { at: 6, page: [211, 211, 206], surface: [239, 239, 234], surface2: [224, 224, 218], ink: [26, 26, 24], secondary: [101, 101, 96], accent: [181, 43, 36], portraitOpacity: 0.93 },\n { at: 12, page: [171, 168, 162], surface: [211, 208, 201], surface2: [190, 186, 179], ink: [27, 26, 24], secondary: [83, 79, 74], accent: [166, 54, 42], portraitOpacity: 0.94 },\n { at: 18, page: [117, 112, 106], surface: [154, 148, 140], surface2: [128, 122, 115], ink: [24, 22, 20], secondary: [65, 61, 56], accent: [154, 56, 42], portraitOpacity: 0.94 },\n { at: 24, page: [43, 39, 37], surface: [48, 43, 40], surface2: [58, 51, 46], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [181, 92, 54], portraitOpacity: 0.94 },\n { at: 30, page: [17, 17, 17], surface: [30, 27, 25], surface2: [41, 35, 30], ink: [244, 241, 232], secondary: [184, 180, 169], accent: [193, 154, 73], portraitOpacity: 0.94 },\n];\n\nexport function clampFrame(value: number): number {\n if (!Number.isFinite(value)) return 0;\n return Math.min(PREVIEW_MAX_FRAME, Math.max(0, Math.round(value)));\n}\n\nexport function frameForEffort(index: number, count: number): number {\n if (count <= 1 || !Number.isFinite(index)) return 0;\n const safe = Math.min(count - 1, Math.max(0, Math.round(index)));\n return Math.round((safe / (count - 1)) * PREVIEW_MAX_FRAME);\n}\n\nexport function nearestEffortIndex(frame: number, efforts: readonly EffortLike[]): number {\n if (efforts.length === 0) return -1;\n const safe = clampFrame(frame);\n let best = 0;\n let distance = Math.abs(safe - frameForEffort(0, efforts.length));\n for (let index = 1; index < efforts.length; index += 1) {\n const next = Math.abs(safe - frameForEffort(index, efforts.length));\n if (next < distance) {\n best = index;\n distance = next;\n }\n }\n return best;\n}\n\nexport function selectedEffortIndex(\n efforts: readonly EffortLike[],\n selectedId?: string,\n defaultId?: string,\n): number {\n const id = selectedId ?? defaultId;\n return id === undefined ? -1 : efforts.findIndex((effort) => effort.id === id);\n}\n\nexport function portraitBlendForLevel(level: number, anchors: readonly number[]) {\n if (anchors.length === 0) return { lowerIndex: -1, upperIndex: -1, mix: 0 };\n const safeLevel = Number.isFinite(level)\n ? Math.min(anchors[anchors.length - 1], Math.max(anchors[0], level))\n : anchors[0];\n let upperIndex = anchors.findIndex((anchor) => anchor >= safeLevel);\n if (upperIndex < 0) upperIndex = anchors.length - 1;\n const lowerIndex = Math.max(0, upperIndex - (anchors[upperIndex] > safeLevel ? 1 : 0));\n const span = anchors[upperIndex] - anchors[lowerIndex];\n return {\n lowerIndex,\n upperIndex,\n mix: span === 0 ? 0 : (safeLevel - anchors[lowerIndex]) / span,\n };\n}\n\nexport function liangRankForFrame(rawFrame: number): string {\n const level = (clampFrame(rawFrame) / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const index = level >= MAX_LEVEL ? LIANG_RANKS.length - 1 : Math.floor(level / 6);\n return LIANG_RANKS[Math.min(LIANG_RANKS.length - 1, Math.max(0, index))];\n}\n\nexport function indicatorLabel(rawFrame: number, efforts: readonly EffortLike[]): string {\n const effort = efforts[nearestEffortIndex(rawFrame, efforts)];\n return effort === undefined\n ? liangRankForFrame(rawFrame)\n : `${liangRankForFrame(rawFrame)} \u00B7 ${effort.name}`;\n}\n\nfunction lerp(a: number, b: number, amount: number): number {\n return a + (b - a) * amount;\n}\n\nfunction mix(a: Rgb, b: Rgb, amount: number): Rgb {\n return [\n Math.round(lerp(a[0], b[0], amount)),\n Math.round(lerp(a[1], b[1], amount)),\n Math.round(lerp(a[2], b[2], amount)),\n ];\n}\n\nfunction rgb(value: Rgb, alpha = 1): string {\n return alpha === 1\n ? `rgb(${value[0]} ${value[1]} ${value[2]})`\n : `rgb(${value[0]} ${value[1]} ${value[2]} / ${alpha})`;\n}\n\nexport function paletteForFrame(rawFrame: number): Palette {\n const frame = clampFrame(rawFrame);\n const level = (frame / PREVIEW_MAX_FRAME) * MAX_LEVEL;\n const portraitStage = Math.min(5, Math.floor(level / 6));\n const portraitFrom = STOPS[portraitStage];\n const portraitTo = STOPS[Math.min(5, portraitStage + 1)];\n const portraitAmount = portraitFrom === portraitTo\n ? 0\n : (level - portraitFrom.at) / (portraitTo.at - portraitFrom.at);\n\n // The UI itself is intentionally binary: levels 0\u201323 keep the native light\n // shell; entering the original \u6881\u795E/\u6881\u7956 region at level 24 switches black/gold.\n const dark = level >= 24;\n const stage = dark ? 5 : 0;\n const ui = dark ? STOPS[5] : STOPS[0];\n const page = ui.page;\n const surface = ui.surface;\n const surface2 = ui.surface2;\n const sidebar = mix(page, surface2, 0.25);\n const ink = ui.ink;\n const secondary = ui.secondary;\n // Keep Harness' native blue in the light shell. The original calibrator's\n // antique gold only becomes the product accent once the dark region begins.\n const accent: Rgb = dark ? [193, 154, 73] : [65, 118, 230];\n const accentHover = mix(accent, ink, 0.13);\n\n return {\n level,\n stage,\n strength: level / MAX_LEVEL,\n page: rgb(page),\n // Keep the shell readable while allowing the right-side portrait to remain\n // visibly present. Dense controls use the opaque layer tokens below.\n base: rgb(page, dark ? 0.42 : 0.28),\n layer1: rgb(surface, 0.94),\n layer2: rgb(surface2, 0.96),\n layer3: rgb(surface2, 0.99),\n sidebar: rgb(sidebar, 0.96),\n ink: rgb(ink),\n secondary: rgb(secondary),\n tertiary: rgb(mix(secondary, page, 0.28)),\n border: rgb(ink, dark ? 0.15 : 0.12),\n accent: rgb(accent),\n accentHover: rgb(accentHover),\n hover: rgb(ink, dark ? 0.09 : 0.07),\n portraitOpacity: String(lerp(\n portraitFrom.portraitOpacity,\n portraitTo.portraitOpacity,\n portraitAmount,\n )),\n };\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAMO;AACP,sCAAuB;;;ACPvB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA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",
|
|
6
|
+
"names": []
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@leon___/dsh-client-liang-intensity-skin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "滑动变祖:an opt-in adaptive reasoning slider skin for DeepSeek Harness",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -48,7 +48,8 @@
|
|
|
48
48
|
],
|
|
49
49
|
"scripts": {
|
|
50
50
|
"build": "node ./scripts/build-client.mjs",
|
|
51
|
-
"test": "vitest run"
|
|
51
|
+
"test": "vitest run",
|
|
52
|
+
"test:compatibility": "npm run build && node ./scripts/test-client-compatibility.mjs && node ./scripts/test-client-runtime.mjs"
|
|
52
53
|
},
|
|
53
54
|
"dsh": {
|
|
54
55
|
"bundle": {
|
|
@@ -62,6 +63,7 @@
|
|
|
62
63
|
"@deepseek-ai/dsh-client-ui-settings",
|
|
63
64
|
"@deepseek-ai/dsh-client-ui-theme",
|
|
64
65
|
"@deepseek-ai/dsh-client-ui-settings-general",
|
|
66
|
+
"@deepseek-ai/dsh-client-ui-primitives",
|
|
65
67
|
"@deepseek-ai/dsh-client-locale",
|
|
66
68
|
"@deepseek-ai/dsh-api-remotes"
|
|
67
69
|
]
|
|
@@ -70,6 +72,7 @@
|
|
|
70
72
|
"devDependencies": {
|
|
71
73
|
"@types/react": "~18.3.1",
|
|
72
74
|
"esbuild": "^0.25.0",
|
|
75
|
+
"playwright-core": "^1.64.1",
|
|
73
76
|
"vitest": "^4.1.10"
|
|
74
77
|
}
|
|
75
78
|
}
|