dsh-router-core 0.4.7 → 0.4.9
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 +14 -70
- package/cordis.patch.yml +2 -7
- package/docs/ext.md +3 -17
- package/docs/suppliers.md +1 -1
- package/lib/client-registry.js +137 -590
- package/lib/client.js +137 -590
- package/lib/ext-prompt/index.js +20 -15
- package/lib/index.js +0 -419
- package/lib/types/ext/contract.d.ts +1 -1
- package/lib/types/ext-prompt/content.d.ts +11 -0
- package/lib/types/ext-prompt/index.d.ts +7 -9
- package/lib/types/ext-prompt/mount.d.ts +2 -2
- package/lib/types/ext-prompt/plugin.d.ts +3 -5
- package/lib/types/router/types.d.ts +11 -0
- package/lib/types/shared.d.ts +2 -0
- package/lib/types/suppliers/registry.d.ts +0 -1
- package/package.json +1 -10
- package/src/client/CombosTab.tsx +29 -8
- package/src/client/ExtDetail.tsx +1 -13
- package/src/client/SupplierDetail.tsx +11 -5
- package/src/client/group-controls.test.ts +1 -1
- package/src/client/group-controls.ts +1 -1
- package/src/client/index.tsx +0 -17
- package/src/client/model-label.test.ts +33 -0
- package/src/client/model-label.ts +48 -0
- package/src/client/router-components.test.ts +1 -1
- package/src/client/router.css +24 -412
- package/src/ext/contract.ts +1 -1
- package/src/ext-prompt/content.ts +17 -12
- package/src/ext-prompt/ext-prompt.test.ts +3 -3
- package/src/ext-prompt/index.ts +7 -9
- package/src/ext-prompt/mount.ts +2 -2
- package/src/ext-prompt/plugin.ts +3 -5
- package/src/router/index.ts +2 -3
- package/src/router/models-cache.test.ts +21 -6
- package/src/router/supplier-switch.test.ts +1 -1
- package/src/router/types.ts +11 -0
- package/src/shared.ts +2 -0
- package/src/suppliers/registry.ts +0 -71
- package/lib/contract-D4BWZ7Xe.js +0 -13
- package/lib/ext-test/index.js +0 -36
- package/lib/ext-test/locale/en.json +0 -6
- package/lib/ext-test/locale/zh.json +0 -6
- package/lib/ext-test/package.json +0 -5
- package/lib/types/ext-test/index.d.ts +0 -21
- package/lib/types/ext-test/plugin.d.ts +0 -23
- package/lib/types/suppliers/probe.d.ts +0 -160
- package/src/client/ExtTestPanel.tsx +0 -392
- package/src/client/comp-button-scope.test.ts +0 -58
- package/src/client/comp-panel-layout.test.ts +0 -58
- package/src/client/ext-panels.test.ts +0 -44
- package/src/client/ext-panels.ts +0 -49
- package/src/client/model-choice.test.ts +0 -41
- package/src/client/model-choice.ts +0 -37
- package/src/ext-test/ext-test.test.ts +0 -60
- package/src/ext-test/index.ts +0 -35
- package/src/ext-test/locale/en.json +0 -6
- package/src/ext-test/locale/zh.json +0 -6
- package/src/ext-test/plugin.ts +0 -34
- package/src/ext-test/row.json +0 -5
- package/src/suppliers/probe.test.ts +0 -266
- package/src/suppliers/probe.ts +0 -475
package/src/client/router.css
CHANGED
|
@@ -1900,9 +1900,16 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
|
|
|
1900
1900
|
cursor: default;
|
|
1901
1901
|
}
|
|
1902
1902
|
|
|
1903
|
-
|
|
1903
|
+
/* 主标签 = 上游的可读名(缺省回落成 key),正文字号;key 用等宽淡字跟在后面,
|
|
1904
|
+
两者相同时不渲染 key(判据见 model-label.ts) */
|
|
1905
|
+
.dshr-modelChipName {
|
|
1906
|
+
font-size: 12px;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
.dshr-modelChipKey {
|
|
1904
1910
|
font-family: var(--rs-mono);
|
|
1905
|
-
font-size:
|
|
1911
|
+
font-size: 10px;
|
|
1912
|
+
color: var(--rs-faint);
|
|
1906
1913
|
}
|
|
1907
1914
|
|
|
1908
1915
|
.dshr-modelChipCtx {
|
|
@@ -2047,61 +2054,6 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
|
|
|
2047
2054
|
opacity: 1;
|
|
2048
2055
|
}
|
|
2049
2056
|
|
|
2050
|
-
/* 旧 .dshr-modelChip 独立样式(disabled 区仍用) */
|
|
2051
|
-
.dshr-modelChip {
|
|
2052
|
-
display: inline-flex;
|
|
2053
|
-
align-items: center;
|
|
2054
|
-
gap: 6px;
|
|
2055
|
-
padding: 6px 10px;
|
|
2056
|
-
border: 1px solid var(--rs-line);
|
|
2057
|
-
border-radius: 8px;
|
|
2058
|
-
color: var(--rs-text);
|
|
2059
|
-
background: var(--rs-layer-1);
|
|
2060
|
-
font-size: 12px;
|
|
2061
|
-
cursor: pointer;
|
|
2062
|
-
transition:
|
|
2063
|
-
border-color 0.12s ease,
|
|
2064
|
-
background 0.12s ease,
|
|
2065
|
-
color 0.12s ease;
|
|
2066
|
-
}
|
|
2067
|
-
|
|
2068
|
-
.dshr-modelChip:hover {
|
|
2069
|
-
border-color: var(--rs-accent);
|
|
2070
|
-
background: color-mix(in srgb, var(--rs-accent) 6%, transparent);
|
|
2071
|
-
}
|
|
2072
|
-
|
|
2073
|
-
.dshr-modelChip:disabled {
|
|
2074
|
-
opacity: 0.6;
|
|
2075
|
-
cursor: default;
|
|
2076
|
-
}
|
|
2077
|
-
|
|
2078
|
-
.dshr-modelChipId {
|
|
2079
|
-
font-family: var(--rs-mono);
|
|
2080
|
-
font-size: 11px;
|
|
2081
|
-
}
|
|
2082
|
-
|
|
2083
|
-
.dshr-modelChipCtx {
|
|
2084
|
-
flex: none;
|
|
2085
|
-
color: var(--rs-faint);
|
|
2086
|
-
font-size: 10px;
|
|
2087
|
-
}
|
|
2088
|
-
|
|
2089
|
-
.dshr-modelChip-off {
|
|
2090
|
-
border-style: dashed;
|
|
2091
|
-
color: var(--rs-faint);
|
|
2092
|
-
opacity: 0.8;
|
|
2093
|
-
}
|
|
2094
|
-
|
|
2095
|
-
.dshr-modelChip-off:hover {
|
|
2096
|
-
color: var(--rs-accent);
|
|
2097
|
-
border-color: var(--rs-accent);
|
|
2098
|
-
}
|
|
2099
|
-
|
|
2100
|
-
.dshr-modelChipRestore {
|
|
2101
|
-
color: var(--rs-accent);
|
|
2102
|
-
font-size: 10px;
|
|
2103
|
-
}
|
|
2104
|
-
|
|
2105
2057
|
/* 计数徽标跟在标题/操作按钮右侧(模型卡片) */
|
|
2106
2058
|
.dshr-cardMetaAfter {
|
|
2107
2059
|
margin-left: 0;
|
|
@@ -2484,9 +2436,20 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
|
|
|
2484
2436
|
}
|
|
2485
2437
|
|
|
2486
2438
|
.dshr-comboPickName {
|
|
2487
|
-
flex: 1;
|
|
2439
|
+
flex: 0 1 auto;
|
|
2488
2440
|
min-width: 0;
|
|
2441
|
+
overflow: hidden;
|
|
2442
|
+
text-overflow: ellipsis;
|
|
2443
|
+
white-space: nowrap;
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
/* 挑选项里的上游 key:可读名之后的小号等宽淡字,两者相同时不渲染 */
|
|
2447
|
+
.dshr-comboPickKey {
|
|
2448
|
+
flex: none;
|
|
2449
|
+
margin-left: auto;
|
|
2489
2450
|
font-family: var(--rs-mono);
|
|
2451
|
+
font-size: 10px;
|
|
2452
|
+
color: var(--rs-faint);
|
|
2490
2453
|
overflow: hidden;
|
|
2491
2454
|
text-overflow: ellipsis;
|
|
2492
2455
|
white-space: nowrap;
|
|
@@ -3456,9 +3419,9 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
|
|
|
3456
3419
|
}
|
|
3457
3420
|
|
|
3458
3421
|
/* 标题 + 「修改」按钮的**同一行**(`ExtDetail` 的子开关区)。
|
|
3459
|
-
⚠️ 单独一个类而不改 `.dshr-compRowName`:那个类 `RouterComponentsSection`
|
|
3460
|
-
|
|
3461
|
-
flex
|
|
3422
|
+
⚠️ 单独一个类而不改 `.dshr-compRowName`:那个类 `RouterComponentsSection`
|
|
3423
|
+
也在用,给它加 `display:flex` 会把**那一页的标题**也变成
|
|
3424
|
+
flex 盒子(那边标题后面没有按钮,平白多一层)。
|
|
3462
3425
|
没有这层时按钮会掉到**下一行**:`.dshr-compRowMain` 是 column,而
|
|
3463
3426
|
`.dshr-compRowName` 是行内元素、标题一长就折行(2026-09-29 用户报)。 */
|
|
3464
3427
|
/* 子开关区:`.dshr-compGroup` 的 `gap: 12px` 覆盖为 0(2026-09-30 用户要求)。
|
|
@@ -3512,354 +3475,3 @@ html[data-dsh-router-active]:not([data-dsh-taskboard-active]):not(
|
|
|
3512
3475
|
缩进那种「引用块」的额外装饰(用户要求),层级只靠颜色就够。 */
|
|
3513
3476
|
white-space: pre-wrap;
|
|
3514
3477
|
}
|
|
3515
|
-
|
|
3516
|
-
/* ============================================================
|
|
3517
|
-
dsh-router — 插件自检面板(设置 → 路由 → 扩展 → 插件自检)
|
|
3518
|
-
------------------------------------------------------------
|
|
3519
|
-
这一页渲染在**宿主的插件页**里,DOM 祖先既不是 .dshr-settings 也不是
|
|
3520
|
-
.dshr-shell,所以文件顶部那套 `--rs-*` 主题变量在这里**不存在**(未定义的
|
|
3521
|
-
var() 会让整条声明失效:边框/文字色退成继承值)。
|
|
3522
|
-
|
|
3523
|
-
所以这里**不用**设置页那套组件样式,直接按宿主页面的视觉语言写,用宿主的
|
|
3524
|
-
`--dsw-alias-*` token:几何对齐它(14px 小标题、12px 次要文字、0.5px 描边、
|
|
3525
|
-
12px 圆角),配色也从同一套 token 取 —— 于是这块面板看起来就是原生的一部分。
|
|
3526
|
-
主按钮不用在这里画:交给宿主的 Button 原语(见 env.d.ts),配色由原语自己的
|
|
3527
|
-
token 家族决定,不必猜「主色底上配什么字色」。
|
|
3528
|
-
============================================================ */
|
|
3529
|
-
|
|
3530
|
-
.dshr-comp {
|
|
3531
|
-
gap: 16px;
|
|
3532
|
-
}
|
|
3533
|
-
|
|
3534
|
-
.dshr-compIntro {
|
|
3535
|
-
margin: 0;
|
|
3536
|
-
color: var(--dsw-alias-label-secondary);
|
|
3537
|
-
font-size: 13px;
|
|
3538
|
-
line-height: 20px;
|
|
3539
|
-
}
|
|
3540
|
-
|
|
3541
|
-
/* 三栏收进同一块面板,读起来是「一组控件」而不是三个飘着的输入框。
|
|
3542
|
-
窄了换行(详情区宽度随窗口变,写死三列会在窄窗口挤成一团)。 */
|
|
3543
|
-
.dshr-compForm {
|
|
3544
|
-
display: grid;
|
|
3545
|
-
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
|
3546
|
-
gap: 14px 16px;
|
|
3547
|
-
padding: 14px 16px;
|
|
3548
|
-
border: 0.5px solid var(--dsw-alias-border-l1);
|
|
3549
|
-
border-radius: 12px;
|
|
3550
|
-
background: var(--dsw-alias-bg-layer-1);
|
|
3551
|
-
}
|
|
3552
|
-
|
|
3553
|
-
.dshr-compField {
|
|
3554
|
-
display: flex;
|
|
3555
|
-
flex-direction: column;
|
|
3556
|
-
gap: 6px;
|
|
3557
|
-
min-width: 0;
|
|
3558
|
-
}
|
|
3559
|
-
|
|
3560
|
-
.dshr-compFieldHead {
|
|
3561
|
-
display: flex;
|
|
3562
|
-
align-items: baseline;
|
|
3563
|
-
justify-content: space-between;
|
|
3564
|
-
gap: 8px;
|
|
3565
|
-
}
|
|
3566
|
-
|
|
3567
|
-
.dshr-compFieldLabel {
|
|
3568
|
-
color: var(--dsw-alias-label-primary);
|
|
3569
|
-
font-size: 12px;
|
|
3570
|
-
font-weight: 500;
|
|
3571
|
-
line-height: 18px;
|
|
3572
|
-
}
|
|
3573
|
-
|
|
3574
|
-
/* 标题右侧的用法要点。语义放这里比塞进顶部那段长文字更容易被读到 ——
|
|
3575
|
-
「模型只列可用的」「连接留空 = 池内任选」都是用这一栏时才关心的。 */
|
|
3576
|
-
.dshr-compFieldNote {
|
|
3577
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3578
|
-
font-size: 12px;
|
|
3579
|
-
line-height: 18px;
|
|
3580
|
-
text-align: right;
|
|
3581
|
-
}
|
|
3582
|
-
|
|
3583
|
-
/* 36px / 12px 圆角,与宿主 Button 原语的 md 尺寸对齐。 */
|
|
3584
|
-
.dshr-compSelect {
|
|
3585
|
-
width: 100%;
|
|
3586
|
-
height: 36px;
|
|
3587
|
-
padding: 0 32px 0 11px;
|
|
3588
|
-
appearance: none;
|
|
3589
|
-
border: 0.5px solid var(--dsw-alias-border-l2);
|
|
3590
|
-
border-radius: 12px;
|
|
3591
|
-
background-color: var(--dsw-alias-bg-layer-2);
|
|
3592
|
-
background-image:
|
|
3593
|
-
linear-gradient(45deg, transparent 50%, var(--dsw-alias-label-tertiary) 50%),
|
|
3594
|
-
linear-gradient(135deg, var(--dsw-alias-label-tertiary) 50%, transparent 50%);
|
|
3595
|
-
background-position:
|
|
3596
|
-
calc(100% - 17px) 16px,
|
|
3597
|
-
calc(100% - 12px) 16px;
|
|
3598
|
-
background-size: 5px 5px;
|
|
3599
|
-
background-repeat: no-repeat;
|
|
3600
|
-
color: var(--dsw-alias-label-primary);
|
|
3601
|
-
font: inherit;
|
|
3602
|
-
font-size: 13px;
|
|
3603
|
-
line-height: 18px;
|
|
3604
|
-
text-overflow: ellipsis;
|
|
3605
|
-
cursor: pointer;
|
|
3606
|
-
}
|
|
3607
|
-
|
|
3608
|
-
.dshr-compSelect:hover:not(:disabled) {
|
|
3609
|
-
border-color: var(--dsw-alias-border-l3);
|
|
3610
|
-
}
|
|
3611
|
-
|
|
3612
|
-
.dshr-compSelect:focus {
|
|
3613
|
-
outline: none;
|
|
3614
|
-
border-color: var(--dsw-alias-brand-primary);
|
|
3615
|
-
box-shadow: 0 0 0 3px color-mix(in srgb, var(--dsw-alias-brand-primary) 22%, transparent);
|
|
3616
|
-
}
|
|
3617
|
-
|
|
3618
|
-
.dshr-compSelect:disabled {
|
|
3619
|
-
border-color: var(--dsw-alias-border-l1);
|
|
3620
|
-
background-color: var(--dsw-alias-bg-layer-1);
|
|
3621
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3622
|
-
cursor: not-allowed;
|
|
3623
|
-
}
|
|
3624
|
-
|
|
3625
|
-
/* 动作行:把按钮与它旁边的提示排在一条基线上。两个动作行(访问测试 / 契约体检)
|
|
3626
|
-
共用 `dshr-compBtnRow` —— 那条抬特异性的字色规则就挂在它上面(见下)。 */
|
|
3627
|
-
.dshr-compActions {
|
|
3628
|
-
display: flex;
|
|
3629
|
-
align-items: center;
|
|
3630
|
-
gap: 12px;
|
|
3631
|
-
}
|
|
3632
|
-
|
|
3633
|
-
.dshr-compHint {
|
|
3634
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3635
|
-
font-size: 12px;
|
|
3636
|
-
line-height: 18px;
|
|
3637
|
-
}
|
|
3638
|
-
|
|
3639
|
-
/* 结果区:成功/失败/请求失败 三种语气。底下垫一层极淡的状态色,比只有一行
|
|
3640
|
-
彩色文字更容易扫到 —— 自检的结果是这一页唯一重要的信息。 */
|
|
3641
|
-
.dshr-compNotice {
|
|
3642
|
-
display: flex;
|
|
3643
|
-
gap: 10px;
|
|
3644
|
-
padding: 12px 14px;
|
|
3645
|
-
border: 0.5px solid var(--dsw-alias-border-l1);
|
|
3646
|
-
border-radius: 12px;
|
|
3647
|
-
background: var(--dsw-alias-bg-layer-1);
|
|
3648
|
-
}
|
|
3649
|
-
|
|
3650
|
-
.dshr-compNotice[data-tone="ok"] {
|
|
3651
|
-
border-color: color-mix(in srgb, var(--dsw-alias-state-success-primary) 34%, transparent);
|
|
3652
|
-
background: color-mix(in srgb, var(--dsw-alias-state-success-primary) 8%, transparent);
|
|
3653
|
-
}
|
|
3654
|
-
|
|
3655
|
-
.dshr-compNotice[data-tone="fail"],
|
|
3656
|
-
.dshr-compNotice[data-tone="network"] {
|
|
3657
|
-
border-color: color-mix(in srgb, var(--dsw-alias-state-error-primary) 34%, transparent);
|
|
3658
|
-
background: color-mix(in srgb, var(--dsw-alias-state-error-primary) 8%, transparent);
|
|
3659
|
-
}
|
|
3660
|
-
|
|
3661
|
-
.dshr-compNoticeIcon {
|
|
3662
|
-
flex: none;
|
|
3663
|
-
width: 16px;
|
|
3664
|
-
height: 16px;
|
|
3665
|
-
margin-top: 2px;
|
|
3666
|
-
color: var(--dsw-alias-state-success-secondary);
|
|
3667
|
-
}
|
|
3668
|
-
|
|
3669
|
-
.dshr-compNotice[data-tone="fail"] .dshr-compNoticeIcon,
|
|
3670
|
-
.dshr-compNotice[data-tone="network"] .dshr-compNoticeIcon {
|
|
3671
|
-
color: var(--dsw-alias-state-error-primary);
|
|
3672
|
-
}
|
|
3673
|
-
|
|
3674
|
-
.dshr-compNoticeBody {
|
|
3675
|
-
display: flex;
|
|
3676
|
-
flex-direction: column;
|
|
3677
|
-
gap: 2px;
|
|
3678
|
-
min-width: 0;
|
|
3679
|
-
}
|
|
3680
|
-
|
|
3681
|
-
.dshr-compNoticeTitle {
|
|
3682
|
-
color: var(--dsw-alias-label-primary);
|
|
3683
|
-
font-size: 13px;
|
|
3684
|
-
font-weight: 500;
|
|
3685
|
-
line-height: 20px;
|
|
3686
|
-
}
|
|
3687
|
-
|
|
3688
|
-
.dshr-compNoticeText {
|
|
3689
|
-
color: var(--dsw-alias-label-secondary);
|
|
3690
|
-
font-size: 12.5px;
|
|
3691
|
-
line-height: 19px;
|
|
3692
|
-
/* 上游可能回一整段 HTML/JSON,限定宽度换行,别把布局撑破 */
|
|
3693
|
-
overflow-wrap: anywhere;
|
|
3694
|
-
}
|
|
3695
|
-
|
|
3696
|
-
/* 回显测的是哪三样。一条「通过」如果不带对象,就是没法归因的一串绿字。 */
|
|
3697
|
-
.dshr-compNoticeMeta {
|
|
3698
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3699
|
-
font-size: 12px;
|
|
3700
|
-
line-height: 18px;
|
|
3701
|
-
overflow-wrap: anywhere;
|
|
3702
|
-
}
|
|
3703
|
-
|
|
3704
|
-
/* 宿主 Button 原语的 primary 想把字色设成 --dsw-alias-label-primary-foreground,
|
|
3705
|
-
但上面那条兜底 `.dshr-settings button { color: inherit; font: inherit }`
|
|
3706
|
-
特异性 (1,1) **高于**原语的 `.primary` (1,0) —— 赢的是它。于是按钮变成
|
|
3707
|
-
「#0f1115 的底 + 继承来的 #0f1115 的字」,黑底黑字、按钮看着是空的。
|
|
3708
|
-
|
|
3709
|
-
按本文件既有的抬特异性办法修(见文件里 .dshr-tab-on / .dshr-period 那几处注释:
|
|
3710
|
-
凡是受这条兜底影响的规则,都必须带挂载容器抬到 (2,0) 以上)。这里
|
|
3711
|
-
`.dshr-comp .dshr-compBtnRow button` 是 (2,1),不依赖源码顺序,以后有人挪块也不会翻车。
|
|
3712
|
-
|
|
3713
|
-
作用域挂在**动作行的共用类 `dshr-compBtnRow`** 上,不是某个具体容器:上一版这条
|
|
3714
|
-
只写了 `.dshr-compActions`,随后新增的「契约体检」按钮在另一个容器里,于是又变回
|
|
3715
|
-
黑底黑字。现在两个动作行共用这个类,再加按钮只需沿用它。
|
|
3716
|
-
|
|
3717
|
-
修的是**把原语的意图还回去**,不是自己另挑一个颜色:字色仍由原语那个 token 决定。 */
|
|
3718
|
-
.dshr-comp .dshr-compBtnRow button {
|
|
3719
|
-
color: var(--dsw-alias-label-primary-foreground);
|
|
3720
|
-
font-size: 14px;
|
|
3721
|
-
line-height: 22px;
|
|
3722
|
-
}
|
|
3723
|
-
|
|
3724
|
-
/* --- 契约体检区(插件自检面板的第二块) ---
|
|
3725
|
-
状态靠 data-state 上色,和「结果卡」那套语气一致:过了是绿、失败是红、
|
|
3726
|
-
没实现是灰、不执行是中性(它是**故意**不跑的,不是问题)。 */
|
|
3727
|
-
|
|
3728
|
-
.dshr-compSection {
|
|
3729
|
-
display: flex;
|
|
3730
|
-
flex-direction: column;
|
|
3731
|
-
gap: 12px;
|
|
3732
|
-
margin-top: 4px;
|
|
3733
|
-
padding-top: 16px;
|
|
3734
|
-
border-top: 0.5px solid var(--dsw-alias-border-l1);
|
|
3735
|
-
}
|
|
3736
|
-
|
|
3737
|
-
.dshr-compHead {
|
|
3738
|
-
display: flex;
|
|
3739
|
-
align-items: baseline;
|
|
3740
|
-
justify-content: space-between;
|
|
3741
|
-
gap: 8px;
|
|
3742
|
-
}
|
|
3743
|
-
|
|
3744
|
-
.dshr-compSectionTitle {
|
|
3745
|
-
margin: 0;
|
|
3746
|
-
color: var(--dsw-alias-label-primary);
|
|
3747
|
-
font-size: 14px;
|
|
3748
|
-
font-weight: 500;
|
|
3749
|
-
line-height: 20px;
|
|
3750
|
-
}
|
|
3751
|
-
|
|
3752
|
-
.dshr-compSectionNote {
|
|
3753
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3754
|
-
font-size: 12px;
|
|
3755
|
-
line-height: 18px;
|
|
3756
|
-
}
|
|
3757
|
-
|
|
3758
|
-
.dshr-compProbeRow {
|
|
3759
|
-
display: flex;
|
|
3760
|
-
align-items: flex-end;
|
|
3761
|
-
gap: 12px;
|
|
3762
|
-
}
|
|
3763
|
-
|
|
3764
|
-
.dshr-compProbeRow .dshr-compField {
|
|
3765
|
-
flex: 1;
|
|
3766
|
-
}
|
|
3767
|
-
|
|
3768
|
-
.dshr-compProbeBtn {
|
|
3769
|
-
flex: none;
|
|
3770
|
-
}
|
|
3771
|
-
|
|
3772
|
-
.dshr-compReport {
|
|
3773
|
-
display: flex;
|
|
3774
|
-
flex-direction: column;
|
|
3775
|
-
gap: 8px;
|
|
3776
|
-
padding: 12px 14px;
|
|
3777
|
-
border: 0.5px solid var(--dsw-alias-border-l1);
|
|
3778
|
-
border-radius: 12px;
|
|
3779
|
-
background: var(--dsw-alias-bg-layer-1);
|
|
3780
|
-
}
|
|
3781
|
-
|
|
3782
|
-
.dshr-compReportHead {
|
|
3783
|
-
display: flex;
|
|
3784
|
-
align-items: baseline;
|
|
3785
|
-
justify-content: space-between;
|
|
3786
|
-
gap: 10px;
|
|
3787
|
-
flex-wrap: wrap;
|
|
3788
|
-
}
|
|
3789
|
-
|
|
3790
|
-
.dshr-compReportName {
|
|
3791
|
-
color: var(--dsw-alias-label-primary);
|
|
3792
|
-
font-size: 13px;
|
|
3793
|
-
font-weight: 500;
|
|
3794
|
-
line-height: 20px;
|
|
3795
|
-
}
|
|
3796
|
-
|
|
3797
|
-
.dshr-compReportSum {
|
|
3798
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3799
|
-
font-size: 12px;
|
|
3800
|
-
line-height: 18px;
|
|
3801
|
-
}
|
|
3802
|
-
|
|
3803
|
-
.dshr-compMembers {
|
|
3804
|
-
display: flex;
|
|
3805
|
-
flex-direction: column;
|
|
3806
|
-
margin: 0;
|
|
3807
|
-
padding: 0;
|
|
3808
|
-
list-style: none;
|
|
3809
|
-
}
|
|
3810
|
-
|
|
3811
|
-
.dshr-compMember {
|
|
3812
|
-
display: grid;
|
|
3813
|
-
grid-template-columns: 16px minmax(0, auto) minmax(0, 1fr);
|
|
3814
|
-
align-items: baseline;
|
|
3815
|
-
gap: 10px;
|
|
3816
|
-
padding: 5px 0;
|
|
3817
|
-
border-bottom: 0.5px solid var(--dsw-alias-border-l1);
|
|
3818
|
-
}
|
|
3819
|
-
|
|
3820
|
-
.dshr-compMember:last-child {
|
|
3821
|
-
border-bottom: 0;
|
|
3822
|
-
}
|
|
3823
|
-
|
|
3824
|
-
.dshr-compMemberState {
|
|
3825
|
-
flex: none;
|
|
3826
|
-
text-align: center;
|
|
3827
|
-
font-size: 12px;
|
|
3828
|
-
line-height: 18px;
|
|
3829
|
-
}
|
|
3830
|
-
|
|
3831
|
-
.dshr-compMember[data-state="ok"] .dshr-compMemberState {
|
|
3832
|
-
color: var(--dsw-alias-state-success-secondary);
|
|
3833
|
-
}
|
|
3834
|
-
|
|
3835
|
-
.dshr-compMember[data-state="fail"] .dshr-compMemberState {
|
|
3836
|
-
color: var(--dsw-alias-state-error-primary);
|
|
3837
|
-
}
|
|
3838
|
-
|
|
3839
|
-
.dshr-compMember[data-state="absent"] .dshr-compMemberState,
|
|
3840
|
-
.dshr-compMember[data-state="skipped"] .dshr-compMemberState {
|
|
3841
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3842
|
-
}
|
|
3843
|
-
|
|
3844
|
-
.dshr-compMemberName {
|
|
3845
|
-
color: var(--dsw-alias-label-primary);
|
|
3846
|
-
font-size: 12.5px;
|
|
3847
|
-
line-height: 19px;
|
|
3848
|
-
white-space: nowrap;
|
|
3849
|
-
}
|
|
3850
|
-
|
|
3851
|
-
.dshr-compMemberKey {
|
|
3852
|
-
margin-left: 6px;
|
|
3853
|
-
color: var(--dsw-alias-label-tertiary);
|
|
3854
|
-
font-family: var(--dsw-font-mono, ui-monospace, SFMono-Regular, Menlo, monospace);
|
|
3855
|
-
font-size: 11px;
|
|
3856
|
-
}
|
|
3857
|
-
|
|
3858
|
-
.dshr-compMemberDetail {
|
|
3859
|
-
color: var(--dsw-alias-label-secondary);
|
|
3860
|
-
font-size: 12px;
|
|
3861
|
-
line-height: 18px;
|
|
3862
|
-
overflow-wrap: anywhere;
|
|
3863
|
-
}
|
|
3864
|
-
|
|
3865
|
-
|
package/src/ext/contract.ts
CHANGED
|
@@ -182,7 +182,7 @@ export interface ExtControl {
|
|
|
182
182
|
/**
|
|
183
183
|
* 分组名(可选;缺省 = 无组)—— 面板按它把控制条**分节**渲染,组间插一条
|
|
184
184
|
* 组标题行,组内顺序照旧。**无组的条目照旧平铺** ⇒ 没用这个字段的扩展
|
|
185
|
-
*
|
|
185
|
+
* 面板行为一个像素都不变。
|
|
186
186
|
*
|
|
187
187
|
* 为什么要有:一条扩展同时管两类东西时(分层提示词 = 准则分类 + 宿主段落),
|
|
188
188
|
* 平铺成一长列会让"哪条是准则、哪条是宿主的段"无从分辨 —— 分组是**归属
|
|
@@ -26,6 +26,17 @@
|
|
|
26
26
|
* `categories`/`text`/`order` 里残留的 `hardening` 键无须迁移 ——
|
|
27
27
|
* `resolveCategories` 规则 2 会忽略不认识的 id。
|
|
28
28
|
* ② 身份气质:「默认中文」→「回复、思考过程必须使用中文」。
|
|
29
|
+
*
|
|
30
|
+
* ⚠️ 2026-10-27 用户点名的四处改动:
|
|
31
|
+
* ① **删掉「可判定」分类**(整条移除,id `verdifiable`);已存配置里的残留键
|
|
32
|
+
* 由 `resolveCategories` 忽略,无须迁移。
|
|
33
|
+
* ② **删掉「绝不偷懒」分类**(整条移除,id `no-cheap`)——用户判定它与别处重复。
|
|
34
|
+
* ③ 执行顺序重写:去掉「查结构行号 / 声明任务四件套 / 读码取切片 / 循既有骨架 /
|
|
35
|
+
* 以闸门为准」几段,改为「循既有架构/提出更优架构 → 验证以测试/e2e 验收」;
|
|
36
|
+
* 并在首尾补上「读文档」与「更新文档」—— 任务不是从零开始,也不以提交收尾。
|
|
37
|
+
* ④ **新增「文档」分类**(id `doc`):用户口述「文档不写流水账、只写权威内容」
|
|
38
|
+
* + 点名范围「docs/ 下的调研、设计、任务」,本文件只做润色。
|
|
39
|
+
* 排在「全局收口」之后 —— 收口查"文档过期没有",这条管"文档该写什么"。
|
|
29
40
|
*/
|
|
30
41
|
|
|
31
42
|
/** 一个可独立开关的提示词分类。 */
|
|
@@ -87,11 +98,12 @@ export const PROMPT_CATEGORIES: readonly PromptCategory[] = [
|
|
|
87
98
|
'做完那块区域该比动手前更整或更少。',
|
|
88
99
|
},
|
|
89
100
|
{
|
|
90
|
-
id: '
|
|
91
|
-
title: '
|
|
101
|
+
id: 'doc',
|
|
102
|
+
title: '文档',
|
|
92
103
|
defaultOn: true,
|
|
93
104
|
body:
|
|
94
|
-
'
|
|
105
|
+
'文档:docs/ 里的调研/设计/任务文档,只写权威内容——结论、约束、怎么用;' +
|
|
106
|
+
'不写流水账(过程、试错、时间线),历史归 git。',
|
|
95
107
|
},
|
|
96
108
|
{
|
|
97
109
|
id: 'root-cause',
|
|
@@ -123,13 +135,6 @@ export const PROMPT_CATEGORIES: readonly PromptCategory[] = [
|
|
|
123
135
|
'结构:先让结构对再让代码短;命名/边界/单一职责优先于行数;依赖单向无环、公共逻辑收敛一处;' +
|
|
124
136
|
'单文件单功能,软顶函数 ~40 行/文件 ~300 行。',
|
|
125
137
|
},
|
|
126
|
-
{
|
|
127
|
-
id: 'no-cheap',
|
|
128
|
-
title: '绝不偷懒',
|
|
129
|
-
defaultOn: true,
|
|
130
|
-
body:
|
|
131
|
-
'绝不偷懒:边界输入校验、防数据丢失、安全、可访问性、真实硬件校准;非平凡逻辑留个能跑的检查。',
|
|
132
|
-
},
|
|
133
138
|
{
|
|
134
139
|
id: 'delivery',
|
|
135
140
|
title: '交付',
|
|
@@ -143,8 +148,8 @@ export const PROMPT_CATEGORIES: readonly PromptCategory[] = [
|
|
|
143
148
|
title: '执行顺序',
|
|
144
149
|
defaultOn: true,
|
|
145
150
|
body:
|
|
146
|
-
'
|
|
147
|
-
'
|
|
151
|
+
'执行:拉记忆→读文档→看全貌→定位任务→建领地→循既有架构/提出更优架构→验证以测试/e2e 验收→' +
|
|
152
|
+
'收口复查全貌→更新文档→提交。',
|
|
148
153
|
},
|
|
149
154
|
] as const
|
|
150
155
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* 1. 登记进 `router.ext` 表,带上可显示的身份(名字/说明/就绪);
|
|
4
4
|
* 2. **幂等**:同一个 id 已在表里就不顶掉别人的登记;
|
|
5
5
|
* 3. `source: 'builtin'`(随核心分发 ⇒ 插件页的原生行,自绘节不重复列);
|
|
6
|
-
* 4. **准则段落真的挂上了** ——
|
|
6
|
+
* 4. **准则段落真的挂上了** —— 这是本扩展唯一的执行面,必须单独验。
|
|
7
7
|
*
|
|
8
8
|
* 为什么第 4 条不可省:扩展的「卡片出现与否」取决于它在不在这张表里,而**准则
|
|
9
9
|
* 有没有进 prompt** 取决于段落挂没挂 —— 两者是**不同的失效**,都静默且都不报错。
|
|
@@ -75,7 +75,7 @@ test('★ patch 里真的声明了这一行,且 id/name 逐字对得上', () =
|
|
|
75
75
|
assert.equal(block![1], 'dsh-router-core/ext-prompt', 'patch 的 name 必须是能解析的子路径说明符')
|
|
76
76
|
})
|
|
77
77
|
|
|
78
|
-
test('★
|
|
78
|
+
test('★ 那一行默认关闭', () => {
|
|
79
79
|
// `disabled: true` = 行默认关 ⇒ loader 不 import ⇒ 扩展不进 `router.ext` 表 ⇒
|
|
80
80
|
// 卡片不出现、准则不进 prompt。
|
|
81
81
|
//
|
|
@@ -148,7 +148,7 @@ test('幂等:同一个 id 已在表里时不顶掉别人的登记', async () =
|
|
|
148
148
|
assert.equal(table[EXT_PROMPT_ID], first, '重复登记不该换成一个新对象')
|
|
149
149
|
})
|
|
150
150
|
|
|
151
|
-
test('★ apply 把准则挂成了 system prompt
|
|
151
|
+
test('★ apply 把准则挂成了 system prompt 段落', async () => {
|
|
152
152
|
const { ctx, sections } = await realCtx()
|
|
153
153
|
apply(ctx as unknown as Parameters<typeof apply>[0])
|
|
154
154
|
assert.equal(sections.length, 1, '准则没挂上 = 卡片亮着但 prompt 里没有准则')
|
package/src/ext-prompt/index.ts
CHANGED
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
* 分层提示词扩展的 **cordis 行** —— 官方插件页(设置 → 插件 → dsh-router-core)详情页
|
|
3
3
|
* 原生「包含的组件」里的那一行。
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* 本扩展要把准则真注入,所以额外等 `systemPrompt` service 就绪后挂 section。
|
|
5
|
+
* 壳的形状 = cordis 身份 + 登记,实现 = `plugin.ts`;**执行面的事**是挂
|
|
6
|
+
* system prompt 段落 —— 所以额外等 `systemPrompt` service 就绪后挂 section。
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* 让准则默认缺席,会变成「用户不知道它存在 ⇒ 协作按另一套规则执行」。
|
|
8
|
+
* **默认关闭**(patch 里 `disabled: true`):开不开由用户决定。行关闭时 loader
|
|
9
|
+
* 根本不 import 本模块,扩展就不在 `router.ext` 表里 ——「打开才出现这张卡片」
|
|
10
|
+
* 是天然的,不需要额外状态位。
|
|
13
11
|
*
|
|
14
12
|
* 登记时把扩展开关置为开:本扩展**没有独立的运行期开关**,它的开关就是这一行
|
|
15
13
|
* (宿主管的那个)。不置上的话,用户开了行还要再点一次,两级开关说同一件事。
|
|
@@ -52,8 +50,8 @@ function systemPromptOf(sctx: Context): SystemPromptFace | undefined {
|
|
|
52
50
|
*
|
|
53
51
|
* ⚠️⚠️ **必须导出这个数组,且 `apply` 里直接用 `ctx.systemPrompt`**(2026-09-29 修)
|
|
54
52
|
* ——我原先写成「在 apply 里 `ctx.inject(['systemPrompt'], cb)`」,**准则一直不进
|
|
55
|
-
* prompt**:面板上卡片、开关、原文全都正常(`GET /router/api/ext`
|
|
56
|
-
*
|
|
53
|
+
* prompt**:面板上卡片、开关、原文全都正常(`GET /router/api/ext` 里 controls 一条
|
|
54
|
+
* 不少),但模型看到的 system prompt 里没有它。
|
|
57
55
|
*
|
|
58
56
|
* 根因(本机 cordis 4.0.4 实测):`ctx.inject(deps, cb)` 的回调**不是同步触发** ——
|
|
59
57
|
* provide 之后立刻 `inject`,回调要等到下一个异步点才跑。插件的 `apply` 是**同步
|
package/src/ext-prompt/mount.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
* 挂载层 —— 把准则注册成 `ctx.systemPrompt` 的**一个**段落。
|
|
3
3
|
*
|
|
4
4
|
* ════════════════════════════════════════════════════════════════════
|
|
5
|
-
*
|
|
5
|
+
* 为什么只注册一段,而不是一段一个分类
|
|
6
6
|
* ════════════════════════════════════════════════════════════════════
|
|
7
|
-
* 面板开关的粒度是「分类」,但 prompt
|
|
7
|
+
* 面板开关的粒度是「分类」,但 prompt 读起来应该是一段连续的准则。分成多段
|
|
8
8
|
* 会让 KV cache 每个分类各占一段,且**增删任意一个分类都让它之后的全部分位**。
|
|
9
9
|
* 一段 + 拼装 ⇒ 分类增删只改这一段内部,段的位置与前缀稳定。
|
|
10
10
|
*
|
package/src/ext-prompt/plugin.ts
CHANGED
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* 分层提示词扩展(`router.ext` 侧的实现)—— 声明与状态都在这里。
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* 注册成一段 system prompt。
|
|
4
|
+
* **不挂任何监听、不改写任何东西**,唯一作用是让用户在官方插件页里看到一张
|
|
5
|
+
* 卡片、能开关它,并把协作准则注册成一段 system prompt。
|
|
7
6
|
*
|
|
8
7
|
* 与 `rtk` / `jev` 那类扩展的区别要写清楚:那两家挂 `tools/execute`
|
|
9
8
|
* 改写**工具调用**;本扩展只往 **system prompt** 加一段。名字同族是因为
|
|
10
9
|
* 都在 `router.ext` 这张表里,拦截面不重叠。
|
|
11
10
|
*
|
|
12
|
-
* 复用 `router.ext` 通道只为拿到**发现 +
|
|
13
|
-
* 真正的注入在 `mount.ts`。
|
|
11
|
+
* 复用 `router.ext` 通道只为拿到**发现 + 开关**两件事,真正的注入在 `mount.ts`。
|
|
14
12
|
*/
|
|
15
13
|
import type { ExtStoreService, RouterExt } from '../ext/contract.ts'
|
|
16
14
|
import { PROMPT_CATEGORIES, PROMPT_TITLE } from './content.ts'
|
package/src/router/index.ts
CHANGED
|
@@ -1043,9 +1043,8 @@ export class Router {
|
|
|
1043
1043
|
// 注意这里**刻意不**把「用户禁用过的模型」也补回来:插件的 listModels 只该报
|
|
1044
1044
|
// 「模型来源」,启用状态由核心合并(见 loader.ts 的 modelsWithEnabled)。
|
|
1045
1045
|
// 插件若在 listModels 里就把自己禁用的过滤掉,那是它违约 —— 该修的是插件,
|
|
1046
|
-
//
|
|
1047
|
-
//
|
|
1048
|
-
// 永远报 OK,那个 bug 就再也没人发现了。
|
|
1046
|
+
// 核心不该反过来替它兜着:兜着之后面板看着正常了,插件那个 bug 就再也没人
|
|
1047
|
+
// 发现了(症状消失、原因还在)。少报就让它少报,用户看得见才好去修插件。
|
|
1049
1048
|
const seen = new Set(models.map((mm) => mm.id))
|
|
1050
1049
|
for (const id of custom) {
|
|
1051
1050
|
if (!seen.has(id)) {
|