mirror of
https://github.com/iflytek/skillhub.git
synced 2026-08-28 11:25:00 +00:00
Implement complete CLI tool for SkillHub with 12 commands, 7 backend API endpoints, and comprehensive documentation. CLI Commands: - help, version: Basic information - login, logout, whoami: Authentication management - search: Discover published skills - install: Install skills to agent directories (14 Tier 1 agents supported) - list, remove, doctor: Local skill management - publish: Publish skill packages - update: Self-update mechanism Backend API: - Add /api/cli/v1 endpoints for auth, search, resolve, download, delete, publish - Implement CliAuthController and CliSkillController - Add security policies for CLI routes - Full test coverage (19 backend tests) CLI Implementation: - TypeScript with strict mode, Bun runtime - Pure JS zip handling (fflate) for cross-platform compatibility - 15 agent profiles (14 Tier 1 + generic fallback) - Secure token storage (0600 permissions) - Path safety validation for remove operations - Comprehensive error handling (404/403/network distinction) - 41 unit and integration tests Documentation: - CLI user guide (Chinese and English) - README updates with quick start - GitHub Actions workflow for cross-platform CI Quality: - lint: 0 errors - typecheck: pass - test: 41/41 pass - build: 0.30 MB (target=node for npm/npx compatibility)
38 lines
1.4 KiB
TypeScript
38 lines
1.4 KiB
TypeScript
import { describe, expect, test } from 'bun:test'
|
|
import { allProfiles, profileMap } from '../../../src/agents/detector'
|
|
|
|
describe('agent profiles', () => {
|
|
test('has 14 tier 1 profiles', () => {
|
|
expect(allProfiles).toHaveLength(14)
|
|
})
|
|
|
|
test('all profiles have unique ids', () => {
|
|
const ids = allProfiles.map(p => p.id)
|
|
expect(new Set(ids).size).toBe(ids.length)
|
|
})
|
|
|
|
test('profileMap contains all profiles', () => {
|
|
expect(profileMap.size).toBe(14)
|
|
expect(profileMap.has('claude-code')).toBe(true)
|
|
expect(profileMap.has('codex')).toBe(true)
|
|
expect(profileMap.has('cursor')).toBe(true)
|
|
expect(profileMap.has('kilo')).toBe(true)
|
|
})
|
|
|
|
test('claude-code profile returns correct roots', () => {
|
|
const profile = profileMap.get('claude-code')!
|
|
expect(profile.projectRoots('/repo')).toEqual(['/repo/.claude/skills'])
|
|
expect(profile.userRoots('/home/user')).toEqual(['/home/user/.claude/skills'])
|
|
})
|
|
|
|
test('codex profile returns correct roots', () => {
|
|
const profile = profileMap.get('codex')!
|
|
expect(profile.projectRoots('/repo')).toEqual(['/repo/.codex/skills'])
|
|
expect(profile.userRoots('/home/user')).toEqual(['/home/user/.codex/skills'])
|
|
})
|
|
|
|
test('cursor profile returns correct roots', () => {
|
|
const profile = profileMap.get('cursor')!
|
|
expect(profile.projectRoots('/repo')).toEqual(['/repo/.cursor/skills'])
|
|
})
|
|
})
|