dsh-prompt-customizer 0.4.0 → 0.4.2
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/LICENSE +21 -21
- package/README.en.md +278 -227
- package/README.i18n.yaml +2 -2
- package/README.md +278 -227
- package/client/client.js +82 -80
- package/client/client.js.map +1 -1
- package/cordis.patch.yml +8 -8
- package/lib/catalog.js +131 -131
- package/lib/effective.js +161 -158
- package/lib/index.js +943 -943
- package/lib/promotion.js +80 -80
- package/lib/schema.js +124 -124
- package/lib/sectionOps.d.mts +32 -32
- package/lib/sectionOps.mjs +128 -133
- package/lib/store.js +124 -124
- package/lib/vars.js +147 -147
- package/package.json +84 -64
- package/src/client/PresetsTab.tsx +281 -281
- package/src/client/PreviewTab.tsx +91 -91
- package/src/client/PreviewTools.tsx +33 -33
- package/src/client/SectionsTab.tsx +539 -556
- package/src/client/ToolsTab.tsx +293 -266
- package/src/client/index.ts +433 -422
- package/src/client/locales.ts +263 -259
- package/src/client/preset-io.ts +226 -226
- package/src/client/presets.ts +413 -408
- package/src/client/styles.ts +49 -49
- package/src/client/types.ts +128 -128
package/client/client.js
CHANGED
|
@@ -65,6 +65,8 @@ window.__ModuleLoader__.load({
|
|
|
65
65
|
importInvalid: "无效的配置文件",
|
|
66
66
|
targetGlobal: "目标:全局默认",
|
|
67
67
|
targetHint: "选择编辑目标 —— 选中某个 agent 预设后,改动只对该预设生效(字段级覆盖)。",
|
|
68
|
+
syncAllPhases: "三态同步",
|
|
69
|
+
syncAllPhasesHint: "勾选后,屏蔽 / 解除屏蔽对三个阶段一起生效(只作用于同名的那一个工具或提示词段)。默认关闭:三个阶段需逐一处理。",
|
|
68
70
|
broken: "损坏",
|
|
69
71
|
brokenPreset: "该 agent 预设当前无法挂载,仍可编辑其定制(修复预设后自动生效)。",
|
|
70
72
|
phaseBootstrap: "仅引导阶段",
|
|
@@ -192,6 +194,8 @@ window.__ModuleLoader__.load({
|
|
|
192
194
|
importInvalid: "Invalid preset file",
|
|
193
195
|
targetGlobal: "Target: global default",
|
|
194
196
|
targetHint: "Pick an edit target — changes apply only to the chosen agent preset (field-level override).",
|
|
197
|
+
syncAllPhases: "Sync phases",
|
|
198
|
+
syncAllPhasesHint: "When checked, blocking / unblocking applies to the same-named tool or section across all three phases at once. Unchecked (default): handle each phase separately.",
|
|
195
199
|
broken: "broken",
|
|
196
200
|
brokenPreset: "This agent preset cannot mount right now; its customization is still editable and applies once fixed.",
|
|
197
201
|
phaseBootstrap: "Bootstrap only",
|
|
@@ -703,7 +707,7 @@ window.__ModuleLoader__.load({
|
|
|
703
707
|
/**
|
|
704
708
|
* 计算应用预设时的配置补丁:
|
|
705
709
|
* - 同名段被覆盖(顺序列表在运行时驱动这一行为)
|
|
706
|
-
* -
|
|
710
|
+
* - 预设中有、当前系统里匹配不上的段默认跳过(跨系统导入不凭空建段)
|
|
707
711
|
* - 当前有、但不在预设有序列表中的段默认被屏蔽
|
|
708
712
|
* - 只有预设的「激活段」(在 order 列表且不在其屏蔽名单中)被解除屏蔽;
|
|
709
713
|
* 预设自己屏蔽的段保持屏蔽。
|
|
@@ -715,8 +719,8 @@ window.__ModuleLoader__.load({
|
|
|
715
719
|
function applyPresetData(data, cfg, currentNames) {
|
|
716
720
|
const presetOrder = data.order ?? [];
|
|
717
721
|
const presetNames = new Set(presetOrder.map((x) => x.name));
|
|
718
|
-
const blocked = new Set(data.sections ?? []);
|
|
719
|
-
const inject = resolveOrder(presetOrder);
|
|
722
|
+
const blocked = new Set((data.sections ?? []).filter((n) => currentNames.has(n)));
|
|
723
|
+
const inject = resolveOrder(presetOrder.filter((x) => currentNames.has(x.name)));
|
|
720
724
|
const kept = new Set(inject.map((x) => x.name));
|
|
721
725
|
let order = inject.length;
|
|
722
726
|
for (const item of cfg.inject ?? []) {
|
|
@@ -914,11 +918,11 @@ window.__ModuleLoader__.load({
|
|
|
914
918
|
if (phase === "always") return true;
|
|
915
919
|
return phase === key;
|
|
916
920
|
}
|
|
917
|
-
/**
|
|
921
|
+
/** 该阶段自己的屏蔽名单(三态互相独立:引导期 sectionsBootstrap /
|
|
922
|
+
* 压缩受控期 sectionsCompaction / 常驻期 sections,互不继承、互不影响)。 */
|
|
918
923
|
function deniedNames(cfg, key) {
|
|
919
924
|
const list = sectionListOf(key);
|
|
920
|
-
|
|
921
|
-
return [...cfg.sections ?? [], ...phase];
|
|
925
|
+
return list === "bootstrap" ? cfg.sectionsBootstrap ?? [] : list === "compaction" ? cfg.sectionsCompaction ?? [] : cfg.sections ?? [];
|
|
922
926
|
}
|
|
923
927
|
/**
|
|
924
928
|
* 某个阶段部分当前的注入身份(含未保存草稿)。
|
|
@@ -959,48 +963,25 @@ window.__ModuleLoader__.load({
|
|
|
959
963
|
}
|
|
960
964
|
/**
|
|
961
965
|
* 屏蔽/恢复一个段(当前阶段语义):返回需要写盘的字段补丁。
|
|
962
|
-
*
|
|
963
|
-
*
|
|
964
|
-
*
|
|
966
|
+
* 三态名单互相独立:只读写本阶段自己的名单(引导期 → sectionsBootstrap,
|
|
967
|
+
* 压缩受控期 → sectionsCompaction,常驻期 → sections),屏蔽 / 恢复都绝不
|
|
968
|
+
* 波及其它阶段的名单 —— 一个阶段的屏蔽不再连带屏蔽另一个阶段。
|
|
965
969
|
* 名单无变化时不产出字段(空补丁 = 不写盘),避免把继承值冻结成无意义的
|
|
966
970
|
* 空数组覆盖。
|
|
967
971
|
*/
|
|
968
972
|
function blockPatch(cfg, key, name, blocked) {
|
|
969
973
|
const list = sectionListOf(key);
|
|
970
|
-
const
|
|
971
|
-
const
|
|
972
|
-
const
|
|
973
|
-
if (list === "global") {
|
|
974
|
-
if (blocked) {
|
|
975
|
-
if (gi < 0) {
|
|
976
|
-
g.push(name);
|
|
977
|
-
patch.sections = g;
|
|
978
|
-
}
|
|
979
|
-
} else if (gi >= 0) {
|
|
980
|
-
g.splice(gi, 1);
|
|
981
|
-
patch.sections = g;
|
|
982
|
-
}
|
|
983
|
-
return patch;
|
|
984
|
-
}
|
|
985
|
-
const field = list === "bootstrap" ? "sectionsBootstrap" : "sectionsCompaction";
|
|
986
|
-
const phase = (cfg[field] ?? []).slice();
|
|
987
|
-
const pi = phase.indexOf(name);
|
|
974
|
+
const field = list === "bootstrap" ? "sectionsBootstrap" : list === "compaction" ? "sectionsCompaction" : "sections";
|
|
975
|
+
const cur = (cfg[field] ?? []).slice();
|
|
976
|
+
const i = cur.indexOf(name);
|
|
988
977
|
if (blocked) {
|
|
989
|
-
if (
|
|
990
|
-
|
|
991
|
-
patch[field] = phase;
|
|
992
|
-
}
|
|
978
|
+
if (i >= 0) return {};
|
|
979
|
+
cur.push(name);
|
|
993
980
|
} else {
|
|
994
|
-
if (
|
|
995
|
-
|
|
996
|
-
patch[field] = phase;
|
|
997
|
-
}
|
|
998
|
-
if (gi >= 0) {
|
|
999
|
-
g.splice(gi, 1);
|
|
1000
|
-
patch.sections = g;
|
|
1001
|
-
}
|
|
981
|
+
if (i < 0) return {};
|
|
982
|
+
cur.splice(i, 1);
|
|
1002
983
|
}
|
|
1003
|
-
return
|
|
984
|
+
return { [field]: cur };
|
|
1004
985
|
}
|
|
1005
986
|
/**
|
|
1006
987
|
* 重排/插入一个阶段的有序行列表:把 dragName 从列表中移除后,插入到
|
|
@@ -1050,8 +1031,8 @@ window.__ModuleLoader__.load({
|
|
|
1050
1031
|
* - 被屏蔽的段与普通段一模一样:留在列表原位、一样可操作(拖拽/箭头/替换/
|
|
1051
1032
|
* 恢复/删除),随时可互相转换,唯一区别是屏蔽勾选框与「已屏蔽」徽标 ——
|
|
1052
1033
|
* 屏蔽只意味着不注入模型,不剥夺任何编辑能力(v1 语义)。屏蔽勾选直接
|
|
1053
|
-
*
|
|
1054
|
-
*
|
|
1034
|
+
* 绑定该阶段自己的名单(deniedNames 三态互相独立,含未保存草稿),
|
|
1035
|
+
* 点击立即反馈 —— 屏蔽一个阶段绝不连带屏蔽另一个阶段。
|
|
1055
1036
|
* - 重排(拖入/箭头)走 `persistPhase`:把该阶段全部行重写为连续整数
|
|
1056
1037
|
* 虚拟 order(系统段写空文本 = 仅 order 覆盖,服务端保留原文;custom 段
|
|
1057
1038
|
* 保留文本)—— UI 行序叠加同一份 order 立即重排,拖动即时可见。
|
|
@@ -1067,20 +1048,22 @@ window.__ModuleLoader__.load({
|
|
|
1067
1048
|
* 在目标阶段被屏蔽则同步解除屏蔽 —— 行立即出现)。上三段 → 全部:从该
|
|
1068
1049
|
* 阶段移除 —— custom 段删除注入条目;系统段等价于屏蔽该阶段(系统段是
|
|
1069
1050
|
* 装配的一部分,无法真正删除)。
|
|
1070
|
-
* -
|
|
1071
|
-
*
|
|
1072
|
-
*
|
|
1051
|
+
* - 屏蔽 / 解除屏蔽的写入严格落在当前编辑目标的草稿里(全局默认 → 全局名单;
|
|
1052
|
+
* agent 预设 → 该预设自己的 override,显式空名单也是接管语义)—— 预设之间
|
|
1053
|
+
* 互相独立:在 A 预设里的任何屏蔽 / 解除屏蔽对 B 预设与全局默认零影响。
|
|
1073
1054
|
* - 每个阶段部分按自己那一阶段的装配结果给出警示:该 scope 有 complete 段
|
|
1074
1055
|
* 整段接管最终提示词,或本插件产出的段被下游装配规则丢弃时,明确写出
|
|
1075
1056
|
* 「段级定制不会(完全)进入模型看到的提示词」,避免提示词 Tab 与预览 Tab
|
|
1076
1057
|
* 各说各话。
|
|
1058
|
+
* - 「三态同步」勾选(默认关):屏蔽勾选对三个阶段一起生效,只作用于同名
|
|
1059
|
+
* 的那一段;拖拽 / 排序仍按各自阶段的副本语义只动本阶段。
|
|
1077
1060
|
*
|
|
1078
1061
|
* 全部阶段状态逻辑来自 lib/sectionOps.mjs(纯函数,node --test 单测直接
|
|
1079
1062
|
* 覆盖同一份代码)。
|
|
1080
1063
|
*/
|
|
1081
1064
|
/** 编辑态的键:段名之外还要带阶段,否则三个部分里同名的行会同时展开编辑器。 */
|
|
1082
1065
|
const editKey = (key, name) => `${key}:${name}`;
|
|
1083
|
-
function SectionsTab({ cfg, inv, phases,
|
|
1066
|
+
function SectionsTab({ cfg, inv, phases, syncAll, t, write }) {
|
|
1084
1067
|
const [editing, setEditing] = (0, react.useState)(null);
|
|
1085
1068
|
const [draft, setDraft] = (0, react.useState)("");
|
|
1086
1069
|
const [dragName, setDragName] = (0, react.useState)(null);
|
|
@@ -1176,27 +1159,13 @@ window.__ModuleLoader__.load({
|
|
|
1176
1159
|
return rows;
|
|
1177
1160
|
};
|
|
1178
1161
|
const applyBlock = (key, name, blocked) => {
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
return;
|
|
1186
|
-
}
|
|
1187
|
-
const patch = blockPatch(cfg, key, name, false);
|
|
1188
|
-
const effectiveOwned = ownedSections && ownedSections.length > 0 ? ownedSections : void 0;
|
|
1189
|
-
for (const [field, value] of Object.entries(patch)) {
|
|
1190
|
-
if (field === "sections") {
|
|
1191
|
-
if ((globalSections ?? []).includes(name) && (!effectiveOwned || ownedSections.includes(name))) writeGlobalField("sections", (globalSections ?? []).filter((n) => n !== name));
|
|
1192
|
-
if (effectiveOwned?.includes(name)) write("sections", value);
|
|
1193
|
-
continue;
|
|
1194
|
-
}
|
|
1195
|
-
if (JSON.stringify(value) === JSON.stringify(cfg[field] ?? [])) continue;
|
|
1196
|
-
write(field, value);
|
|
1197
|
-
}
|
|
1162
|
+
const patch = blockPatch(cfg, key, name, blocked);
|
|
1163
|
+
for (const [field, value] of Object.entries(patch)) write(field, value);
|
|
1164
|
+
};
|
|
1165
|
+
const toggleBlocked = (key, name) => {
|
|
1166
|
+
const blocked = !deniedNames(cfg, key).includes(name);
|
|
1167
|
+
for (const k of syncAll ? PART_ORDER : [key]) applyBlock(k, name, blocked);
|
|
1198
1168
|
};
|
|
1199
|
-
const toggleBlocked = (key, name) => applyBlock(key, name, !deniedNames(cfg, key).includes(name));
|
|
1200
1169
|
const inBaseOf = (key, name) => (phases?.[key]?.baseSections ?? []).some((sec) => sec.name === name);
|
|
1201
1170
|
const persistPhase = (key, rows) => {
|
|
1202
1171
|
write("inject", phaseInjectEntries(cfg, key, rows));
|
|
@@ -1277,7 +1246,7 @@ window.__ModuleLoader__.load({
|
|
|
1277
1246
|
});
|
|
1278
1247
|
};
|
|
1279
1248
|
const carryFor = (key, source, name) => {
|
|
1280
|
-
if (source.
|
|
1249
|
+
if (source.custom) return {
|
|
1281
1250
|
text: "",
|
|
1282
1251
|
blocked: false
|
|
1283
1252
|
};
|
|
@@ -1285,7 +1254,7 @@ window.__ModuleLoader__.load({
|
|
|
1285
1254
|
text: "",
|
|
1286
1255
|
blocked: false
|
|
1287
1256
|
};
|
|
1288
|
-
if (source.text === "") return {
|
|
1257
|
+
if (source.text === "" || source.text.startsWith("<")) return {
|
|
1289
1258
|
text: "",
|
|
1290
1259
|
blocked: true
|
|
1291
1260
|
};
|
|
@@ -1312,7 +1281,7 @@ window.__ModuleLoader__.load({
|
|
|
1312
1281
|
};
|
|
1313
1282
|
const next = reorderInsert(rows, dragName, targetName, pos, newRow);
|
|
1314
1283
|
if (next === null) return;
|
|
1315
|
-
if (dragSource.
|
|
1284
|
+
if (dragSource.key !== key && inBaseOf(key, dragName) && deniedNames(cfg, key).includes(dragName)) applyBlock(key, dragName, false);
|
|
1316
1285
|
persistPhase(key, next);
|
|
1317
1286
|
};
|
|
1318
1287
|
const rowDrop = (e, key, name) => {
|
|
@@ -1342,7 +1311,7 @@ window.__ModuleLoader__.load({
|
|
|
1342
1311
|
override: carry.text,
|
|
1343
1312
|
blocked: false
|
|
1344
1313
|
});
|
|
1345
|
-
if (dragSource.
|
|
1314
|
+
if (dragSource.key !== key && inBaseOf(key, dragName) && deniedNames(cfg, key).includes(dragName)) applyBlock(key, dragName, false);
|
|
1346
1315
|
persistPhase(key, next);
|
|
1347
1316
|
} else setNotice(t("sectionDynamicNoAdd", { name: dragName }));
|
|
1348
1317
|
}
|
|
@@ -1388,7 +1357,7 @@ window.__ModuleLoader__.load({
|
|
|
1388
1357
|
onDragStart: (e) => startDrag(e, row.name, {
|
|
1389
1358
|
kind: "part",
|
|
1390
1359
|
key,
|
|
1391
|
-
text: row.
|
|
1360
|
+
text: row.override || row.text,
|
|
1392
1361
|
custom: row.custom
|
|
1393
1362
|
}),
|
|
1394
1363
|
onDragOver: (e) => rowDragOver(e, key, row.name),
|
|
@@ -1568,8 +1537,10 @@ window.__ModuleLoader__.load({
|
|
|
1568
1537
|
* - 拖动:全部 → 某阶段 = 让该工具在这一阶段出现;阶段 → 阶段 = 搬移(源阶段
|
|
1569
1538
|
* 隐藏 + 目标阶段显示);上三段 → 全部 = 在该阶段隐藏它。
|
|
1570
1539
|
* - 只有黑名单,没有白名单:每个动作只作用于被拖 / 被点的那一个工具,绝不
|
|
1571
|
-
* 因为「拖进了一个工具」而把该阶段其它工具一起关掉。
|
|
1572
|
-
|
|
1540
|
+
* 因为「拖进了一个工具」而把该阶段其它工具一起关掉。
|
|
1541
|
+
* - 「三态同步」勾选(默认关):勾选 / 取消勾选对三个阶段一起生效,只作用
|
|
1542
|
+
* 于同名的那一个工具;拖拽仍按复制 / 搬移语义只动涉及的阶段。 */
|
|
1543
|
+
function ToolsTab({ cfg, inv, phases, syncAll, t, write }) {
|
|
1573
1544
|
const [dragFrom, setDragFrom] = (0, react.useState)(null);
|
|
1574
1545
|
const [draggedName, setDraggedName] = (0, react.useState)(null);
|
|
1575
1546
|
const [dropHint, setDropHint] = (0, react.useState)(null);
|
|
@@ -1617,6 +1588,19 @@ window.__ModuleLoader__.load({
|
|
|
1617
1588
|
return [...catalog, ...added];
|
|
1618
1589
|
};
|
|
1619
1590
|
const toggleHide = (key, name, currentlyHidden) => {
|
|
1591
|
+
if (syncAll) {
|
|
1592
|
+
let tools = cfg.tools;
|
|
1593
|
+
for (const k of PART_ORDER) {
|
|
1594
|
+
const add = addOf(k);
|
|
1595
|
+
const exclude = excludeOf(k);
|
|
1596
|
+
if (currentlyHidden) tools = withPhaseExclude(tools, k, exclude.filter((x) => x !== name));
|
|
1597
|
+
else if (add.includes(name)) tools = withPhaseAdd(tools, k, add.filter((x) => x !== name));
|
|
1598
|
+
else if (!exclude.includes(name)) tools = withPhaseExclude(tools, k, [...exclude, name]);
|
|
1599
|
+
}
|
|
1600
|
+
write("tools", tools);
|
|
1601
|
+
setNotice(null);
|
|
1602
|
+
return;
|
|
1603
|
+
}
|
|
1620
1604
|
if (currentlyHidden) addToPhase(key, name, false);
|
|
1621
1605
|
else {
|
|
1622
1606
|
let exclude = excludeOf(key);
|
|
@@ -2337,6 +2321,7 @@ window.__ModuleLoader__.load({
|
|
|
2337
2321
|
const [error, setError] = (0, react.useState)(null);
|
|
2338
2322
|
const [refreshId, setRefreshId] = (0, react.useState)(0);
|
|
2339
2323
|
const [target, setTarget] = (0, react.useState)(void 0);
|
|
2324
|
+
const [syncAll, setSyncAll] = (0, react.useState)(false);
|
|
2340
2325
|
const [version, setVersion] = (0, react.useState)(0);
|
|
2341
2326
|
const [draft, setDraft] = (0, react.useState)(null);
|
|
2342
2327
|
const [saving, setSaving] = (0, react.useState)(false);
|
|
@@ -2457,7 +2442,6 @@ window.__ModuleLoader__.load({
|
|
|
2457
2442
|
}).catch((e) => setError(String(e instanceof Error ? e.message : e)));
|
|
2458
2443
|
};
|
|
2459
2444
|
const writeGlobal = writeField;
|
|
2460
|
-
const writeGlobalField = writeField;
|
|
2461
2445
|
const resetAll = () => {
|
|
2462
2446
|
fetch(CONFIG_RESET_URL, {
|
|
2463
2447
|
method: "POST",
|
|
@@ -2546,6 +2530,26 @@ window.__ModuleLoader__.load({
|
|
|
2546
2530
|
value: p.id,
|
|
2547
2531
|
style: s.option
|
|
2548
2532
|
}, `${p.name}${p.broken ? ` (${t("broken")})` : ""}`))]),
|
|
2533
|
+
tab === "sections" || tab === "tools" ? (0, react.createElement)("label", {
|
|
2534
|
+
style: {
|
|
2535
|
+
...s.muted,
|
|
2536
|
+
marginLeft: 6,
|
|
2537
|
+
display: "inline-flex",
|
|
2538
|
+
alignItems: "center",
|
|
2539
|
+
gap: 4,
|
|
2540
|
+
cursor: "pointer",
|
|
2541
|
+
whiteSpace: "nowrap"
|
|
2542
|
+
},
|
|
2543
|
+
title: t("syncAllPhasesHint")
|
|
2544
|
+
}, [(0, react.createElement)("input", {
|
|
2545
|
+
type: "checkbox",
|
|
2546
|
+
checked: syncAll,
|
|
2547
|
+
onChange: (e) => setSyncAll(e.target.checked),
|
|
2548
|
+
style: {
|
|
2549
|
+
margin: 0,
|
|
2550
|
+
cursor: "pointer"
|
|
2551
|
+
}
|
|
2552
|
+
}), t("syncAllPhases")]) : null,
|
|
2549
2553
|
(0, react.createElement)("button", {
|
|
2550
2554
|
style: draft?.dirty ? s.saveBtnDirty : s.saveBtn,
|
|
2551
2555
|
disabled: !draft?.dirty || saving,
|
|
@@ -2564,18 +2568,16 @@ window.__ModuleLoader__.load({
|
|
|
2564
2568
|
cfg: view,
|
|
2565
2569
|
inv,
|
|
2566
2570
|
phases,
|
|
2567
|
-
|
|
2568
|
-
globalSections: cfg.sections,
|
|
2569
|
-
ownedSections: target ? cfg.overrides?.[target]?.sections : void 0,
|
|
2571
|
+
syncAll,
|
|
2570
2572
|
t,
|
|
2571
|
-
write: edit
|
|
2572
|
-
writeGlobalField
|
|
2573
|
+
write: edit
|
|
2573
2574
|
}) : tab === "tools" ? (0, react.createElement)(ToolsTab, {
|
|
2574
2575
|
cfg: view,
|
|
2575
2576
|
inv,
|
|
2576
2577
|
phases,
|
|
2577
2578
|
t,
|
|
2578
|
-
write: edit
|
|
2579
|
+
write: edit,
|
|
2580
|
+
syncAll
|
|
2579
2581
|
}) : tab === "presets" ? (0, react.createElement)(PresetsTab, {
|
|
2580
2582
|
cfg: view,
|
|
2581
2583
|
inv,
|