dsh-prompt-customizer 0.2.5 → 0.2.7
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/client.js +150 -78
- package/client/client.js.map +1 -1
- package/lib/index.js +197 -38
- package/lib/schema.js +18 -0
- package/package.json +1 -1
- package/src/client/PreviewTab.tsx +66 -0
- package/src/client/PreviewTools.tsx +31 -0
- package/src/client/ToolsTab.tsx +18 -14
- package/src/client/index.ts +6 -2
- package/src/client/locales.ts +16 -4
- package/src/client/styles.ts +3 -0
- package/src/client/types.ts +34 -0
package/client/client.js
CHANGED
|
@@ -15,6 +15,7 @@ window.__ModuleLoader__.load({
|
|
|
15
15
|
tabsSections: "提示词",
|
|
16
16
|
tabsTools: "工具",
|
|
17
17
|
tabsPresets: "预设",
|
|
18
|
+
tabsPreview: "预览",
|
|
18
19
|
refresh: "刷新",
|
|
19
20
|
blockedOff: "未屏蔽",
|
|
20
21
|
blockedOn: "已屏蔽",
|
|
@@ -30,13 +31,18 @@ window.__ModuleLoader__.load({
|
|
|
30
31
|
add: "添加",
|
|
31
32
|
hiddenOff: "可见",
|
|
32
33
|
hiddenOn: "已隐藏",
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
selectAll: "全选",
|
|
35
|
+
selectNone: "全不选",
|
|
35
36
|
empty: "(空)",
|
|
36
37
|
dynamic: "<动态生成>",
|
|
37
38
|
drag: "拖动排序",
|
|
38
39
|
moveUp: "上移",
|
|
39
40
|
moveDown: "下移",
|
|
41
|
+
previewHint: "以下为屏蔽/替换/注入后的最终系统提示词:",
|
|
42
|
+
previewPrompt: "提示词预览",
|
|
43
|
+
previewSections: "段",
|
|
44
|
+
previewTools: "工具预览",
|
|
45
|
+
previewToolCount: "个工具",
|
|
40
46
|
savePreset: "保存当前为预设",
|
|
41
47
|
presetName: "预设名称",
|
|
42
48
|
save: "保存",
|
|
@@ -55,6 +61,7 @@ window.__ModuleLoader__.load({
|
|
|
55
61
|
tabsSections: "Sections",
|
|
56
62
|
tabsTools: "Tools",
|
|
57
63
|
tabsPresets: "Presets",
|
|
64
|
+
tabsPreview: "Preview",
|
|
58
65
|
refresh: "Refresh",
|
|
59
66
|
blockedOff: "Active",
|
|
60
67
|
blockedOn: "Blocked",
|
|
@@ -70,13 +77,18 @@ window.__ModuleLoader__.load({
|
|
|
70
77
|
add: "Add",
|
|
71
78
|
hiddenOff: "Visible",
|
|
72
79
|
hiddenOn: "Hidden",
|
|
73
|
-
|
|
74
|
-
|
|
80
|
+
selectAll: "Select all",
|
|
81
|
+
selectNone: "Select none",
|
|
75
82
|
empty: "(empty)",
|
|
76
83
|
dynamic: "<dynamic>",
|
|
77
84
|
drag: "Drag to reorder",
|
|
78
85
|
moveUp: "Move up",
|
|
79
86
|
moveDown: "Move down",
|
|
87
|
+
previewHint: "Final system prompt after block/replace/inject:",
|
|
88
|
+
previewPrompt: "Prompt preview",
|
|
89
|
+
previewSections: "sections",
|
|
90
|
+
previewTools: "Tools preview",
|
|
91
|
+
previewToolCount: "tools",
|
|
80
92
|
savePreset: "Save current as preset",
|
|
81
93
|
presetName: "Preset name",
|
|
82
94
|
save: "Save",
|
|
@@ -179,6 +191,34 @@ window.__ModuleLoader__.load({
|
|
|
179
191
|
textOverflow: "ellipsis",
|
|
180
192
|
whiteSpace: "nowrap"
|
|
181
193
|
},
|
|
194
|
+
previewText: {
|
|
195
|
+
fontFamily: "monospace",
|
|
196
|
+
fontSize: 12,
|
|
197
|
+
lineHeight: 1.6,
|
|
198
|
+
whiteSpace: "pre-wrap",
|
|
199
|
+
wordBreak: "break-word",
|
|
200
|
+
maxHeight: 480,
|
|
201
|
+
overflowY: "auto",
|
|
202
|
+
padding: 10,
|
|
203
|
+
border: "1px solid rgba(128,128,128,.2)",
|
|
204
|
+
borderRadius: 8,
|
|
205
|
+
background: "rgba(0,0,0,.18)",
|
|
206
|
+
margin: 0
|
|
207
|
+
},
|
|
208
|
+
toolWrap: {
|
|
209
|
+
display: "flex",
|
|
210
|
+
flexWrap: "wrap",
|
|
211
|
+
gap: 6
|
|
212
|
+
},
|
|
213
|
+
toolChip: {
|
|
214
|
+
fontFamily: "monospace",
|
|
215
|
+
fontSize: 12,
|
|
216
|
+
color: "rgba(128,128,128,.95)",
|
|
217
|
+
border: "1px solid rgba(128,128,128,.3)",
|
|
218
|
+
borderRadius: 6,
|
|
219
|
+
padding: "2px 6px",
|
|
220
|
+
cursor: "help"
|
|
221
|
+
},
|
|
182
222
|
badgeOk: {
|
|
183
223
|
color: "#3fb950",
|
|
184
224
|
fontSize: 11,
|
|
@@ -478,60 +518,6 @@ window.__ModuleLoader__.load({
|
|
|
478
518
|
replace
|
|
479
519
|
};
|
|
480
520
|
}
|
|
481
|
-
/** Whether a tool is hidden under the current include/exclude config. */
|
|
482
|
-
function isToolHidden(name, toolsCfg) {
|
|
483
|
-
const include = toolsCfg?.include ?? [];
|
|
484
|
-
const exclude = toolsCfg?.exclude ?? [];
|
|
485
|
-
return include.length > 0 ? !include.includes(name) : exclude.includes(name);
|
|
486
|
-
}
|
|
487
|
-
/** Toggle a tool's hidden state, returning a new tools config. */
|
|
488
|
-
function toggleTool(name, currentlyHidden, toolsCfg) {
|
|
489
|
-
const include = toolsCfg?.include ?? [];
|
|
490
|
-
const exclude = toolsCfg?.exclude ?? [];
|
|
491
|
-
if (include.length > 0) {
|
|
492
|
-
const next = include.slice();
|
|
493
|
-
if (currentlyHidden) {
|
|
494
|
-
next.push(name);
|
|
495
|
-
return {
|
|
496
|
-
exclude: exclude.filter((n) => n !== name),
|
|
497
|
-
include: next
|
|
498
|
-
};
|
|
499
|
-
}
|
|
500
|
-
const i = next.indexOf(name);
|
|
501
|
-
if (i >= 0) next.splice(i, 1);
|
|
502
|
-
return {
|
|
503
|
-
exclude,
|
|
504
|
-
include: next
|
|
505
|
-
};
|
|
506
|
-
}
|
|
507
|
-
const next = exclude.slice();
|
|
508
|
-
if (currentlyHidden) {
|
|
509
|
-
const i = next.indexOf(name);
|
|
510
|
-
if (i >= 0) next.splice(i, 1);
|
|
511
|
-
} else next.push(name);
|
|
512
|
-
return {
|
|
513
|
-
exclude: next,
|
|
514
|
-
include
|
|
515
|
-
};
|
|
516
|
-
}
|
|
517
|
-
/**
|
|
518
|
-
* Switch between include (whitelist) and exclude (blacklist) modes. Turning
|
|
519
|
-
* include mode on discards names unknown to the current tool set and seeds the
|
|
520
|
-
* include list from the currently non-excluded tools; turning it off clears the
|
|
521
|
-
* include list (keep only known exclude names).
|
|
522
|
-
*/
|
|
523
|
-
function setToolMode(on, toolsCfg, toolNames) {
|
|
524
|
-
const known = new Set(toolNames);
|
|
525
|
-
const exclude = (toolsCfg?.exclude ?? []).filter((n) => known.has(n));
|
|
526
|
-
if (on) return {
|
|
527
|
-
exclude,
|
|
528
|
-
include: toolNames.filter((n) => !exclude.includes(n))
|
|
529
|
-
};
|
|
530
|
-
return {
|
|
531
|
-
exclude,
|
|
532
|
-
include: []
|
|
533
|
-
};
|
|
534
|
-
}
|
|
535
521
|
/** Serialize a preset for export (JSON-safe full snapshot). */
|
|
536
522
|
function serializePreset(preset) {
|
|
537
523
|
return {
|
|
@@ -808,36 +794,44 @@ window.__ModuleLoader__.load({
|
|
|
808
794
|
}
|
|
809
795
|
//#endregion
|
|
810
796
|
//#region src/client/ToolsTab.tsx
|
|
811
|
-
/** Tools tab: hide tools from the model catalog
|
|
797
|
+
/** Tools tab: hide tools from the model catalog (blacklist only — check = hide). */
|
|
812
798
|
function ToolsTab({ cfg, inv, scope, t }) {
|
|
813
799
|
const tools = inv?.tools ?? [];
|
|
814
|
-
const
|
|
815
|
-
|
|
816
|
-
include: []
|
|
817
|
-
};
|
|
818
|
-
const includeMode = (toolsCfg.include ?? []).length > 0;
|
|
800
|
+
const exclude = cfg.tools?.exclude ?? [];
|
|
801
|
+
const hidden = (name) => exclude.includes(name);
|
|
819
802
|
const toggle = (name, currentlyHidden) => {
|
|
820
|
-
|
|
803
|
+
const next = exclude.slice();
|
|
804
|
+
if (currentlyHidden) {
|
|
805
|
+
const i = next.indexOf(name);
|
|
806
|
+
if (i >= 0) next.splice(i, 1);
|
|
807
|
+
} else next.push(name);
|
|
808
|
+
scope.set("tools", {
|
|
809
|
+
exclude: next,
|
|
810
|
+
include: []
|
|
811
|
+
});
|
|
821
812
|
};
|
|
822
|
-
const
|
|
823
|
-
scope.set("tools",
|
|
813
|
+
const setAll = (hideAll) => {
|
|
814
|
+
scope.set("tools", {
|
|
815
|
+
exclude: hideAll ? tools.map((tool) => tool.name) : [],
|
|
816
|
+
include: []
|
|
817
|
+
});
|
|
824
818
|
};
|
|
825
819
|
return (0, react.createElement)("div", {}, [(0, react.createElement)("div", { style: s.bar }, [(0, react.createElement)("button", {
|
|
826
|
-
style:
|
|
827
|
-
onClick: () =>
|
|
828
|
-
}, t("
|
|
829
|
-
style:
|
|
830
|
-
onClick: () =>
|
|
831
|
-
}, t("
|
|
832
|
-
const
|
|
820
|
+
style: s.mini,
|
|
821
|
+
onClick: () => setAll(true)
|
|
822
|
+
}, t("selectAll")), (0, react.createElement)("button", {
|
|
823
|
+
style: s.mini,
|
|
824
|
+
onClick: () => setAll(false)
|
|
825
|
+
}, t("selectNone"))]), (0, react.createElement)("div", { style: s.list }, [tools.length === 0 ? (0, react.createElement)("div", { style: s.muted }, t("empty")) : null, tools.map((tool) => {
|
|
826
|
+
const isHidden = hidden(tool.name);
|
|
833
827
|
return (0, react.createElement)("div", {
|
|
834
828
|
key: tool.name,
|
|
835
829
|
style: s.row
|
|
836
830
|
}, [(0, react.createElement)("label", { style: s.switchWrap }, [(0, react.createElement)("input", {
|
|
837
831
|
type: "checkbox",
|
|
838
|
-
checked:
|
|
839
|
-
onChange: () => toggle(tool.name,
|
|
840
|
-
}), (0, react.createElement)("span", { style:
|
|
832
|
+
checked: isHidden,
|
|
833
|
+
onChange: () => toggle(tool.name, isHidden)
|
|
834
|
+
}), (0, react.createElement)("span", { style: isHidden ? s.badgeBlocked : s.badgeOk }, isHidden ? t("hiddenOn") : t("hiddenOff"))]), (0, react.createElement)("div", { style: s.rowBody }, [(0, react.createElement)("div", { style: s.rowTitle }, (0, react.createElement)("span", { style: s.code }, tool.name)), (0, react.createElement)("div", { style: s.preview }, String(tool.description ?? "").slice(0, 140))])]);
|
|
841
835
|
})])]);
|
|
842
836
|
}
|
|
843
837
|
//#endregion
|
|
@@ -945,6 +939,77 @@ window.__ModuleLoader__.load({
|
|
|
945
939
|
return "p_" + Date.now().toString(36) + Math.random().toString(36).slice(2, 7);
|
|
946
940
|
}
|
|
947
941
|
//#endregion
|
|
942
|
+
//#region src/client/PreviewTools.tsx
|
|
943
|
+
/** Tools preview: read-only whitelist-style list of the tools the current
|
|
944
|
+
* preset will inject (the FINAL model-visible catalog after include/exclude).
|
|
945
|
+
* A tool being listed means it is visible — there is no "blocked" state here.
|
|
946
|
+
* This view never edits the blacklist/whitelist config. */
|
|
947
|
+
function norm(tool) {
|
|
948
|
+
return typeof tool === "string" ? {
|
|
949
|
+
name: tool,
|
|
950
|
+
description: ""
|
|
951
|
+
} : tool;
|
|
952
|
+
}
|
|
953
|
+
function PreviewTools({ tools, t }) {
|
|
954
|
+
if (tools.length === 0) return (0, react.createElement)("div", { style: s.muted }, t("empty"));
|
|
955
|
+
return (0, react.createElement)("div", { style: s.list }, [(0, react.createElement)("div", { style: s.rowTitle }, [(0, react.createElement)("span", { style: s.orderTag }, `${tools.length} ${t("previewToolCount")}`)]), tools.map((tool) => {
|
|
956
|
+
const { name, description } = norm(tool);
|
|
957
|
+
return (0, react.createElement)("div", {
|
|
958
|
+
key: name,
|
|
959
|
+
style: s.row
|
|
960
|
+
}, [(0, react.createElement)("div", { style: s.rowBody }, [(0, react.createElement)("div", { style: s.rowTitle }, (0, react.createElement)("span", { style: s.code }, name)), (0, react.createElement)("div", { style: s.preview }, String(description ?? "").slice(0, 140))])]);
|
|
961
|
+
})]);
|
|
962
|
+
}
|
|
963
|
+
//#endregion
|
|
964
|
+
//#region src/client/PreviewTab.tsx
|
|
965
|
+
/** Preview tab: two read-only sub-tabs — the FINAL assembled system prompt
|
|
966
|
+
* after every plugin's filter, and the tools the current preset will inject
|
|
967
|
+
* (whitelist-style, after include/exclude). Neither view edits config. */
|
|
968
|
+
const PREVIEW_URL = "/api/prompt-customizer/preview";
|
|
969
|
+
function PreviewTab({ scope, t }) {
|
|
970
|
+
const [sub, setSub] = (0, react.useState)("prompt");
|
|
971
|
+
const [data, setData] = (0, react.useState)(null);
|
|
972
|
+
const [error, setError] = (0, react.useState)(null);
|
|
973
|
+
const inFlight = (0, react.useRef)(false);
|
|
974
|
+
const pending = (0, react.useRef)(false);
|
|
975
|
+
const load = () => {
|
|
976
|
+
if (inFlight.current) {
|
|
977
|
+
pending.current = true;
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
inFlight.current = true;
|
|
981
|
+
setData(null);
|
|
982
|
+
fetch(PREVIEW_URL, { cache: "no-store" }).then((r) => r.json()).then((body) => {
|
|
983
|
+
if (body && body.ok === false) throw new Error(body.error ?? "preview failed");
|
|
984
|
+
setData(body);
|
|
985
|
+
setError(null);
|
|
986
|
+
}).catch((e) => setError(String(e instanceof Error ? e.message : e))).finally(() => {
|
|
987
|
+
inFlight.current = false;
|
|
988
|
+
if (pending.current) {
|
|
989
|
+
pending.current = false;
|
|
990
|
+
load();
|
|
991
|
+
}
|
|
992
|
+
});
|
|
993
|
+
};
|
|
994
|
+
(0, react.useEffect)(load, []);
|
|
995
|
+
(0, react.useEffect)(() => scope.subscribe(load), [scope]);
|
|
996
|
+
return (0, react.createElement)("div", { style: s.list }, [
|
|
997
|
+
(0, react.createElement)("div", { style: s.bar }, [(0, react.createElement)("button", {
|
|
998
|
+
style: sub === "prompt" ? s.tabActive : s.tab,
|
|
999
|
+
onClick: () => setSub("prompt")
|
|
1000
|
+
}, t("previewPrompt")), (0, react.createElement)("button", {
|
|
1001
|
+
style: sub === "tools" ? s.tabActive : s.tab,
|
|
1002
|
+
onClick: () => setSub("tools")
|
|
1003
|
+
}, t("previewTools"))]),
|
|
1004
|
+
error ? (0, react.createElement)("div", { style: s.error }, String(error)) : null,
|
|
1005
|
+
data === null && !error ? (0, react.createElement)("div", { style: s.muted }, t("loading")) : null,
|
|
1006
|
+
sub === "prompt" ? data ? [(0, react.createElement)("div", { style: s.rowTitle }, [(0, react.createElement)("span", { style: s.muted }, t("previewHint")), (0, react.createElement)("span", { style: s.orderTag }, `${data.sections.length} ${t("previewSections")}`)]), (0, react.createElement)("pre", { style: s.previewText }, data.text || t("empty"))] : null : data ? (0, react.createElement)(PreviewTools, {
|
|
1007
|
+
tools: data.tools,
|
|
1008
|
+
t
|
|
1009
|
+
}) : null
|
|
1010
|
+
]);
|
|
1011
|
+
}
|
|
1012
|
+
//#endregion
|
|
948
1013
|
//#region src/client/index.ts
|
|
949
1014
|
/**
|
|
950
1015
|
* dsh-prompt-customizer — browser half (TypeScript source).
|
|
@@ -1017,6 +1082,10 @@ window.__ModuleLoader__.load({
|
|
|
1017
1082
|
style: tab === "presets" ? s.tabActive : s.tab,
|
|
1018
1083
|
onClick: () => setTab("presets")
|
|
1019
1084
|
}, t("tabsPresets")),
|
|
1085
|
+
(0, react.createElement)("button", {
|
|
1086
|
+
style: tab === "preview" ? s.tabActive : s.tab,
|
|
1087
|
+
onClick: () => setTab("preview")
|
|
1088
|
+
}, t("tabsPreview")),
|
|
1020
1089
|
(0, react.createElement)("button", {
|
|
1021
1090
|
style: s.refresh,
|
|
1022
1091
|
onClick: refresh
|
|
@@ -1033,11 +1102,14 @@ window.__ModuleLoader__.load({
|
|
|
1033
1102
|
inv,
|
|
1034
1103
|
scope,
|
|
1035
1104
|
t
|
|
1036
|
-
}) : (0, react.createElement)(PresetsTab, {
|
|
1105
|
+
}) : tab === "presets" ? (0, react.createElement)(PresetsTab, {
|
|
1037
1106
|
cfg,
|
|
1038
1107
|
inv,
|
|
1039
1108
|
scope,
|
|
1040
1109
|
t
|
|
1110
|
+
}) : (0, react.createElement)(PreviewTab, {
|
|
1111
|
+
scope,
|
|
1112
|
+
t
|
|
1041
1113
|
})
|
|
1042
1114
|
]);
|
|
1043
1115
|
}
|