@skillmark/cli 0.1.0

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.
Files changed (101) hide show
  1. package/dist/cli-entry-point.d.ts +3 -0
  2. package/dist/cli-entry-point.d.ts.map +1 -0
  3. package/dist/cli-entry-point.js +207 -0
  4. package/dist/cli-entry-point.js.map +1 -0
  5. package/dist/commands/auth-setup-and-token-storage-command.d.ts +21 -0
  6. package/dist/commands/auth-setup-and-token-storage-command.d.ts.map +1 -0
  7. package/dist/commands/auth-setup-and-token-storage-command.js +166 -0
  8. package/dist/commands/auth-setup-and-token-storage-command.js.map +1 -0
  9. package/dist/commands/publish-results-command.d.ts +21 -0
  10. package/dist/commands/publish-results-command.d.ts.map +1 -0
  11. package/dist/commands/publish-results-command.js +256 -0
  12. package/dist/commands/publish-results-command.js.map +1 -0
  13. package/dist/commands/run-benchmark-command.d.ts +6 -0
  14. package/dist/commands/run-benchmark-command.d.ts.map +1 -0
  15. package/dist/commands/run-benchmark-command.js +331 -0
  16. package/dist/commands/run-benchmark-command.js.map +1 -0
  17. package/dist/commands/view-leaderboard-command.d.ts +8 -0
  18. package/dist/commands/view-leaderboard-command.d.ts.map +1 -0
  19. package/dist/commands/view-leaderboard-command.js +169 -0
  20. package/dist/commands/view-leaderboard-command.js.map +1 -0
  21. package/dist/config/api-key-config-reader.d.ts +14 -0
  22. package/dist/config/api-key-config-reader.d.ts.map +1 -0
  23. package/dist/config/api-key-config-reader.js +107 -0
  24. package/dist/config/api-key-config-reader.js.map +1 -0
  25. package/dist/config/api-key-config-reader.test.d.ts +2 -0
  26. package/dist/config/api-key-config-reader.test.d.ts.map +1 -0
  27. package/dist/config/api-key-config-reader.test.js +21 -0
  28. package/dist/config/api-key-config-reader.test.js.map +1 -0
  29. package/dist/engine/claude-cli-executor.d.ts +33 -0
  30. package/dist/engine/claude-cli-executor.d.ts.map +1 -0
  31. package/dist/engine/claude-cli-executor.js +251 -0
  32. package/dist/engine/claude-cli-executor.js.map +1 -0
  33. package/dist/engine/concept-accuracy-scorer.d.ts +24 -0
  34. package/dist/engine/concept-accuracy-scorer.d.ts.map +1 -0
  35. package/dist/engine/concept-accuracy-scorer.js +186 -0
  36. package/dist/engine/concept-accuracy-scorer.js.map +1 -0
  37. package/dist/engine/concept-accuracy-scorer.test.d.ts +2 -0
  38. package/dist/engine/concept-accuracy-scorer.test.d.ts.map +1 -0
  39. package/dist/engine/concept-accuracy-scorer.test.js +230 -0
  40. package/dist/engine/concept-accuracy-scorer.test.js.map +1 -0
  41. package/dist/engine/enhanced-test-prompt-builder.d.ts +30 -0
  42. package/dist/engine/enhanced-test-prompt-builder.d.ts.map +1 -0
  43. package/dist/engine/enhanced-test-prompt-builder.js +134 -0
  44. package/dist/engine/enhanced-test-prompt-builder.js.map +1 -0
  45. package/dist/engine/markdown-test-definition-parser.d.ts +18 -0
  46. package/dist/engine/markdown-test-definition-parser.d.ts.map +1 -0
  47. package/dist/engine/markdown-test-definition-parser.js +525 -0
  48. package/dist/engine/markdown-test-definition-parser.js.map +1 -0
  49. package/dist/engine/markdown-test-definition-parser.test.d.ts +2 -0
  50. package/dist/engine/markdown-test-definition-parser.test.d.ts.map +1 -0
  51. package/dist/engine/markdown-test-definition-parser.test.js +265 -0
  52. package/dist/engine/markdown-test-definition-parser.test.js.map +1 -0
  53. package/dist/engine/retry-with-degrade-utils.d.ts +58 -0
  54. package/dist/engine/retry-with-degrade-utils.d.ts.map +1 -0
  55. package/dist/engine/retry-with-degrade-utils.js +86 -0
  56. package/dist/engine/retry-with-degrade-utils.js.map +1 -0
  57. package/dist/engine/skill-content-collector.d.ts +53 -0
  58. package/dist/engine/skill-content-collector.d.ts.map +1 -0
  59. package/dist/engine/skill-content-collector.js +157 -0
  60. package/dist/engine/skill-content-collector.js.map +1 -0
  61. package/dist/engine/skill-creator-invoker.d.ts +36 -0
  62. package/dist/engine/skill-creator-invoker.d.ts.map +1 -0
  63. package/dist/engine/skill-creator-invoker.js +222 -0
  64. package/dist/engine/skill-creator-invoker.js.map +1 -0
  65. package/dist/engine/transcript-jsonl-parser.d.ts +28 -0
  66. package/dist/engine/transcript-jsonl-parser.d.ts.map +1 -0
  67. package/dist/engine/transcript-jsonl-parser.js +175 -0
  68. package/dist/engine/transcript-jsonl-parser.js.map +1 -0
  69. package/dist/sources/git-repository-skill-source-handler.d.ts +18 -0
  70. package/dist/sources/git-repository-skill-source-handler.d.ts.map +1 -0
  71. package/dist/sources/git-repository-skill-source-handler.js +119 -0
  72. package/dist/sources/git-repository-skill-source-handler.js.map +1 -0
  73. package/dist/sources/local-skill-source-handler.d.ts +21 -0
  74. package/dist/sources/local-skill-source-handler.d.ts.map +1 -0
  75. package/dist/sources/local-skill-source-handler.js +138 -0
  76. package/dist/sources/local-skill-source-handler.js.map +1 -0
  77. package/dist/sources/local-skill-source-handler.test.d.ts +2 -0
  78. package/dist/sources/local-skill-source-handler.test.d.ts.map +1 -0
  79. package/dist/sources/local-skill-source-handler.test.js +55 -0
  80. package/dist/sources/local-skill-source-handler.test.js.map +1 -0
  81. package/dist/sources/skillsh-registry-source-handler.d.ts +18 -0
  82. package/dist/sources/skillsh-registry-source-handler.d.ts.map +1 -0
  83. package/dist/sources/skillsh-registry-source-handler.js +130 -0
  84. package/dist/sources/skillsh-registry-source-handler.js.map +1 -0
  85. package/dist/sources/unified-skill-source-resolver.d.ts +20 -0
  86. package/dist/sources/unified-skill-source-resolver.d.ts.map +1 -0
  87. package/dist/sources/unified-skill-source-resolver.js +64 -0
  88. package/dist/sources/unified-skill-source-resolver.js.map +1 -0
  89. package/dist/sources/unified-skill-source-resolver.test.d.ts +2 -0
  90. package/dist/sources/unified-skill-source-resolver.test.d.ts.map +1 -0
  91. package/dist/sources/unified-skill-source-resolver.test.js +84 -0
  92. package/dist/sources/unified-skill-source-resolver.test.js.map +1 -0
  93. package/dist/types/benchmark-types.d.ts +142 -0
  94. package/dist/types/benchmark-types.d.ts.map +1 -0
  95. package/dist/types/benchmark-types.js +5 -0
  96. package/dist/types/benchmark-types.js.map +1 -0
  97. package/dist/types/index.d.ts +5 -0
  98. package/dist/types/index.d.ts.map +1 -0
  99. package/dist/types/index.js +5 -0
  100. package/dist/types/index.js.map +1 -0
  101. package/package.json +38 -0
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Local skill source handler - loads skills from local filesystem paths
3
+ */
4
+ import { access, readdir, readFile, stat } from 'node:fs/promises';
5
+ import { basename, join, resolve } from 'node:path';
6
+ /** Files that indicate a skill directory */
7
+ const SKILL_INDICATORS = ['SKILL.md', 'skill.md', 'README.md', 'index.ts', 'index.js'];
8
+ /**
9
+ * Check if a path is a local skill source
10
+ */
11
+ export function isLocalSource(source) {
12
+ // Local paths start with /, ./, ../, or are just directory names
13
+ return (source.startsWith('/') ||
14
+ source.startsWith('./') ||
15
+ source.startsWith('../') ||
16
+ source.startsWith('~') ||
17
+ (!source.includes('://') && !source.includes('/') && !source.startsWith('skill.sh')));
18
+ }
19
+ /**
20
+ * Resolve a local skill source
21
+ */
22
+ export async function resolveLocalSource(source) {
23
+ // Expand ~ to home directory
24
+ let resolvedPath = source;
25
+ if (source.startsWith('~')) {
26
+ const home = process.env.HOME || process.env.USERPROFILE || '';
27
+ resolvedPath = source.replace('~', home);
28
+ }
29
+ // Make absolute
30
+ resolvedPath = resolve(resolvedPath);
31
+ // Verify path exists
32
+ try {
33
+ await access(resolvedPath);
34
+ }
35
+ catch {
36
+ throw new Error(`Skill path not found: ${source}`);
37
+ }
38
+ // Check if it's a directory or file
39
+ const stats = await stat(resolvedPath);
40
+ if (stats.isFile()) {
41
+ // Single file skill (e.g., SKILL.md)
42
+ return {
43
+ type: 'local',
44
+ original: source,
45
+ localPath: resolvedPath,
46
+ name: extractSkillName(resolvedPath),
47
+ };
48
+ }
49
+ if (stats.isDirectory()) {
50
+ // Validate it looks like a skill directory
51
+ const isValid = await validateSkillDirectory(resolvedPath);
52
+ if (!isValid) {
53
+ throw new Error(`Directory does not appear to be a skill: ${source}\n` +
54
+ `Expected one of: ${SKILL_INDICATORS.join(', ')}`);
55
+ }
56
+ return {
57
+ type: 'local',
58
+ original: source,
59
+ localPath: resolvedPath,
60
+ name: extractSkillName(resolvedPath),
61
+ };
62
+ }
63
+ throw new Error(`Invalid skill path (not a file or directory): ${source}`);
64
+ }
65
+ /**
66
+ * Validate that a directory contains skill files
67
+ */
68
+ async function validateSkillDirectory(dirPath) {
69
+ try {
70
+ const files = await readdir(dirPath);
71
+ return SKILL_INDICATORS.some((indicator) => files.some((f) => f.toLowerCase() === indicator.toLowerCase()));
72
+ }
73
+ catch {
74
+ return false;
75
+ }
76
+ }
77
+ /**
78
+ * Extract skill name from path
79
+ */
80
+ function extractSkillName(skillPath) {
81
+ const base = basename(skillPath);
82
+ // If it's a file, use parent directory name
83
+ if (base.includes('.')) {
84
+ const parentDir = basename(resolve(skillPath, '..'));
85
+ return parentDir;
86
+ }
87
+ return base;
88
+ }
89
+ /**
90
+ * Find test files in a skill directory
91
+ */
92
+ export async function findTestsInSkillDir(skillPath) {
93
+ const testsDir = join(skillPath, 'tests');
94
+ try {
95
+ await access(testsDir);
96
+ const files = await readdir(testsDir);
97
+ return files
98
+ .filter((f) => f.endsWith('.md'))
99
+ .map((f) => join(testsDir, f));
100
+ }
101
+ catch {
102
+ // No tests directory, look for test files in root
103
+ try {
104
+ const files = await readdir(skillPath);
105
+ return files
106
+ .filter((f) => f.endsWith('.test.md') || f.startsWith('test-'))
107
+ .map((f) => join(skillPath, f));
108
+ }
109
+ catch {
110
+ return [];
111
+ }
112
+ }
113
+ }
114
+ /**
115
+ * Read skill metadata from SKILL.md or README.md
116
+ */
117
+ export async function readSkillMetadata(skillPath) {
118
+ const stats = await stat(skillPath);
119
+ const dir = stats.isDirectory() ? skillPath : resolve(skillPath, '..');
120
+ for (const filename of ['SKILL.md', 'skill.md', 'README.md']) {
121
+ const filePath = join(dir, filename);
122
+ try {
123
+ const content = await readFile(filePath, 'utf-8');
124
+ // Extract name from first heading
125
+ const nameMatch = content.match(/^#\s+(.+)$/m);
126
+ const name = nameMatch ? nameMatch[1].trim() : basename(dir);
127
+ // Extract description from first paragraph after heading
128
+ const descMatch = content.match(/^#.+\n\n(.+?)(?:\n\n|$)/s);
129
+ const description = descMatch ? descMatch[1].trim() : '';
130
+ return { name, description };
131
+ }
132
+ catch {
133
+ continue;
134
+ }
135
+ }
136
+ return null;
137
+ }
138
+ //# sourceMappingURL=local-skill-source-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-skill-source-handler.js","sourceRoot":"","sources":["../../src/sources/local-skill-source-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=local-skill-source-handler.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-skill-source-handler.test.d.ts","sourceRoot":"","sources":["../../src/sources/local-skill-source-handler.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Tests for local-skill-source-handler.ts
3
+ * Verifies local path detection and validation
4
+ */
5
+ import { describe, it, expect } from 'vitest';
6
+ import { isLocalSource } from './local-skill-source-handler.js';
7
+ describe('isLocalSource', () => {
8
+ describe('absolute paths', () => {
9
+ it('returns true for paths starting with /', () => {
10
+ expect(isLocalSource('/Users/me/skill')).toBe(true);
11
+ expect(isLocalSource('/home/user/.claude/skills/test')).toBe(true);
12
+ expect(isLocalSource('/')).toBe(true);
13
+ });
14
+ });
15
+ describe('relative paths', () => {
16
+ it('returns true for paths starting with ./', () => {
17
+ expect(isLocalSource('./skill')).toBe(true);
18
+ expect(isLocalSource('./path/to/skill')).toBe(true);
19
+ });
20
+ it('returns true for paths starting with ../', () => {
21
+ expect(isLocalSource('../skill')).toBe(true);
22
+ expect(isLocalSource('../../skills/test')).toBe(true);
23
+ });
24
+ });
25
+ describe('home directory paths', () => {
26
+ it('returns true for paths starting with ~', () => {
27
+ expect(isLocalSource('~/.claude/skills/my-skill')).toBe(true);
28
+ expect(isLocalSource('~/skills')).toBe(true);
29
+ });
30
+ });
31
+ describe('simple directory names', () => {
32
+ it('returns true for names without slashes or protocols', () => {
33
+ expect(isLocalSource('my-skill')).toBe(true);
34
+ expect(isLocalSource('test-skill-v2')).toBe(true);
35
+ expect(isLocalSource('skill_name')).toBe(true);
36
+ });
37
+ });
38
+ describe('non-local sources', () => {
39
+ it('returns false for URLs with protocol', () => {
40
+ expect(isLocalSource('https://github.com/user/repo')).toBe(false);
41
+ expect(isLocalSource('git://github.com/user/repo')).toBe(false);
42
+ expect(isLocalSource('http://example.com/skill')).toBe(false);
43
+ });
44
+ it('returns false for skill.sh references', () => {
45
+ expect(isLocalSource('skill.sh/user/my-skill')).toBe(false);
46
+ expect(isLocalSource('skill.sh/org/test')).toBe(false);
47
+ });
48
+ it('returns false for paths with slashes that look like org/repo', () => {
49
+ // These are treated as potential git shorthand (user/repo)
50
+ expect(isLocalSource('user/repo')).toBe(false);
51
+ expect(isLocalSource('org/skill-name')).toBe(false);
52
+ });
53
+ });
54
+ });
55
+ //# sourceMappingURL=local-skill-source-handler.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-skill-source-handler.test.js","sourceRoot":"","sources":["../../src/sources/local-skill-source-handler.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { SkillSource } from '../types/index.js';
2
+ /**
3
+ * Check if a source is a skill.sh reference
4
+ */
5
+ export declare function isSkillshSource(source: string): boolean;
6
+ /**
7
+ * Resolve a skill.sh source by downloading the skill
8
+ */
9
+ export declare function resolveSkillshSource(source: string): Promise<SkillSource>;
10
+ /**
11
+ * List available skills from a user on skill.sh
12
+ */
13
+ export declare function listUserSkills(user: string): Promise<string[]>;
14
+ /**
15
+ * Clean up skill.sh cache
16
+ */
17
+ export declare function cleanSkillshCache(): Promise<void>;
18
+ //# sourceMappingURL=skillsh-registry-source-handler.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillsh-registry-source-handler.d.ts","sourceRoot":"","sources":["../../src/sources/skillsh-registry-source-handler.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAerD;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAEvD;AAyBD;;GAEG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA4C/E;AA8BD;;GAEG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAcpE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * skill.sh registry source handler - downloads skills from skill.sh registry
3
+ */
4
+ import { mkdir, rm, writeFile } from 'node:fs/promises';
5
+ import { join } from 'node:path';
6
+ /** skill.sh URL patterns */
7
+ const SKILLSH_PATTERNS = [
8
+ /^skill\.sh\//,
9
+ /^https?:\/\/skill\.sh\//,
10
+ /^skillsh:/,
11
+ ];
12
+ /** Cache directory for skill.sh downloads */
13
+ const CACHE_DIR = join(process.env.HOME || '/tmp', '.skillmark', 'skillsh-cache');
14
+ /** skill.sh API base URL */
15
+ const SKILLSH_API = 'https://skill.sh/api';
16
+ /**
17
+ * Check if a source is a skill.sh reference
18
+ */
19
+ export function isSkillshSource(source) {
20
+ return SKILLSH_PATTERNS.some((pattern) => pattern.test(source));
21
+ }
22
+ /**
23
+ * Parse skill.sh reference to get user and skill name
24
+ */
25
+ function parseSkillshRef(source) {
26
+ // Remove prefix
27
+ let cleaned = source
28
+ .replace(/^skill\.sh\//, '')
29
+ .replace(/^https?:\/\/skill\.sh\//, '')
30
+ .replace(/^skillsh:/, '');
31
+ // Parse user/name@version format
32
+ const versionMatch = cleaned.match(/^(.+)@(.+)$/);
33
+ if (versionMatch) {
34
+ cleaned = versionMatch[1];
35
+ const version = versionMatch[2];
36
+ const [user, name] = cleaned.split('/');
37
+ return { user, name, version };
38
+ }
39
+ const [user, name] = cleaned.split('/');
40
+ return { user, name };
41
+ }
42
+ /**
43
+ * Resolve a skill.sh source by downloading the skill
44
+ */
45
+ export async function resolveSkillshSource(source) {
46
+ const { user, name, version } = parseSkillshRef(source);
47
+ const cacheId = version ? `${user}-${name}-${version}` : `${user}-${name}`;
48
+ const localPath = join(CACHE_DIR, cacheId);
49
+ await mkdir(CACHE_DIR, { recursive: true });
50
+ try {
51
+ // Try to fetch from skill.sh API
52
+ const skillContent = await fetchSkillFromRegistry(user, name, version);
53
+ // Write to cache
54
+ await rm(localPath, { recursive: true, force: true });
55
+ await mkdir(localPath, { recursive: true });
56
+ // Write SKILL.md
57
+ await writeFile(join(localPath, 'SKILL.md'), skillContent);
58
+ return {
59
+ type: 'skillsh',
60
+ original: source,
61
+ localPath,
62
+ name: `${user}/${name}`,
63
+ };
64
+ }
65
+ catch (error) {
66
+ // Fallback: try to clone from GitHub if skill.sh API fails
67
+ // Many skill.sh skills are hosted on GitHub
68
+ const githubUrl = `https://github.com/${user}/${name}`;
69
+ try {
70
+ const { resolveGitSource } = await import('./git-repository-skill-source-handler.js');
71
+ const gitSource = await resolveGitSource(githubUrl);
72
+ return {
73
+ ...gitSource,
74
+ type: 'skillsh',
75
+ original: source,
76
+ };
77
+ }
78
+ catch {
79
+ throw new Error(`Failed to fetch skill from skill.sh: ${source}\n` +
80
+ `Error: ${error instanceof Error ? error.message : String(error)}`);
81
+ }
82
+ }
83
+ }
84
+ /**
85
+ * Fetch skill content from skill.sh registry
86
+ */
87
+ async function fetchSkillFromRegistry(user, name, version) {
88
+ const url = version
89
+ ? `${SKILLSH_API}/skills/${user}/${name}/versions/${version}`
90
+ : `${SKILLSH_API}/skills/${user}/${name}/latest`;
91
+ const response = await fetch(url);
92
+ if (!response.ok) {
93
+ throw new Error(`skill.sh API returned ${response.status}: ${response.statusText}`);
94
+ }
95
+ const data = (await response.json());
96
+ const content = data.content || data.skill?.content;
97
+ if (!content) {
98
+ throw new Error('No skill content found in response');
99
+ }
100
+ return content;
101
+ }
102
+ /**
103
+ * List available skills from a user on skill.sh
104
+ */
105
+ export async function listUserSkills(user) {
106
+ const url = `${SKILLSH_API}/users/${user}/skills`;
107
+ try {
108
+ const response = await fetch(url);
109
+ if (!response.ok) {
110
+ return [];
111
+ }
112
+ const data = (await response.json());
113
+ return data.skills?.map((s) => s.name) || [];
114
+ }
115
+ catch {
116
+ return [];
117
+ }
118
+ }
119
+ /**
120
+ * Clean up skill.sh cache
121
+ */
122
+ export async function cleanSkillshCache() {
123
+ try {
124
+ await rm(CACHE_DIR, { recursive: true, force: true });
125
+ }
126
+ catch {
127
+ // Ignore errors
128
+ }
129
+ }
130
+ //# sourceMappingURL=skillsh-registry-source-handler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skillsh-registry-source-handler.js","sourceRoot":"","sources":["../../src/sources/skillsh-registry-source-handler.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Unified skill source resolver - routes to appropriate handler based on source type
3
+ */
4
+ import type { SkillSource } from '../types/index.js';
5
+ /**
6
+ * Detect source type from input string
7
+ */
8
+ export declare function detectSourceType(source: string): 'local' | 'git' | 'skillsh' | 'unknown';
9
+ /**
10
+ * Resolve any skill source to a local path
11
+ */
12
+ export declare function resolveSkillSource(source: string): Promise<SkillSource>;
13
+ /**
14
+ * Format source for display
15
+ */
16
+ export declare function formatSourceDisplay(source: SkillSource): string;
17
+ export { isLocalSource, resolveLocalSource } from './local-skill-source-handler.js';
18
+ export { isGitSource, resolveGitSource, cleanGitCache } from './git-repository-skill-source-handler.js';
19
+ export { isSkillshSource, resolveSkillshSource, cleanSkillshCache } from './skillsh-registry-source-handler.js';
20
+ //# sourceMappingURL=unified-skill-source-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-skill-source-resolver.d.ts","sourceRoot":"","sources":["../../src/sources/unified-skill-source-resolver.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAKrD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,GAAG,KAAK,GAAG,SAAS,GAAG,SAAS,CAKxF;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA6B7E;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAW/D;AAGD,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC"}
@@ -0,0 +1,64 @@
1
+ import { isLocalSource, resolveLocalSource } from './local-skill-source-handler.js';
2
+ import { isGitSource, resolveGitSource } from './git-repository-skill-source-handler.js';
3
+ import { isSkillshSource, resolveSkillshSource } from './skillsh-registry-source-handler.js';
4
+ /**
5
+ * Detect source type from input string
6
+ */
7
+ export function detectSourceType(source) {
8
+ if (isSkillshSource(source))
9
+ return 'skillsh';
10
+ if (isGitSource(source))
11
+ return 'git';
12
+ if (isLocalSource(source))
13
+ return 'local';
14
+ return 'unknown';
15
+ }
16
+ /**
17
+ * Resolve any skill source to a local path
18
+ */
19
+ export async function resolveSkillSource(source) {
20
+ const sourceType = detectSourceType(source);
21
+ switch (sourceType) {
22
+ case 'local':
23
+ return resolveLocalSource(source);
24
+ case 'git':
25
+ return resolveGitSource(source);
26
+ case 'skillsh':
27
+ return resolveSkillshSource(source);
28
+ case 'unknown':
29
+ default:
30
+ // Try local first, then git
31
+ try {
32
+ return await resolveLocalSource(source);
33
+ }
34
+ catch {
35
+ try {
36
+ return await resolveGitSource(`https://github.com/${source}`);
37
+ }
38
+ catch {
39
+ throw new Error(`Unable to resolve skill source: ${source}\n` +
40
+ 'Expected: local path, git URL, or skill.sh reference');
41
+ }
42
+ }
43
+ }
44
+ }
45
+ /**
46
+ * Format source for display
47
+ */
48
+ export function formatSourceDisplay(source) {
49
+ switch (source.type) {
50
+ case 'local':
51
+ return `Local: ${source.localPath}`;
52
+ case 'git':
53
+ return `Git: ${source.original}`;
54
+ case 'skillsh':
55
+ return `skill.sh: ${source.original}`;
56
+ default:
57
+ return source.original;
58
+ }
59
+ }
60
+ // Re-export individual handlers for direct use
61
+ export { isLocalSource, resolveLocalSource } from './local-skill-source-handler.js';
62
+ export { isGitSource, resolveGitSource, cleanGitCache } from './git-repository-skill-source-handler.js';
63
+ export { isSkillshSource, resolveSkillshSource, cleanSkillshCache } from './skillsh-registry-source-handler.js';
64
+ //# sourceMappingURL=unified-skill-source-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-skill-source-resolver.js","sourceRoot":"","sources":["../../src/sources/unified-skill-source-resolver.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AACzF,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AAE7F;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAc;IAC7C,IAAI,eAAe,CAAC,MAAM,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9C,IAAI,WAAW,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IACtC,IAAI,aAAa,CAAC,MAAM,CAAC;QAAE,OAAO,OAAO,CAAC;IAC1C,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,MAAc;IACrD,MAAM,UAAU,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAE5C,QAAQ,UAAU,EAAE,CAAC;QACnB,KAAK,OAAO;YACV,OAAO,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAEpC,KAAK,KAAK;YACR,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAC;QAElC,KAAK,SAAS;YACZ,OAAO,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAEtC,KAAK,SAAS,CAAC;QACf;YACE,4BAA4B;YAC5B,IAAI,CAAC;gBACH,OAAO,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,CAAC;oBACH,OAAO,MAAM,gBAAgB,CAAC,sBAAsB,MAAM,EAAE,CAAC,CAAC;gBAChE,CAAC;gBAAC,MAAM,CAAC;oBACP,MAAM,IAAI,KAAK,CACb,mCAAmC,MAAM,IAAI;wBAC3C,sDAAsD,CACzD,CAAC;gBACJ,CAAC;YACH,CAAC;IACL,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAmB;IACrD,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,OAAO;YACV,OAAO,UAAU,MAAM,CAAC,SAAS,EAAE,CAAC;QACtC,KAAK,KAAK;YACR,OAAO,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;QACnC,KAAK,SAAS;YACZ,OAAO,aAAa,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxC;YACE,OAAO,MAAM,CAAC,QAAQ,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,+CAA+C;AAC/C,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,0CAA0C,CAAC;AACxG,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=unified-skill-source-resolver.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-skill-source-resolver.test.d.ts","sourceRoot":"","sources":["../../src/sources/unified-skill-source-resolver.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Tests for unified-skill-source-resolver.ts
3
+ * Verifies source type detection and routing logic
4
+ */
5
+ import { describe, it, expect } from 'vitest';
6
+ import { detectSourceType, formatSourceDisplay } from './unified-skill-source-resolver.js';
7
+ describe('detectSourceType', () => {
8
+ describe('local sources', () => {
9
+ it('detects absolute paths starting with /', () => {
10
+ expect(detectSourceType('/Users/me/skills/my-skill')).toBe('local');
11
+ expect(detectSourceType('/home/user/.claude/skills/test')).toBe('local');
12
+ });
13
+ it('detects relative paths starting with ./', () => {
14
+ expect(detectSourceType('./my-skill')).toBe('local');
15
+ expect(detectSourceType('./path/to/skill')).toBe('local');
16
+ });
17
+ it('detects parent relative paths starting with ../', () => {
18
+ expect(detectSourceType('../my-skill')).toBe('local');
19
+ expect(detectSourceType('../../skills/test')).toBe('local');
20
+ });
21
+ it('detects home directory paths starting with ~', () => {
22
+ expect(detectSourceType('~/.claude/skills/my-skill')).toBe('local');
23
+ expect(detectSourceType('~/skills/test')).toBe('local');
24
+ });
25
+ it('detects simple directory names without slashes', () => {
26
+ expect(detectSourceType('my-skill')).toBe('local');
27
+ expect(detectSourceType('test-skill-v2')).toBe('local');
28
+ });
29
+ });
30
+ describe('git sources', () => {
31
+ it('detects https:// git URLs', () => {
32
+ expect(detectSourceType('https://github.com/user/repo')).toBe('git');
33
+ expect(detectSourceType('https://gitlab.com/user/repo.git')).toBe('git');
34
+ });
35
+ it('detects git:// protocol URLs', () => {
36
+ expect(detectSourceType('git://github.com/user/repo')).toBe('git');
37
+ });
38
+ it('detects SSH git URLs', () => {
39
+ expect(detectSourceType('git@github.com:user/repo.git')).toBe('git');
40
+ });
41
+ });
42
+ describe('skill.sh sources', () => {
43
+ it('detects skill.sh/ prefixed references', () => {
44
+ expect(detectSourceType('skill.sh/user/my-skill')).toBe('skillsh');
45
+ expect(detectSourceType('skill.sh/org/advanced-skill')).toBe('skillsh');
46
+ });
47
+ });
48
+ describe('unknown sources', () => {
49
+ it('returns unknown for unrecognized patterns', () => {
50
+ // Note: This case is handled by fallback logic in resolveSkillSource
51
+ // detectSourceType may classify some edge cases differently
52
+ });
53
+ });
54
+ });
55
+ describe('formatSourceDisplay', () => {
56
+ it('formats local source correctly', () => {
57
+ const source = {
58
+ type: 'local',
59
+ original: './my-skill',
60
+ localPath: '/Users/me/projects/my-skill',
61
+ name: 'my-skill',
62
+ };
63
+ expect(formatSourceDisplay(source)).toBe('Local: /Users/me/projects/my-skill');
64
+ });
65
+ it('formats git source correctly', () => {
66
+ const source = {
67
+ type: 'git',
68
+ original: 'https://github.com/user/skill-repo',
69
+ localPath: '/tmp/skillmark-cache/skill-repo',
70
+ name: 'skill-repo',
71
+ };
72
+ expect(formatSourceDisplay(source)).toBe('Git: https://github.com/user/skill-repo');
73
+ });
74
+ it('formats skill.sh source correctly', () => {
75
+ const source = {
76
+ type: 'skillsh',
77
+ original: 'skill.sh/user/my-skill',
78
+ localPath: '/tmp/skillmark-cache/my-skill',
79
+ name: 'my-skill',
80
+ };
81
+ expect(formatSourceDisplay(source)).toBe('skill.sh: skill.sh/user/my-skill');
82
+ });
83
+ });
84
+ //# sourceMappingURL=unified-skill-source-resolver.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unified-skill-source-resolver.test.js","sourceRoot":"","sources":["../../src/sources/unified-skill-source-resolver.test.ts"],"names":[],"mappings":"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"}