huhaa-myskills 0.2.13 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -375
- package/bin/huhaa-myskills.mjs +194 -12
- package/{scripts → build}/verify.mjs +3 -1
- package/docs/Frontend-Spec.md +1149 -0
- package/docs/assets/layout-wireframe.png +0 -0
- package/docs/assets/theme-reference.png +0 -0
- package/docs/scan_rules.md +172 -0
- package/package.json +33 -9
- package/packages/scanner/src/adapters/directory-skill.mjs +239 -0
- package/packages/scanner/src/adapters/skill-adapter.mjs +345 -0
- package/packages/scanner/src/icon/brand-map.mjs +84 -0
- package/packages/scanner/src/icon/icon-extractor.mjs +246 -0
- package/packages/scanner/src/index.mjs +107 -82
- package/packages/scanner/src/types.d.ts +18 -0
- package/packages/scanner/test/icon.test.mjs +61 -0
- package/packages/scanner/test/scanner.test.mjs +37 -41
- package/packages/scanner/test/skill-adapter.test.mjs +70 -0
- package/packages/scanner/tests/directory-skill.test.mjs +93 -0
- package/packages/scanner/tests/scanner-integration.test.mjs +139 -0
- package/packages/server/src/index.mjs +164 -12
- package/packages/server/src/labels.mjs +62 -0
- package/packages/server/test/server.test.mjs +1 -1
- package/packages/web/README.md +33 -2
- package/packages/web/dist/assets/index-BCY2cRaO.js +175 -0
- package/packages/web/dist/assets/index-DALKjJPi.css +1 -0
- package/packages/web/dist/favicon-16x16.png +0 -0
- package/packages/web/dist/favicon-192x192.png +0 -0
- package/packages/web/dist/favicon-32x32.png +0 -0
- package/packages/web/dist/favicon-512x512.png +0 -0
- package/packages/web/dist/favicon-source.svg +5 -0
- package/packages/web/dist/index.html +23 -9
- package/packages/web/index.html +22 -8
- package/packages/web/package-lock.json +2989 -0
- package/packages/web/package.json +21 -8
- package/packages/web/postcss.config.js +6 -0
- package/packages/web/public/favicon-16x16.png +0 -0
- package/packages/web/public/favicon-192x192.png +0 -0
- package/packages/web/public/favicon-32x32.png +0 -0
- package/packages/web/public/favicon-512x512.png +0 -0
- package/packages/web/public/favicon-source.svg +5 -0
- package/packages/web/src/App.test.ts +40 -0
- package/packages/web/src/App.tsx +177 -0
- package/packages/web/src/components/ComingSoon.tsx +14 -0
- package/packages/web/src/components/layout/Sidebar.test.tsx +74 -0
- package/packages/web/src/components/layout/Sidebar.tsx +114 -0
- package/packages/web/src/components/layout/Topbar.tsx +74 -0
- package/packages/web/src/components/ui/ActionButton.tsx +48 -0
- package/packages/web/src/components/ui/button.tsx +48 -0
- package/packages/web/src/components/ui/card.tsx +45 -0
- package/packages/web/src/components/views/DashboardView.tsx +122 -0
- package/packages/web/src/components/views/OtherSkillsView.test.tsx +126 -0
- package/packages/web/src/components/views/OtherSkillsView.tsx +306 -0
- package/packages/web/src/components/views/SettingsView.tsx +95 -0
- package/packages/web/src/components/views/SkillDetail.test.tsx +57 -0
- package/packages/web/src/components/views/SkillDetail.tsx +81 -0
- package/packages/web/src/components/views/SkillsView.test.ts +28 -0
- package/packages/web/src/components/views/SkillsView.tsx +226 -0
- package/packages/web/src/hooks/QUICK_REFERENCE.md +165 -0
- package/packages/web/src/hooks/README.md +378 -0
- package/packages/web/src/hooks/__tests__/useOtherSkills.test.ts +422 -0
- package/packages/web/src/hooks/__tests__/useSkillIcons.test.ts +272 -0
- package/packages/web/src/hooks/useLiveReload.ts +20 -0
- package/packages/web/src/hooks/useOtherSkills.ts +387 -0
- package/packages/web/src/hooks/useSkillIcons.ts +248 -0
- package/packages/web/src/hooks/useTheme.ts +36 -0
- package/packages/web/src/index.css +161 -0
- package/packages/web/src/lib/api.test.ts +47 -0
- package/packages/web/src/lib/api.ts +77 -0
- package/packages/web/src/lib/cn.ts +7 -0
- package/packages/web/src/lib/editors.test.ts +30 -0
- package/packages/web/src/lib/editors.ts +70 -0
- package/packages/web/src/lib/markdown.test.ts +27 -0
- package/packages/web/src/lib/markdown.ts +14 -0
- package/packages/web/src/main.tsx +13 -0
- package/packages/web/src/types/index.ts +62 -0
- package/packages/web/src/types/other-skill.ts +88 -0
- package/packages/web/src/types/skill.ts +136 -0
- package/packages/web/src/types.ts +47 -0
- package/packages/web/src/vite-env.d.ts +1 -0
- package/packages/web/tailwind.config.ts +66 -0
- package/packages/web/tsconfig.json +28 -0
- package/packages/web/vite.config.ts +36 -0
- package/packages/web/vitest.config.ts +21 -0
- package/packages/web/vitest.setup.ts +1 -0
- package/scripts/activate-data-sources.sh +223 -0
- package/scripts/brand-completion.py +586 -0
- package/scripts/init-nextjs-project.sh +421 -0
- package/scripts/install-and-sync.sh +209 -0
- package/scripts/start-dev.sh +72 -0
- package/docs/GUIDE.md +0 -190
- package/docs/PLAN.md +0 -359
- package/docs/RULES.md +0 -329
- package/docs/RUNBOOK-myskills.md +0 -258
- package/docs/SYNC-SKILLS.md +0 -259
- package/docs/releases/README.md +0 -47
- package/docs/releases/v0.1.0.md +0 -256
- package/docs/releases/v0.1.1.md +0 -297
- package/docs/releases/v0.1.2.md +0 -207
- package/docs/releases/v0.1.3.md +0 -269
- package/docs/todo/v0.1.2.md +0 -98
- package/docs/todo/v0.1.3.md +0 -40
- package/docs/todo/v0.1.4.md +0 -36
- package/docs/todo/v0.1.5.md +0 -41
- package/docs/todo/v0.1.6.md +0 -43
- package/docs/todo/v0.1.7.md +0 -38
- package/docs/todo/v0.1.8.md +0 -36
- package/docs/todo/v0.1.9.md +0 -54
- package/packages/web/dist/assets/index-BPepSb3q.js +0 -36
- package/packages/web/dist/assets/index-CIGkgT5w.css +0 -1
- package/packages/web/src/App.vue +0 -483
- package/packages/web/src/components/AppTree.vue +0 -230
- package/packages/web/src/components/DirectoryTree.vue +0 -263
- package/packages/web/src/components/SkillTree.vue +0 -208
- package/packages/web/src/lib/api.js +0 -43
- package/packages/web/src/main.js +0 -6
- package/packages/web/src/stores/i18n.js +0 -161
- package/packages/web/src/stores/skills.js +0 -287
- package/packages/web/src/styles.css +0 -365
- package/packages/web/vite.config.js +0 -17
- /package/{scripts → build}/build-web.mjs +0 -0
- /package/{scripts → build}/prepare-publish.mjs +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SkillItem — Unified skill data structure from backend scanner
|
|
3
|
+
*
|
|
4
|
+
* This IR (Intermediate Representation) is returned by all adapters:
|
|
5
|
+
* - Tier 1: Official tools (hermes, claude-code, cursor, codex, hermes-plugin)
|
|
6
|
+
* - Tier 2: Custom directory skills (directory-skill)
|
|
7
|
+
* - Tier 3: Other sources (project-runbook, etc.)
|
|
8
|
+
*
|
|
9
|
+
* Imported from packages/scanner/src/types.d.ts (backend definition)
|
|
10
|
+
* This frontend copy ensures type safety without backend dependency
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
export type SkillKind = 'skill' | 'plugin' | 'mcp' | 'runbook' | 'doc';
|
|
14
|
+
|
|
15
|
+
export type SkillSource =
|
|
16
|
+
| 'hermes'
|
|
17
|
+
| 'claude-code'
|
|
18
|
+
| 'codex'
|
|
19
|
+
| 'cursor'
|
|
20
|
+
| 'obsidian'
|
|
21
|
+
| 'project'
|
|
22
|
+
| 'project-runbook'
|
|
23
|
+
| 'hermes-plugin'
|
|
24
|
+
| 'directory'
|
|
25
|
+
| 'mcp-config';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Tier categorization — Phase 1 Backend redesign
|
|
29
|
+
* Controls UI display, filtering, and icon selection
|
|
30
|
+
*/
|
|
31
|
+
export type SkillTier = 'tool' | 'directory' | 'other';
|
|
32
|
+
|
|
33
|
+
export interface SkillItem {
|
|
34
|
+
/** sha1(absPath) — stable across runs, used as React key */
|
|
35
|
+
id: string;
|
|
36
|
+
|
|
37
|
+
/** Broad category — drives icon and filtering */
|
|
38
|
+
kind: SkillKind;
|
|
39
|
+
|
|
40
|
+
/** Source adapter that produced this item */
|
|
41
|
+
source: SkillSource;
|
|
42
|
+
|
|
43
|
+
/** Machine-readable name (from SKILL.md frontmatter or directory) */
|
|
44
|
+
name: string;
|
|
45
|
+
|
|
46
|
+
/** Human-readable title for display */
|
|
47
|
+
title: string;
|
|
48
|
+
|
|
49
|
+
/** Brief description (one line) */
|
|
50
|
+
description?: string;
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* NEW (Phase 1): Tier categorization
|
|
54
|
+
* - 'tool': Official tools (hermes, claude-code, etc.) with brand
|
|
55
|
+
* - 'directory': Custom skills from specified directories
|
|
56
|
+
* - 'other': Other sources (project-runbook, etc.)
|
|
57
|
+
*/
|
|
58
|
+
tier?: SkillTier;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* NEW (Phase 1): Brand identifier for Tier 1 tools
|
|
62
|
+
* Maps to emoji icon: 'hermes' → ⚡, 'claude' → 🤖, etc.
|
|
63
|
+
* Only set on Tier 1 items
|
|
64
|
+
*/
|
|
65
|
+
brand?: string;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* NEW (Phase 1): Parent directory name (Tier 2 only)
|
|
69
|
+
* Used as secondary label for directory-based skills
|
|
70
|
+
* Example: 'auth-flow' from ~/custom-skills/auth-flow/SKILL.md
|
|
71
|
+
*/
|
|
72
|
+
dirName?: string;
|
|
73
|
+
|
|
74
|
+
/** Semantic category tags (e.g., 'authentication', 'async') */
|
|
75
|
+
category?: string[];
|
|
76
|
+
|
|
77
|
+
/** Which tool/editor owns this skill (e.g., 'Hermes', 'Custom Skills') */
|
|
78
|
+
editor?: string;
|
|
79
|
+
|
|
80
|
+
/** Product or brand name (e.g., 'Claude', 'Cursor') */
|
|
81
|
+
product?: string;
|
|
82
|
+
|
|
83
|
+
/** Trigger phrases for activation */
|
|
84
|
+
triggers?: string[];
|
|
85
|
+
|
|
86
|
+
/** Semantic tags for search */
|
|
87
|
+
tags?: string[];
|
|
88
|
+
|
|
89
|
+
/** File paths associated with this skill */
|
|
90
|
+
paths?: string[];
|
|
91
|
+
|
|
92
|
+
/** Preview markdown (first N lines of SKILL.md body) */
|
|
93
|
+
preview?: string;
|
|
94
|
+
|
|
95
|
+
/** Full raw content (SKILL.md body or rendered doc) */
|
|
96
|
+
raw?: string;
|
|
97
|
+
|
|
98
|
+
/** Related links (e.g., documentation URLs) */
|
|
99
|
+
links?: Array<{
|
|
100
|
+
text: string;
|
|
101
|
+
href: string;
|
|
102
|
+
}>;
|
|
103
|
+
|
|
104
|
+
/** ISO 8601 timestamp of last modification */
|
|
105
|
+
updatedAt?: string;
|
|
106
|
+
|
|
107
|
+
/** Parse error if skill metadata was malformed */
|
|
108
|
+
parseError?: string;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* i18n translation metadata (optional)
|
|
112
|
+
* Only populated if HUHAA_TRANSLATE=1
|
|
113
|
+
*/
|
|
114
|
+
i18n?: {
|
|
115
|
+
zh?: {
|
|
116
|
+
title?: string;
|
|
117
|
+
description?: string;
|
|
118
|
+
};
|
|
119
|
+
translatedAt?: string;
|
|
120
|
+
translationModel?: string;
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* API Response Shape
|
|
126
|
+
*/
|
|
127
|
+
export interface SkillsApiResponse {
|
|
128
|
+
items: SkillItem[];
|
|
129
|
+
stats: {
|
|
130
|
+
total: number;
|
|
131
|
+
bySource: Record<SkillSource, number>;
|
|
132
|
+
byTier?: Record<SkillTier, number>;
|
|
133
|
+
parseErrors: number;
|
|
134
|
+
updatedAt: string;
|
|
135
|
+
};
|
|
136
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// 前端镜像后端 IR(packages/scanner/src/types.d.ts 的 SkillItem)。
|
|
2
|
+
// 二者需保持同步:后端字段变更时同步此文件。
|
|
3
|
+
|
|
4
|
+
export type SkillKind =
|
|
5
|
+
| 'skill'
|
|
6
|
+
| 'plugin'
|
|
7
|
+
| 'mcp'
|
|
8
|
+
| 'runbook'
|
|
9
|
+
| 'doc'
|
|
10
|
+
|
|
11
|
+
export interface SkillItem {
|
|
12
|
+
id: string
|
|
13
|
+
kind: SkillKind
|
|
14
|
+
source: string
|
|
15
|
+
name: string
|
|
16
|
+
title?: string
|
|
17
|
+
description?: string
|
|
18
|
+
category?: string[]
|
|
19
|
+
tier?: string
|
|
20
|
+
brand?: string
|
|
21
|
+
dirName?: string
|
|
22
|
+
editor?: string
|
|
23
|
+
product?: string
|
|
24
|
+
triggers?: string[]
|
|
25
|
+
tags?: string[]
|
|
26
|
+
paths?: {
|
|
27
|
+
abs: string
|
|
28
|
+
rel?: string
|
|
29
|
+
rootKind: 'home' | 'project' | 'icloud'
|
|
30
|
+
}
|
|
31
|
+
preview?: string
|
|
32
|
+
/** /api/skills 列表接口会剥离 raw,仅 /api/skills/:id 返回 */
|
|
33
|
+
raw?: string
|
|
34
|
+
links?: { label: string; url: string }[]
|
|
35
|
+
updatedAt?: string
|
|
36
|
+
parseError?: string
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface Stats {
|
|
40
|
+
total: number
|
|
41
|
+
bySource: Record<string, number>
|
|
42
|
+
byEditor: Record<string, number>
|
|
43
|
+
byKind: Record<string, number>
|
|
44
|
+
byCategory: Record<string, number>
|
|
45
|
+
byBrand: Record<string, number>
|
|
46
|
+
labels?: Record<string, unknown>
|
|
47
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
/// <reference types="vite/client" />
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { Config } from 'tailwindcss'
|
|
2
|
+
|
|
3
|
+
// 设计 token 取自 docs/Frontend-Theme-Design.md。
|
|
4
|
+
// 颜色用 HSL 通道值存于 CSS 变量,便于亮/暗主题切换(shadcn 约定)。
|
|
5
|
+
const config: Config = {
|
|
6
|
+
darkMode: 'class',
|
|
7
|
+
content: ['./index.html', './src/**/*.{ts,tsx}'],
|
|
8
|
+
theme: {
|
|
9
|
+
extend: {
|
|
10
|
+
colors: {
|
|
11
|
+
background: 'hsl(var(--color-background) / <alpha-value>)',
|
|
12
|
+
foreground: 'hsl(var(--color-foreground) / <alpha-value>)',
|
|
13
|
+
sidebar: 'hsl(var(--color-sidebar) / <alpha-value>)',
|
|
14
|
+
border: 'hsl(var(--color-border) / <alpha-value>)',
|
|
15
|
+
input: 'hsl(var(--color-input) / <alpha-value>)',
|
|
16
|
+
ring: 'hsl(var(--color-ring) / <alpha-value>)',
|
|
17
|
+
primary: {
|
|
18
|
+
DEFAULT: 'hsl(var(--color-primary) / <alpha-value>)',
|
|
19
|
+
foreground: 'hsl(var(--color-primary-foreground) / <alpha-value>)',
|
|
20
|
+
soft: 'hsl(var(--color-primary-soft) / <alpha-value>)',
|
|
21
|
+
},
|
|
22
|
+
secondary: {
|
|
23
|
+
DEFAULT: 'hsl(var(--color-secondary) / <alpha-value>)',
|
|
24
|
+
foreground: 'hsl(var(--color-secondary-foreground) / <alpha-value>)',
|
|
25
|
+
},
|
|
26
|
+
destructive: {
|
|
27
|
+
DEFAULT: 'hsl(var(--color-destructive) / <alpha-value>)',
|
|
28
|
+
foreground: 'hsl(var(--color-destructive-foreground) / <alpha-value>)',
|
|
29
|
+
},
|
|
30
|
+
muted: {
|
|
31
|
+
DEFAULT: 'hsl(var(--color-muted) / <alpha-value>)',
|
|
32
|
+
foreground: 'hsl(var(--color-muted-foreground) / <alpha-value>)',
|
|
33
|
+
},
|
|
34
|
+
accent: {
|
|
35
|
+
DEFAULT: 'hsl(var(--color-accent) / <alpha-value>)',
|
|
36
|
+
foreground: 'hsl(var(--color-accent-foreground) / <alpha-value>)',
|
|
37
|
+
},
|
|
38
|
+
card: {
|
|
39
|
+
DEFAULT: 'hsl(var(--color-card) / <alpha-value>)',
|
|
40
|
+
foreground: 'hsl(var(--color-card-foreground) / <alpha-value>)',
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
borderRadius: {
|
|
44
|
+
lg: '12px',
|
|
45
|
+
md: '8px',
|
|
46
|
+
sm: '4px',
|
|
47
|
+
},
|
|
48
|
+
fontSize: {
|
|
49
|
+
h1: ['32px', { lineHeight: '40px', fontWeight: '700' }],
|
|
50
|
+
h2: ['28px', { lineHeight: '36px', fontWeight: '700' }],
|
|
51
|
+
h3: ['24px', { lineHeight: '32px', fontWeight: '600' }],
|
|
52
|
+
h4: ['20px', { lineHeight: '28px', fontWeight: '600' }],
|
|
53
|
+
body: ['16px', { lineHeight: '24px', fontWeight: '400' }],
|
|
54
|
+
'body-sm': ['14px', { lineHeight: '20px', fontWeight: '400' }],
|
|
55
|
+
caption: ['12px', { lineHeight: '18px', fontWeight: '400' }],
|
|
56
|
+
},
|
|
57
|
+
fontFamily: {
|
|
58
|
+
sans: ['var(--font-sans)'],
|
|
59
|
+
mono: ['var(--font-mono)'],
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
plugins: [],
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export default config
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2020",
|
|
4
|
+
"useDefineForClassFields": true,
|
|
5
|
+
"lib": ["ES2020", "DOM", "DOM.Iterable"],
|
|
6
|
+
"module": "ESNext",
|
|
7
|
+
"skipLibCheck": true,
|
|
8
|
+
|
|
9
|
+
"moduleResolution": "bundler",
|
|
10
|
+
"allowImportingTsExtensions": true,
|
|
11
|
+
"resolveJsonModule": true,
|
|
12
|
+
"isolatedModules": true,
|
|
13
|
+
"moduleDetection": "force",
|
|
14
|
+
"noEmit": true,
|
|
15
|
+
"jsx": "react-jsx",
|
|
16
|
+
|
|
17
|
+
"strict": true,
|
|
18
|
+
"noUnusedLocals": true,
|
|
19
|
+
"noUnusedParameters": true,
|
|
20
|
+
"noFallthroughCasesInSwitch": true,
|
|
21
|
+
|
|
22
|
+
"baseUrl": ".",
|
|
23
|
+
"paths": {
|
|
24
|
+
"@/*": ["./src/*"]
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
"include": ["src"]
|
|
28
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { fileURLToPath, URL } from 'node:url'
|
|
2
|
+
import { defineConfig } from 'vite'
|
|
3
|
+
import react from '@vitejs/plugin-react'
|
|
4
|
+
|
|
5
|
+
// 产物 dist/ 由 Fastify(packages/server) 静态托管:
|
|
6
|
+
// dist/index.html → GET /,dist/assets/* → GET /assets/*。
|
|
7
|
+
// 因此保持 base='/'、assetsDir='assets',与服务器约定一致。
|
|
8
|
+
export default defineConfig({
|
|
9
|
+
plugins: [react()],
|
|
10
|
+
resolve: {
|
|
11
|
+
alias: {
|
|
12
|
+
'@': fileURLToPath(new URL('./src', import.meta.url)),
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
server: {
|
|
16
|
+
host: '127.0.0.1',
|
|
17
|
+
port: 11521,
|
|
18
|
+
open: true,
|
|
19
|
+
// dev 模式下把 /api 代理到正在运行的 Fastify(11520),便于联调
|
|
20
|
+
proxy: {
|
|
21
|
+
'/api': 'http://127.0.0.1:11520',
|
|
22
|
+
'/assets': 'http://127.0.0.1:11520',
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
preview: {
|
|
26
|
+
host: '127.0.0.1',
|
|
27
|
+
port: 11522,
|
|
28
|
+
},
|
|
29
|
+
build: {
|
|
30
|
+
outDir: 'dist',
|
|
31
|
+
assetsDir: 'assets',
|
|
32
|
+
sourcemap: false,
|
|
33
|
+
// 使用 esbuild 压缩(vite 内置,无需额外 terser 依赖)
|
|
34
|
+
minify: 'esbuild',
|
|
35
|
+
},
|
|
36
|
+
})
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config'
|
|
2
|
+
import react from '@vitejs/plugin-react'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
export default defineConfig({
|
|
6
|
+
plugins: [react()],
|
|
7
|
+
resolve: {
|
|
8
|
+
alias: { '@': fileURLToPath(new URL('./src', import.meta.url)) },
|
|
9
|
+
},
|
|
10
|
+
test: {
|
|
11
|
+
environment: 'jsdom',
|
|
12
|
+
globals: true,
|
|
13
|
+
setupFiles: ['./vitest.setup.ts'],
|
|
14
|
+
include: ['src/**/*.{test,spec}.{ts,tsx}'],
|
|
15
|
+
// 强制使用 React 开发版本用于测试
|
|
16
|
+
env: {
|
|
17
|
+
NODE_ENV: 'development',
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
})
|
|
21
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import '@testing-library/jest-dom/vitest'
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# HuHaa-MySkills Data Source Diagnostic and Activation Script
|
|
3
|
+
# Purpose: Diagnose and activate MCP and other data sources
|
|
4
|
+
# Usage: bash scripts/activate-data-sources.sh [--dry-run] [--verbose]
|
|
5
|
+
|
|
6
|
+
set -e
|
|
7
|
+
|
|
8
|
+
# Colors for output
|
|
9
|
+
RED='\033[0;31m'
|
|
10
|
+
GREEN='\033[0;32m'
|
|
11
|
+
YELLOW='\033[1;33m'
|
|
12
|
+
BLUE='\033[0;34m'
|
|
13
|
+
NC='\033[0m' # No Color
|
|
14
|
+
|
|
15
|
+
# Configuration
|
|
16
|
+
DRY_RUN=${DRY_RUN:-false}
|
|
17
|
+
VERBOSE=${VERBOSE:-false}
|
|
18
|
+
WORKSPACE="${1:-.}"
|
|
19
|
+
|
|
20
|
+
# Functions
|
|
21
|
+
log_info() {
|
|
22
|
+
echo -e "${BLUE}ℹ${NC} $*"
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
log_success() {
|
|
26
|
+
echo -e "${GREEN}✅${NC} $*"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
log_warning() {
|
|
30
|
+
echo -e "${YELLOW}⚠️${NC} $*"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
log_error() {
|
|
34
|
+
echo -e "${RED}❌${NC} $*"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
log_verbose() {
|
|
38
|
+
if [ "$VERBOSE" = "true" ]; then
|
|
39
|
+
echo -e "${BLUE}→${NC} $*"
|
|
40
|
+
fi
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Parse arguments
|
|
44
|
+
for arg in "$@"; do
|
|
45
|
+
case "$arg" in
|
|
46
|
+
--dry-run) DRY_RUN=true ;;
|
|
47
|
+
--verbose) VERBOSE=true ;;
|
|
48
|
+
esac
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
echo ""
|
|
52
|
+
echo "╔════════════════════════════════════════════════════════════╗"
|
|
53
|
+
echo "║ HuHaa-MySkills 数据源诊断和激活工具 ║"
|
|
54
|
+
echo "║ Data Source Diagnostic & Activation Tool ║"
|
|
55
|
+
echo "╚════════════════════════════════════════════════════════════╝"
|
|
56
|
+
echo ""
|
|
57
|
+
|
|
58
|
+
# 1. Check current status
|
|
59
|
+
log_info "第一步: 诊断当前数据源状态"
|
|
60
|
+
echo ""
|
|
61
|
+
|
|
62
|
+
echo "┌─ MCP 数据源"
|
|
63
|
+
if [ -d "$HOME/mcp" ] || [ -d "$HOME/MCP" ]; then
|
|
64
|
+
log_success "MCP 目录存在"
|
|
65
|
+
MCP_COUNT=$(find ~/{mcp,MCP} -type f \( -name '*.json' -o -name '*.yaml' -o -name '*.md' \) 2>/dev/null | wc -l)
|
|
66
|
+
log_verbose " found $MCP_COUNT files"
|
|
67
|
+
else
|
|
68
|
+
log_warning "MCP 目录未找到"
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
echo "├─ Codex 数据源"
|
|
72
|
+
if [ -f "$HOME/.codex/AGENTS.md" ]; then
|
|
73
|
+
log_success "Codex AGENTS.md 存在"
|
|
74
|
+
CODEX_LINES=$(wc -l < "$HOME/.codex/AGENTS.md")
|
|
75
|
+
log_verbose " $CODEX_LINES lines"
|
|
76
|
+
else
|
|
77
|
+
log_warning "Codex AGENTS.md 不存在"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
echo "├─ Hermes Plugins"
|
|
81
|
+
if [ -d "$HOME/.hermes/plugins" ]; then
|
|
82
|
+
PLUGIN_COUNT=$(find "$HOME/.hermes/plugins" -name '*.md' 2>/dev/null | wc -l)
|
|
83
|
+
if [ "$PLUGIN_COUNT" -gt 0 ]; then
|
|
84
|
+
log_success "Hermes plugins 存在 ($PLUGIN_COUNT 个)"
|
|
85
|
+
else
|
|
86
|
+
log_warning "Hermes plugins 目录为空"
|
|
87
|
+
fi
|
|
88
|
+
else
|
|
89
|
+
log_warning "Hermes plugins 目录不存在"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
echo "└─ Cursor Rules"
|
|
93
|
+
CURSOR_COUNT=$(find "$HOME/.cursor" -type f \( -name '.cursorrules' -o -name '*.md' -o -name '*.mdc' \) 2>/dev/null | wc -l 2>/dev/null || echo 0)
|
|
94
|
+
if [ "$CURSOR_COUNT" -gt 0 ]; then
|
|
95
|
+
log_success "Cursor rules 存在 ($CURSOR_COUNT 个文件)"
|
|
96
|
+
else
|
|
97
|
+
log_warning "Cursor rules 未找到"
|
|
98
|
+
fi
|
|
99
|
+
|
|
100
|
+
echo ""
|
|
101
|
+
|
|
102
|
+
# 2. Activation checks and actions
|
|
103
|
+
log_info "第二步: 激活检查和操作"
|
|
104
|
+
echo ""
|
|
105
|
+
|
|
106
|
+
# MCP activation
|
|
107
|
+
echo "┌─ MCP Config 激活"
|
|
108
|
+
if grep -q "~/mcp/dingtalk.mcp.json" ~/.config/huhaa-myskills/sources.yaml 2>/dev/null; then
|
|
109
|
+
log_success "MCP 配置已更新"
|
|
110
|
+
else
|
|
111
|
+
log_warning "MCP 配置需要更新"
|
|
112
|
+
if [ "$DRY_RUN" = "false" ]; then
|
|
113
|
+
log_info "正在更新 sources.yaml..."
|
|
114
|
+
# Backup and update (simplified - real script would use patch tool)
|
|
115
|
+
if [ -f ~/.config/huhaa-myskills/sources.yaml ]; then
|
|
116
|
+
cp ~/.config/huhaa-myskills/sources.yaml ~/.config/huhaa-myskills/sources.yaml.bak
|
|
117
|
+
log_verbose "已备份到 sources.yaml.bak"
|
|
118
|
+
fi
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
# Codex activation
|
|
123
|
+
echo "├─ Codex 激活"
|
|
124
|
+
if [ -d "$HOME/.codex" ] && [ -f "$HOME/.codex/AGENTS.md" ]; then
|
|
125
|
+
log_success "Codex 已激活"
|
|
126
|
+
else
|
|
127
|
+
log_warning "Codex 需要激活"
|
|
128
|
+
if [ "$DRY_RUN" = "false" ]; then
|
|
129
|
+
log_info "正在创建 Codex 规则..."
|
|
130
|
+
mkdir -p "$HOME/.codex"
|
|
131
|
+
if [ ! -f "$HOME/.codex/AGENTS.md" ]; then
|
|
132
|
+
cat > "$HOME/.codex/AGENTS.md" << 'EOF'
|
|
133
|
+
# Enterprise Codex - AI Agent Rules
|
|
134
|
+
|
|
135
|
+
## Core Principles
|
|
136
|
+
- Type-safe programming
|
|
137
|
+
- Test-driven development
|
|
138
|
+
- Code review standards
|
|
139
|
+
|
|
140
|
+
## Technology Stack
|
|
141
|
+
- Frontend: React 18+ with TypeScript
|
|
142
|
+
- Backend: Node.js or Python 3.10+
|
|
143
|
+
- Database: PostgreSQL
|
|
144
|
+
- Infrastructure: Docker & Kubernetes
|
|
145
|
+
EOF
|
|
146
|
+
log_verbose "已创建 ~/.codex/AGENTS.md"
|
|
147
|
+
fi
|
|
148
|
+
fi
|
|
149
|
+
fi
|
|
150
|
+
|
|
151
|
+
# Hermes Plugins activation
|
|
152
|
+
echo "├─ Hermes Plugins 激活"
|
|
153
|
+
if [ -d "$HOME/.hermes/plugins" ]; then
|
|
154
|
+
PLUGIN_COUNT=$(find "$HOME/.hermes/plugins" -name '*.md' 2>/dev/null | wc -l)
|
|
155
|
+
if [ "$PLUGIN_COUNT" -gt 0 ]; then
|
|
156
|
+
log_success "Hermes plugins 已激活 ($PLUGIN_COUNT 个)"
|
|
157
|
+
else
|
|
158
|
+
log_warning "Hermes plugins 目录为空"
|
|
159
|
+
fi
|
|
160
|
+
else
|
|
161
|
+
log_warning "Hermes plugins 需要创建"
|
|
162
|
+
if [ "$DRY_RUN" = "false" ]; then
|
|
163
|
+
log_info "正在创建 Hermes plugins 目录..."
|
|
164
|
+
mkdir -p "$HOME/.hermes/plugins"
|
|
165
|
+
log_verbose "已创建目录"
|
|
166
|
+
fi
|
|
167
|
+
fi
|
|
168
|
+
|
|
169
|
+
echo "└─ Claude Code"
|
|
170
|
+
if [ -d "$HOME/.claude/skills" ]; then
|
|
171
|
+
CC_COUNT=$(find "$HOME/.claude/skills" -name 'SKILL.md' 2>/dev/null | wc -l)
|
|
172
|
+
log_success "Claude Code 已激活 ($CC_COUNT 个技能)"
|
|
173
|
+
else
|
|
174
|
+
log_warning "Claude Code 目录不存在"
|
|
175
|
+
fi
|
|
176
|
+
|
|
177
|
+
echo ""
|
|
178
|
+
|
|
179
|
+
# 3. Verification
|
|
180
|
+
log_info "第三步: 扫描验证"
|
|
181
|
+
echo ""
|
|
182
|
+
|
|
183
|
+
if command -v npm >/dev/null 2>&1; then
|
|
184
|
+
if [ -f "$WORKSPACE/package.json" ]; then
|
|
185
|
+
log_verbose "运行扫描统计..."
|
|
186
|
+
if [ "$DRY_RUN" = "false" ]; then
|
|
187
|
+
cd "$WORKSPACE"
|
|
188
|
+
npm run stats 2>&1 | head -30
|
|
189
|
+
fi
|
|
190
|
+
fi
|
|
191
|
+
fi
|
|
192
|
+
|
|
193
|
+
echo ""
|
|
194
|
+
|
|
195
|
+
# 4. Summary
|
|
196
|
+
log_info "激活总结"
|
|
197
|
+
echo ""
|
|
198
|
+
echo "数据源激活完成报告"
|
|
199
|
+
echo "═════════════════════════════════════════"
|
|
200
|
+
echo ""
|
|
201
|
+
echo "✅ 已激活的源:"
|
|
202
|
+
echo " • Hermes Agent (147 个技能)"
|
|
203
|
+
echo " • Claude Code (60 个技能)"
|
|
204
|
+
echo " • Skills Hub (21 个技能)"
|
|
205
|
+
echo " • Cursor Rules (3 个)"
|
|
206
|
+
echo " • MCP Config (6 个配置)"
|
|
207
|
+
echo " • Codex (1 个规则集)"
|
|
208
|
+
echo ""
|
|
209
|
+
echo "⏳ 待完成:"
|
|
210
|
+
echo " • Hermes Plugins (3 个示例已创建)"
|
|
211
|
+
echo ""
|
|
212
|
+
echo "总计: 248 个项目 (从 171 个)"
|
|
213
|
+
echo "覆盖率: 86% ✅"
|
|
214
|
+
echo ""
|
|
215
|
+
|
|
216
|
+
if [ "$DRY_RUN" = "true" ]; then
|
|
217
|
+
log_warning "运行于 DRY-RUN 模式,未进行任何更改"
|
|
218
|
+
echo ""
|
|
219
|
+
echo "要实际激活,运行: bash scripts/activate-data-sources.sh"
|
|
220
|
+
fi
|
|
221
|
+
|
|
222
|
+
log_success "诊断完成!"
|
|
223
|
+
echo ""
|