@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.
Files changed (2) hide show
  1. package/client.js +205 -58
  2. 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
- function findMcp() {
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(mcpSearch.trim()), { method: 'GET' }).then(function (r) {
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
- api('/market/skills?search=' + encodeURIComponent(skillSearch.trim()), { method: 'GET' }).then(function (r) {
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 () { if (!d) openMcp(s.id) },
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 () { if (!d) openSkill(s.id) },
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: 'pm_groupHead' }, 'MCP 市场 MCP Plaza'),
595
- createElement('div', { className: 'pm_search' },
596
- createElement('input', {
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
- skillRows.length ? skillRows : (skillResult ? createElement('div', { className: 'pm_empty' }, '没有匹配的技能。No matching skills.') : null),
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 a lazy detail panel.
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: 'pm_card', key: item.id },
636
- createElement('div', { className: 'pm_cardHead' },
637
- createElement('span', { className: 'pm_name' }, item.name || item.id),
638
- item.configured ? badge('已配置', 'ok') : null,
639
- badge(item.id, 'muted'),
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: 'pm_meta' },
643
- 'by ' + (item.publisher || '—'),
644
- item.views !== undefined ? ' · ' + item.views + ' 浏览' : '',
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 || '复制配置 Copy config')
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 !== undefined && d.stars !== null ? badge('★ ' + d.stars, 'muted') : null,
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
- ? selectField('配置变体 Config variant', variant === null ? 0 : variant, configs.map(function (_, i) { return 'variant ' + (i + 1) }), function (i) { setVariant(Number(i)) })
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 with install commands and local "record source".
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: 'pm_card', key: item.id },
718
- createElement('div', { className: 'pm_cardHead' },
719
- createElement('span', { className: 'pm_name' }, item.name || item.id),
720
- item.installed || alreadyLinked ? badge('已安装', 'ok') : null,
721
- item.developer ? badge('by ' + item.developer, 'muted') : null,
722
- item.category ? badge(item.category, 'muted') : null,
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: 'pm_meta' },
726
- item.downloads !== undefined ? item.downloads + ' 下载' : '',
727
- item.views !== undefined ? ' · ' + item.views + ' 浏览' : '',
728
- item.license ? ' · ' + item.license : '',
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
- '市场更新时间 Market modified: ' + (d.fileModified || '—'),
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
- selectField('关联本地技能 Link to local skill', target || '', props.skills.map(function (s) { return s.name }), setTarget),
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.0",
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",