mirror of
https://github.com/iflytek/skillhub.git
synced 2026-09-10 22:41:02 +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)
31 lines
897 B
TypeScript
31 lines
897 B
TypeScript
export function userStateDir(home = process.env.HOME || process.env.USERPROFILE || ''): string {
|
|
if (!home) {
|
|
throw new Error('Cannot resolve user home directory')
|
|
}
|
|
return `${home.replace(/\\/g, '/')}/.skillhub`
|
|
}
|
|
|
|
export function joinPath(...parts: string[]): string {
|
|
return parts.join('/').replace(/\/+/g, '/')
|
|
}
|
|
|
|
export async function ensureDir(dir: string): Promise<void> {
|
|
const { mkdir } = await import('node:fs/promises')
|
|
await mkdir(dir, { recursive: true })
|
|
}
|
|
|
|
export async function pathExists(path: string): Promise<boolean> {
|
|
const { access } = await import('node:fs/promises')
|
|
try {
|
|
await access(path)
|
|
return true
|
|
} catch {
|
|
return false
|
|
}
|
|
}
|
|
|
|
export async function applyCredentialPermissions(path: string): Promise<void> {
|
|
if (process.platform === 'win32') return
|
|
const { chmod } = await import('node:fs/promises')
|
|
await chmod(path, 0o600)
|
|
}
|