dsh-skill-picker 0.5.23 → 0.5.25
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 +2 -0
- package/lib/client.js +16 -31
- package/lib/client.js.map +2 -2
- package/package.json +1 -1
- package/src/client/index.jsx +48 -38
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-skill-picker",
|
|
3
3
|
"description": "DSH Web GUI skill picker: a button beside the composer opens a searchable list of installed skills; picking one inserts the official `/skill-name` gesture into the input box, so the skill loads with your message (WorkBuddy-style skill invocation for DeepSeek Harness).",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.25",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|
|
7
7
|
"exports": {
|
package/src/client/index.jsx
CHANGED
|
@@ -274,10 +274,21 @@ const buttonStyle = {
|
|
|
274
274
|
flex: 'none',
|
|
275
275
|
}
|
|
276
276
|
|
|
277
|
+
/**
|
|
278
|
+
* Panel placement.
|
|
279
|
+
*
|
|
280
|
+
* Fixed (not absolute) and anchored to the RIGHT EDGE OF THE WINDOW, with the
|
|
281
|
+
* vertical offset measured from the ⚡ button so it still opens just above the
|
|
282
|
+
* composer.
|
|
283
|
+
*
|
|
284
|
+
* Why not `absolute; right: 0` on the button's own wrapper — which is what it
|
|
285
|
+
* used to be: the ⚡ sits next to the model picker, well left of the composer's
|
|
286
|
+
* right edge, so the panel was right-aligned to *that* and threw itself across
|
|
287
|
+
* the middle of the conversation, covering the text. 国豪 spotted it.
|
|
288
|
+
*/
|
|
277
289
|
const popoverStyle = {
|
|
278
|
-
position: '
|
|
279
|
-
|
|
280
|
-
right: '0',
|
|
290
|
+
position: 'fixed',
|
|
291
|
+
right: '24px',
|
|
281
292
|
width: '340px',
|
|
282
293
|
maxHeight: '320px',
|
|
283
294
|
display: 'flex',
|
|
@@ -409,26 +420,6 @@ const menuItemStyle = {
|
|
|
409
420
|
whiteSpace: 'nowrap',
|
|
410
421
|
}
|
|
411
422
|
|
|
412
|
-
/** Lightweight source badge shown only when the list came from the host scan fallback (official API unavailable). */
|
|
413
|
-
const sourceBadgeStyle = {
|
|
414
|
-
display: 'inline-flex',
|
|
415
|
-
alignItems: 'center',
|
|
416
|
-
alignSelf: 'flex-start',
|
|
417
|
-
margin: '0 8px 8px',
|
|
418
|
-
padding: '2px 8px',
|
|
419
|
-
border: '1px solid rgba(255, 193, 7, 0.35)',
|
|
420
|
-
borderRadius: '999px',
|
|
421
|
-
background: 'rgba(255, 193, 7, 0.1)',
|
|
422
|
-
color: '#d9a520',
|
|
423
|
-
fontSize: '11px',
|
|
424
|
-
lineHeight: '16px',
|
|
425
|
-
flex: 'none',
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
const sourceBadgeTextStyle = {
|
|
429
|
-
fontFamily: 'var(--ds-font-family-code, ui-monospace, monospace)',
|
|
430
|
-
}
|
|
431
|
-
|
|
432
423
|
/** The picker's bolt glyph: DeepSeek palette gradient + slim stroke. */
|
|
433
424
|
function BoltIcon() {
|
|
434
425
|
return (
|
|
@@ -486,6 +477,12 @@ function SkillPickerButton(props) {
|
|
|
486
477
|
const itemRefs = useRef([])
|
|
487
478
|
/** Pending long-press timer for the touch path (see the menu below). */
|
|
488
479
|
const longPressRef = useRef(0)
|
|
480
|
+
/**
|
|
481
|
+
* Distance from the window bottom to the panel's bottom edge, measured from
|
|
482
|
+
* the ⚡ button each time the panel opens. See `popoverStyle`: the horizontal
|
|
483
|
+
* anchor is the window's right edge, only the height follows the button.
|
|
484
|
+
*/
|
|
485
|
+
const [panelBottom, setPanelBottom] = useState(88)
|
|
489
486
|
|
|
490
487
|
// The usage store is shared with the official `/` menu: picks made there go
|
|
491
488
|
// through window.__dshSkillPickerTrack (localStorage only). Refresh this
|
|
@@ -670,8 +667,34 @@ function SkillPickerButton(props) {
|
|
|
670
667
|
}
|
|
671
668
|
}, [menu])
|
|
672
669
|
|
|
670
|
+
/**
|
|
671
|
+
* The panel used to show "本地扫描" / "/ 增强:运行时接管" as badges under the
|
|
672
|
+
* list. They are diagnostics for whoever is debugging, not something a user
|
|
673
|
+
* needs on screen — they occupied two rows and said nothing useful day to day
|
|
674
|
+
* (国豪's call, and he was right).
|
|
675
|
+
*
|
|
676
|
+
* They are not simply dropped: "the plugin is fine" and "the plugin is not
|
|
677
|
+
* running at all" look identical without them, which is the whole lesson
|
|
678
|
+
* behind issue #14. So they moved here (one console line per panel open) and
|
|
679
|
+
* into the ⚡ button's tooltip.
|
|
680
|
+
*/
|
|
681
|
+
useEffect(() => {
|
|
682
|
+
if (skills === undefined) return
|
|
683
|
+
console.info(
|
|
684
|
+
`[dsh-skill-picker] 技能列表 ${skills.length} 条,来源:${source === 'host' ? '本地扫描(官方 skills API 不可用)' : '官方 API'}`
|
|
685
|
+
+ `;/ 增强:${slashEnhancementMode() === 'runtime' ? '运行时接管,已生效' : '未生效(见 issue #14)'}`,
|
|
686
|
+
)
|
|
687
|
+
}, [skills, source])
|
|
688
|
+
|
|
673
689
|
const toggle = () => {
|
|
674
690
|
if (!open) {
|
|
691
|
+
// Measure before opening so the panel is already in place on its first
|
|
692
|
+
// paint (no visible jump).
|
|
693
|
+
const el = boxRef.current
|
|
694
|
+
if (el !== null) {
|
|
695
|
+
const rect = el.getBoundingClientRect()
|
|
696
|
+
setPanelBottom(Math.max(64, Math.round(window.innerHeight - rect.top + 8)))
|
|
697
|
+
}
|
|
675
698
|
// Pull first: a pin or a pick made on another client (desktop ↔ web ↔
|
|
676
699
|
// phone) should be visible the moment this panel opens. The pull fires
|
|
677
700
|
// SHARED_STATE_EVENT, which is what refreshes `usage`/`pinned` here.
|
|
@@ -782,7 +805,7 @@ function SkillPickerButton(props) {
|
|
|
782
805
|
<button
|
|
783
806
|
type="button"
|
|
784
807
|
onClick={toggle}
|
|
785
|
-
title=
|
|
808
|
+
title={`选择技能(插入 /技能名 到发送框)${source === 'host' ? ' · 列表来自本地扫描' : ''}${slashEnhancementMode() === 'runtime' ? ' · / 增强:运行时接管' : ''}`}
|
|
786
809
|
aria-label="选择技能"
|
|
787
810
|
style={{
|
|
788
811
|
...buttonStyle,
|
|
@@ -792,7 +815,7 @@ function SkillPickerButton(props) {
|
|
|
792
815
|
<BoltIcon />
|
|
793
816
|
</button>
|
|
794
817
|
{open && (
|
|
795
|
-
<div style={popoverStyle}>
|
|
818
|
+
<div style={{ ...popoverStyle, bottom: `${panelBottom}px` }}>
|
|
796
819
|
<input
|
|
797
820
|
value={query}
|
|
798
821
|
onChange={(event) => setQuery(event.target.value)}
|
|
@@ -998,19 +1021,6 @@ function SkillPickerButton(props) {
|
|
|
998
1021
|
))}
|
|
999
1022
|
</div>
|
|
1000
1023
|
)}
|
|
1001
|
-
{source === 'host' && (
|
|
1002
|
-
<div style={sourceBadgeStyle} title="官方技能 API 不可用,列表来自本地目录扫描(与官方 / 补全同源)">
|
|
1003
|
-
<span style={sourceBadgeTextStyle}>本地扫描</span>
|
|
1004
|
-
</div>
|
|
1005
|
-
)}
|
|
1006
|
-
{slashEnhancementMode() === 'runtime' && (
|
|
1007
|
-
<div
|
|
1008
|
-
style={sourceBadgeStyle}
|
|
1009
|
-
title="`/` 菜单的模糊+拼音搜索由本插件在运行时接管官方技能源(不依赖改写任何文件,issue #14)"
|
|
1010
|
-
>
|
|
1011
|
-
<span style={sourceBadgeTextStyle}>/ 增强:运行时接管</span>
|
|
1012
|
-
</div>
|
|
1013
|
-
)}
|
|
1014
1024
|
<div style={{ margin: '0 10px 8px', fontSize: '11px', color: 'var(--dsw-alias-label-tertiary, #8a94a6)' }}>
|
|
1015
1025
|
右键技能 = 置顶 / 关闭 / 定位 / 卸载(手机长按)
|
|
1016
1026
|
</div>
|