dsh-custom-mode 1.7.1 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/client.js +144 -31
- package/locales.mjs +18 -0
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -98,6 +98,15 @@ try {
|
|
|
98
98
|
"api.alreadyLast": "「{name}」已经在最后面。",
|
|
99
99
|
"api.badVariableName": "变量引用的写法不合法:{variable} 里的名字只能用小写字母、数字、下划线,且以字母开头。要写字面量花括号,请用单个左花括号,或不闭合的双左花括号。",
|
|
100
100
|
"api.unknownVariable": "{variable} 不是已注册的变量,渲染会报错并让本模式每个请求都失败。可用:{known}。",
|
|
101
|
+
"aria.expand": "展开详情",
|
|
102
|
+
"aria.collapse": "收起详情",
|
|
103
|
+
"detail.id": "行 id",
|
|
104
|
+
"detail.note": "说明",
|
|
105
|
+
"detail.state": "开关状态",
|
|
106
|
+
"detail.explicitOn": "已手动启用",
|
|
107
|
+
"detail.explicitOff": "已手动停用",
|
|
108
|
+
"detail.untouched": "未改动(跟随官方默认)",
|
|
109
|
+
"detail.platform": "平台条件",
|
|
101
110
|
"api.saved": "已保存({name},基础模式 {mode})。新建会话即生效,当前会话保持原配置。",
|
|
102
111
|
"api.created": "已创建「{name}」。现在可以为它写系统提示词。",
|
|
103
112
|
"api.duplicated": "已复制自「{from}」。两份从此各改各的。",
|
|
@@ -272,6 +281,15 @@ try {
|
|
|
272
281
|
"api.alreadyLast": "「{name}」 is already last.",
|
|
273
282
|
"api.badVariableName": "{variable} is not a valid variable reference: names may use lower-case letters, digits and underscores, and must start with a letter. For a literal brace, use a single opening brace or an unclosed double brace.",
|
|
274
283
|
"api.unknownVariable": "{variable} is not a registered variable — rendering would fail every request in this mode. Available: {known}.",
|
|
284
|
+
"aria.expand": "Show details",
|
|
285
|
+
"aria.collapse": "Hide details",
|
|
286
|
+
"detail.id": "Row id",
|
|
287
|
+
"detail.note": "Note",
|
|
288
|
+
"detail.state": "Switch",
|
|
289
|
+
"detail.explicitOn": "Set to on by you",
|
|
290
|
+
"detail.explicitOff": "Set to off by you",
|
|
291
|
+
"detail.untouched": "Untouched (follows the shipped default)",
|
|
292
|
+
"detail.platform": "Platform condition",
|
|
275
293
|
"api.saved": "Saved ({name}, base mode {mode}). A new session picks it up; the current one keeps its configuration.",
|
|
276
294
|
"api.created": "Created 「{name}」. You can write its system prompt now.",
|
|
277
295
|
"api.duplicated": "Copied from 「{from}」. The two are independent from now on.",
|
|
@@ -567,14 +585,25 @@ try {
|
|
|
567
585
|
".cpfe-actions{display:flex;flex-wrap:wrap;gap:var(--g);align-items:center;margin-top:4px}",
|
|
568
586
|
".cpfe-newrow{display:flex;gap:var(--g);align-items:center;flex-wrap:wrap;margin-top:10px}",
|
|
569
587
|
".cpfe-field{display:flex;width:100%;margin-bottom:8px}",
|
|
570
|
-
".cpfe-row-head{
|
|
571
|
-
".cpfe-row-switch{flex:0 0 auto
|
|
588
|
+
".cpfe-row-head{font-size:13px;line-height:18px;color:var(--dsw-alias-label-primary)}",
|
|
589
|
+
".cpfe-row-switch{flex:0 0 auto}",
|
|
590
|
+
".cpfe-row-line{display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-width:0}",
|
|
591
|
+
".cpfe-row-note{min-height:16px;font-size:12px;line-height:16px;color:var(--dsw-alias-label-secondary);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}",
|
|
592
|
+
".cpfe-row-toggle{flex:0 0 auto;width:22px;height:22px;padding:0;border:0;border-radius:6px;background:transparent;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:11px;line-height:1}",
|
|
593
|
+
".cpfe-row-toggle:hover{background:var(--dsw-alias-bg-layer-2)}",
|
|
594
|
+
".cpfe-row-open{border-color:var(--dsw-alias-border-l2)}",
|
|
595
|
+
".cpfe-row-detail{display:flex;flex-direction:column;gap:4px;margin:0 0 2px 14px;padding:8px 12px;border-left:.5px solid var(--dsw-alias-border-l1);font-size:12px;line-height:17px;color:var(--dsw-alias-label-secondary)}",
|
|
596
|
+
".cpfe-detail-line{display:flex;gap:8px;min-width:0}",
|
|
597
|
+
".cpfe-detail-key{flex:0 0 62px;color:var(--dsw-alias-label-secondary)}",
|
|
598
|
+
".cpfe-detail-value{min-width:0;overflow-wrap:anywhere}",
|
|
572
599
|
".cpfe-sec-head{display:flex;align-items:center;justify-content:space-between;gap:var(--g);flex-wrap:wrap}",
|
|
573
600
|
".cpfe-newinput{flex:1;min-width:200px}",
|
|
574
|
-
|
|
575
|
-
".cpfe-
|
|
576
|
-
".cpfe-
|
|
577
|
-
".cpfe-
|
|
601
|
+
// 单列、行高统一(对齐官方插件页的形态);之前的自适应多列网格会让行高参差不齐。
|
|
602
|
+
".cpfe-rows{display:flex;flex-direction:column;gap:6px;margin-top:4px}",
|
|
603
|
+
".cpfe-line{display:flex;flex-direction:column;gap:6px;min-width:0}",
|
|
604
|
+
".cpfe-group{display:flex;flex-direction:column;gap:6px;margin-top:8px;min-width:0}",
|
|
605
|
+
".cpfe-kids{display:flex;flex-direction:column;gap:6px;margin-left:14px;padding-left:14px;border-left:.5px solid var(--dsw-alias-border-l1)}",
|
|
606
|
+
".cpfe-row{display:flex;gap:10px;align-items:center;box-sizing:border-box;min-height:52px;padding:8px 12px;border-radius:10px;border:.5px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1)}",
|
|
578
607
|
".cpfe-row-meta{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1}",
|
|
579
608
|
".cpfe-row-badges{display:flex;align-items:center;gap:6px;flex-wrap:wrap}",
|
|
580
609
|
".cpfe-editor{box-sizing:border-box;width:100%;min-height:240px;resize:vertical;padding:12px;border-radius:10px;border:.5px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-base);color:var(--dsw-alias-label-primary);font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:13px;line-height:20px}",
|
|
@@ -704,9 +733,17 @@ try {
|
|
|
704
733
|
return String(template).replace("{name}", name)
|
|
705
734
|
}
|
|
706
735
|
|
|
707
|
-
/**
|
|
736
|
+
/**
|
|
737
|
+
* One row of the plugin switch list.
|
|
738
|
+
*
|
|
739
|
+
* Laid out like the shell's own plugin page: **one compact line per row** — title, status tags, a
|
|
740
|
+
* one-line truncated description and the switch on the right — with everything else (the row id, the
|
|
741
|
+
* full note, the tri-state detail, the platform condition) behind a per-row disclosure. Measured before
|
|
742
|
+
* this change: 33 rows at 274px wide and 84–117px tall with a bare `tool-bash` line each, i.e. uneven
|
|
743
|
+
* heights and a lot of vertical noise for information most users never read.
|
|
744
|
+
*/
|
|
708
745
|
function RowList(props) {
|
|
709
|
-
const { rows, overrides, onToggle, depth, t } = props
|
|
746
|
+
const { rows, overrides, onToggle, expanded, onToggleExpand, depth, t } = props
|
|
710
747
|
return react.createElement(
|
|
711
748
|
"div",
|
|
712
749
|
{ className: depth === 0 ? "cpfe-rows" : "cpfe-kids" },
|
|
@@ -716,49 +753,109 @@ try {
|
|
|
716
753
|
const effective = overrides[row.id] !== undefined ? overrides[row.id] : !row.disabled
|
|
717
754
|
const changed = overrides[row.id] !== undefined
|
|
718
755
|
const rowTitle = t("row." + row.id + ".label", row.label)
|
|
756
|
+
const note = row.note === null || row.note === undefined ? null : t("row." + row.id + ".note", row.note)
|
|
757
|
+
const open = expanded !== undefined && expanded[row.id] === true
|
|
719
758
|
return react.createElement(
|
|
720
759
|
"div",
|
|
721
|
-
{ key: row.id, className: row.children.length > 0 ? "cpfe-group" :
|
|
760
|
+
{ key: row.id, className: row.children.length > 0 ? "cpfe-group" : "cpfe-line" },
|
|
722
761
|
react.createElement(
|
|
723
762
|
"div",
|
|
724
|
-
{ className: "cpfe-row" },
|
|
763
|
+
{ className: "cpfe-row" + (open ? " cpfe-row-open" : "") },
|
|
764
|
+
react.createElement(
|
|
765
|
+
"div",
|
|
766
|
+
{ className: "cpfe-row-meta" },
|
|
767
|
+
react.createElement(
|
|
768
|
+
"div",
|
|
769
|
+
{ className: "cpfe-row-line" },
|
|
770
|
+
react.createElement("span", { className: "cpfe-row-head" }, rowTitle),
|
|
771
|
+
react.createElement(
|
|
772
|
+
"div",
|
|
773
|
+
{ className: "cpfe-row-badges" },
|
|
774
|
+
react.createElement(
|
|
775
|
+
A.Tag,
|
|
776
|
+
{ tone: effective ? "success" : "neutral" },
|
|
777
|
+
effective ? t("status.enabled") : t("status.disabled"),
|
|
778
|
+
),
|
|
779
|
+
row.essential ? react.createElement(A.Tag, { tone: "warning" }, t("tag.essential")) : null,
|
|
780
|
+
row.disabledExpression !== null && row.disabledExpression !== undefined
|
|
781
|
+
? react.createElement(A.Tag, { tone: "outline" }, t("tag.followPlatform"))
|
|
782
|
+
: null,
|
|
783
|
+
changed ? react.createElement(A.Tag, { tone: "info" }, t("status.changed")) : null,
|
|
784
|
+
),
|
|
785
|
+
),
|
|
786
|
+
// 折叠时只留一行说明(超出截断,悬停给全文)。**没有说明就留空**:裸露的行 id
|
|
787
|
+
// 是开发者信息,已经在「详情」里 —— 之前它作为副标题占了每行一行。
|
|
788
|
+
react.createElement("span", { className: "cpfe-row-note", title: note ?? "" }, note ?? ""),
|
|
789
|
+
),
|
|
790
|
+
react.createElement(
|
|
791
|
+
"button",
|
|
792
|
+
{
|
|
793
|
+
type: "button",
|
|
794
|
+
className: "cpfe-row-toggle",
|
|
795
|
+
"aria-expanded": open,
|
|
796
|
+
"aria-label": t(open ? "aria.collapse" : "aria.expand"),
|
|
797
|
+
onClick: () => onToggleExpand(row.id),
|
|
798
|
+
},
|
|
799
|
+
open ? "▾" : "▸",
|
|
800
|
+
),
|
|
725
801
|
react.createElement(A.Switch, {
|
|
726
802
|
checked: effective,
|
|
727
803
|
onChange: (next) => onToggle(row.id, next),
|
|
728
804
|
// `Switch` renders NO text: its `label` is the accessible name only, so the
|
|
729
|
-
// visible title is drawn
|
|
805
|
+
// visible title is drawn next to it (an unlabelled toggle is unusable).
|
|
730
806
|
label: rowTitle,
|
|
731
807
|
className: "cpfe-row-switch",
|
|
732
808
|
}),
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
react.createElement("span", { className: "cpfe-row-head" }, rowTitle),
|
|
737
|
-
react.createElement(
|
|
809
|
+
),
|
|
810
|
+
open
|
|
811
|
+
? react.createElement(
|
|
738
812
|
"div",
|
|
739
|
-
{ className: "cpfe-row-
|
|
813
|
+
{ className: "cpfe-row-detail" },
|
|
740
814
|
react.createElement(
|
|
741
|
-
|
|
742
|
-
{
|
|
743
|
-
|
|
815
|
+
"div",
|
|
816
|
+
{ className: "cpfe-detail-line" },
|
|
817
|
+
react.createElement("span", { className: "cpfe-detail-key" }, t("detail.id")),
|
|
818
|
+
react.createElement("span", { className: "cpfe-mono" }, row.id),
|
|
744
819
|
),
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
820
|
+
note === null
|
|
821
|
+
? null
|
|
822
|
+
: react.createElement(
|
|
823
|
+
"div",
|
|
824
|
+
{ className: "cpfe-detail-line" },
|
|
825
|
+
react.createElement("span", { className: "cpfe-detail-key" }, t("detail.note")),
|
|
826
|
+
react.createElement("span", { className: "cpfe-detail-value" }, note),
|
|
827
|
+
),
|
|
828
|
+
react.createElement(
|
|
829
|
+
"div",
|
|
830
|
+
{ className: "cpfe-detail-line" },
|
|
831
|
+
react.createElement("span", { className: "cpfe-detail-key" }, t("detail.state")),
|
|
832
|
+
react.createElement(
|
|
833
|
+
"span",
|
|
834
|
+
{ className: "cpfe-detail-value" },
|
|
835
|
+
changed
|
|
836
|
+
? effective
|
|
837
|
+
? t("detail.explicitOn")
|
|
838
|
+
: t("detail.explicitOff")
|
|
839
|
+
: t("detail.untouched"),
|
|
840
|
+
),
|
|
841
|
+
),
|
|
842
|
+
row.disabledExpression !== null && row.disabledExpression !== undefined
|
|
843
|
+
? react.createElement(
|
|
844
|
+
"div",
|
|
845
|
+
{ className: "cpfe-detail-line" },
|
|
846
|
+
react.createElement("span", { className: "cpfe-detail-key" }, t("detail.platform")),
|
|
847
|
+
react.createElement("span", { className: "cpfe-mono" }, String(row.disabledExpression)),
|
|
848
|
+
)
|
|
748
849
|
: null,
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
react.createElement("span", { className: "cpfe-mono" }, row.id),
|
|
752
|
-
row.note !== null
|
|
753
|
-
? react.createElement("span", { className: "cpfe-note" }, t("row." + row.id + ".note", row.note))
|
|
754
|
-
: null,
|
|
755
|
-
),
|
|
756
|
-
),
|
|
850
|
+
)
|
|
851
|
+
: null,
|
|
757
852
|
row.children.length > 0
|
|
758
853
|
? react.createElement(RowList, {
|
|
759
854
|
rows: row.children,
|
|
760
855
|
overrides: overrides,
|
|
761
856
|
onToggle: onToggle,
|
|
857
|
+
expanded: expanded,
|
|
858
|
+
onToggleExpand: onToggleExpand,
|
|
762
859
|
depth: depth + 1,
|
|
763
860
|
t: t,
|
|
764
861
|
})
|
|
@@ -818,6 +915,20 @@ try {
|
|
|
818
915
|
const [newName, setNewName] = react.useState("")
|
|
819
916
|
const [deleteOpen, setDeleteOpen] = react.useState(false)
|
|
820
917
|
const [acknowledged, setAcknowledged] = react.useState(false)
|
|
918
|
+
/**
|
|
919
|
+
* Which rows have their detail open, by row id.
|
|
920
|
+
*
|
|
921
|
+
* Per-row and local to the section: the list is long (33 rows measured) and the interesting detail
|
|
922
|
+
* differs per user, so nothing is expanded by default and nothing is persisted.
|
|
923
|
+
*/
|
|
924
|
+
const [expandedRows, setExpandedRows] = react.useState({})
|
|
925
|
+
const toggleRowExpanded = (id) =>
|
|
926
|
+
setExpandedRows((previous) => {
|
|
927
|
+
const next = { ...previous }
|
|
928
|
+
if (next[id] === true) delete next[id]
|
|
929
|
+
else next[id] = true
|
|
930
|
+
return next
|
|
931
|
+
})
|
|
821
932
|
/** Hidden `<input type="file">` behind the 「导入」 button. */
|
|
822
933
|
const fileInput = react.useRef(null)
|
|
823
934
|
|
|
@@ -1377,6 +1488,8 @@ try {
|
|
|
1377
1488
|
react.createElement("h2", { className: "cpfe-h" }, t("rows.heading")),
|
|
1378
1489
|
react.createElement("p", { className: "cpfe-sub" }, t("rows.hint")),
|
|
1379
1490
|
react.createElement(RowList, {
|
|
1491
|
+
expanded: expandedRows,
|
|
1492
|
+
onToggleExpand: toggleRowExpanded,
|
|
1380
1493
|
rows: payload.rows,
|
|
1381
1494
|
overrides: draft.overrides,
|
|
1382
1495
|
onToggle: (id, next) => update({ overrides: { ...draft.overrides, [id]: next } }),
|
package/locales.mjs
CHANGED
|
@@ -57,6 +57,15 @@ export const zh = {
|
|
|
57
57
|
'api.alreadyLast': '「{name}」已经在最后面。',
|
|
58
58
|
'api.badVariableName': '变量引用的写法不合法:{variable} 里的名字只能用小写字母、数字、下划线,且以字母开头。要写字面量花括号,请用单个左花括号,或不闭合的双左花括号。',
|
|
59
59
|
'api.unknownVariable': '{variable} 不是已注册的变量,渲染会报错并让本模式每个请求都失败。可用:{known}。',
|
|
60
|
+
'aria.expand': '展开详情',
|
|
61
|
+
'aria.collapse': '收起详情',
|
|
62
|
+
'detail.id': '行 id',
|
|
63
|
+
'detail.note': '说明',
|
|
64
|
+
'detail.state': '开关状态',
|
|
65
|
+
'detail.explicitOn': '已手动启用',
|
|
66
|
+
'detail.explicitOff': '已手动停用',
|
|
67
|
+
'detail.untouched': '未改动(跟随官方默认)',
|
|
68
|
+
'detail.platform': '平台条件',
|
|
60
69
|
'api.saved': '已保存({name},基础模式 {mode})。新建会话即生效,当前会话保持原配置。',
|
|
61
70
|
'api.created': '已创建「{name}」。现在可以为它写系统提示词。',
|
|
62
71
|
'api.duplicated': '已复制自「{from}」。两份从此各改各的。',
|
|
@@ -247,6 +256,15 @@ export const en = {
|
|
|
247
256
|
'api.alreadyLast': '「{name}」 is already last.',
|
|
248
257
|
'api.badVariableName': '{variable} is not a valid variable reference: names may use lower-case letters, digits and underscores, and must start with a letter. For a literal brace, use a single opening brace or an unclosed double brace.',
|
|
249
258
|
'api.unknownVariable': '{variable} is not a registered variable — rendering would fail every request in this mode. Available: {known}.',
|
|
259
|
+
'aria.expand': 'Show details',
|
|
260
|
+
'aria.collapse': 'Hide details',
|
|
261
|
+
'detail.id': 'Row id',
|
|
262
|
+
'detail.note': 'Note',
|
|
263
|
+
'detail.state': 'Switch',
|
|
264
|
+
'detail.explicitOn': 'Set to on by you',
|
|
265
|
+
'detail.explicitOff': 'Set to off by you',
|
|
266
|
+
'detail.untouched': 'Untouched (follows the shipped default)',
|
|
267
|
+
'detail.platform': 'Platform condition',
|
|
250
268
|
'api.saved': 'Saved ({name}, base mode {mode}). A new session picks it up; the current one keeps its configuration.',
|
|
251
269
|
'api.created': 'Created 「{name}」. You can write its system prompt now.',
|
|
252
270
|
'api.duplicated': 'Copied from 「{from}」. The two are independent from now on.',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-custom-mode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.0",
|
|
4
4
|
"description": "Custom modes and custom prompts for DeepSeek Harness (dsh): edit a mode's system prompt on the settings page (it takes effect on the next model step), choose its base mode, switch plugins row by row, and keep several assistants side by side.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|