@ai-wendao/ant 0.3.17 → 0.3.19
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 +75 -44
- package/index.js +10 -7
- package/package.json +1 -1
- package/skill-install.js +10 -4
package/client.js
CHANGED
|
@@ -382,7 +382,7 @@ window.__ModuleLoader__.load({
|
|
|
382
382
|
if (generation !== refreshGeneration.current) return
|
|
383
383
|
setSkills(result.skills)
|
|
384
384
|
setLoadError(false)
|
|
385
|
-
setMessage(result.warning || (result.skills.length ? '' : '
|
|
385
|
+
setMessage(result.warning || (result.skills.length ? '' : '当前没有可显示的全市场或本企业技能。管理员可能尚未启用,或已隐藏待启用的市场技能;下方仍可查看 DSH 官方技能。'))
|
|
386
386
|
} catch (error) {
|
|
387
387
|
if (generation !== refreshGeneration.current) return
|
|
388
388
|
setSkills([])
|
|
@@ -398,7 +398,7 @@ window.__ModuleLoader__.load({
|
|
|
398
398
|
? skill.conflict_reason === 'other-source'
|
|
399
399
|
? '这台 DSH 已安装另一个来源的同名技能。确认卸载本机旧来源?已修改的本地文件不会被删除。'
|
|
400
400
|
: `从这台 DSH 卸载 ${skill.title}?已修改的本地文件不会被删除。`
|
|
401
|
-
: `将 ${skill.title} ${action}到这台 DSH?\n\n本机依赖:${skill.requirements}\n\n技能可能让 DSH 读取文件或执行脚本,仍受 DSH 的工具授权控制。ANT 不会自动安装系统依赖。`
|
|
401
|
+
: `将 ${skill.title} ${action}到这台 DSH?\n\n外部数据交互:${skill.data_interactions || '待管理员补充;使用前请先核实数据去向。'}\n\n本机依赖:${skill.requirements}\n\n技能可能让 DSH 读取文件或执行脚本,仍受 DSH 的工具授权控制。ANT 不会自动安装系统依赖。`
|
|
402
402
|
if (!window.confirm(prompt)) return
|
|
403
403
|
setWorkingId(skill.id)
|
|
404
404
|
setMessage(`正在${action} ${skill.title}…`)
|
|
@@ -442,10 +442,11 @@ window.__ModuleLoader__.load({
|
|
|
442
442
|
}
|
|
443
443
|
}
|
|
444
444
|
const visible = skills.filter((skill) => {
|
|
445
|
+
const canInstall = skill.scope !== 'market' || skill.team_enabled === true
|
|
445
446
|
const matchesFilter = filter === 'all'
|
|
446
|
-
|| filter === 'available' && ['not-installed', 'update-available'].includes(skill.local_status)
|
|
447
|
+
|| filter === 'available' && canInstall && ['not-installed', 'update-available'].includes(skill.local_status)
|
|
447
448
|
|| filter === 'installed' && ['installed', 'update-available'].includes(skill.local_status)
|
|
448
|
-
|| filter === 'updates' && skill.local_status === 'update-available'
|
|
449
|
+
|| filter === 'updates' && canInstall && skill.local_status === 'update-available'
|
|
449
450
|
const matchesQuery = !query.trim() || `${skill.title} ${skillIntroduction(skill)} ${skill.description} ${skill.dsh_name}`.toLowerCase().includes(query.trim().toLowerCase())
|
|
450
451
|
return matchesFilter && matchesQuery
|
|
451
452
|
&& (scopeFilter === 'all' || (skill.scope || 'team') === scopeFilter)
|
|
@@ -518,25 +519,14 @@ window.__ModuleLoader__.load({
|
|
|
518
519
|
...categories.map((category) => h('option', { key: category, value: category }, category))))),
|
|
519
520
|
),
|
|
520
521
|
includePlugins ? h('h2', { style: { margin: 0, fontSize: 20 } }, loading ? '技能 · 读取中…' : `技能 · ${visible.length + visibleOfficial.length}`) : null,
|
|
521
|
-
message && (!includePlugins || loadError || skills.length
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
h('h2', { style: { margin: 0, fontSize: 20 } }, 'DSH 官方 Office'),
|
|
525
|
-
h('p', { style: { ...mutedTextStyle, marginTop: 4 } }, '这些能力随对应版本的 DSH 提供,ANT 无需重复安装。在新会话中直接描述任务即可;不计入 ANT 的本机安装筛选。'),
|
|
526
|
-
h('a', { href: officialOfficeGuide, target: '_blank', rel: 'noopener noreferrer', style: { color: 'var(--dsw-alias-link)', fontSize: 13 } }, '查看中文官方说明 ↗')),
|
|
527
|
-
h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 300px), 1fr))', gap: 14 } },
|
|
528
|
-
...visibleOfficial.map((skill) => h('article', { key: skill.name, style: { ...panelStyle, gap: 10 } },
|
|
529
|
-
h('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 } },
|
|
530
|
-
h('h3', { style: { margin: 0, fontSize: 17 } }, skill.title),
|
|
531
|
-
h('span', { style: mutedTextStyle }, 'DSH 官方')),
|
|
532
|
-
h('p', { style: mutedTextStyle }, skill.description),
|
|
533
|
-
h('p', { style: mutedTextStyle }, `在新会话中说:“${skill.prompt}”。也可输入 /${skill.name}。`),
|
|
534
|
-
h('p', { style: mutedTextStyle }, `DSH ${skill.since} 起提供;旧版请使用 DSH 自带的检查更新。`),
|
|
535
|
-
h('a', { href: officialOfficeEnglish(skill), target: '_blank', rel: 'noopener noreferrer',
|
|
536
|
-
style: { ...secondaryButtonStyle, display: 'inline-flex', alignItems: 'center', width: 'fit-content', textDecoration: 'none' } }, '查看英文原文 ↗'))))) : null,
|
|
522
|
+
message && (!includePlugins || loadError || skills.length || (!loading && !query.trim()))
|
|
523
|
+
? h('p', { role: loadError ? 'alert' : 'status', style: mutedTextStyle }, message) : null,
|
|
524
|
+
visible.length && !includePlugins ? h('h2', { style: { margin: 0, fontSize: 20 } }, '全市场与本企业技能') : null,
|
|
537
525
|
visible.length ? h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 420px), 1fr))', gap: 16 } },
|
|
538
526
|
...visible.map((skill) => {
|
|
527
|
+
const marketPending = skill.scope === 'market' && skill.team_enabled !== true
|
|
539
528
|
const description = skillIntroduction(skill)
|
|
529
|
+
const dataInteractions = skill.data_interactions?.trim() || '待管理员补充。使用前请核实这项技能是否调用外部服务,以及会发送哪些数据。'
|
|
540
530
|
const originalEnglish = Boolean(curatedSkillIntroduction(skill)) || !hasChineseIntroduction(skill.description)
|
|
541
531
|
const englishSource = skillEnglishSource(skill)
|
|
542
532
|
const sourceRef = skill.source_ref || ''
|
|
@@ -544,34 +534,64 @@ window.__ModuleLoader__.load({
|
|
|
544
534
|
const sourceLabel = /^https:\/\/github\.com\//u.test(skill.source_url || '') ? 'GitHub'
|
|
545
535
|
: /^https:\/\/clawhub\.ai\//u.test(skill.source_url || '') ? 'ClawHub'
|
|
546
536
|
: skill.source_kind === 'upload' ? '管理员上传' : '原作者来源'
|
|
537
|
+
const actions = !marketPending && skill.local_status !== 'conflict'
|
|
538
|
+
? h('div', { style: { display: 'flex', flexWrap: 'wrap', gap: 8 } },
|
|
539
|
+
skill.local_status === 'installed' ? null : h('button', { type: 'button', disabled: Boolean(workingId),
|
|
540
|
+
onClick: () => void changeInstall(skill), style: primaryButtonStyle },
|
|
541
|
+
skill.local_status === 'update-available' ? '更新技能' : '安装到这台 DSH'),
|
|
542
|
+
skill.local_status === 'not-installed' ? null : h('button', { type: 'button', disabled: Boolean(workingId),
|
|
543
|
+
onClick: () => void changeInstall(skill, true), style: secondaryButtonStyle }, '卸载'))
|
|
544
|
+
: null
|
|
547
545
|
return h('article', { key: skill.id, style: { ...panelStyle, gap: 13 } },
|
|
548
546
|
h('div', { style: { display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 } },
|
|
549
547
|
h('div', { style: { display: 'flex', alignItems: 'baseline', flexWrap: 'wrap', gap: 8 } },
|
|
550
548
|
h('h2', { style: { margin: 0, fontSize: 19 } }, skill.title),
|
|
551
549
|
h('span', { style: { ...mutedTextStyle, padding: '2px 7px', borderRadius: 6, backgroundColor: 'var(--dsw-alias-bg-layer-2)' } }, skill.scope === 'market' ? '全市场精选' : '本企业'),
|
|
552
550
|
h('span', { style: mutedTextStyle }, skillCategory(skill))),
|
|
553
|
-
h('span', { style: mutedTextStyle },
|
|
551
|
+
h('span', { style: mutedTextStyle }, marketPending
|
|
552
|
+
? skill.team_connected ? '待企业启用' : '连接企业后查看启用状态'
|
|
553
|
+
: statusLabel[skill.local_status] || '状态未知')),
|
|
554
554
|
h('p', { style: mutedTextStyle }, description.length > 180 ? `${description.slice(0, 180)}…` : description),
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
color: 'var(--dsw-alias-link)', fontSize: 13, textAlign: 'left' } },
|
|
560
|
-
originalEnglish ? '查看英文原文 →' : '查看原始说明 →'),
|
|
561
|
-
h('p', { style: mutedTextStyle }, `来源:${sourceLabel} · 许可:${skill.license}`),
|
|
555
|
+
h('section', { style: { display: 'grid', gap: 5, padding: '10px 12px', borderRadius: 8,
|
|
556
|
+
border: '0.5px solid var(--dsw-alias-border-l2)', backgroundColor: 'var(--dsw-alias-bg-layer-2)' } },
|
|
557
|
+
h('strong', { style: { fontSize: 13 } }, '外部数据交互'),
|
|
558
|
+
h('p', { style: { ...mutedTextStyle, whiteSpace: 'pre-wrap', overflowWrap: 'anywhere' } }, dataInteractions)),
|
|
562
559
|
description.length > 180 ? h('details', null,
|
|
563
560
|
h('summary', { style: { cursor: 'pointer', fontSize: 13 } }, '查看完整说明'),
|
|
564
561
|
h('p', { style: { ...mutedTextStyle, marginTop: 8, whiteSpace: 'pre-wrap' } }, description)) : null,
|
|
565
|
-
h('
|
|
566
|
-
h('
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
h('
|
|
571
|
-
|
|
572
|
-
? h('a', { href:
|
|
573
|
-
|
|
574
|
-
|
|
562
|
+
h('div', { style: { display: 'grid', gap: 5 } },
|
|
563
|
+
h('div', { style: { display: 'flex', alignItems: 'center', justifyContent: 'space-between', flexWrap: 'wrap', gap: 8 } },
|
|
564
|
+
h('p', { style: { ...mutedTextStyle, flex: '1 1 180px' } }, `来源:${sourceLabel} · 许可:${skill.license}`),
|
|
565
|
+
actions),
|
|
566
|
+
h('details', null,
|
|
567
|
+
h('summary', { style: { cursor: 'pointer', fontSize: 13 } }, '查看来源、文件与使用条件'),
|
|
568
|
+
h('div', { style: { display: 'grid', gap: 5, marginTop: 9, overflowWrap: 'anywhere' } },
|
|
569
|
+
englishSource ? h('a', { href: englishSource, target: '_blank', rel: 'noopener noreferrer',
|
|
570
|
+
style: { color: 'var(--dsw-alias-link)', fontSize: 13 } }, originalEnglish ? '查看英文原文 ↗' : '查看原始说明 ↗')
|
|
571
|
+
: h('button', { type: 'button', onClick: () => void openOriginal(skill),
|
|
572
|
+
style: { border: 0, padding: 0, background: 'transparent', cursor: 'pointer',
|
|
573
|
+
color: 'var(--dsw-alias-link)', fontSize: 13, textAlign: 'left' } },
|
|
574
|
+
originalEnglish ? '查看英文原文 →' : '查看原始说明 →'),
|
|
575
|
+
h('p', { style: mutedTextStyle }, `${fileCountFormat.format(skill.file_count)} 个文件`),
|
|
576
|
+
h('p', { style: mutedTextStyle }, `本机条件:${skill.requirements}`),
|
|
577
|
+
h('p', { style: mutedTextStyle, title: sourceRef }, `固定版本:${versionLabel || '已锁定制品'}`),
|
|
578
|
+
/^https:\/\//u.test(skill.source_url || '')
|
|
579
|
+
? h('a', { href: skill.source_url, target: '_blank', rel: 'noopener noreferrer', style: { fontSize: 13, color: 'var(--dsw-alias-link)' } }, '查看原始来源 ↗')
|
|
580
|
+
: h('p', { style: mutedTextStyle }, '来源:管理员上传并审核')))),
|
|
581
|
+
marketPending
|
|
582
|
+
? h('div', { style: { display: 'grid', gap: 8, marginTop: 'auto' } },
|
|
583
|
+
h('p', { role: 'status', style: mutedTextStyle }, skill.team_connected
|
|
584
|
+
? '本企业尚未启用这个固定版本。你可以先浏览介绍;需要使用时请联系企业管理员。'
|
|
585
|
+
: '连接企业并验证工作邮箱后,才能查看本企业是否启用并安装这个技能。'),
|
|
586
|
+
skill.local_status === 'conflict' && skill.conflict_reason === 'other-source'
|
|
587
|
+
? h('button', { type: 'button', disabled: Boolean(workingId),
|
|
588
|
+
onClick: () => void changeInstall(skill, true), style: { ...secondaryButtonStyle, width: 'fit-content' } }, '卸载旧来源')
|
|
589
|
+
: null,
|
|
590
|
+
['installed', 'update-available'].includes(skill.local_status)
|
|
591
|
+
? h('button', { type: 'button', disabled: Boolean(workingId),
|
|
592
|
+
onClick: () => void changeInstall(skill, true), style: { ...secondaryButtonStyle, width: 'fit-content' } }, '卸载本机副本')
|
|
593
|
+
: null)
|
|
594
|
+
: skill.local_status === 'conflict'
|
|
575
595
|
? h('div', { style: { display: 'grid', gap: 8 } },
|
|
576
596
|
h('p', { role: 'status', style: mutedTextStyle }, skill.conflict_reason === 'other-source'
|
|
577
597
|
? '本机已安装另一个来源的同名技能。可主动卸载本机旧来源,再安装此版本。'
|
|
@@ -580,13 +600,24 @@ window.__ModuleLoader__.load({
|
|
|
580
600
|
? h('button', { type: 'button', disabled: Boolean(workingId),
|
|
581
601
|
onClick: () => void changeInstall(skill, true), style: { ...secondaryButtonStyle, width: 'fit-content' } }, '卸载旧来源')
|
|
582
602
|
: null)
|
|
583
|
-
:
|
|
584
|
-
skill.local_status === 'installed' ? null : h('button', { type: 'button', disabled: Boolean(workingId),
|
|
585
|
-
onClick: () => void changeInstall(skill), style: primaryButtonStyle },
|
|
586
|
-
skill.local_status === 'update-available' ? '更新技能' : '安装到这台 DSH'),
|
|
587
|
-
skill.local_status !== 'not-installed' ? h('button', { type: 'button', disabled: Boolean(workingId),
|
|
588
|
-
onClick: () => void changeInstall(skill, true), style: secondaryButtonStyle }, '卸载') : null))
|
|
603
|
+
: null)
|
|
589
604
|
})) : !includePlugins && !loading && (skills.length || officialOfficeSkills.length) && !visibleOfficial.length ? h('p', { style: mutedTextStyle }, '没有符合筛选条件的技能。') : null,
|
|
605
|
+
visibleOfficial.length ? h('section', { 'aria-label': 'DSH 官方 Office 技能', style: { display: 'grid', gap: 12 } },
|
|
606
|
+
h('div', null,
|
|
607
|
+
h('h2', { style: { margin: 0, fontSize: 20 } }, 'DSH 官方 Office'),
|
|
608
|
+
h('p', { style: { ...mutedTextStyle, marginTop: 4 } }, '这些能力随对应版本的 DSH 提供,无需通过 ANT 安装。在新会话中直接描述任务即可;不计入 ANT 的本机安装筛选。'),
|
|
609
|
+
h('a', { href: officialOfficeGuide, target: '_blank', rel: 'noopener noreferrer', style: { color: 'var(--dsw-alias-link)', fontSize: 13 } }, '查看中文官方说明 ↗')),
|
|
610
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 300px), 1fr))', gap: 14 } },
|
|
611
|
+
...visibleOfficial.map((skill) => h('article', { key: skill.name, style: { ...panelStyle, gap: 10 } },
|
|
612
|
+
h('div', { style: { display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 } },
|
|
613
|
+
h('h3', { style: { margin: 0, fontSize: 17 } }, skill.title),
|
|
614
|
+
h('span', { style: { ...mutedTextStyle, padding: '2px 8px', borderRadius: 6,
|
|
615
|
+
backgroundColor: 'var(--dsw-alias-bg-layer-2)' } }, 'DSH 自带 · 无需在 ANT 安装')),
|
|
616
|
+
h('p', { style: mutedTextStyle }, skill.description),
|
|
617
|
+
h('p', { style: mutedTextStyle }, `在新会话中说:“${skill.prompt}”。也可输入 /${skill.name}。`),
|
|
618
|
+
h('p', { style: mutedTextStyle }, `DSH ${skill.since} 起提供;如果无法使用,请在 DSH 检查更新。`),
|
|
619
|
+
h('a', { href: officialOfficeEnglish(skill), target: '_blank', rel: 'noopener noreferrer',
|
|
620
|
+
style: { color: 'var(--dsw-alias-link)', fontSize: 13, lineHeight: 1.6, padding: '4px 0' } }, '英文原文 ↗'))))) : null,
|
|
590
621
|
includePlugins ? h(PluginCenterPage, { remote, onBack, onAll, onSkills, openBundle,
|
|
591
622
|
embedded: true, query, onQueryChange, externalFilter: filter,
|
|
592
623
|
hasSkillMatches: visible.length + visibleOfficial.length > 0, skillCatalogReady: !loading && !loadError,
|
package/index.js
CHANGED
|
@@ -376,7 +376,9 @@ async function fetchMemberSkills(request, credentials, settings) {
|
|
|
376
376
|
catch { return { status: 'rejected' } }
|
|
377
377
|
}
|
|
378
378
|
const team = await settle(connection ? listSkills(connection) : Promise.resolve([]))
|
|
379
|
-
const market = await settle(
|
|
379
|
+
const market = await settle(connection
|
|
380
|
+
? listSkills({ ...connection, marketManaged: true }, 'market')
|
|
381
|
+
: listSkills(marketSkillConnection(), 'market'))
|
|
380
382
|
if (market.status === 'rejected' && (team.status === 'rejected' || !connection)) {
|
|
381
383
|
throw new Error('暂时无法读取公共技能市场;请稍后刷新。')
|
|
382
384
|
}
|
|
@@ -406,10 +408,11 @@ async function fetchSkillOriginal(request, credentials, settings) {
|
|
|
406
408
|
return jsonResponse(400, { message: '技能原文地址无效。' })
|
|
407
409
|
}
|
|
408
410
|
try {
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
+
const memberConnection = await memberSkillConnection(credentials, settings)
|
|
412
|
+
const connection = scope === 'market' ? memberConnection || marketSkillConnection() : memberConnection
|
|
411
413
|
if (!connection) return jsonResponse(401, { message: '请先连接 ANT 团队。' })
|
|
412
|
-
const path = scope === 'market' ?
|
|
414
|
+
const path = scope === 'market' ? memberConnection
|
|
415
|
+
? `/api/me/market-skills/${skillId}/original` : `/api/market/skills/${skillId}/original`
|
|
413
416
|
: `/api/me/skills/${skillId}/original`
|
|
414
417
|
const upstream = await fetch(new URL(path, connection.serviceUrl), {
|
|
415
418
|
headers: connection.token ? { authorization: `Bearer ${connection.token}`, accept: 'text/plain' }
|
|
@@ -443,10 +446,10 @@ async function installMemberSkill(request, credentials, settings) {
|
|
|
443
446
|
}
|
|
444
447
|
try {
|
|
445
448
|
const scope = body?.scope || 'team'
|
|
446
|
-
const connection =
|
|
447
|
-
: await memberSkillConnection(credentials, settings)
|
|
449
|
+
const connection = await memberSkillConnection(credentials, settings)
|
|
448
450
|
if (!connection) return jsonResponse(401, { message: '请先连接 ANT 团队,或重新验证工作邮箱。' })
|
|
449
|
-
return jsonResponse(200, await installSkill(
|
|
451
|
+
return jsonResponse(200, await installSkill(scope === 'market'
|
|
452
|
+
? { ...connection, marketManaged: true } : connection, body?.skill_id, scope))
|
|
450
453
|
} catch (error) {
|
|
451
454
|
return jsonResponse(409, { message: error instanceof Error ? error.message : '技能安装失败。' })
|
|
452
455
|
}
|
package/package.json
CHANGED
package/skill-install.js
CHANGED
|
@@ -137,6 +137,7 @@ async function verifyManagedTree(root, name, marker) {
|
|
|
137
137
|
|
|
138
138
|
async function boundedBytes(response, maxBytes) {
|
|
139
139
|
if (response.status === 404) throw new Error('此技能可能已下架或不再可访问,请刷新目录后重试。')
|
|
140
|
+
if (response.status === 403) throw new Error('本企业尚未启用这个技能,或授权已撤销;请刷新目录。')
|
|
140
141
|
if (!response.ok || !response.body) throw new Error(`技能来源无法提供文件(HTTP ${response.status})。`)
|
|
141
142
|
const chunks = []
|
|
142
143
|
let total = 0
|
|
@@ -156,7 +157,9 @@ async function fetchJson(url, token, timeoutMs = 20_000) {
|
|
|
156
157
|
}
|
|
157
158
|
|
|
158
159
|
export async function listSkills(connection, scope = 'team') {
|
|
159
|
-
const path = scope === 'market'
|
|
160
|
+
const path = scope === 'market'
|
|
161
|
+
? connection.marketManaged ? '/api/me/market-skills' : '/api/market/skills'
|
|
162
|
+
: '/api/me/skills'
|
|
160
163
|
const skills = await fetchJson(new URL(path, connection.serviceUrl), connection.token, scope === 'market' ? 8_000 : 20_000)
|
|
161
164
|
if (!Array.isArray(skills)) throw new Error('技能目录格式无效。')
|
|
162
165
|
const { root, conflicts } = await safeRoot()
|
|
@@ -165,7 +168,9 @@ export async function listSkills(connection, scope = 'team') {
|
|
|
165
168
|
let local_status = conflicts.has(skill.dsh_name) ? 'conflict' : 'not-installed'
|
|
166
169
|
let conflict_reason = ''
|
|
167
170
|
const actualScope = skill.scope === 'market' ? 'market' : scope
|
|
168
|
-
|
|
171
|
+
const marketState = actualScope === 'market' ? { team_enabled: Boolean(connection.marketManaged && skill.team_enabled === true),
|
|
172
|
+
team_connected: Boolean(connection.marketManaged) } : {}
|
|
173
|
+
if (local_status === 'conflict') return { ...skill, scope: actualScope, local_status, ...marketState }
|
|
169
174
|
try {
|
|
170
175
|
const marker = await readManaged(root, skill.dsh_name)
|
|
171
176
|
if (marker) {
|
|
@@ -178,7 +183,7 @@ export async function listSkills(connection, scope = 'team') {
|
|
|
178
183
|
local_status = marker.content_sha256 === skill.content_sha256 ? 'installed' : 'update-available'
|
|
179
184
|
}
|
|
180
185
|
} catch { local_status = 'conflict' }
|
|
181
|
-
return { ...skill, scope: actualScope, local_status, conflict_reason }
|
|
186
|
+
return { ...skill, scope: actualScope, local_status, conflict_reason, ...marketState }
|
|
182
187
|
}))
|
|
183
188
|
}
|
|
184
189
|
|
|
@@ -217,7 +222,8 @@ function contentDigest(files) {
|
|
|
217
222
|
export async function installSkill(connection, skillId, scope = 'team') {
|
|
218
223
|
if (typeof skillId !== 'string' || !/^[0-9a-f-]{36}$/iu.test(skillId)) throw new Error('技能编号无效。')
|
|
219
224
|
if (scope !== 'team' && scope !== 'market') throw new Error('技能来源无效。')
|
|
220
|
-
|
|
225
|
+
if (scope === 'market' && !connection.marketManaged) throw new Error('请先连接团队,再安装本企业已启用的全市场技能。')
|
|
226
|
+
const basePath = scope === 'market' ? '/api/me/market-skills' : '/api/me/skills'
|
|
221
227
|
const manifest = await fetchJson(new URL(`${basePath}/${skillId}/files`, connection.serviceUrl), connection.token)
|
|
222
228
|
validateManifest(manifest, skillId)
|
|
223
229
|
const { root, conflicts } = await safeRoot()
|