mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-16 13:03:31 +08:00
test: add skill market contracts
This commit is contained in:
parent
56a4be3d14
commit
9d08ca4e43
68
src/server/__tests__/fixtures/skill-market.ts
Normal file
68
src/server/__tests__/fixtures/skill-market.ts
Normal 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',
|
||||
},
|
||||
}
|
||||
23
src/server/__tests__/skill-market.test.ts
Normal file
23
src/server/__tests__/skill-market.test.ts
Normal 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' }),
|
||||
})
|
||||
})
|
||||
})
|
||||
73
src/server/services/skillMarket/types.ts
Normal file
73
src/server/services/skillMarket/types.ts
Normal 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
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user