@omdp/dsh-connector 0.2.0 → 0.2.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/client.js +205 -58
- package/package.json +1 -1
package/client.js
CHANGED
|
@@ -57,7 +57,7 @@ window.__ModuleLoader__.load({
|
|
|
57
57
|
'.pm_badge.err{color:var(--dsw-alias-state-error-primary,#f87171)}' +
|
|
58
58
|
/* buttons */
|
|
59
59
|
'.pm_actions{display:flex;gap:8px;align-items:center;flex-wrap:wrap}' +
|
|
60
|
-
'.pm_btn{cursor:pointer;font:inherit;font-size:12px;padding:5px 12px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.4));background:transparent;color:inherit;transition:background .12s}' +
|
|
60
|
+
'.pm_btn{cursor:pointer;font:inherit;font-size:12px;padding:5px 12px;border-radius:8px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.4));background:transparent;color:inherit;transition:background .12s;flex:none}' +
|
|
61
61
|
'.pm_btn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2,rgba(128,128,128,.14))}' +
|
|
62
62
|
'.pm_btn:disabled{opacity:.45;cursor:default}' +
|
|
63
63
|
'.pm_btn.primary{border-color:transparent;background:var(--dsw-alias-brand-primary,#5b8cff);color:#fff}' +
|
|
@@ -84,7 +84,25 @@ window.__ModuleLoader__.load({
|
|
|
84
84
|
'.pm_err{color:var(--dsw-alias-state-error-primary,#f87171);font-size:12px}' +
|
|
85
85
|
'.pm_ok{color:var(--dsw-alias-state-success-primary,#4ade80);font-size:12px}' +
|
|
86
86
|
'.pm_empty{font-size:12px;color:var(--dsw-alias-label-secondary,#888);padding:10px 2px}' +
|
|
87
|
-
'.pm_btnrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap}'
|
|
87
|
+
'.pm_btnrow{display:flex;gap:8px;align-items:center;flex-wrap:wrap}' +
|
|
88
|
+
/* market grid & icons */
|
|
89
|
+
'.pm_grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin-top:2px;align-items:start}' +
|
|
90
|
+
'@media(max-width:760px){.pm_grid{grid-template-columns:1fr}}' +
|
|
91
|
+
'.pm_mcard{background:var(--dsw-alias-bg-layer-1,rgba(255,255,255,.035));border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.22));border-radius:12px;padding:12px 14px;display:flex;flex-direction:column;gap:8px;transition:background .15s,border-color .15s}' +
|
|
92
|
+
'.pm_mcard:hover{background:var(--dsw-alias-bg-layer-2,rgba(255,255,255,.06));border-color:var(--dsw-alias-border-l2,rgba(128,128,128,.4))}' +
|
|
93
|
+
'.pm_mhead{display:flex;align-items:center;gap:10px;min-width:0}' +
|
|
94
|
+
'.pm_icon{width:38px;height:38px;border-radius:10px;flex:none;object-fit:cover;background:var(--dsw-alias-bg-layer-2,#333);border:1px solid var(--dsw-alias-border-l1,rgba(128,128,128,.25))}' +
|
|
95
|
+
'.pm_avatar{width:38px;height:38px;border-radius:10px;flex:none;display:flex;align-items:center;justify-content:center;font-weight:700;font-size:16px;color:#fff;background:linear-gradient(135deg,var(--dsw-alias-brand-primary,#5b8cff),#a06bff);text-transform:uppercase}' +
|
|
96
|
+
'.pm_mtitle{min-width:0;flex:1}' +
|
|
97
|
+
'.pm_mname{font-weight:600;font-size:13.5px;color:var(--dsw-alias-label-primary,#eee);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;display:flex;align-items:center;gap:6px}' +
|
|
98
|
+
'.pm_mid{font-size:11px;color:var(--dsw-alias-label-secondary,#9aa);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}' +
|
|
99
|
+
'.pm_stats{display:flex;gap:12px;flex-wrap:wrap}' +
|
|
100
|
+
'.pm_stat{font-size:11.5px;color:var(--dsw-alias-label-secondary,#9aa);display:inline-flex;align-items:center;gap:4px}' +
|
|
101
|
+
'.pm_stat b{font-weight:600;color:var(--dsw-alias-label-primary,#ddd)}' +
|
|
102
|
+
'.pm_chips{display:flex;gap:6px;flex-wrap:wrap}' +
|
|
103
|
+
'.pm_chip{cursor:pointer;font:inherit;font-size:11.5px;padding:4px 12px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2,rgba(128,128,128,.35));background:transparent;color:var(--dsw-alias-label-secondary,#9aa);transition:all .12s}' +
|
|
104
|
+
'.pm_chip:hover{color:var(--dsw-alias-label-primary,#ddd);border-color:var(--dsw-alias-brand-primary,#5b8cff)}' +
|
|
105
|
+
'.pm_chip.active{background:var(--dsw-alias-brand-primary,#5b8cff);border-color:transparent;color:#fff}'
|
|
88
106
|
|
|
89
107
|
if (typeof document !== 'undefined' && document.querySelector('style[data-plugin-css="@omdp/dsh-connector/section"]') === null) {
|
|
90
108
|
var tag = document.createElement('style')
|
|
@@ -502,6 +520,52 @@ window.__ModuleLoader__.load({
|
|
|
502
520
|
|
|
503
521
|
/* ─────────────────────────── marketplace ─────────────────────────── */
|
|
504
522
|
|
|
523
|
+
// 12 official ModelScope skill categories (skills-center.md taxonomy).
|
|
524
|
+
var SKILL_CATEGORIES = [
|
|
525
|
+
{ id: '', label: '全部' },
|
|
526
|
+
{ id: 'developer-tools', label: '开发者工具' },
|
|
527
|
+
{ id: 'code-quality-testing', label: '代码质量' },
|
|
528
|
+
{ id: 'ai-media', label: 'AI 媒体' },
|
|
529
|
+
{ id: 'frontend-development', label: '前端开发' },
|
|
530
|
+
{ id: 'cloud-devops', label: '云与运维' },
|
|
531
|
+
{ id: 'ai-automation', label: 'AI 自动化' },
|
|
532
|
+
{ id: 'analytics', label: '数据分析' },
|
|
533
|
+
{ id: 'doc-processing', label: '文档处理' },
|
|
534
|
+
{ id: 'skill-management', label: '技能管理' },
|
|
535
|
+
{ id: 'mobile-development', label: '移动开发' },
|
|
536
|
+
{ id: 'marketing-seo', label: '营销 SEO' },
|
|
537
|
+
{ id: 'other', label: '其他' },
|
|
538
|
+
]
|
|
539
|
+
|
|
540
|
+
// 12438 -> "12.4k", 987654 -> "987.7k", 1.2e7 -> "12.0M"
|
|
541
|
+
function fmtNum(n) {
|
|
542
|
+
var v = Number(n)
|
|
543
|
+
if (!isFinite(v)) return ''
|
|
544
|
+
if (v >= 1e8) return (v / 1e8).toFixed(1).replace(/\.0$/, '') + '亿'
|
|
545
|
+
if (v >= 1e6) return (v / 1e6).toFixed(1).replace(/\.0$/, '') + 'M'
|
|
546
|
+
if (v >= 1e3) return (v / 1e3).toFixed(1).replace(/\.0$/, '') + 'k'
|
|
547
|
+
return String(v)
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
var SKILL_CAT_LABEL = {}
|
|
551
|
+
SKILL_CATEGORIES.forEach(function (c) { if (c.id) SKILL_CAT_LABEL[c.id] = c.label })
|
|
552
|
+
function catLabel(id) { return SKILL_CAT_LABEL[id] || id }
|
|
553
|
+
|
|
554
|
+
function MarketIcon(props) {
|
|
555
|
+
var _a = react.useState(true)
|
|
556
|
+
var ok = _a[0]
|
|
557
|
+
var setOk = _a[1]
|
|
558
|
+
if (props.logo && ok) {
|
|
559
|
+
return createElement('img', {
|
|
560
|
+
className: 'pm_icon',
|
|
561
|
+
src: props.logo,
|
|
562
|
+
alt: '',
|
|
563
|
+
onError: function () { setOk(false) },
|
|
564
|
+
})
|
|
565
|
+
}
|
|
566
|
+
return createElement('div', { className: 'pm_avatar' }, (props.label || '?').charAt(0))
|
|
567
|
+
}
|
|
568
|
+
|
|
505
569
|
function MarketPane(props) {
|
|
506
570
|
var _a = react.useState('')
|
|
507
571
|
var mcpSearch = _a[0]
|
|
@@ -530,19 +594,30 @@ window.__ModuleLoader__.load({
|
|
|
530
594
|
var _i = react.useState('')
|
|
531
595
|
var err = _i[0]
|
|
532
596
|
var setErr = _i[1]
|
|
533
|
-
|
|
534
|
-
|
|
597
|
+
var _j = react.useState('')
|
|
598
|
+
var category = _j[0]
|
|
599
|
+
var setCategory = _j[1]
|
|
600
|
+
var _k = react.useState('mcp')
|
|
601
|
+
var sub = _k[0]
|
|
602
|
+
var setSub = _k[1]
|
|
603
|
+
|
|
604
|
+
function findMcp(term) {
|
|
605
|
+
var q = (term !== undefined ? term : mcpSearch).trim()
|
|
535
606
|
setMcpBusy(true)
|
|
536
607
|
setErr('')
|
|
537
|
-
api('/market/mcp?search=' + encodeURIComponent(
|
|
608
|
+
api('/market/mcp?search=' + encodeURIComponent(q), { method: 'GET' }).then(function (r) {
|
|
538
609
|
if (r && r.error) { setErr(r.error); setMcpResult(null); return }
|
|
539
610
|
setMcpResult(r)
|
|
540
611
|
}).finally(function () { setMcpBusy(false) })
|
|
541
612
|
}
|
|
542
|
-
function findSkills() {
|
|
613
|
+
function findSkills(term, cat) {
|
|
614
|
+
var q = (term !== undefined ? term : skillSearch).trim()
|
|
615
|
+
var c = cat !== undefined ? cat : category
|
|
543
616
|
setSkillBusy(true)
|
|
544
617
|
setErr('')
|
|
545
|
-
|
|
618
|
+
var qs = '/market/skills?search=' + encodeURIComponent(q)
|
|
619
|
+
if (c) qs += '&category=' + encodeURIComponent(c)
|
|
620
|
+
api(qs, { method: 'GET' }).then(function (r) {
|
|
546
621
|
if (r && r.error) { setErr(r.error); setSkillResult(null); return }
|
|
547
622
|
setSkillResult(r)
|
|
548
623
|
}).finally(function () { setSkillBusy(false) })
|
|
@@ -564,12 +639,27 @@ window.__ModuleLoader__.load({
|
|
|
564
639
|
})
|
|
565
640
|
}
|
|
566
641
|
|
|
642
|
+
// Load the default (hot) lists right away so the tab never opens empty.
|
|
643
|
+
react.useEffect(function () {
|
|
644
|
+
findMcp('')
|
|
645
|
+
findSkills('', '')
|
|
646
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
647
|
+
}, [])
|
|
648
|
+
|
|
567
649
|
var mcpRows = mcpResult && mcpResult.items
|
|
568
650
|
? mcpResult.items.map(function (s) {
|
|
569
651
|
var d = mcpDetail[s.id]
|
|
570
652
|
return createElement(McpMarketItem, {
|
|
571
653
|
key: s.id, item: s, detail: d,
|
|
572
|
-
onOpen: function () {
|
|
654
|
+
onOpen: function () {
|
|
655
|
+
if (d) {
|
|
656
|
+
var next = Object.assign({}, mcpDetail)
|
|
657
|
+
delete next[s.id]
|
|
658
|
+
setMcpDetail(next)
|
|
659
|
+
} else {
|
|
660
|
+
openMcp(s.id)
|
|
661
|
+
}
|
|
662
|
+
},
|
|
573
663
|
})
|
|
574
664
|
})
|
|
575
665
|
: []
|
|
@@ -579,7 +669,15 @@ window.__ModuleLoader__.load({
|
|
|
579
669
|
var d = skillDetail[s.id]
|
|
580
670
|
return createElement(SkillMarketItem, {
|
|
581
671
|
key: s.id, item: s, detail: d, skills: props.skills,
|
|
582
|
-
onOpen: function () {
|
|
672
|
+
onOpen: function () {
|
|
673
|
+
if (d) {
|
|
674
|
+
var next = Object.assign({}, skillDetail)
|
|
675
|
+
delete next[s.id]
|
|
676
|
+
setSkillDetail(next)
|
|
677
|
+
} else {
|
|
678
|
+
openSkill(s.id)
|
|
679
|
+
}
|
|
680
|
+
},
|
|
583
681
|
onChanged: props.onChanged,
|
|
584
682
|
})
|
|
585
683
|
})
|
|
@@ -591,33 +689,55 @@ window.__ModuleLoader__.load({
|
|
|
591
689
|
'浏览魔搭社区(ModelScope)技能中心与 MCP 广场。列表数据缓存在 DSH 进程内存(30 分钟),不写任何文件;安装/部署请复制命令自行执行。Browse ModelScope Skills Center & MCP Plaza; cached in-process only, nothing saved to disk.'),
|
|
592
690
|
err ? createElement('div', { className: 'pm_err' }, err) : null,
|
|
593
691
|
|
|
594
|
-
createElement('div', { className: '
|
|
595
|
-
|
|
596
|
-
createElement('
|
|
597
|
-
placeholder: '搜索 MCP 服务,如 map / github / fetch Search…',
|
|
598
|
-
value: mcpSearch,
|
|
599
|
-
onChange: function (e) { setMcpSearch(e.target.value) },
|
|
600
|
-
onKeyDown: function (e) { if (e.key === 'Enter') findMcp() },
|
|
601
|
-
}),
|
|
602
|
-
createElement('button', { className: 'pm_btn primary', disabled: mcpBusy, onClick: findMcp }, mcpBusy ? '搜索中…' : '搜索'),
|
|
603
|
-
),
|
|
604
|
-
mcpRows.length ? mcpRows : (mcpResult ? createElement('div', { className: 'pm_empty' }, '没有匹配的 MCP 服务。No matching MCP servers.') : null),
|
|
605
|
-
|
|
606
|
-
createElement('div', { className: 'pm_groupHead', style: { marginTop: '18px' } }, 'Skills 市场 Skills Center'),
|
|
607
|
-
createElement('div', { className: 'pm_search' },
|
|
608
|
-
createElement('input', {
|
|
609
|
-
placeholder: '搜索技能,如 code-review / deploy Search…',
|
|
610
|
-
value: skillSearch,
|
|
611
|
-
onChange: function (e) { setSkillSearch(e.target.value) },
|
|
612
|
-
onKeyDown: function (e) { if (e.key === 'Enter') findSkills() },
|
|
613
|
-
}),
|
|
614
|
-
createElement('button', { className: 'pm_btn primary', disabled: skillBusy, onClick: findSkills }, skillBusy ? '搜索中…' : '搜索'),
|
|
692
|
+
createElement('div', { className: 'pm_chips', style: { margin: '2px 0 4px' } },
|
|
693
|
+
createElement('button', { className: 'pm_chip' + (sub === 'mcp' ? ' active' : ''), onClick: function () { setSub('mcp') } }, 'MCP 市场'),
|
|
694
|
+
createElement('button', { className: 'pm_chip' + (sub === 'skills' ? ' active' : ''), onClick: function () { setSub('skills') } }, 'Skills 市场'),
|
|
615
695
|
),
|
|
616
|
-
|
|
696
|
+
|
|
697
|
+
sub === 'mcp'
|
|
698
|
+
? createElement('div', { className: 'pm_section' },
|
|
699
|
+
createElement('div', { className: 'pm_search' },
|
|
700
|
+
createElement('input', {
|
|
701
|
+
placeholder: '搜索 MCP 服务,如 map / github / fetch Search…',
|
|
702
|
+
value: mcpSearch,
|
|
703
|
+
onChange: function (e) { setMcpSearch(e.target.value) },
|
|
704
|
+
onKeyDown: function (e) { if (e.key === 'Enter') findMcp() },
|
|
705
|
+
}),
|
|
706
|
+
createElement('button', { className: 'pm_btn primary', disabled: mcpBusy, onClick: function () { findMcp() } }, mcpBusy ? '搜索中…' : '搜索'),
|
|
707
|
+
),
|
|
708
|
+
createElement('div', { className: 'pm_grid' }, mcpRows),
|
|
709
|
+
mcpResult && mcpResult.items && !mcpResult.items.length
|
|
710
|
+
? createElement('div', { className: 'pm_empty' }, '没有匹配的 MCP 服务。No matching MCP servers.')
|
|
711
|
+
: null,
|
|
712
|
+
)
|
|
713
|
+
: createElement('div', { className: 'pm_section' },
|
|
714
|
+
createElement('div', { className: 'pm_search' },
|
|
715
|
+
createElement('input', {
|
|
716
|
+
placeholder: '搜索技能,如 code-review / deploy Search…',
|
|
717
|
+
value: skillSearch,
|
|
718
|
+
onChange: function (e) { setSkillSearch(e.target.value) },
|
|
719
|
+
onKeyDown: function (e) { if (e.key === 'Enter') findSkills() },
|
|
720
|
+
}),
|
|
721
|
+
createElement('button', { className: 'pm_btn primary', disabled: skillBusy, onClick: function () { findSkills() } }, skillBusy ? '搜索中…' : '搜索'),
|
|
722
|
+
),
|
|
723
|
+
createElement('div', { className: 'pm_chips' },
|
|
724
|
+
SKILL_CATEGORIES.map(function (c) {
|
|
725
|
+
return createElement('button', {
|
|
726
|
+
key: c.id || 'all',
|
|
727
|
+
className: 'pm_chip' + (category === c.id ? ' active' : ''),
|
|
728
|
+
onClick: function () { setCategory(c.id); findSkills(skillSearch, c.id) },
|
|
729
|
+
}, c.label)
|
|
730
|
+
}),
|
|
731
|
+
),
|
|
732
|
+
createElement('div', { className: 'pm_grid' }, skillRows),
|
|
733
|
+
skillResult && skillResult.items && !skillResult.items.length
|
|
734
|
+
? createElement('div', { className: 'pm_empty' }, '没有匹配的技能。No matching skills.')
|
|
735
|
+
: null,
|
|
736
|
+
),
|
|
617
737
|
)
|
|
618
738
|
}
|
|
619
739
|
|
|
620
|
-
// One MCP market entry with
|
|
740
|
+
// One MCP market entry — 2-col grid card with icon, lazy detail panel.
|
|
621
741
|
function McpMarketItem(props) {
|
|
622
742
|
var item = props.item
|
|
623
743
|
var d = props.detail
|
|
@@ -632,30 +752,39 @@ window.__ModuleLoader__.load({
|
|
|
632
752
|
cfgText = JSON.stringify(sel, null, 2)
|
|
633
753
|
}
|
|
634
754
|
|
|
635
|
-
return createElement('div', { className: '
|
|
636
|
-
createElement('div', { className: '
|
|
637
|
-
createElement(
|
|
638
|
-
|
|
639
|
-
|
|
755
|
+
return createElement('div', { className: 'pm_mcard', key: item.id },
|
|
756
|
+
createElement('div', { className: 'pm_mhead' },
|
|
757
|
+
createElement(MarketIcon, { logo: item.logo, label: (item.name || item.id).charAt(0) }),
|
|
758
|
+
createElement('div', { className: 'pm_mtitle' },
|
|
759
|
+
createElement('div', { className: 'pm_mname' },
|
|
760
|
+
item.name || item.id,
|
|
761
|
+
item.configured ? badge('已配置', 'ok') : null,
|
|
762
|
+
),
|
|
763
|
+
createElement('div', { className: 'pm_mid' }, item.id),
|
|
764
|
+
),
|
|
640
765
|
),
|
|
641
766
|
createElement('div', { className: 'pm_desc' }, item.description || ''),
|
|
642
|
-
createElement('div', { className: '
|
|
643
|
-
'by '
|
|
644
|
-
item.views !== undefined
|
|
767
|
+
createElement('div', { className: 'pm_stats' },
|
|
768
|
+
createElement('span', { className: 'pm_stat' }, 'by ', createElement('b', null, item.publisher || '—')),
|
|
769
|
+
item.views !== undefined
|
|
770
|
+
? createElement('span', { className: 'pm_stat' }, '👁 ', createElement('b', null, fmtNum(item.views)))
|
|
771
|
+
: null,
|
|
772
|
+
(item.categories && item.categories.length)
|
|
773
|
+
? createElement('span', { className: 'pm_stat' }, createElement('b', null, item.categories.slice(0, 2).join(' / ')))
|
|
774
|
+
: null,
|
|
645
775
|
),
|
|
646
776
|
createElement('div', { className: 'pm_actions' },
|
|
647
777
|
createElement('button', { className: 'pm_btn', onClick: props.onOpen }, d ? '收起' : '详情'),
|
|
648
778
|
d && configs.length
|
|
649
779
|
? createElement('button', { className: 'pm_btn primary', onClick: function () { copied.copy(cfgText) } },
|
|
650
|
-
copied.copied || '复制配置
|
|
780
|
+
copied.copied || '复制配置')
|
|
651
781
|
: null,
|
|
652
782
|
),
|
|
653
783
|
d ? createElement('div', { className: 'pm_section', style: { marginTop: '4px' } },
|
|
654
784
|
createElement('div', { className: 'pm_actions' },
|
|
655
785
|
d.hosted ? badge('Hosted 官方托管', 'brand') : null,
|
|
656
786
|
d.verified ? badge('已认证 Verified', 'brand') : null,
|
|
657
|
-
d.stars
|
|
658
|
-
(d.categories && d.categories.length) ? badge(d.categories.slice(0, 3).join(' / '), 'muted') : null,
|
|
787
|
+
d.stars > 0 ? badge('★ ' + fmtNum(d.stars), 'muted') : null,
|
|
659
788
|
),
|
|
660
789
|
(d.envSchema && d.envSchema.length)
|
|
661
790
|
? createElement('div', { className: 'pm_meta' },
|
|
@@ -671,7 +800,12 @@ window.__ModuleLoader__.load({
|
|
|
671
800
|
configs.length
|
|
672
801
|
? createElement('div', { className: 'pm_section' },
|
|
673
802
|
configs.length > 1
|
|
674
|
-
?
|
|
803
|
+
? createElement('label', null,
|
|
804
|
+
'配置变体 Config variant',
|
|
805
|
+
createElement('select', { value: variant === null ? 0 : variant, onChange: function (e) { setVariant(Number(e.target.value)) } },
|
|
806
|
+
configs.map(function (_, i) { return createElement('option', { value: i, key: i }, 'variant ' + (i + 1)) }),
|
|
807
|
+
),
|
|
808
|
+
)
|
|
675
809
|
: null,
|
|
676
810
|
createElement('div', { className: 'pm_code' }, cfgText),
|
|
677
811
|
)
|
|
@@ -682,7 +816,7 @@ window.__ModuleLoader__.load({
|
|
|
682
816
|
)
|
|
683
817
|
}
|
|
684
818
|
|
|
685
|
-
// One market skill entry
|
|
819
|
+
// One market skill entry — grid card, install commands, record-source link.
|
|
686
820
|
function SkillMarketItem(props) {
|
|
687
821
|
var item = props.item
|
|
688
822
|
var d = props.detail
|
|
@@ -714,26 +848,34 @@ window.__ModuleLoader__.load({
|
|
|
714
848
|
})
|
|
715
849
|
}
|
|
716
850
|
|
|
717
|
-
return createElement('div', { className: '
|
|
718
|
-
createElement('div', { className: '
|
|
719
|
-
createElement(
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
851
|
+
return createElement('div', { className: 'pm_mcard', key: item.id },
|
|
852
|
+
createElement('div', { className: 'pm_mhead' },
|
|
853
|
+
createElement(MarketIcon, { logo: item.logo, label: (item.name || item.id).charAt(0) }),
|
|
854
|
+
createElement('div', { className: 'pm_mtitle' },
|
|
855
|
+
createElement('div', { className: 'pm_mname' },
|
|
856
|
+
item.name || item.id,
|
|
857
|
+
item.installed || alreadyLinked ? badge('已安装', 'ok') : null,
|
|
858
|
+
d && d.updateAvailable ? badge('有更新', 'warn') : null,
|
|
859
|
+
),
|
|
860
|
+
createElement('div', { className: 'pm_mid' }, item.id),
|
|
861
|
+
),
|
|
723
862
|
),
|
|
724
863
|
createElement('div', { className: 'pm_desc' }, item.description || ''),
|
|
725
|
-
createElement('div', { className: '
|
|
726
|
-
item.downloads !== undefined
|
|
727
|
-
|
|
728
|
-
|
|
864
|
+
createElement('div', { className: 'pm_stats' },
|
|
865
|
+
item.downloads !== undefined
|
|
866
|
+
? createElement('span', { className: 'pm_stat' }, '⬇ ', createElement('b', null, fmtNum(item.downloads)), ' 下载')
|
|
867
|
+
: createElement('span', { className: 'pm_stat' }, 'by ', createElement('b', null, item.developer || '—')),
|
|
868
|
+
item.views !== undefined
|
|
869
|
+
? createElement('span', { className: 'pm_stat' }, '👁 ', createElement('b', null, fmtNum(item.views)))
|
|
870
|
+
: null,
|
|
871
|
+
item.category ? createElement('span', { className: 'pm_stat' }, createElement('b', null, catLabel(item.category))) : null,
|
|
729
872
|
),
|
|
730
873
|
createElement('div', { className: 'pm_actions' },
|
|
731
874
|
createElement('button', { className: 'pm_btn', onClick: props.onOpen }, d ? '收起' : '详情'),
|
|
732
|
-
d && d.updateAvailable ? badge('有更新', 'warn') : null,
|
|
733
875
|
),
|
|
734
876
|
d ? createElement('div', { className: 'pm_section', style: { marginTop: '4px' } },
|
|
735
877
|
createElement('div', { className: 'pm_meta' },
|
|
736
|
-
'
|
|
878
|
+
'市场更新 Market modified: ' + (d.fileModified || '—'),
|
|
737
879
|
d.localSkill ? ' · 本地记录: ' + d.localSkill.sourceUpdated : '',
|
|
738
880
|
),
|
|
739
881
|
installs.length
|
|
@@ -750,7 +892,12 @@ window.__ModuleLoader__.load({
|
|
|
750
892
|
alreadyLinked
|
|
751
893
|
? createElement('div', { className: 'pm_ok' }, '已关联到本地技能 ✓ Linked to a local skill.')
|
|
752
894
|
: createElement('div', { className: 'pm_btnrow' },
|
|
753
|
-
|
|
895
|
+
createElement('label', { style: { fontSize: 12, color: 'var(--dsw-alias-label-secondary,#9aa)' } },
|
|
896
|
+
'关联本地技能 Link to local skill',
|
|
897
|
+
createElement('select', { value: target || '', onChange: function (e) { setTarget(e.target.value) } },
|
|
898
|
+
props.skills.map(function (s) { return createElement('option', { value: s.name, key: s.name }, s.name) }),
|
|
899
|
+
),
|
|
900
|
+
),
|
|
754
901
|
createElement('button', { className: 'pm_btn', onClick: recordSource }, '记录来源 Record source'),
|
|
755
902
|
),
|
|
756
903
|
linkErr ? createElement('div', { className: 'pm_err' }, linkErr) : null,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@omdp/dsh-connector",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Unified DeepSeek Harness connector: edit MCP servers (cordis.patch.yml), user skills (~/.dsh/skills) and browse the ModelScope MCP/Skills marketplaces from one Web UI settings page.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|