mirror of
https://github.com/NanmiCoder/cc-haha
synced 2026-07-18 13:23:33 +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