@artemiskit/cli 0.1.7 → 0.1.8
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/CHANGELOG.md +23 -0
- package/dist/index.js +2639 -4816
- package/dist/src/cli.d.ts.map +1 -1
- package/dist/src/commands/init.d.ts.map +1 -1
- package/dist/src/utils/update-checker.d.ts +31 -0
- package/dist/src/utils/update-checker.d.ts.map +1 -0
- package/package.json +6 -6
- package/src/cli.ts +22 -1
- package/src/commands/init.ts +50 -10
- package/src/utils/update-checker.ts +121 -0
package/dist/src/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,SAAS,IAAI,OAAO,CAuCnC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAyNpC,wBAAgB,WAAW,IAAI,OAAO,CAqFrC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-blocking update checker for ArtemisKit CLI
|
|
3
|
+
*/
|
|
4
|
+
export interface UpdateInfo {
|
|
5
|
+
currentVersion: string;
|
|
6
|
+
latestVersion: string;
|
|
7
|
+
updateAvailable: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Check for updates (non-blocking)
|
|
11
|
+
* Returns update info or null if check fails
|
|
12
|
+
*/
|
|
13
|
+
export declare function checkForUpdate(): Promise<UpdateInfo | null>;
|
|
14
|
+
/**
|
|
15
|
+
* Get the current CLI version
|
|
16
|
+
*/
|
|
17
|
+
export declare function getCurrentVersion(): string;
|
|
18
|
+
/**
|
|
19
|
+
* Format version display string
|
|
20
|
+
*/
|
|
21
|
+
export declare function formatVersionDisplay(version: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Format update available message
|
|
24
|
+
*/
|
|
25
|
+
export declare function formatUpdateMessage(current: string, latest: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Non-blocking update check that prints message if update available
|
|
28
|
+
* Use this to fire-and-forget an update check
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkForUpdateAndNotify(): void;
|
|
31
|
+
//# sourceMappingURL=update-checker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-checker.d.ts","sourceRoot":"","sources":["../../../src/utils/update-checker.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,MAAM,WAAW,UAAU;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,OAAO,CAAC;CAC1B;AAgDD;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAYjE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAE1C;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAE3E;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,IAAI,IAAI,CAW9C"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@artemiskit/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"description": "Command-line interface for ArtemisKit LLM evaluation toolkit",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -45,11 +45,11 @@
|
|
|
45
45
|
"test": "bun test"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
|
-
"@artemiskit/adapter-openai": "0.1.
|
|
49
|
-
"@artemiskit/adapter-vercel-ai": "0.1.
|
|
50
|
-
"@artemiskit/core": "0.1.
|
|
51
|
-
"@artemiskit/redteam": "0.1.
|
|
52
|
-
"@artemiskit/reports": "0.1.
|
|
48
|
+
"@artemiskit/adapter-openai": "0.1.6",
|
|
49
|
+
"@artemiskit/adapter-vercel-ai": "0.1.6",
|
|
50
|
+
"@artemiskit/core": "0.1.6",
|
|
51
|
+
"@artemiskit/redteam": "0.1.6",
|
|
52
|
+
"@artemiskit/reports": "0.1.6",
|
|
53
53
|
"chalk": "^5.3.0",
|
|
54
54
|
"cli-table3": "^0.6.3",
|
|
55
55
|
"commander": "^12.0.0",
|
package/src/cli.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { redteamCommand } from './commands/redteam';
|
|
|
11
11
|
import { reportCommand } from './commands/report';
|
|
12
12
|
import { runCommand } from './commands/run';
|
|
13
13
|
import { stressCommand } from './commands/stress';
|
|
14
|
+
import { checkForUpdate, formatUpdateMessage, formatVersionDisplay } from './utils/update-checker';
|
|
14
15
|
|
|
15
16
|
export function createCLI(): Command {
|
|
16
17
|
const program = new Command();
|
|
@@ -20,7 +21,27 @@ export function createCLI(): Command {
|
|
|
20
21
|
.description(
|
|
21
22
|
'ArtemisKit - Open-source Agent Reliability Toolkit - Test, validate, audit and evaluate LLMs and LLM-driven agents'
|
|
22
23
|
)
|
|
23
|
-
.version(version)
|
|
24
|
+
.version(version, '-v, --version', 'Output the current version')
|
|
25
|
+
.option('-V, --version-check', 'Output version and check for updates')
|
|
26
|
+
.action(async () => {
|
|
27
|
+
// Handle root command with --version-check flag
|
|
28
|
+
const opts = program.opts();
|
|
29
|
+
if (opts.versionCheck) {
|
|
30
|
+
console.log(formatVersionDisplay(version));
|
|
31
|
+
console.log('\nChecking for updates...');
|
|
32
|
+
const updateInfo = await checkForUpdate();
|
|
33
|
+
if (updateInfo?.updateAvailable) {
|
|
34
|
+
console.log(formatUpdateMessage(updateInfo.currentVersion, updateInfo.latestVersion));
|
|
35
|
+
} else if (updateInfo) {
|
|
36
|
+
console.log('You are using the latest version.');
|
|
37
|
+
} else {
|
|
38
|
+
console.log('Could not check for updates (network unavailable).');
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
// No subcommand provided, show help
|
|
42
|
+
program.help();
|
|
43
|
+
}
|
|
44
|
+
});
|
|
24
45
|
|
|
25
46
|
program.addCommand(initCommand());
|
|
26
47
|
program.addCommand(runCommand());
|
package/src/commands/init.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { join } from 'node:path';
|
|
|
8
8
|
import chalk from 'chalk';
|
|
9
9
|
import { Command } from 'commander';
|
|
10
10
|
import { createSpinner, icons } from '../ui/index.js';
|
|
11
|
+
import { checkForUpdateAndNotify, getCurrentVersion } from '../utils/update-checker.js';
|
|
11
12
|
|
|
12
13
|
const DEFAULT_CONFIG = `# ArtemisKit Configuration
|
|
13
14
|
project: my-project
|
|
@@ -86,18 +87,54 @@ const ENV_KEYS = [
|
|
|
86
87
|
];
|
|
87
88
|
|
|
88
89
|
function renderWelcomeBanner(): string {
|
|
90
|
+
// Brand color for "KIT" portion: #fb923c (orange)
|
|
91
|
+
const brandColor = chalk.hex('#fb923c');
|
|
92
|
+
const version = getCurrentVersion();
|
|
93
|
+
|
|
94
|
+
// Randomly color each border character white or brand color
|
|
95
|
+
const colorBorderChar = (char: string): string => {
|
|
96
|
+
return Math.random() > 0.5 ? chalk.white(char) : brandColor(char);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const colorBorder = (str: string): string => {
|
|
100
|
+
return str.split('').map(colorBorderChar).join('');
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
// All lines are exactly 52 chars inside the borders for perfect alignment
|
|
104
|
+
const topBorder = `╭${'─'.repeat(52)}╮`;
|
|
105
|
+
const bottomBorder = `╰${'─'.repeat(52)}╯`;
|
|
106
|
+
const sideBorderLeft = '│';
|
|
107
|
+
const sideBorderRight = '│';
|
|
108
|
+
const emptyContent = ' '.repeat(52);
|
|
109
|
+
|
|
110
|
+
// Version line: "v0.1.7" centered in brand color
|
|
111
|
+
const versionText = `v${version}`;
|
|
112
|
+
const versionPadding = Math.floor((52 - versionText.length) / 2);
|
|
113
|
+
const versionLine =
|
|
114
|
+
' '.repeat(versionPadding) +
|
|
115
|
+
brandColor(versionText) +
|
|
116
|
+
' '.repeat(52 - versionPadding - versionText.length);
|
|
117
|
+
|
|
118
|
+
// Tagline centered
|
|
119
|
+
const tagline = 'Open-source testing toolkit for LLM applications';
|
|
120
|
+
const taglinePadding = Math.floor((52 - tagline.length) / 2);
|
|
121
|
+
const taglineLine =
|
|
122
|
+
' '.repeat(taglinePadding) +
|
|
123
|
+
chalk.gray(tagline) +
|
|
124
|
+
' '.repeat(52 - taglinePadding - tagline.length);
|
|
125
|
+
|
|
89
126
|
const lines = [
|
|
90
127
|
'',
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
chalk.
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
128
|
+
` ${colorBorder(topBorder)}`,
|
|
129
|
+
` ${colorBorderChar(sideBorderLeft)}${emptyContent}${colorBorderChar(sideBorderRight)}`,
|
|
130
|
+
` ${colorBorderChar(sideBorderLeft)} ${chalk.bold.white('▄▀█ █▀█ ▀█▀ █▀▀ █▀▄▀█ █ █▀ ')}${brandColor.bold('█▄▀ █ ▀█▀')} ${colorBorderChar(sideBorderRight)}`,
|
|
131
|
+
` ${colorBorderChar(sideBorderLeft)} ${chalk.bold.white('█▀█ █▀▄ █ ██▄ █ ▀ █ █ ▄█ ')}${brandColor.bold('█ █ █ █ ')} ${colorBorderChar(sideBorderRight)}`,
|
|
132
|
+
` ${colorBorderChar(sideBorderLeft)}${emptyContent}${colorBorderChar(sideBorderRight)}`,
|
|
133
|
+
` ${colorBorderChar(sideBorderLeft)}${versionLine}${colorBorderChar(sideBorderRight)}`,
|
|
134
|
+
` ${colorBorderChar(sideBorderLeft)}${emptyContent}${colorBorderChar(sideBorderRight)}`,
|
|
135
|
+
` ${colorBorderChar(sideBorderLeft)}${taglineLine}${colorBorderChar(sideBorderRight)}`,
|
|
136
|
+
` ${colorBorderChar(sideBorderLeft)}${emptyContent}${colorBorderChar(sideBorderRight)}`,
|
|
137
|
+
` ${colorBorder(bottomBorder)}`,
|
|
101
138
|
'',
|
|
102
139
|
];
|
|
103
140
|
return lines.join('\n');
|
|
@@ -260,6 +297,9 @@ export function initCommand(): Command {
|
|
|
260
297
|
|
|
261
298
|
// Show success panel
|
|
262
299
|
console.log(renderSuccessPanel());
|
|
300
|
+
|
|
301
|
+
// Non-blocking update check (fire and forget)
|
|
302
|
+
checkForUpdateAndNotify();
|
|
263
303
|
} catch (error) {
|
|
264
304
|
spinner.fail('Error');
|
|
265
305
|
console.error(chalk.red(`\n${icons.failed} ${(error as Error).message}`));
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Non-blocking update checker for ArtemisKit CLI
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import { version as currentVersion } from '../../package.json';
|
|
7
|
+
|
|
8
|
+
const PACKAGE_NAME = '@artemiskit/cli';
|
|
9
|
+
const NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}/latest`;
|
|
10
|
+
const FETCH_TIMEOUT_MS = 3000; // 3 second timeout to avoid blocking
|
|
11
|
+
|
|
12
|
+
// Brand color
|
|
13
|
+
const brandColor = chalk.hex('#fb923c');
|
|
14
|
+
|
|
15
|
+
export interface UpdateInfo {
|
|
16
|
+
currentVersion: string;
|
|
17
|
+
latestVersion: string;
|
|
18
|
+
updateAvailable: boolean;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Fetches the latest version from npm registry with a timeout
|
|
23
|
+
*/
|
|
24
|
+
async function fetchLatestVersion(): Promise<string | null> {
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const timeoutId = setTimeout(() => controller.abort(), FETCH_TIMEOUT_MS);
|
|
27
|
+
|
|
28
|
+
try {
|
|
29
|
+
const response = await fetch(NPM_REGISTRY_URL, {
|
|
30
|
+
signal: controller.signal,
|
|
31
|
+
headers: {
|
|
32
|
+
Accept: 'application/json',
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
if (!response.ok) {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const data = (await response.json()) as { version?: string };
|
|
41
|
+
return data.version || null;
|
|
42
|
+
} catch {
|
|
43
|
+
// Silently fail - network issues shouldn't block CLI usage
|
|
44
|
+
return null;
|
|
45
|
+
} finally {
|
|
46
|
+
clearTimeout(timeoutId);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Compares two semver versions
|
|
52
|
+
* Returns true if latest > current
|
|
53
|
+
*/
|
|
54
|
+
function isNewerVersion(current: string, latest: string): boolean {
|
|
55
|
+
const currentParts = current.replace(/^v/, '').split('.').map(Number);
|
|
56
|
+
const latestParts = latest.replace(/^v/, '').split('.').map(Number);
|
|
57
|
+
|
|
58
|
+
for (let i = 0; i < 3; i++) {
|
|
59
|
+
const c = currentParts[i] || 0;
|
|
60
|
+
const l = latestParts[i] || 0;
|
|
61
|
+
if (l > c) return true;
|
|
62
|
+
if (l < c) return false;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Check for updates (non-blocking)
|
|
69
|
+
* Returns update info or null if check fails
|
|
70
|
+
*/
|
|
71
|
+
export async function checkForUpdate(): Promise<UpdateInfo | null> {
|
|
72
|
+
const latestVersion = await fetchLatestVersion();
|
|
73
|
+
|
|
74
|
+
if (!latestVersion) {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
currentVersion,
|
|
80
|
+
latestVersion,
|
|
81
|
+
updateAvailable: isNewerVersion(currentVersion, latestVersion),
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Get the current CLI version
|
|
87
|
+
*/
|
|
88
|
+
export function getCurrentVersion(): string {
|
|
89
|
+
return currentVersion;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Format version display string
|
|
94
|
+
*/
|
|
95
|
+
export function formatVersionDisplay(version: string): string {
|
|
96
|
+
return `${chalk.bold('ArtemisKit CLI')} ${brandColor(`v${version}`)}`;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Format update available message
|
|
101
|
+
*/
|
|
102
|
+
export function formatUpdateMessage(current: string, latest: string): string {
|
|
103
|
+
return `\n${chalk.yellow('╭─────────────────────────────────────────────────────╮')}\n${chalk.yellow('│')}${chalk.yellow(' Update available! ')}${chalk.gray(`${current}`)}${chalk.yellow(' → ')}${brandColor.bold(`${latest}`)}${' '.repeat(24 - current.length - latest.length)}${chalk.yellow('│')}\n${chalk.yellow('│')}${chalk.white(' Run ')}${chalk.cyan('npm install -g @artemiskit/cli')}${chalk.white(' to update ')}${chalk.yellow('│')}\n${chalk.yellow('╰─────────────────────────────────────────────────────╯')}`;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Non-blocking update check that prints message if update available
|
|
108
|
+
* Use this to fire-and-forget an update check
|
|
109
|
+
*/
|
|
110
|
+
export function checkForUpdateAndNotify(): void {
|
|
111
|
+
// Fire and forget - don't await
|
|
112
|
+
checkForUpdate()
|
|
113
|
+
.then((info) => {
|
|
114
|
+
if (info?.updateAvailable) {
|
|
115
|
+
console.log(formatUpdateMessage(info.currentVersion, info.latestVersion));
|
|
116
|
+
}
|
|
117
|
+
})
|
|
118
|
+
.catch(() => {
|
|
119
|
+
// Silently ignore errors
|
|
120
|
+
});
|
|
121
|
+
}
|