dsh-skill-hub 0.3.1 → 0.3.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/lib/client.js +38 -1
- package/lib/client.js.map +1 -1
- package/lib/types/client/slash-dots.d.ts +0 -8
- package/package.json +1 -1
- package/src/client/slash-dots.tsx +48 -3
|
@@ -35,14 +35,6 @@ export declare function findSkillSource(service: InputTriggerServiceContract): I
|
|
|
35
35
|
* catalog wins after reconnect; exported for deterministic unit tests.
|
|
36
36
|
*/
|
|
37
37
|
export declare function resetModelCache(): void;
|
|
38
|
-
/**
|
|
39
|
-
* Wrap the core skill source so every menu row carries the invocation dot.
|
|
40
|
-
* Exported for unit tests; production wiring goes through setupSkillSlashDots.
|
|
41
|
-
* @param source - the registered `/skill` source.
|
|
42
|
-
* @param api - hub browser API for the modelInvocable lookup.
|
|
43
|
-
* @param scope - hub settings scope for the dot colors.
|
|
44
|
-
* @returns a disposer restoring the original candidates.
|
|
45
|
-
*/
|
|
46
38
|
export declare function wrapSkillSource(source: InputTriggerSource, api: SkillHubApi, scope: SettingsScope<HubSettingsValue>): () => void;
|
|
47
39
|
/**
|
|
48
40
|
* Mount the slash-menu dots on the registered `/skill` source. Idempotent and
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-skill-hub",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
4
4
|
"description": "In-GUI skill hub for DeepSeek Harness (dsh): browse the full local skill catalog from the official ctx.skills registry (every root + third-party providers), toggle skills on/off, inspect bodies, surface frontmatter diagnostics, and scaffold new skills — plus a codex-style skill market (built-in catalog, upstream update checks, one-click update-all) with tracked source sync. The full manager beyond the read-only dsh-skill-manager browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -119,6 +119,47 @@ function dotIcon(color: string): InputTriggerCandidate['icon'] {
|
|
|
119
119
|
* @param scope - hub settings scope for the dot colors.
|
|
120
120
|
* @returns a disposer restoring the original candidates.
|
|
121
121
|
*/
|
|
122
|
+
/**
|
|
123
|
+
* DOM 兜底:在 alpha.2 新版 MenuView(icon 仅枚举)下通过直接操作
|
|
124
|
+
* 已渲染的 `[role="option"]` 列表注入彩色点,绕过 `icon` 限制。
|
|
125
|
+
* 旧版仍走 `icon` 注入,此处仅为新版。
|
|
126
|
+
*/
|
|
127
|
+
function injectDotsViaDOM(modelByName: Map<string, boolean>, modelColor: string, userColor: string): void {
|
|
128
|
+
if (typeof document === 'undefined' || typeof requestAnimationFrame === 'undefined') return
|
|
129
|
+
const run = (): void => {
|
|
130
|
+
const options = document.querySelectorAll('[role="option"]')
|
|
131
|
+
for (const opt of options) {
|
|
132
|
+
// 已注入则跳过(由 data 属性标记)
|
|
133
|
+
if (opt.querySelector('[data-skill-dot]') !== null) continue
|
|
134
|
+
// 技能名在 .itemName 中,取文本匹配 catalog
|
|
135
|
+
const nameEl = opt.querySelector('[class*="itemName"]') as HTMLElement | null
|
|
136
|
+
if (nameEl === null) continue
|
|
137
|
+
const name = (nameEl.textContent ?? '').trim()
|
|
138
|
+
if (name.length === 0) continue
|
|
139
|
+
if (!modelByName.has(name) && nameEl.textContent !== name) continue // 保守:仅处理已知名
|
|
140
|
+
const color = (modelByName.get(name) ?? true) ? modelColor : userColor
|
|
141
|
+
const dot = document.createElement('span')
|
|
142
|
+
dot.setAttribute('data-skill-dot', '')
|
|
143
|
+
dot.setAttribute('aria-hidden', 'true')
|
|
144
|
+
dot.style.display = 'inline-block'
|
|
145
|
+
dot.style.width = '6px'
|
|
146
|
+
dot.style.height = '6px'
|
|
147
|
+
dot.style.borderRadius = '3px'
|
|
148
|
+
dot.style.background = color
|
|
149
|
+
dot.style.flex = 'none'
|
|
150
|
+
// 插在名称前;若存在 icon 槽则插在其后,兼容旧版结构
|
|
151
|
+
const iconEl = opt.querySelector('[class*="itemIcon"]')
|
|
152
|
+
if (iconEl !== null && iconEl.nextSibling !== null) {
|
|
153
|
+
iconEl.parentElement?.insertBefore(dot, iconEl.nextSibling)
|
|
154
|
+
} else {
|
|
155
|
+
nameEl.parentElement?.insertBefore(dot, nameEl)
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// 菜单由 React 异步渲染,需等下一帧
|
|
160
|
+
requestAnimationFrame(() => setTimeout(run, 0))
|
|
161
|
+
}
|
|
162
|
+
|
|
122
163
|
export function wrapSkillSource(source: InputTriggerSource, api: SkillHubApi, scope: SettingsScope<HubSettingsValue>): () => void {
|
|
123
164
|
const original = source.candidates
|
|
124
165
|
source.candidates = async (session, req) => {
|
|
@@ -126,15 +167,19 @@ export function wrapSkillSource(source: InputTriggerSource, api: SkillHubApi, sc
|
|
|
126
167
|
if (req.signal.aborted) return items
|
|
127
168
|
// Dual-compat: 0.1.2-alpha.2 的 MenuView 将 icon 收窄为 'file'|'folder'|'session'
|
|
128
169
|
// 并通过 ReferenceIcon 渲染,旧版的自定义 ReactElement 点已无法展示。
|
|
129
|
-
// 以 `drilled` 是否存在探测新版(alpha.2 必有,rc
|
|
130
|
-
// icon,旧版保持彩色点,避免新版传入非法 icon 导致渲染异常。
|
|
170
|
+
// 以 `drilled` 是否存在探测新版(alpha.2 必有,rc 无)。
|
|
131
171
|
const isNewHost = req !== null && typeof req === 'object' && 'drilled' in (req as unknown as Record<string, unknown>)
|
|
132
|
-
if (isNewHost) return items
|
|
133
172
|
const modelByName = await modelInvocableMap(api)
|
|
134
173
|
if (req.signal.aborted) return items
|
|
135
174
|
const snapshot = scope.getSnapshot()
|
|
136
175
|
const modelColor = snapshot.value?.dotModelColor ?? DEFAULT_DOT_MODEL_COLOR
|
|
137
176
|
const userColor = snapshot.value?.dotUserColor ?? DEFAULT_DOT_USER_COLOR
|
|
177
|
+
if (isNewHost) {
|
|
178
|
+
// 新版:不通过 icon(枚举限制),改为 DOM 注入
|
|
179
|
+
injectDotsViaDOM(modelByName, modelColor, userColor)
|
|
180
|
+
return items
|
|
181
|
+
}
|
|
182
|
+
// 旧版:保持原有 icon 注入
|
|
138
183
|
return items.map((item) => ({
|
|
139
184
|
...item,
|
|
140
185
|
icon: dotIcon((modelByName.get(item.name) ?? true) ? modelColor : userColor),
|