@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.
- package/dist/cli-entry-point.d.ts +3 -0
- package/dist/cli-entry-point.d.ts.map +1 -0
- package/dist/cli-entry-point.js +207 -0
- package/dist/cli-entry-point.js.map +1 -0
- package/dist/commands/auth-setup-and-token-storage-command.d.ts +21 -0
- package/dist/commands/auth-setup-and-token-storage-command.d.ts.map +1 -0
- package/dist/commands/auth-setup-and-token-storage-command.js +166 -0
- package/dist/commands/auth-setup-and-token-storage-command.js.map +1 -0
- package/dist/commands/publish-results-command.d.ts +21 -0
- package/dist/commands/publish-results-command.d.ts.map +1 -0
- package/dist/commands/publish-results-command.js +256 -0
- package/dist/commands/publish-results-command.js.map +1 -0
- package/dist/commands/run-benchmark-command.d.ts +6 -0
- package/dist/commands/run-benchmark-command.d.ts.map +1 -0
- package/dist/commands/run-benchmark-command.js +331 -0
- package/dist/commands/run-benchmark-command.js.map +1 -0
- package/dist/commands/view-leaderboard-command.d.ts +8 -0
- package/dist/commands/view-leaderboard-command.d.ts.map +1 -0
- package/dist/commands/view-leaderboard-command.js +169 -0
- package/dist/commands/view-leaderboard-command.js.map +1 -0
- package/dist/config/api-key-config-reader.d.ts +14 -0
- package/dist/config/api-key-config-reader.d.ts.map +1 -0
- package/dist/config/api-key-config-reader.js +107 -0
- package/dist/config/api-key-config-reader.js.map +1 -0
- package/dist/config/api-key-config-reader.test.d.ts +2 -0
- package/dist/config/api-key-config-reader.test.d.ts.map +1 -0
- package/dist/config/api-key-config-reader.test.js +21 -0
- package/dist/config/api-key-config-reader.test.js.map +1 -0
- package/dist/engine/claude-cli-executor.d.ts +33 -0
- package/dist/engine/claude-cli-executor.d.ts.map +1 -0
- package/dist/engine/claude-cli-executor.js +251 -0
- package/dist/engine/claude-cli-executor.js.map +1 -0
- package/dist/engine/concept-accuracy-scorer.d.ts +24 -0
- package/dist/engine/concept-accuracy-scorer.d.ts.map +1 -0
- package/dist/engine/concept-accuracy-scorer.js +186 -0
- package/dist/engine/concept-accuracy-scorer.js.map +1 -0
- package/dist/engine/concept-accuracy-scorer.test.d.ts +2 -0
- package/dist/engine/concept-accuracy-scorer.test.d.ts.map +1 -0
- package/dist/engine/concept-accuracy-scorer.test.js +230 -0
- package/dist/engine/concept-accuracy-scorer.test.js.map +1 -0
- package/dist/engine/enhanced-test-prompt-builder.d.ts +30 -0
- package/dist/engine/enhanced-test-prompt-builder.d.ts.map +1 -0
- package/dist/engine/enhanced-test-prompt-builder.js +134 -0
- package/dist/engine/enhanced-test-prompt-builder.js.map +1 -0
- package/dist/engine/markdown-test-definition-parser.d.ts +18 -0
- package/dist/engine/markdown-test-definition-parser.d.ts.map +1 -0
- package/dist/engine/markdown-test-definition-parser.js +525 -0
- package/dist/engine/markdown-test-definition-parser.js.map +1 -0
- package/dist/engine/markdown-test-definition-parser.test.d.ts +2 -0
- package/dist/engine/markdown-test-definition-parser.test.d.ts.map +1 -0
- package/dist/engine/markdown-test-definition-parser.test.js +265 -0
- package/dist/engine/markdown-test-definition-parser.test.js.map +1 -0
- package/dist/engine/retry-with-degrade-utils.d.ts +58 -0
- package/dist/engine/retry-with-degrade-utils.d.ts.map +1 -0
- package/dist/engine/retry-with-degrade-utils.js +86 -0
- package/dist/engine/retry-with-degrade-utils.js.map +1 -0
- package/dist/engine/skill-content-collector.d.ts +53 -0
- package/dist/engine/skill-content-collector.d.ts.map +1 -0
- package/dist/engine/skill-content-collector.js +157 -0
- package/dist/engine/skill-content-collector.js.map +1 -0
- package/dist/engine/skill-creator-invoker.d.ts +36 -0
- package/dist/engine/skill-creator-invoker.d.ts.map +1 -0
- package/dist/engine/skill-creator-invoker.js +222 -0
- package/dist/engine/skill-creator-invoker.js.map +1 -0
- package/dist/engine/transcript-jsonl-parser.d.ts +28 -0
- package/dist/engine/transcript-jsonl-parser.d.ts.map +1 -0
- package/dist/engine/transcript-jsonl-parser.js +175 -0
- package/dist/engine/transcript-jsonl-parser.js.map +1 -0
- package/dist/sources/git-repository-skill-source-handler.d.ts +18 -0
- package/dist/sources/git-repository-skill-source-handler.d.ts.map +1 -0
- package/dist/sources/git-repository-skill-source-handler.js +119 -0
- package/dist/sources/git-repository-skill-source-handler.js.map +1 -0
- package/dist/sources/local-skill-source-handler.d.ts +21 -0
- package/dist/sources/local-skill-source-handler.d.ts.map +1 -0
- package/dist/sources/local-skill-source-handler.js +138 -0
- package/dist/sources/local-skill-source-handler.js.map +1 -0
- package/dist/sources/local-skill-source-handler.test.d.ts +2 -0
- package/dist/sources/local-skill-source-handler.test.d.ts.map +1 -0
- package/dist/sources/local-skill-source-handler.test.js +55 -0
- package/dist/sources/local-skill-source-handler.test.js.map +1 -0
- package/dist/sources/skillsh-registry-source-handler.d.ts +18 -0
- package/dist/sources/skillsh-registry-source-handler.d.ts.map +1 -0
- package/dist/sources/skillsh-registry-source-handler.js +130 -0
- package/dist/sources/skillsh-registry-source-handler.js.map +1 -0
- package/dist/sources/unified-skill-source-resolver.d.ts +20 -0
- package/dist/sources/unified-skill-source-resolver.d.ts.map +1 -0
- package/dist/sources/unified-skill-source-resolver.js +64 -0
- package/dist/sources/unified-skill-source-resolver.js.map +1 -0
- package/dist/sources/unified-skill-source-resolver.test.d.ts +2 -0
- package/dist/sources/unified-skill-source-resolver.test.d.ts.map +1 -0
- package/dist/sources/unified-skill-source-resolver.test.js +84 -0
- package/dist/sources/unified-skill-source-resolver.test.js.map +1 -0
- package/dist/types/benchmark-types.d.ts +142 -0
- package/dist/types/benchmark-types.d.ts.map +1 -0
- package/dist/types/benchmark-types.js +5 -0
- package/dist/types/benchmark-types.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/package.json +38 -0
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View leaderboard command - displays skill rankings from API
|
|
3
|
+
*/
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
/** Default API endpoint */
|
|
7
|
+
const DEFAULT_ENDPOINT = 'https://skillmark.sh/api';
|
|
8
|
+
/**
|
|
9
|
+
* Execute the leaderboard command
|
|
10
|
+
*/
|
|
11
|
+
export async function viewLeaderboard(skillName, options = {}) {
|
|
12
|
+
const spinner = ora();
|
|
13
|
+
try {
|
|
14
|
+
const endpoint = options.endpoint || DEFAULT_ENDPOINT;
|
|
15
|
+
const limit = options.limit || 20;
|
|
16
|
+
if (skillName) {
|
|
17
|
+
// Show specific skill details
|
|
18
|
+
spinner.start(`Fetching details for ${skillName}...`);
|
|
19
|
+
const skill = await fetchSkillDetails(skillName, endpoint);
|
|
20
|
+
spinner.stop();
|
|
21
|
+
displaySkillDetails(skill);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
// Show leaderboard
|
|
25
|
+
spinner.start('Fetching leaderboard...');
|
|
26
|
+
const entries = await fetchLeaderboard(endpoint, limit);
|
|
27
|
+
spinner.stop();
|
|
28
|
+
displayLeaderboard(entries);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
spinner.fail('Failed to fetch leaderboard');
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Fetch leaderboard from API
|
|
38
|
+
*/
|
|
39
|
+
async function fetchLeaderboard(endpoint, limit) {
|
|
40
|
+
const url = `${endpoint}/leaderboard?limit=${limit}`;
|
|
41
|
+
const response = await fetch(url);
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
throw new Error(`API error (${response.status}): ${response.statusText}`);
|
|
44
|
+
}
|
|
45
|
+
const data = await response.json();
|
|
46
|
+
return data.entries || [];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Fetch specific skill details from API
|
|
50
|
+
*/
|
|
51
|
+
async function fetchSkillDetails(skillName, endpoint) {
|
|
52
|
+
const url = `${endpoint}/skill/${encodeURIComponent(skillName)}`;
|
|
53
|
+
const response = await fetch(url);
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
if (response.status === 404) {
|
|
56
|
+
throw new Error(`Skill not found: ${skillName}`);
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`API error (${response.status}): ${response.statusText}`);
|
|
59
|
+
}
|
|
60
|
+
return response.json();
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Display leaderboard table
|
|
64
|
+
*/
|
|
65
|
+
function displayLeaderboard(entries) {
|
|
66
|
+
if (entries.length === 0) {
|
|
67
|
+
console.log(chalk.yellow('\nNo benchmark results found.\n'));
|
|
68
|
+
console.log('Run a benchmark and publish results to appear on the leaderboard:');
|
|
69
|
+
console.log(chalk.gray(' skillmark run <skill-path>'));
|
|
70
|
+
console.log(chalk.gray(' skillmark publish ./skillmark-results/result.json --api-key <key>'));
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
console.log(chalk.bold('\n═══ Skillmark Leaderboard ═══\n'));
|
|
74
|
+
// Header
|
|
75
|
+
console.log(chalk.gray(padRight('#', 4) +
|
|
76
|
+
padRight('Skill', 30) +
|
|
77
|
+
padRight('Accuracy', 10) +
|
|
78
|
+
padRight('Model', 10) +
|
|
79
|
+
padRight('Tokens', 12) +
|
|
80
|
+
padRight('Cost', 10) +
|
|
81
|
+
'Last Tested'));
|
|
82
|
+
console.log(chalk.gray('─'.repeat(100)));
|
|
83
|
+
// Rows
|
|
84
|
+
entries.forEach((entry, index) => {
|
|
85
|
+
const rank = String(index + 1);
|
|
86
|
+
const accuracy = `${entry.bestAccuracy.toFixed(1)}%`;
|
|
87
|
+
const tokens = entry.avgTokens.toLocaleString();
|
|
88
|
+
const cost = `$${entry.avgCost.toFixed(4)}`;
|
|
89
|
+
const lastTested = formatDate(entry.lastTested);
|
|
90
|
+
// Color accuracy
|
|
91
|
+
const accuracyColored = entry.bestAccuracy >= 90
|
|
92
|
+
? chalk.green(accuracy)
|
|
93
|
+
: entry.bestAccuracy >= 70
|
|
94
|
+
? chalk.yellow(accuracy)
|
|
95
|
+
: chalk.red(accuracy);
|
|
96
|
+
console.log(padRight(rank, 4) +
|
|
97
|
+
padRight(truncate(entry.skillName, 28), 30) +
|
|
98
|
+
padRight(accuracyColored, 10 + (accuracyColored.length - accuracy.length)) +
|
|
99
|
+
padRight(entry.bestModel, 10) +
|
|
100
|
+
padRight(tokens, 12) +
|
|
101
|
+
padRight(cost, 10) +
|
|
102
|
+
chalk.gray(lastTested));
|
|
103
|
+
});
|
|
104
|
+
console.log(chalk.gray('\n─'.repeat(100)));
|
|
105
|
+
console.log(chalk.gray(`Showing top ${entries.length} skills\n`));
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Display skill details
|
|
109
|
+
*/
|
|
110
|
+
function displaySkillDetails(skill) {
|
|
111
|
+
console.log(chalk.bold(`\n═══ ${skill.skillName} ═══\n`));
|
|
112
|
+
console.log(`${chalk.gray('Source:')} ${skill.source}`);
|
|
113
|
+
console.log(`${chalk.gray('Best Accuracy:')} ${chalk.green(skill.bestAccuracy.toFixed(1) + '%')}`);
|
|
114
|
+
console.log(`${chalk.gray('Best Model:')} ${skill.bestModel}`);
|
|
115
|
+
console.log(`${chalk.gray('Avg Tokens:')} ${skill.avgTokens.toLocaleString()}`);
|
|
116
|
+
console.log(`${chalk.gray('Avg Cost:')} $${skill.avgCost.toFixed(4)}`);
|
|
117
|
+
console.log(`${chalk.gray('Total Runs:')} ${skill.totalRuns}`);
|
|
118
|
+
console.log(`${chalk.gray('Last Tested:')} ${formatDate(skill.lastTested)}`);
|
|
119
|
+
// Show history if available
|
|
120
|
+
if (skill.history && skill.history.length > 0) {
|
|
121
|
+
console.log(chalk.bold('\nRecent Results:\n'));
|
|
122
|
+
for (const h of skill.history.slice(0, 10)) {
|
|
123
|
+
const bar = '█'.repeat(Math.round(h.accuracy / 5));
|
|
124
|
+
const accuracyColor = h.accuracy >= 90 ? chalk.green : h.accuracy >= 70 ? chalk.yellow : chalk.red;
|
|
125
|
+
console.log(` ${chalk.gray(formatDate(h.date))} ${accuracyColor(bar)} ${h.accuracy.toFixed(1)}%`);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
console.log('');
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Pad string to right
|
|
132
|
+
*/
|
|
133
|
+
function padRight(str, length) {
|
|
134
|
+
return str.padEnd(length);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Truncate string with ellipsis
|
|
138
|
+
*/
|
|
139
|
+
function truncate(str, maxLength) {
|
|
140
|
+
if (str.length <= maxLength)
|
|
141
|
+
return str;
|
|
142
|
+
return str.slice(0, maxLength - 1) + '…';
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Format ISO date to readable format
|
|
146
|
+
*/
|
|
147
|
+
function formatDate(isoDate) {
|
|
148
|
+
try {
|
|
149
|
+
const date = new Date(isoDate);
|
|
150
|
+
const now = new Date();
|
|
151
|
+
const diffMs = now.getTime() - date.getTime();
|
|
152
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
153
|
+
if (diffDays === 0)
|
|
154
|
+
return 'today';
|
|
155
|
+
if (diffDays === 1)
|
|
156
|
+
return 'yesterday';
|
|
157
|
+
if (diffDays < 7)
|
|
158
|
+
return `${diffDays}d ago`;
|
|
159
|
+
if (diffDays < 30)
|
|
160
|
+
return `${Math.floor(diffDays / 7)}w ago`;
|
|
161
|
+
if (diffDays < 365)
|
|
162
|
+
return `${Math.floor(diffDays / 30)}mo ago`;
|
|
163
|
+
return `${Math.floor(diffDays / 365)}y ago`;
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return isoDate;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=view-leaderboard-command.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"view-leaderboard-command.js","sourceRoot":"","sources":["../../src/commands/view-leaderboard-command.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface ApiKeyConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
source: 'env' | 'skillmarkrc' | 'claude-env';
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Read API key from configured sources
|
|
7
|
+
* Priority: env > ~/.skillmarkrc > ~/.claude/.env
|
|
8
|
+
*/
|
|
9
|
+
export declare function readApiKeyConfig(): Promise<ApiKeyConfig | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Get human-readable description of config source
|
|
12
|
+
*/
|
|
13
|
+
export declare function getConfigSourceDescription(source: ApiKeyConfig['source']): string;
|
|
14
|
+
//# sourceMappingURL=api-key-config-reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-config-reader.d.ts","sourceRoot":"","sources":["../../src/config/api-key-config-reader.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,KAAK,GAAG,aAAa,GAAG,YAAY,CAAC;CAC9C;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAkCrE;AAuDD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC,GAAG,MAAM,CASjF"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API key configuration reader for Skillmark CLI
|
|
3
|
+
* Reads API key from multiple sources with priority:
|
|
4
|
+
* 1. SKILLMARK_API_KEY environment variable
|
|
5
|
+
* 2. ~/.skillmarkrc config file
|
|
6
|
+
* 3. ~/.claude/.env file
|
|
7
|
+
*/
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import { join } from 'node:path';
|
|
10
|
+
import { homedir } from 'node:os';
|
|
11
|
+
const ENV_VAR_NAME = 'SKILLMARK_API_KEY';
|
|
12
|
+
const SKILLMARKRC_FILE = '.skillmarkrc';
|
|
13
|
+
const CLAUDE_ENV_FILE = '.claude/.env';
|
|
14
|
+
/**
|
|
15
|
+
* Read API key from configured sources
|
|
16
|
+
* Priority: env > ~/.skillmarkrc > ~/.claude/.env
|
|
17
|
+
*/
|
|
18
|
+
export async function readApiKeyConfig() {
|
|
19
|
+
// 1. Check environment variable
|
|
20
|
+
const envKey = process.env[ENV_VAR_NAME];
|
|
21
|
+
if (envKey && envKey.trim()) {
|
|
22
|
+
return { apiKey: envKey.trim(), source: 'env' };
|
|
23
|
+
}
|
|
24
|
+
const home = homedir();
|
|
25
|
+
// 2. Check ~/.skillmarkrc
|
|
26
|
+
try {
|
|
27
|
+
const skillmarkrcPath = join(home, SKILLMARKRC_FILE);
|
|
28
|
+
const content = await readFile(skillmarkrcPath, 'utf-8');
|
|
29
|
+
const key = parseConfigFile(content);
|
|
30
|
+
if (key) {
|
|
31
|
+
return { apiKey: key, source: 'skillmarkrc' };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
// File doesn't exist or can't be read, continue
|
|
36
|
+
}
|
|
37
|
+
// 3. Check ~/.claude/.env
|
|
38
|
+
try {
|
|
39
|
+
const claudeEnvPath = join(home, CLAUDE_ENV_FILE);
|
|
40
|
+
const content = await readFile(claudeEnvPath, 'utf-8');
|
|
41
|
+
const key = parseEnvFile(content, ENV_VAR_NAME);
|
|
42
|
+
if (key) {
|
|
43
|
+
return { apiKey: key, source: 'claude-env' };
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// File doesn't exist or can't be read, continue
|
|
48
|
+
}
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Parse skillmarkrc config file
|
|
53
|
+
* Format: key=value or api_key=value
|
|
54
|
+
*/
|
|
55
|
+
function parseConfigFile(content) {
|
|
56
|
+
const lines = content.split('\n');
|
|
57
|
+
for (const line of lines) {
|
|
58
|
+
const trimmed = line.trim();
|
|
59
|
+
// Skip comments and empty lines
|
|
60
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
// Parse key=value
|
|
64
|
+
const match = trimmed.match(/^(?:api_key|apiKey|key)\s*=\s*(.+)$/i);
|
|
65
|
+
if (match) {
|
|
66
|
+
const value = match[1].trim();
|
|
67
|
+
// Remove quotes if present
|
|
68
|
+
return value.replace(/^["']|["']$/g, '');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Parse .env file for specific key
|
|
75
|
+
*/
|
|
76
|
+
function parseEnvFile(content, keyName) {
|
|
77
|
+
const lines = content.split('\n');
|
|
78
|
+
for (const line of lines) {
|
|
79
|
+
const trimmed = line.trim();
|
|
80
|
+
// Skip comments and empty lines
|
|
81
|
+
if (!trimmed || trimmed.startsWith('#')) {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
// Parse KEY=value
|
|
85
|
+
const match = trimmed.match(/^([^=]+)=(.*)$/);
|
|
86
|
+
if (match && match[1].trim() === keyName) {
|
|
87
|
+
const value = match[2].trim();
|
|
88
|
+
// Remove quotes if present
|
|
89
|
+
return value.replace(/^["']|["']$/g, '');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Get human-readable description of config source
|
|
96
|
+
*/
|
|
97
|
+
export function getConfigSourceDescription(source) {
|
|
98
|
+
switch (source) {
|
|
99
|
+
case 'env':
|
|
100
|
+
return `SKILLMARK_API_KEY environment variable`;
|
|
101
|
+
case 'skillmarkrc':
|
|
102
|
+
return `~/${SKILLMARKRC_FILE}`;
|
|
103
|
+
case 'claude-env':
|
|
104
|
+
return `~/${CLAUDE_ENV_FILE}`;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=api-key-config-reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-config-reader.js","sourceRoot":"","sources":["../../src/config/api-key-config-reader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-config-reader.test.d.ts","sourceRoot":"","sources":["../../src/config/api-key-config-reader.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for api-key-config-reader.ts
|
|
3
|
+
* Verifies API key config source descriptions and priority logic
|
|
4
|
+
*/
|
|
5
|
+
import { describe, it, expect } from 'vitest';
|
|
6
|
+
import { getConfigSourceDescription } from './api-key-config-reader.js';
|
|
7
|
+
describe('getConfigSourceDescription', () => {
|
|
8
|
+
it('returns env variable description for env source', () => {
|
|
9
|
+
const result = getConfigSourceDescription('env');
|
|
10
|
+
expect(result).toBe('SKILLMARK_API_KEY environment variable');
|
|
11
|
+
});
|
|
12
|
+
it('returns skillmarkrc path for skillmarkrc source', () => {
|
|
13
|
+
const result = getConfigSourceDescription('skillmarkrc');
|
|
14
|
+
expect(result).toBe('~/.skillmarkrc');
|
|
15
|
+
});
|
|
16
|
+
it('returns claude env path for claude-env source', () => {
|
|
17
|
+
const result = getConfigSourceDescription('claude-env');
|
|
18
|
+
expect(result).toBe('~/.claude/.env');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
//# sourceMappingURL=api-key-config-reader.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-key-config-reader.test.js","sourceRoot":"","sources":["../../src/config/api-key-config-reader.test.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAExE,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,MAAM,GAAG,0BAA0B,CAAC,KAAK,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,wCAAwC,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,MAAM,GAAG,0BAA0B,CAAC,aAAa,CAAC,CAAC;QACzD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,MAAM,GAAG,0BAA0B,CAAC,YAAY,CAAC,CAAC;QACxD,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { TestDefinition, TranscriptEntry } from '../types/index.js';
|
|
2
|
+
/** Result from executing a single test */
|
|
3
|
+
export interface ExecutionResult {
|
|
4
|
+
/** Claude's response text */
|
|
5
|
+
response: string;
|
|
6
|
+
/** Path to JSONL transcript */
|
|
7
|
+
transcriptPath: string;
|
|
8
|
+
/** Parsed transcript entries */
|
|
9
|
+
transcript: TranscriptEntry[];
|
|
10
|
+
/** Total input tokens */
|
|
11
|
+
inputTokens: number;
|
|
12
|
+
/** Total output tokens */
|
|
13
|
+
outputTokens: number;
|
|
14
|
+
/** Total cost in USD */
|
|
15
|
+
costUsd: number;
|
|
16
|
+
/** Duration in milliseconds */
|
|
17
|
+
durationMs: number;
|
|
18
|
+
/** Number of tool calls */
|
|
19
|
+
toolCount: number;
|
|
20
|
+
/** Whether execution succeeded */
|
|
21
|
+
success: boolean;
|
|
22
|
+
/** Error message if failed */
|
|
23
|
+
error?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Execute a test against Claude CLI with a skill
|
|
27
|
+
*/
|
|
28
|
+
export declare function executeTest(test: TestDefinition, skillPath: string, model: 'haiku' | 'sonnet' | 'opus', workDir: string): Promise<ExecutionResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Clean up temporary transcript files
|
|
31
|
+
*/
|
|
32
|
+
export declare function cleanupTranscripts(workDir: string): Promise<void>;
|
|
33
|
+
//# sourceMappingURL=claude-cli-executor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-cli-executor.d.ts","sourceRoot":"","sources":["../../src/engine/claude-cli-executor.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAGzE,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,6BAA6B;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,gCAAgC;IAChC,UAAU,EAAE,eAAe,EAAE,CAAC;IAC9B,yBAAyB;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,0BAA0B;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,+BAA+B;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,2BAA2B;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,kCAAkC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AASD;;GAEG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,cAAc,EACpB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,EAClC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,eAAe,CAAC,CAyD1B;AA8ND;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAOvE"}
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI executor - invokes Claude CLI and captures output
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from 'node:child_process';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { mkdir, rm } from 'node:fs/promises';
|
|
7
|
+
import { join } from 'node:path';
|
|
8
|
+
import { getStoredToken } from '../commands/auth-setup-and-token-storage-command.js';
|
|
9
|
+
/** Model name mapping for Claude CLI */
|
|
10
|
+
const MODEL_MAP = {
|
|
11
|
+
haiku: 'claude-3-5-haiku-latest',
|
|
12
|
+
sonnet: 'claude-sonnet-4-20250514',
|
|
13
|
+
opus: 'claude-opus-4-20250514',
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Execute a test against Claude CLI with a skill
|
|
17
|
+
*/
|
|
18
|
+
export async function executeTest(test, skillPath, model, workDir) {
|
|
19
|
+
const sessionId = randomUUID();
|
|
20
|
+
const transcriptDir = join(workDir, '.skillmark-transcripts');
|
|
21
|
+
const transcriptPath = join(transcriptDir, `${sessionId}.jsonl`);
|
|
22
|
+
await mkdir(transcriptDir, { recursive: true });
|
|
23
|
+
const startTime = Date.now();
|
|
24
|
+
const modelId = MODEL_MAP[model];
|
|
25
|
+
// Build Claude CLI command
|
|
26
|
+
// -p is the print mode flag that takes the prompt as argument
|
|
27
|
+
const args = [
|
|
28
|
+
'-p', test.prompt, // Print mode with prompt - non-interactive
|
|
29
|
+
'--model', modelId,
|
|
30
|
+
'--output-format', 'json',
|
|
31
|
+
'--max-turns', '50',
|
|
32
|
+
'--dangerously-skip-permissions', // Skip permission prompts for benchmarks
|
|
33
|
+
];
|
|
34
|
+
// Add skill if provided
|
|
35
|
+
if (skillPath) {
|
|
36
|
+
args.push('--allowedTools', `Skill(${skillPath})`);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const result = await runClaudeCli(args, workDir, test.timeout * 1000);
|
|
40
|
+
const durationMs = Date.now() - startTime;
|
|
41
|
+
// Parse the JSON result from Claude CLI
|
|
42
|
+
const cliResult = parseCliResult(result.stdout);
|
|
43
|
+
return {
|
|
44
|
+
response: cliResult.response,
|
|
45
|
+
transcriptPath,
|
|
46
|
+
transcript: [], // Simplified - we use the result JSON directly
|
|
47
|
+
inputTokens: cliResult.inputTokens,
|
|
48
|
+
outputTokens: cliResult.outputTokens,
|
|
49
|
+
costUsd: cliResult.costUsd,
|
|
50
|
+
durationMs,
|
|
51
|
+
toolCount: cliResult.toolCount,
|
|
52
|
+
success: true,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return {
|
|
57
|
+
response: '',
|
|
58
|
+
transcriptPath,
|
|
59
|
+
transcript: [],
|
|
60
|
+
inputTokens: 0,
|
|
61
|
+
outputTokens: 0,
|
|
62
|
+
costUsd: 0,
|
|
63
|
+
durationMs: Date.now() - startTime,
|
|
64
|
+
toolCount: 0,
|
|
65
|
+
success: false,
|
|
66
|
+
error: error instanceof Error ? error.message : String(error),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Run Claude CLI as a subprocess
|
|
72
|
+
*/
|
|
73
|
+
async function runClaudeCli(args, cwd, timeoutMs) {
|
|
74
|
+
// Get stored OAuth token
|
|
75
|
+
const storedToken = await getStoredToken();
|
|
76
|
+
// Prepare environment with token if available
|
|
77
|
+
const env = { ...process.env };
|
|
78
|
+
if (storedToken) {
|
|
79
|
+
env.CLAUDE_CODE_OAUTH_TOKEN = storedToken;
|
|
80
|
+
}
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
const proc = spawn('claude', args, {
|
|
83
|
+
cwd,
|
|
84
|
+
env,
|
|
85
|
+
stdio: ['ignore', 'pipe', 'pipe'], // ignore stdin to prevent hanging
|
|
86
|
+
});
|
|
87
|
+
let stdout = '';
|
|
88
|
+
let stderr = '';
|
|
89
|
+
proc.stdout.on('data', (data) => {
|
|
90
|
+
stdout += data.toString();
|
|
91
|
+
});
|
|
92
|
+
proc.stderr.on('data', (data) => {
|
|
93
|
+
stderr += data.toString();
|
|
94
|
+
});
|
|
95
|
+
const timeout = setTimeout(() => {
|
|
96
|
+
proc.kill('SIGTERM');
|
|
97
|
+
reject(new Error(`Execution timed out after ${timeoutMs}ms`));
|
|
98
|
+
}, timeoutMs);
|
|
99
|
+
proc.on('close', (code) => {
|
|
100
|
+
clearTimeout(timeout);
|
|
101
|
+
// Check for auth errors in JSON response (Claude CLI returns error in JSON, not stderr)
|
|
102
|
+
if (stdout) {
|
|
103
|
+
try {
|
|
104
|
+
const result = JSON.parse(stdout);
|
|
105
|
+
if (result.is_error && result.result) {
|
|
106
|
+
const errorMsg = result.result;
|
|
107
|
+
if (errorMsg.includes('Invalid API key') || errorMsg.includes('/login')) {
|
|
108
|
+
reject(new Error(`Authentication required. Run 'skillmark auth' to authenticate.`));
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (result.is_error) {
|
|
112
|
+
reject(new Error(`Claude CLI error: ${errorMsg}`));
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
// Not JSON, continue with normal handling
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (code === 0) {
|
|
122
|
+
resolve({ stdout, stderr });
|
|
123
|
+
}
|
|
124
|
+
else {
|
|
125
|
+
// Include stdout in error for better diagnostics when stderr is empty
|
|
126
|
+
const errorDetail = stderr || stdout.slice(0, 200) || 'No error details';
|
|
127
|
+
reject(new Error(`Claude CLI exited with code ${code}: ${errorDetail}`));
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
proc.on('error', (err) => {
|
|
131
|
+
clearTimeout(timeout);
|
|
132
|
+
reject(err);
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Parse Claude CLI JSON result output
|
|
138
|
+
*/
|
|
139
|
+
function parseCliResult(output) {
|
|
140
|
+
try {
|
|
141
|
+
// Find the JSON result in the output (may have other text before it)
|
|
142
|
+
const jsonMatch = output.match(/\{[\s\S]*"type"\s*:\s*"result"[\s\S]*\}/);
|
|
143
|
+
if (!jsonMatch) {
|
|
144
|
+
// Fallback: try parsing the whole output as JSON
|
|
145
|
+
const parsed = JSON.parse(output.trim());
|
|
146
|
+
return extractFromCliResult(parsed);
|
|
147
|
+
}
|
|
148
|
+
const parsed = JSON.parse(jsonMatch[0]);
|
|
149
|
+
return extractFromCliResult(parsed);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
// Return empty result if parsing fails
|
|
153
|
+
return { response: '', inputTokens: 0, outputTokens: 0, costUsd: 0, toolCount: 0 };
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
function extractFromCliResult(result) {
|
|
157
|
+
const usage = result.usage || {};
|
|
158
|
+
const inputTokens = (usage.input_tokens || 0) +
|
|
159
|
+
(usage.cache_creation_input_tokens || 0) +
|
|
160
|
+
(usage.cache_read_input_tokens || 0);
|
|
161
|
+
return {
|
|
162
|
+
response: result.result || '',
|
|
163
|
+
inputTokens,
|
|
164
|
+
outputTokens: usage.output_tokens || 0,
|
|
165
|
+
costUsd: result.total_cost_usd || 0,
|
|
166
|
+
toolCount: result.num_turns || 0, // num_turns as proxy for tool usage
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Parse JSONL output from Claude CLI (legacy)
|
|
171
|
+
*/
|
|
172
|
+
function parseJsonlOutput(output) {
|
|
173
|
+
const entries = [];
|
|
174
|
+
const lines = output.split('\n').filter((line) => line.trim());
|
|
175
|
+
for (const line of lines) {
|
|
176
|
+
try {
|
|
177
|
+
const entry = JSON.parse(line);
|
|
178
|
+
entries.push(entry);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// Skip non-JSON lines
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
return entries;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Extract metrics from transcript entries
|
|
188
|
+
*/
|
|
189
|
+
function extractMetrics(transcript) {
|
|
190
|
+
let inputTokens = 0;
|
|
191
|
+
let outputTokens = 0;
|
|
192
|
+
let costUsd = 0;
|
|
193
|
+
let toolCount = 0;
|
|
194
|
+
for (const entry of transcript) {
|
|
195
|
+
if (entry.inputTokens)
|
|
196
|
+
inputTokens += entry.inputTokens;
|
|
197
|
+
if (entry.outputTokens)
|
|
198
|
+
outputTokens += entry.outputTokens;
|
|
199
|
+
if (entry.cacheCreationInputTokens)
|
|
200
|
+
inputTokens += entry.cacheCreationInputTokens;
|
|
201
|
+
if (entry.cacheReadInputTokens)
|
|
202
|
+
inputTokens += entry.cacheReadInputTokens;
|
|
203
|
+
if (entry.costUSD)
|
|
204
|
+
costUsd += entry.costUSD;
|
|
205
|
+
// Count tool uses
|
|
206
|
+
if (entry.type === 'assistant' && entry.message?.content) {
|
|
207
|
+
const content = entry.message.content;
|
|
208
|
+
if (Array.isArray(content)) {
|
|
209
|
+
toolCount += content.filter((c) => c.type === 'tool_use').length;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return { inputTokens, outputTokens, costUsd, toolCount };
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Extract final response text from transcript
|
|
217
|
+
*/
|
|
218
|
+
function extractResponse(transcript) {
|
|
219
|
+
// Get last assistant message
|
|
220
|
+
for (let i = transcript.length - 1; i >= 0; i--) {
|
|
221
|
+
const entry = transcript[i];
|
|
222
|
+
if (entry.type === 'assistant' && entry.message?.content) {
|
|
223
|
+
const content = entry.message.content;
|
|
224
|
+
if (typeof content === 'string') {
|
|
225
|
+
return content;
|
|
226
|
+
}
|
|
227
|
+
if (Array.isArray(content)) {
|
|
228
|
+
const textParts = content
|
|
229
|
+
.filter((c) => c.type === 'text' && c.text)
|
|
230
|
+
.map((c) => c.text)
|
|
231
|
+
.join('\n');
|
|
232
|
+
if (textParts)
|
|
233
|
+
return textParts;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return '';
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Clean up temporary transcript files
|
|
241
|
+
*/
|
|
242
|
+
export async function cleanupTranscripts(workDir) {
|
|
243
|
+
const transcriptDir = join(workDir, '.skillmark-transcripts');
|
|
244
|
+
try {
|
|
245
|
+
await rm(transcriptDir, { recursive: true, force: true });
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
// Ignore cleanup errors
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=claude-cli-executor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-cli-executor.js","sourceRoot":"","sources":["../../src/engine/claude-cli-executor.ts"],"names":[],"mappings":"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"}
|