@artemiskit/cli 0.1.8 → 0.2.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.
@@ -1 +1 @@
1
- {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/commands/compare.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2HpC,wBAAgB,cAAc,IAAI,OAAO,CAkFxC"}
1
+ {"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../../../src/commands/compare.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA6HpC,wBAAgB,cAAc,IAAI,OAAO,CAsGxC"}
@@ -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;AAyNpC,wBAAgB,WAAW,IAAI,OAAO,CAqFrC"}
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;AA4RpC,wBAAgB,WAAW,IAAI,OAAO,CA0HrC"}
@@ -1 +1 @@
1
- {"version":3,"file":"redteam.d.ts","sourceRoot":"","sources":["../../../src/commands/redteam.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8BH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAiCpC,wBAAgB,cAAc,IAAI,OAAO,CAyZxC"}
1
+ {"version":3,"file":"redteam.d.ts","sourceRoot":"","sources":["../../../src/commands/redteam.ts"],"names":[],"mappings":"AAAA;;GAEG;AAkCH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAkCpC,wBAAgB,cAAc,IAAI,OAAO,CA6bxC"}
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC,wBAAgB,UAAU,IAAI,OAAO,CA8MpC"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../../src/commands/run.ts"],"names":[],"mappings":"AAAA;;GAEG;AAYH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAgVpC,wBAAgB,UAAU,IAAI,OAAO,CAmTpC"}
@@ -1 +1 @@
1
- {"version":3,"file":"stress.d.ts","sourceRoot":"","sources":["../../../src/commands/stress.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiBH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC,wBAAgB,aAAa,IAAI,OAAO,CAoQvC"}
1
+ {"version":3,"file":"stress.d.ts","sourceRoot":"","sources":["../../../src/commands/stress.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmBH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmCpC,wBAAgB,aAAa,IAAI,OAAO,CAuRvC"}
@@ -5,7 +5,9 @@ import { type ArtemisConfig } from './schema';
5
5
  /**
6
6
  * Find and load the configuration file
7
7
  */
8
- export declare function loadConfig(configPath?: string): Promise<ArtemisConfig | null>;
8
+ export declare function loadConfig(configPath?: string): Promise<(ArtemisConfig & {
9
+ _path: string;
10
+ }) | null>;
9
11
  /**
10
12
  * Get a merged config with CLI options taking precedence
11
13
  */
@@ -1 +1 @@
1
- {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,UAAU,CAAC;AAInE;;GAEG;AACH,wBAAsB,UAAU,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CA8BnF;AAiDD;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,aAAa,GAAG,IAAI,EAChC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,GACjC,aAAa,CAWf"}
1
+ {"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/config/loader.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,OAAO,EAAE,KAAK,aAAa,EAAuB,MAAM,UAAU,CAAC;AAInE;;GAEG;AACH,wBAAsB,UAAU,CAC9B,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,CAAC,aAAa,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,GAAG,IAAI,CAAC,CA+BrD;AAiDD;;GAEG;AACH,wBAAgB,WAAW,CACzB,UAAU,EAAE,aAAa,GAAG,IAAI,EAChC,UAAU,EAAE,OAAO,CAAC,aAAa,CAAC,GACjC,aAAa,CAWf"}
@@ -12,6 +12,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
12
12
  resourceName: z.ZodOptional<z.ZodString>;
13
13
  deploymentName: z.ZodOptional<z.ZodString>;
14
14
  apiVersion: z.ZodOptional<z.ZodString>;
15
+ embeddingDeploymentName: z.ZodOptional<z.ZodString>;
15
16
  underlyingProvider: z.ZodOptional<z.ZodEnum<["openai", "azure", "anthropic", "google", "mistral"]>>;
16
17
  }, "strip", z.ZodTypeAny, {
17
18
  apiKey?: string | undefined;
@@ -23,6 +24,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
23
24
  resourceName?: string | undefined;
24
25
  deploymentName?: string | undefined;
25
26
  apiVersion?: string | undefined;
27
+ embeddingDeploymentName?: string | undefined;
26
28
  underlyingProvider?: "openai" | "anthropic" | "google" | "mistral" | "azure" | undefined;
27
29
  }, {
28
30
  apiKey?: string | undefined;
@@ -34,6 +36,7 @@ declare const ProviderConfigSchema: z.ZodObject<{
34
36
  resourceName?: string | undefined;
35
37
  deploymentName?: string | undefined;
36
38
  apiVersion?: string | undefined;
39
+ embeddingDeploymentName?: string | undefined;
37
40
  underlyingProvider?: "openai" | "anthropic" | "google" | "mistral" | "azure" | undefined;
38
41
  }>;
39
42
  declare const StorageConfigSchema: z.ZodObject<{
@@ -69,6 +72,7 @@ export declare const ArtemisConfigSchema: z.ZodObject<{
69
72
  resourceName: z.ZodOptional<z.ZodString>;
70
73
  deploymentName: z.ZodOptional<z.ZodString>;
71
74
  apiVersion: z.ZodOptional<z.ZodString>;
75
+ embeddingDeploymentName: z.ZodOptional<z.ZodString>;
72
76
  underlyingProvider: z.ZodOptional<z.ZodEnum<["openai", "azure", "anthropic", "google", "mistral"]>>;
73
77
  }, "strip", z.ZodTypeAny, {
74
78
  apiKey?: string | undefined;
@@ -80,6 +84,7 @@ export declare const ArtemisConfigSchema: z.ZodObject<{
80
84
  resourceName?: string | undefined;
81
85
  deploymentName?: string | undefined;
82
86
  apiVersion?: string | undefined;
87
+ embeddingDeploymentName?: string | undefined;
83
88
  underlyingProvider?: "openai" | "anthropic" | "google" | "mistral" | "azure" | undefined;
84
89
  }, {
85
90
  apiKey?: string | undefined;
@@ -91,6 +96,7 @@ export declare const ArtemisConfigSchema: z.ZodObject<{
91
96
  resourceName?: string | undefined;
92
97
  deploymentName?: string | undefined;
93
98
  apiVersion?: string | undefined;
99
+ embeddingDeploymentName?: string | undefined;
94
100
  underlyingProvider?: "openai" | "anthropic" | "google" | "mistral" | "azure" | undefined;
95
101
  }>>>;
96
102
  storage: z.ZodOptional<z.ZodObject<{
@@ -154,6 +160,7 @@ export declare const ArtemisConfigSchema: z.ZodObject<{
154
160
  resourceName?: string | undefined;
155
161
  deploymentName?: string | undefined;
156
162
  apiVersion?: string | undefined;
163
+ embeddingDeploymentName?: string | undefined;
157
164
  underlyingProvider?: "openai" | "anthropic" | "google" | "mistral" | "azure" | undefined;
158
165
  }> | undefined;
159
166
  storage?: {
@@ -187,6 +194,7 @@ export declare const ArtemisConfigSchema: z.ZodObject<{
187
194
  resourceName?: string | undefined;
188
195
  deploymentName?: string | undefined;
189
196
  apiVersion?: string | undefined;
197
+ embeddingDeploymentName?: string | undefined;
190
198
  underlyingProvider?: "openai" | "anthropic" | "google" | "mistral" | "azure" | undefined;
191
199
  }> | undefined;
192
200
  storage?: {
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/config/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAcxB,CAAC;AAEH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAMvB,CAAC;AAcH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/config/schema.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,QAAA,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAexB,CAAC;AAEH,QAAA,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;EAMvB,CAAC;AAcH,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS9B,CAAC;AAEH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAChE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAClE,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC"}
@@ -7,10 +7,12 @@ export { colors, icons, colorByPercentage, formatPercentage } from './colors.js'
7
7
  export { isTTY, getTerminalWidth, renderConditional, centerText, padText, stripAnsi, truncate, formatDuration, formatNumber, } from './utils.js';
8
8
  export { renderProgressBar, ProgressBar, renderInlineProgress } from './progress.js';
9
9
  export type { ProgressBarOptions } from './progress.js';
10
- export { renderSummaryPanel, renderStressSummaryPanel, renderRedteamSummaryPanel, renderInfoBox, } from './panels.js';
10
+ export { renderSummaryPanel, renderStressSummaryPanel, renderRedteamSummaryPanel, renderInfoBox, renderFailureReason, } from './panels.js';
11
11
  export type { SummaryData, StressSummaryData, RedteamSummaryData } from './panels.js';
12
12
  export { renderError, renderWarning, getProviderErrorContext } from './errors.js';
13
13
  export type { ErrorContext } from './errors.js';
14
14
  export { LiveTestStatus, Spinner, createSpinner } from './live-status.js';
15
15
  export type { TestStatus } from './live-status.js';
16
+ export { isInteractive, promptProvider, promptModel, promptScenarios, promptConfirm, promptInput, promptPassword, promptSelect, promptApiKeyIfNeeded, getApiKeyEnvVar, runInitWizard, PROVIDER_CHOICES, MODEL_CHOICES, } from './prompts.js';
17
+ export type { InitWizardResult } from './prompts.js';
16
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGjF,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,SAAS,EACT,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrF,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxD,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,EACzB,aAAa,GACd,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,iBAAiB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAGjF,OAAO,EACL,KAAK,EACL,gBAAgB,EAChB,iBAAiB,EACjB,UAAU,EACV,OAAO,EACP,SAAS,EACT,QAAQ,EACR,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrF,YAAY,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAGxD,OAAO,EACL,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,EACzB,aAAa,EACb,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAGtF,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAClF,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,EACL,aAAa,EACb,cAAc,EACd,WAAW,EACX,eAAe,EACf,aAAa,EACb,WAAW,EACX,cAAc,EACd,YAAY,EACZ,oBAAoB,EACpB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,aAAa,GACd,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC"}
@@ -17,9 +17,22 @@ export interface StressSummaryData {
17
17
  duration: number;
18
18
  avgLatency: number;
19
19
  p50Latency: number;
20
+ p90Latency: number;
20
21
  p95Latency: number;
21
22
  p99Latency: number;
22
23
  throughput: number;
24
+ /** Token usage (optional) */
25
+ tokens?: {
26
+ total: number;
27
+ prompt: number;
28
+ completion: number;
29
+ avgPerRequest: number;
30
+ };
31
+ /** Cost estimation (optional) */
32
+ cost?: {
33
+ totalUsd: number;
34
+ model: string;
35
+ };
23
36
  }
24
37
  export interface RedteamSummaryData {
25
38
  totalCases: number;
@@ -46,4 +59,12 @@ export declare function renderRedteamSummaryPanel(data: RedteamSummaryData): str
46
59
  * Render a simple info box
47
60
  */
48
61
  export declare function renderInfoBox(title: string, lines: string[]): string;
62
+ /**
63
+ * Render a styled failure reason for test cases
64
+ * Provides consistent formatting for verbose error output
65
+ */
66
+ export declare function renderFailureReason(reason: string, options?: {
67
+ matcherType?: string;
68
+ indent?: number;
69
+ }): string;
49
70
  //# sourceMappingURL=panels.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../../src/ui/panels.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAiC5D;AAED;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CA0DxE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CA4C1E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAsBpE"}
1
+ {"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../../src/ui/panels.ts"],"names":[],"mappings":"AAAA;;GAEG;AAMH,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,6BAA6B;IAC7B,MAAM,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;QACf,UAAU,EAAE,MAAM,CAAC;QACnB,aAAa,EAAE,MAAM,CAAC;KACvB,CAAC;IACF,iCAAiC;IACjC,IAAI,CAAC,EAAE;QACL,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC5C;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,WAAW,GAAG,MAAM,CAiC5D;AA4BD;;GAEG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,CAiHxE;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CA4C1E;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAsBpE;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IACR,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACA,MAAM,CA0CR"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * Interactive prompts module
3
+ * Provides Inquirer-based user prompts for CLI interactivity
4
+ */
5
+ /**
6
+ * Check if interactive mode is available
7
+ */
8
+ export declare function isInteractive(): boolean;
9
+ /**
10
+ * Provider options for selection
11
+ * Note: Only providers with implemented adapters are included
12
+ */
13
+ export declare const PROVIDER_CHOICES: {
14
+ name: string;
15
+ value: string;
16
+ }[];
17
+ /**
18
+ * Known models by provider - used for validation
19
+ * Updated January 2026
20
+ */
21
+ export declare const KNOWN_MODELS: Record<string, string[]>;
22
+ /**
23
+ * Model choices displayed in the prompt
24
+ * Updated January 2026
25
+ */
26
+ export declare const MODEL_CHOICES: Record<string, {
27
+ name: string;
28
+ value: string;
29
+ }[]>;
30
+ /**
31
+ * Prompt user to select a provider
32
+ */
33
+ export declare function promptProvider(message?: string): Promise<string>;
34
+ /**
35
+ * Prompt user to select a model for a given provider
36
+ * Includes hybrid validation for custom models
37
+ */
38
+ export declare function promptModel(provider: string, message?: string): Promise<string>;
39
+ /**
40
+ * Prompt user to select scenarios from a list
41
+ */
42
+ export declare function promptScenarios(scenarios: {
43
+ path: string;
44
+ name: string;
45
+ }[], message?: string): Promise<string[]>;
46
+ /**
47
+ * Prompt for confirmation
48
+ */
49
+ export declare function promptConfirm(message: string, defaultValue?: boolean): Promise<boolean>;
50
+ /**
51
+ * Prompt for text input
52
+ */
53
+ export declare function promptInput(message: string, options?: {
54
+ default?: string;
55
+ validate?: (input: string) => boolean | string;
56
+ }): Promise<string>;
57
+ /**
58
+ * Prompt for a password/secret (hidden input)
59
+ */
60
+ export declare function promptPassword(message: string, options?: {
61
+ validate?: (input: string) => boolean | string;
62
+ }): Promise<string>;
63
+ /**
64
+ * Prompt for selection from a list
65
+ */
66
+ export declare function promptSelect<T extends string>(message: string, choices: {
67
+ name: string;
68
+ value: T;
69
+ }[]): Promise<T>;
70
+ /**
71
+ * Interactive init wizard configuration
72
+ */
73
+ export interface InitWizardResult {
74
+ projectName: string;
75
+ provider: string;
76
+ model: string;
77
+ storageType: 'local' | 'supabase';
78
+ createExample: boolean;
79
+ }
80
+ /**
81
+ * Run the interactive init wizard
82
+ */
83
+ export declare function runInitWizard(): Promise<InitWizardResult>;
84
+ /**
85
+ * Prompt for API key if not set
86
+ */
87
+ export declare function promptApiKeyIfNeeded(provider: string, envVarName: string): Promise<string | null>;
88
+ /**
89
+ * Get the environment variable name for a provider's API key
90
+ */
91
+ export declare function getApiKeyEnvVar(provider: string): string;
92
+ //# sourceMappingURL=prompts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../src/ui/prompts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;GAEG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAEvC;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB;;;GAQ5B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAgHjD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,CAwD3E,CAAC;AAEF;;GAEG;AACH,wBAAsB,cAAc,CAAC,OAAO,SAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAUpF;AA8QD;;;GAGG;AACH,wBAAsB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,SAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkChG;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,SAAS,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,EAC3C,OAAO,SAA6B,GACnC,OAAO,CAAC,MAAM,EAAE,CAAC,CAoBnB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,UAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAU1F;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,CAAC;CAC3C,GACL,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;GAEG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE;IACP,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,GAAG,MAAM,CAAC;CAC3C,GACL,OAAO,CAAC,MAAM,CAAC,CAWjB;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,MAAM,EACjD,OAAO,EAAE,MAAM,EACf,OAAO,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,CAAC,CAAA;CAAE,EAAE,GACpC,OAAO,CAAC,CAAC,CAAC,CAUZ;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,OAAO,GAAG,UAAU,CAAC;IAClC,aAAa,EAAE,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,gBAAgB,CAAC,CA4C/D;AAED;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CA6BxB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAUxD"}
@@ -1 +1 @@
1
- {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/utils/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,sCAAsC;IACtC,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAClC,wCAAwC;IACxC,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,qCAAqC;IACrC,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B;AAOD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,aAAa,EAAE,aAAa,CAAC;IAC7B,+DAA+D;IAC/D,cAAc,EAAE,cAAc,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CA8ErF;AAuWD;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,MAAM,EACzB,cAAc,CAAC,EAAE,MAAM,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAK5C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAA;CAAE,CAKjE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,MAAM,EACzB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAER;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,GAAG,SAAS,CAEpB"}
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../src/utils/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,MAAM,WAAW,oBAAoB;IACnC,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,sCAAsC;IACtC,UAAU,CAAC,EAAE,aAAa,GAAG,IAAI,CAAC;IAClC,wCAAwC;IACxC,cAAc,CAAC,EAAE,YAAY,CAAC;IAC9B,qCAAqC;IACrC,WAAW,CAAC,EAAE,YAAY,CAAC;CAC5B;AAOD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,aAAa,EAAE,aAAa,CAAC;IAC7B,+DAA+D;IAC/D,cAAc,EAAE,cAAc,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CA8ErF;AA+WD;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,MAAM,EACzB,cAAc,CAAC,EAAE,MAAM,GACtB;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,YAAY,CAAA;CAAE,CAK5C;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB;IAAE,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,MAAM,EAAE,YAAY,GAAG,SAAS,CAAA;CAAE,CAKjE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,WAAW,CAAC,EAAE,MAAM,EACpB,gBAAgB,CAAC,EAAE,MAAM,EACzB,cAAc,CAAC,EAAE,MAAM,GACtB,MAAM,CAER;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,CAAC,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,EACtB,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,GAAG,SAAS,CAEpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artemiskit/cli",
3
- "version": "0.1.8",
3
+ "version": "0.2.0",
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.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",
48
+ "@artemiskit/adapter-openai": "0.1.7",
49
+ "@artemiskit/adapter-vercel-ai": "0.1.7",
50
+ "@artemiskit/core": "0.2.0",
51
+ "@artemiskit/redteam": "0.2.0",
52
+ "@artemiskit/reports": "0.2.0",
53
53
  "chalk": "^5.3.0",
54
54
  "cli-table3": "^0.6.3",
55
55
  "commander": "^12.0.0",
@@ -2,6 +2,9 @@
2
2
  * Compare command - Compare two test runs
3
3
  */
4
4
 
5
+ import { writeFileSync } from 'node:fs';
6
+ import { resolve } from 'node:path';
7
+ import { buildComparisonData, generateCompareHTMLReport } from '@artemiskit/reports';
5
8
  import chalk from 'chalk';
6
9
  import { Command } from 'commander';
7
10
  import { loadConfig } from '../config/loader.js';
@@ -11,6 +14,8 @@ import { createStorage } from '../utils/storage.js';
11
14
  interface CompareOptions {
12
15
  threshold?: number;
13
16
  config?: string;
17
+ html?: string;
18
+ json?: string;
14
19
  }
15
20
 
16
21
  function renderComparisonPanel(
@@ -135,6 +140,8 @@ export function compareCommand(): Command {
135
140
  .argument('<current>', 'Current run ID')
136
141
  .option('--threshold <number>', 'Regression threshold (0-1)', '0.05')
137
142
  .option('--config <path>', 'Path to config file')
143
+ .option('--html <path>', 'Generate HTML comparison report')
144
+ .option('--json <path>', 'Generate JSON comparison report')
138
145
  .action(async (baselineId: string, currentId: string, options: CompareOptions) => {
139
146
  const spinner = createSpinner('Loading runs...');
140
147
  spinner.start();
@@ -165,6 +172,24 @@ export function compareCommand(): Command {
165
172
  const comparison = await storage.compare(baselineId, currentId);
166
173
  const { baseline, current, delta } = comparison;
167
174
 
175
+ // Generate HTML report if requested
176
+ if (options.html) {
177
+ const htmlPath = resolve(options.html);
178
+ const html = generateCompareHTMLReport(baseline, current);
179
+ writeFileSync(htmlPath, html, 'utf-8');
180
+ console.log(`${icons.passed} HTML comparison report saved to: ${chalk.cyan(htmlPath)}`);
181
+ console.log();
182
+ }
183
+
184
+ // Generate JSON report if requested
185
+ if (options.json) {
186
+ const jsonPath = resolve(options.json);
187
+ const comparisonData = buildComparisonData(baseline, current);
188
+ writeFileSync(jsonPath, JSON.stringify(comparisonData, null, 2), 'utf-8');
189
+ console.log(`${icons.passed} JSON comparison report saved to: ${chalk.cyan(jsonPath)}`);
190
+ console.log();
191
+ }
192
+
168
193
  // Show comparison panel
169
194
  if (isTTY) {
170
195
  console.log(renderComparisonPanel(baseline, current, delta));
@@ -7,7 +7,13 @@ import { appendFile, mkdir, readFile, writeFile } from 'node:fs/promises';
7
7
  import { join } from 'node:path';
8
8
  import chalk from 'chalk';
9
9
  import { Command } from 'commander';
10
- import { createSpinner, icons } from '../ui/index.js';
10
+ import {
11
+ type InitWizardResult,
12
+ createSpinner,
13
+ icons,
14
+ isInteractive,
15
+ runInitWizard,
16
+ } from '../ui/index.js';
11
17
  import { checkForUpdateAndNotify, getCurrentVersion } from '../utils/update-checker.js';
12
18
 
13
19
  const DEFAULT_CONFIG = `# ArtemisKit Configuration
@@ -86,6 +92,67 @@ const ENV_KEYS = [
86
92
  'ANTHROPIC_API_KEY=',
87
93
  ];
88
94
 
95
+ /**
96
+ * Generate config content from wizard results
97
+ */
98
+ function generateConfigFromWizard(wizard: InitWizardResult): string {
99
+ const providerConfigs: Record<string, string> = {
100
+ openai: ` openai:
101
+ apiKey: \${OPENAI_API_KEY}
102
+ defaultModel: ${wizard.model}`,
103
+ 'azure-openai': ` azure-openai:
104
+ apiKey: \${AZURE_OPENAI_API_KEY}
105
+ resourceName: \${AZURE_OPENAI_RESOURCE}
106
+ deploymentName: \${AZURE_OPENAI_DEPLOYMENT}
107
+ apiVersion: "2024-02-15-preview"`,
108
+ anthropic: ` anthropic:
109
+ apiKey: \${ANTHROPIC_API_KEY}
110
+ defaultModel: ${wizard.model}`,
111
+ google: ` google:
112
+ apiKey: \${GOOGLE_AI_API_KEY}
113
+ defaultModel: ${wizard.model}`,
114
+ mistral: ` mistral:
115
+ apiKey: \${MISTRAL_API_KEY}
116
+ defaultModel: ${wizard.model}`,
117
+ ollama: ` ollama:
118
+ baseUrl: http://localhost:11434
119
+ defaultModel: ${wizard.model}`,
120
+ };
121
+
122
+ const storageConfig =
123
+ wizard.storageType === 'supabase'
124
+ ? `storage:
125
+ type: supabase
126
+ supabaseUrl: \${SUPABASE_URL}
127
+ supabaseKey: \${SUPABASE_ANON_KEY}`
128
+ : `storage:
129
+ type: local
130
+ basePath: ./artemis-runs`;
131
+
132
+ return `# ArtemisKit Configuration
133
+ project: ${wizard.projectName}
134
+
135
+ # Default provider settings
136
+ provider: ${wizard.provider}
137
+ model: ${wizard.model}
138
+
139
+ # Provider configurations
140
+ providers:
141
+ ${providerConfigs[wizard.provider] || providerConfigs.openai}
142
+
143
+ # Storage configuration
144
+ ${storageConfig}
145
+
146
+ # Scenarios directory
147
+ scenariosDir: ./scenarios
148
+
149
+ # Output settings
150
+ output:
151
+ format: json
152
+ dir: ./artemis-output
153
+ `;
154
+ }
155
+
89
156
  function renderWelcomeBanner(): string {
90
157
  // Brand color for "KIT" portion: #fb923c (orange)
91
158
  const brandColor = chalk.hex('#fb923c');
@@ -230,82 +297,119 @@ export function initCommand(): Command {
230
297
  .description('Initialize ArtemisKit in the current directory')
231
298
  .option('-f, --force', 'Overwrite existing configuration')
232
299
  .option('--skip-env', 'Skip adding environment variables to .env')
233
- .action(async (options: { force?: boolean; skipEnv?: boolean }) => {
234
- const spinner = createSpinner();
235
-
236
- try {
237
- const cwd = process.cwd();
238
-
239
- // Show welcome banner
240
- console.log(renderWelcomeBanner());
241
-
242
- // Step 1: Create directories
243
- spinner.start('Creating project structure...');
244
- await mkdir(join(cwd, 'scenarios'), { recursive: true });
245
- await mkdir(join(cwd, 'artemis-runs'), { recursive: true });
246
- await mkdir(join(cwd, 'artemis-output'), { recursive: true });
247
- spinner.succeed('Created project structure');
248
-
249
- // Step 2: Write config file
250
- const configPath = join(cwd, 'artemis.config.yaml');
251
- const configExists = existsSync(configPath);
252
-
253
- if (configExists && !options.force) {
254
- spinner.info('Config file already exists (use --force to overwrite)');
255
- } else {
256
- spinner.start('Writing configuration...');
257
- await writeFile(configPath, DEFAULT_CONFIG);
258
- spinner.succeed(
259
- configExists ? 'Overwrote artemis.config.yaml' : 'Created artemis.config.yaml'
260
- );
261
- }
300
+ .option('-i, --interactive', 'Run interactive setup wizard')
301
+ .option('-y, --yes', 'Use defaults without prompts (non-interactive)')
302
+ .action(
303
+ async (options: {
304
+ force?: boolean;
305
+ skipEnv?: boolean;
306
+ interactive?: boolean;
307
+ yes?: boolean;
308
+ }) => {
309
+ const spinner = createSpinner();
310
+
311
+ try {
312
+ const cwd = process.cwd();
313
+
314
+ // Show welcome banner
315
+ console.log(renderWelcomeBanner());
316
+
317
+ // Determine if we should run interactive wizard
318
+ const shouldRunWizard =
319
+ options.interactive || (isInteractive() && !options.yes && !options.force);
320
+
321
+ let configContent = DEFAULT_CONFIG;
322
+ let createExample = true;
323
+
324
+ // Run interactive wizard if applicable
325
+ if (shouldRunWizard) {
326
+ try {
327
+ const wizardResult = await runInitWizard();
328
+ configContent = generateConfigFromWizard(wizardResult);
329
+ createExample = wizardResult.createExample;
330
+ console.log(''); // Add spacing after wizard
331
+ } catch (wizardError) {
332
+ // If wizard fails (e.g., user cancels), fall back to defaults
333
+ if ((wizardError as Error).message?.includes('closed')) {
334
+ console.log(chalk.yellow('\n Setup cancelled. Using defaults.\n'));
335
+ } else {
336
+ throw wizardError;
337
+ }
338
+ }
339
+ }
262
340
 
263
- // Step 3: Write example scenario
264
- const scenarioPath = join(cwd, 'scenarios', 'example.yaml');
265
- const scenarioExists = existsSync(scenarioPath);
266
-
267
- if (scenarioExists && !options.force) {
268
- spinner.info('Example scenario already exists (use --force to overwrite)');
269
- } else {
270
- spinner.start('Creating example scenario...');
271
- await writeFile(scenarioPath, DEFAULT_SCENARIO);
272
- spinner.succeed(
273
- scenarioExists ? 'Overwrote scenarios/example.yaml' : 'Created scenarios/example.yaml'
274
- );
275
- }
341
+ // Step 1: Create directories
342
+ spinner.start('Creating project structure...');
343
+ await mkdir(join(cwd, 'scenarios'), { recursive: true });
344
+ await mkdir(join(cwd, 'artemis-runs'), { recursive: true });
345
+ await mkdir(join(cwd, 'artemis-output'), { recursive: true });
346
+ spinner.succeed('Created project structure');
276
347
 
277
- // Step 4: Update .env file
278
- if (!options.skipEnv) {
279
- spinner.start('Updating .env file...');
280
- const { added, skipped } = await appendEnvKeys(cwd);
281
-
282
- if (added.length > 0) {
283
- spinner.succeed(`Added ${added.length} environment variable(s) to .env`);
284
- if (skipped.length > 0) {
285
- console.log(
286
- chalk.dim(
287
- ` ${icons.info} Skipped ${skipped.length} existing key(s): ${skipped.join(', ')}`
288
- )
348
+ // Step 2: Write config file
349
+ const configPath = join(cwd, 'artemis.config.yaml');
350
+ const configExists = existsSync(configPath);
351
+
352
+ if (configExists && !options.force) {
353
+ spinner.info('Config file already exists (use --force to overwrite)');
354
+ } else {
355
+ spinner.start('Writing configuration...');
356
+ await writeFile(configPath, configContent);
357
+ spinner.succeed(
358
+ configExists ? 'Overwrote artemis.config.yaml' : 'Created artemis.config.yaml'
359
+ );
360
+ }
361
+
362
+ // Step 3: Write example scenario (if requested)
363
+ if (createExample) {
364
+ const scenarioPath = join(cwd, 'scenarios', 'example.yaml');
365
+ const scenarioExists = existsSync(scenarioPath);
366
+
367
+ if (scenarioExists && !options.force) {
368
+ spinner.info('Example scenario already exists (use --force to overwrite)');
369
+ } else {
370
+ spinner.start('Creating example scenario...');
371
+ await writeFile(scenarioPath, DEFAULT_SCENARIO);
372
+ spinner.succeed(
373
+ scenarioExists
374
+ ? 'Overwrote scenarios/example.yaml'
375
+ : 'Created scenarios/example.yaml'
289
376
  );
290
377
  }
291
- } else if (skipped.length > 0) {
292
- spinner.info('All environment variables already exist in .env');
293
- } else {
294
- spinner.succeed('Created .env with environment variables');
295
378
  }
296
- }
297
379
 
298
- // Show success panel
299
- console.log(renderSuccessPanel());
380
+ // Step 4: Update .env file
381
+ if (!options.skipEnv) {
382
+ spinner.start('Updating .env file...');
383
+ const { added, skipped } = await appendEnvKeys(cwd);
384
+
385
+ if (added.length > 0) {
386
+ spinner.succeed(`Added ${added.length} environment variable(s) to .env`);
387
+ if (skipped.length > 0) {
388
+ console.log(
389
+ chalk.dim(
390
+ ` ${icons.info} Skipped ${skipped.length} existing key(s): ${skipped.join(', ')}`
391
+ )
392
+ );
393
+ }
394
+ } else if (skipped.length > 0) {
395
+ spinner.info('All environment variables already exist in .env');
396
+ } else {
397
+ spinner.succeed('Created .env with environment variables');
398
+ }
399
+ }
300
400
 
301
- // Non-blocking update check (fire and forget)
302
- checkForUpdateAndNotify();
303
- } catch (error) {
304
- spinner.fail('Error');
305
- console.error(chalk.red(`\n${icons.failed} ${(error as Error).message}`));
306
- process.exit(1);
401
+ // Show success panel
402
+ console.log(renderSuccessPanel());
403
+
404
+ // Non-blocking update check (fire and forget)
405
+ checkForUpdateAndNotify();
406
+ } catch (error) {
407
+ spinner.fail('Error');
408
+ console.error(chalk.red(`\n${icons.failed} ${(error as Error).message}`));
409
+ process.exit(1);
410
+ }
307
411
  }
308
- });
412
+ );
309
413
 
310
414
  return cmd;
311
415
  }