test: add skill market contracts

This commit is contained in:
程序员阿江(Relakkes) 2026-07-03 16:43:33 +08:00
parent 56a4be3d14
commit 9d08ca4e43
3 changed files with 164 additions and 0 deletions

View File

@ -0,0 +1,68 @@
export const CLAWHUB_TOP_SKILLS_RESPONSE = {
items: [
{
slug: 'skill-vetter',
displayName: 'Skill Vetter',
summary: 'Security-first skill vetting for AI agents.',
description: null,
topics: ['GitHub', 'Permission'],
tags: { latest: '1.0.0' },
stats: { comments: 0, downloads: 260911, installs: 11988, stars: 1248, versions: 1 },
latestVersion: { version: '1.0.0', license: 'Apache-2.0' },
metadata: null,
},
],
nextCursor: null,
}
export const CLAWHUB_SCAN_RESPONSE = {
status: 'clean',
hasWarnings: false,
scanners: {
skillspector: { status: 'clean', summary: 'No dangerous patterns detected.' },
},
sha256: 'a'.repeat(64),
}
export const SKILLHUB_TOP_SKILLS_RESPONSE = {
code: 0,
data: {
skills: [
{
slug: 'skill-vetter',
name: 'Skill Vetter',
description: 'Security-first skill vetting for AI agents.',
description_zh: 'AI智能体技能安全预审工具。',
downloads: 273329,
installs: 37273,
stars: 1253,
ownerName: 'spclaudehome',
source: 'clawhub',
upstream_url: 'https://clawhub.ai/spclaudehome/skill-vetter',
version: '1.0.0',
labels: { requires_api_key: 'false' },
verified: false,
},
],
},
}
export const SKILLHUB_DETAIL_RESPONSE = {
contentZhAvailable: true,
latestVersion: { version: '1.0.0' },
owner: { handle: 'spclaudehome', displayName: 'spclaudehome' },
securityReports: {
keen: { status: 'benign', statusText: '安全,无风险' },
sanbu: { status: 'benign', statusText: '安全,无风险' },
},
skill: {
slug: 'skill-vetter',
displayName: 'Skill Vetter',
summary: 'Security-first skill vetting for AI agents.',
summary_zh: 'AI智能体技能安全预审工具。',
sourceUrl: 'https://clawhub.ai/spclaudehome/skill-vetter',
stats: { downloads: 273329, installs: 37273, stars: 1253 },
labels: { requires_api_key: 'false' },
version: '1.0.0',
},
}

View File

@ -0,0 +1,23 @@
import { describe, expect, it } from 'bun:test'
import {
CLAWHUB_TOP_SKILLS_RESPONSE,
SKILLHUB_TOP_SKILLS_RESPONSE,
} from './fixtures/skill-market.js'
describe('skill market fixtures', () => {
it('keeps representative ClawHub fixture shape stable', () => {
expect(CLAWHUB_TOP_SKILLS_RESPONSE.items[0]).toMatchObject({
slug: 'skill-vetter',
displayName: 'Skill Vetter',
stats: expect.objectContaining({ downloads: expect.any(Number) }),
})
})
it('keeps representative SkillHub fixture shape stable', () => {
expect(SKILLHUB_TOP_SKILLS_RESPONSE.data.skills[0]).toMatchObject({
slug: 'skill-vetter',
source: 'clawhub',
labels: expect.objectContaining({ requires_api_key: 'false' }),
})
})
})

View File

@ -0,0 +1,73 @@
export type SkillMarketSource = 'clawhub' | 'skillhub' | 'anthropic-github'
export type SkillMarketSourceMode = 'primary' | 'fallback' | 'enhanced'
export type SkillMarketTrustState =
| 'clean'
| 'benign'
| 'signed'
| 'official'
| 'warning'
| 'unknown'
| 'blocked'
export type SkillMarketRiskLabel =
| 'allowed-tools'
| 'hooks'
| 'scripts'
| 'executables'
| 'external-network'
| 'requires-api-key'
export type SkillMarketItem = {
source: SkillMarketSource
sourceMode: SkillMarketSourceMode
slug: string
displayName: string
summary: string
summaryZh?: string
owner?: string
canonicalUrl: string
upstreamUrl?: string
license?: string | null
version?: string
downloads?: number
installs?: number
stars?: number
category?: string
tags?: string[]
requiresApiKey?: boolean
trustState: SkillMarketTrustState
trustSummary?: string
installed: boolean
}
export type SkillMarketFile = {
path: string
size?: number
sha256?: string
}
export type SkillMarketDetail = SkillMarketItem & {
files: SkillMarketFile[]
entryPreview?: string
riskLabels: SkillMarketRiskLabel[]
installEligibility:
| { status: 'installable' }
| { status: 'installed'; installedSkillName: string }
| { status: 'conflict'; targetPath: string }
| { status: 'blocked'; reason: string }
}
export type SkillMarketListResult = {
items: SkillMarketItem[]
nextCursor: string | null
source: SkillMarketSource
sourceStatus: 'ok' | 'fallback' | 'cached'
message?: string
}
export type SkillMarketInstallResult = {
installed: true
skillName: string
targetPath: string
}