@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 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 ? '' : '暂无团队或市场精选技能;下方仍可查看 DSH 官方技能。'))
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) ? h('p', { role: loadError ? 'alert' : 'status', style: mutedTextStyle }, message) : null,
522
- visibleOfficial.length ? h('section', { 'aria-label': 'DSH 官方 Office 技能', style: { display: 'grid', gap: 12 } },
523
- h('div', null,
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 }, statusLabel[skill.local_status] || '状态未知')),
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
- skill.local_status === 'conflict'
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(listSkills(marketSkillConnection(), 'market'))
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 connection = scope === 'market' ? marketSkillConnection()
410
- : await memberSkillConnection(credentials, settings)
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' ? `/api/market/skills/${skillId}/original`
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 = scope === 'market' ? marketSkillConnection()
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(connection, body?.skill_id, scope))
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-wendao/ant",
3
- "version": "0.3.17",
3
+ "version": "0.3.18",
4
4
  "description": "ANT (AI-native Teams) connects a DeepSeek Harness Desktop profile to team identity and approved models.",
5
5
  "type": "module",
6
6
  "scripts": {
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' ? '/api/market/skills' : '/api/me/skills'
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
- if (local_status === 'conflict') return { ...skill, scope: actualScope, local_status }
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
- const basePath = scope === 'market' ? '/api/market/skills' : '/api/me/skills'
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()