@ai-wendao/ant 0.3.17 → 0.3.18
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 +41 -21
- 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([])
|
|
@@ -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,24 +519,12 @@ 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)
|
|
540
529
|
const originalEnglish = Boolean(curatedSkillIntroduction(skill)) || !hasChineseIntroduction(skill.description)
|
|
541
530
|
const englishSource = skillEnglishSource(skill)
|
|
@@ -550,7 +539,9 @@ window.__ModuleLoader__.load({
|
|
|
550
539
|
h('h2', { style: { margin: 0, fontSize: 19 } }, skill.title),
|
|
551
540
|
h('span', { style: { ...mutedTextStyle, padding: '2px 7px', borderRadius: 6, backgroundColor: 'var(--dsw-alias-bg-layer-2)' } }, skill.scope === 'market' ? '全市场精选' : '本企业'),
|
|
552
541
|
h('span', { style: mutedTextStyle }, skillCategory(skill))),
|
|
553
|
-
h('span', { style: mutedTextStyle },
|
|
542
|
+
h('span', { style: mutedTextStyle }, marketPending
|
|
543
|
+
? skill.team_connected ? '待企业启用' : '连接企业后查看启用状态'
|
|
544
|
+
: statusLabel[skill.local_status] || '状态未知')),
|
|
554
545
|
h('p', { style: mutedTextStyle }, description.length > 180 ? `${description.slice(0, 180)}…` : description),
|
|
555
546
|
englishSource ? h('a', { href: englishSource, target: '_blank', rel: 'noopener noreferrer',
|
|
556
547
|
style: { color: 'var(--dsw-alias-link)', fontSize: 13 } }, originalEnglish ? '查看英文原文 ↗' : '查看原始说明 ↗')
|
|
@@ -571,7 +562,20 @@ window.__ModuleLoader__.load({
|
|
|
571
562
|
/^https:\/\//u.test(skill.source_url || '')
|
|
572
563
|
? h('a', { href: skill.source_url, target: '_blank', rel: 'noopener noreferrer', style: { fontSize: 13, color: 'var(--dsw-alias-link)' } }, '查看原始来源 ↗')
|
|
573
564
|
: h('p', { style: mutedTextStyle }, '来源:管理员上传并审核'))),
|
|
574
|
-
|
|
565
|
+
marketPending
|
|
566
|
+
? h('div', { style: { display: 'grid', gap: 8, marginTop: 'auto' } },
|
|
567
|
+
h('p', { role: 'status', style: mutedTextStyle }, skill.team_connected
|
|
568
|
+
? '本企业尚未启用这个固定版本。你可以先浏览介绍;需要使用时请联系企业管理员。'
|
|
569
|
+
: '连接企业并验证工作邮箱后,才能查看本企业是否启用并安装这个技能。'),
|
|
570
|
+
skill.local_status === 'conflict' && skill.conflict_reason === 'other-source'
|
|
571
|
+
? h('button', { type: 'button', disabled: Boolean(workingId),
|
|
572
|
+
onClick: () => void changeInstall(skill, true), style: { ...secondaryButtonStyle, width: 'fit-content' } }, '卸载旧来源')
|
|
573
|
+
: null,
|
|
574
|
+
['installed', 'update-available'].includes(skill.local_status)
|
|
575
|
+
? h('button', { type: 'button', disabled: Boolean(workingId),
|
|
576
|
+
onClick: () => void changeInstall(skill, true), style: { ...secondaryButtonStyle, width: 'fit-content' } }, '卸载本机副本')
|
|
577
|
+
: null)
|
|
578
|
+
: skill.local_status === 'conflict'
|
|
575
579
|
? h('div', { style: { display: 'grid', gap: 8 } },
|
|
576
580
|
h('p', { role: 'status', style: mutedTextStyle }, skill.conflict_reason === 'other-source'
|
|
577
581
|
? '本机已安装另一个来源的同名技能。可主动卸载本机旧来源,再安装此版本。'
|
|
@@ -587,6 +591,22 @@ window.__ModuleLoader__.load({
|
|
|
587
591
|
skill.local_status !== 'not-installed' ? h('button', { type: 'button', disabled: Boolean(workingId),
|
|
588
592
|
onClick: () => void changeInstall(skill, true), style: secondaryButtonStyle }, '卸载') : null))
|
|
589
593
|
})) : !includePlugins && !loading && (skills.length || officialOfficeSkills.length) && !visibleOfficial.length ? h('p', { style: mutedTextStyle }, '没有符合筛选条件的技能。') : null,
|
|
594
|
+
visibleOfficial.length ? h('section', { 'aria-label': 'DSH 官方 Office 技能', style: { display: 'grid', gap: 12 } },
|
|
595
|
+
h('div', null,
|
|
596
|
+
h('h2', { style: { margin: 0, fontSize: 20 } }, 'DSH 官方 Office'),
|
|
597
|
+
h('p', { style: { ...mutedTextStyle, marginTop: 4 } }, '这些能力随对应版本的 DSH 提供,无需通过 ANT 安装。在新会话中直接描述任务即可;不计入 ANT 的本机安装筛选。'),
|
|
598
|
+
h('a', { href: officialOfficeGuide, target: '_blank', rel: 'noopener noreferrer', style: { color: 'var(--dsw-alias-link)', fontSize: 13 } }, '查看中文官方说明 ↗')),
|
|
599
|
+
h('div', { style: { display: 'grid', gridTemplateColumns: 'repeat(auto-fit, minmax(min(100%, 300px), 1fr))', gap: 14 } },
|
|
600
|
+
...visibleOfficial.map((skill) => h('article', { key: skill.name, style: { ...panelStyle, gap: 10 } },
|
|
601
|
+
h('div', { style: { display: 'flex', flexWrap: 'wrap', justifyContent: 'space-between', alignItems: 'baseline', gap: 8 } },
|
|
602
|
+
h('h3', { style: { margin: 0, fontSize: 17 } }, skill.title),
|
|
603
|
+
h('span', { style: { ...mutedTextStyle, padding: '2px 8px', borderRadius: 6,
|
|
604
|
+
backgroundColor: 'var(--dsw-alias-bg-layer-2)' } }, 'DSH 自带 · 无需在 ANT 安装')),
|
|
605
|
+
h('p', { style: mutedTextStyle }, skill.description),
|
|
606
|
+
h('p', { style: mutedTextStyle }, `在新会话中说:“${skill.prompt}”。也可输入 /${skill.name}。`),
|
|
607
|
+
h('p', { style: mutedTextStyle }, `DSH ${skill.since} 起提供;如果无法使用,请在 DSH 检查更新。`),
|
|
608
|
+
h('a', { href: officialOfficeEnglish(skill), target: '_blank', rel: 'noopener noreferrer',
|
|
609
|
+
style: { color: 'var(--dsw-alias-link)', fontSize: 13, lineHeight: 1.6, padding: '4px 0' } }, '英文原文 ↗'))))) : null,
|
|
590
610
|
includePlugins ? h(PluginCenterPage, { remote, onBack, onAll, onSkills, openBundle,
|
|
591
611
|
embedded: true, query, onQueryChange, externalFilter: filter,
|
|
592
612
|
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()
|