dsh-skill-tag 0.1.6 → 0.1.8
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 +8 -7
- package/lib/index.js +56 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,23 +30,24 @@ office * plugin # 只要 office 包带来的、且是插件相关
|
|
|
30
30
|
## 界面预览
|
|
31
31
|
|
|
32
32
|
> 全部是真实实例截图(105 个技能 / 48 个标签 / 一个开了筛选的工作区),没有 mock。
|
|
33
|
-
> 图片源文件在 `images/`(不进 npm 包,README 里用
|
|
33
|
+
> 图片源文件在 `images/`(不进 npm 包,README 里用 jsDelivr 绝对地址,GitHub 与 npm 都能显示;
|
|
34
|
+
> 之所以不走 `raw.githubusercontent.com`,是因为部分网络到该域名的 IPv6 不通,图片会间歇性加载失败)。
|
|
34
35
|
|
|
35
36
|
### 图 1 · 入口:会话行「…」→「管理标签」
|
|
36
37
|
|
|
37
|
-
<img src="https://
|
|
38
|
+
<img src="https://cdn.jsdelivr.net/gh/aawef/dsh-skill-manager-tags@main/images/session-menu.png" width="240" alt="会话行菜单里的管理标签入口">
|
|
38
39
|
|
|
39
40
|
对话级的配置就挂在会话行的「…」菜单最下面,不用去翻设置页。
|
|
40
41
|
|
|
41
42
|
### 图 2 · 入口:命令面板里的 `/skill-tag-manage`
|
|
42
43
|
|
|
43
|
-
<img src="https://
|
|
44
|
+
<img src="https://cdn.jsdelivr.net/gh/aawef/dsh-skill-manager-tags@main/images/command-palette.png" width="820" alt="命令面板中的管理对话标签命令">
|
|
44
45
|
|
|
45
46
|
在输入框敲 `/` 也能直接开「管理对话标签」——同一个界面,省一次点菜单。
|
|
46
47
|
|
|
47
48
|
### 图 3 · 打标签:设置 →「Skill 标签」
|
|
48
49
|
|
|
49
|
-
<img src="https://
|
|
50
|
+
<img src="https://cdn.jsdelivr.net/gh/aawef/dsh-skill-manager-tags@main/images/tag-settings.png" width="620" alt="Skill 标签管理页:新建标签、按来源分组的标签列表">
|
|
50
51
|
|
|
51
52
|
三个页签分工明确:**tag 联系 skill**(一个标签包含哪些技能)、**skill 联系 tag**
|
|
52
53
|
(一个技能拥有哪些标签)、**编辑标签组**(写表达式存模板)。
|
|
@@ -54,7 +55,7 @@ office * plugin # 只要 office 包带来的、且是插件相关
|
|
|
54
55
|
|
|
55
56
|
### 图 4 · 一个技能看它身上有哪些标签
|
|
56
57
|
|
|
57
|
-
<img src="https://
|
|
58
|
+
<img src="https://cdn.jsdelivr.net/gh/aawef/dsh-skill-manager-tags@main/images/skill-to-tags.png" width="640" alt="skill 联系 tag:左列技能、右列标签勾选">
|
|
58
59
|
|
|
59
60
|
左列 `技能 (105)` 每行标着它有几个标签;右边勾选**即时保存**,不用点确认。
|
|
60
61
|
右列会把该技能**已有的标签排在列表最前面**(并保持它们原来的相对顺序),所以不用滚动
|
|
@@ -63,7 +64,7 @@ office * plugin # 只要 office 包带来的、且是插件相关
|
|
|
63
64
|
|
|
64
65
|
### 图 5 · 工作区「管理标签」:左写条件,右就是下发名单
|
|
65
66
|
|
|
66
|
-
<img src="https://
|
|
67
|
+
<img src="https://cdn.jsdelivr.net/gh/aawef/dsh-skill-manager-tags@main/images/workspace-filter.png" width="900" alt="工作区管理标签双列界面">
|
|
67
68
|
|
|
68
69
|
左列是标签条件,下面实时显示**解析结果**和状态「有条件筛选(严格子集)」;
|
|
69
70
|
右列 `技能 (54)` 就是该工作区下发给模型的全部技能,每行可以「查看 tag」「禁用」,
|
|
@@ -72,7 +73,7 @@ office * plugin # 只要 office 包带来的、且是插件相关
|
|
|
72
73
|
|
|
73
74
|
### 图 6 · 对话「管理标签(对话)」:可以有自己的一份
|
|
74
75
|
|
|
75
|
-
<img src="https://
|
|
76
|
+
<img src="https://cdn.jsdelivr.net/gh/aawef/dsh-skill-manager-tags@main/images/conversation-filter.png" width="900" alt="对话级管理标签界面与继承来源">
|
|
76
77
|
|
|
77
78
|
同一个工作区下的某个对话想单独收窄,就在这里改:它会记下**继承来源**与时间
|
|
78
79
|
(`改动不影响工作区`),左下角一键「继承工作区配置」覆盖回来。
|
package/lib/index.js
CHANGED
|
@@ -18,7 +18,7 @@ import { skillTagDomain } from "../src/storage/schema.js";
|
|
|
18
18
|
import { createDshRepository, serializeConversation, deserializeConversation } from "../src/storage/repository.js";
|
|
19
19
|
import { createServices } from "../src/service.js";
|
|
20
20
|
import { groupIdOf } from "../src/domain/model.js";
|
|
21
|
-
import { workspaceDeniedSkills, normalizeWorkspacePath, activeTagsOf } from "../src/domain/workspace.js";
|
|
21
|
+
import { workspaceDeniedSkills, workspaceSkillView, normalizeWorkspacePath, activeTagsOf } from "../src/domain/workspace.js";
|
|
22
22
|
import { candidatesFor } from "../src/domain/match.js";
|
|
23
23
|
import { mountApi } from "../src/api.js";
|
|
24
24
|
import { scanSkillRoots } from "../src/skill-scan.js";
|
|
@@ -336,6 +336,54 @@ export function runtimeDeniedSkills(ws, universe, candidates) {
|
|
|
336
336
|
});
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
+
/**
|
|
340
|
+
* 运行时真正下发给 provider 的拒绝集:新口径 ∪ 旧口径兜底的**严格补集**。
|
|
341
|
+
*
|
|
342
|
+
* 2026-10-27 修正的 bug:此前调用方把两段结果**无条件并集**——
|
|
343
|
+
* ① workspaceDeniedSkills(懂 manualSkills / disabledSkills)
|
|
344
|
+
* ② computeDeniedSkillIds(只看标签条件,linked − candidates)
|
|
345
|
+
* ② 不知道"手动添加",于是把「打了标签、但没被标签规则命中、靠手动加进对话」
|
|
346
|
+
* 的技能重新判成 deny,推翻 ① 的放行结论。本机唯一受害者是 tagging-skills
|
|
347
|
+
* (它只挂来源标签,靠「管理标签」右列手动添加)。
|
|
348
|
+
*
|
|
349
|
+
* 兜底原本的前提是「universe 扫不到这个名字,所以新口径没机会判定它」。
|
|
350
|
+
* 那就把这个前提写成代码 —— 两道闸:
|
|
351
|
+
* ① 新口径已放行的名字(标签命中 ∪ 手动添加 − 禁用)绝不再 deny;
|
|
352
|
+
* ② universe 里存在的名字已由新口径给出判定,兜底不重复表态。
|
|
353
|
+
* 剩下的才是真正需要兜底的历史残留(已卸载但标签还在的名字)。
|
|
354
|
+
*
|
|
355
|
+
* @param {{config?:object, manualSkills?:string[], disabledSkills?:string[]}} effective 生效配置
|
|
356
|
+
* @param {object} p
|
|
357
|
+
* @param {string[]} p.universe 本趟可发现的全部技能名
|
|
358
|
+
* @param {string[]} p.candidates 标签规则命中的技能名
|
|
359
|
+
* @param {string[]} p.linkedSkillIds 有标签关联的全部技能名(兜底段的输入)
|
|
360
|
+
* @returns {Set<string>}
|
|
361
|
+
*/
|
|
362
|
+
export function computeRuntimeDeniedSkillIds(effective, { universe, candidates, linkedSkillIds }) {
|
|
363
|
+
const view = workspaceSkillView({
|
|
364
|
+
config: effective?.config,
|
|
365
|
+
manualSkills: effective?.manualSkills,
|
|
366
|
+
disabledSkills: effective?.disabledSkills,
|
|
367
|
+
universe,
|
|
368
|
+
candidates,
|
|
369
|
+
});
|
|
370
|
+
const denied = workspaceDeniedSkills({
|
|
371
|
+
config: effective?.config,
|
|
372
|
+
manualSkills: effective?.manualSkills,
|
|
373
|
+
disabledSkills: effective?.disabledSkills,
|
|
374
|
+
universe,
|
|
375
|
+
candidates,
|
|
376
|
+
});
|
|
377
|
+
const allowed = new Set(view.visible);
|
|
378
|
+
const inUniverse = new Set(universe);
|
|
379
|
+
for (const skillId of computeDeniedSkillIds(effective?.config, linkedSkillIds, () => candidates)) {
|
|
380
|
+
if (allowed.has(skillId)) continue;
|
|
381
|
+
if (inUniverse.has(skillId)) continue;
|
|
382
|
+
denied.add(skillId);
|
|
383
|
+
}
|
|
384
|
+
return denied;
|
|
385
|
+
}
|
|
386
|
+
|
|
339
387
|
/**
|
|
340
388
|
* 技能发现:与「模型实际看到的技能目录」对齐的唯一入口。
|
|
341
389
|
*
|
|
@@ -660,15 +708,13 @@ export async function apply(ctx, config) {
|
|
|
660
708
|
config: effective.config,
|
|
661
709
|
active: activeTagsOf(effective.config),
|
|
662
710
|
});
|
|
663
|
-
|
|
664
|
-
//
|
|
665
|
-
for (const skillId of
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
() =>
|
|
669
|
-
))
|
|
670
|
-
denied.add(skillId);
|
|
671
|
-
}
|
|
711
|
+
// 当前生效配置下"该放行"的名字(标签命中 ∪ 手动添加 − 禁用)。
|
|
712
|
+
// 兜底段必须尊重它,否则会把手动添加的技能重新判成 deny。
|
|
713
|
+
for (const skillId of computeRuntimeDeniedSkillIds(effective, {
|
|
714
|
+
universe,
|
|
715
|
+
candidates,
|
|
716
|
+
linkedSkillIds: links.map((l) => l.skillId),
|
|
717
|
+
})) denied.add(skillId);
|
|
672
718
|
}
|
|
673
719
|
}
|
|
674
720
|
const after = [...denied].join(",");
|