@kradle/cli 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -3
- package/dist/lib/api-client.js +7 -1
- package/dist/lib/evaluation/evaluator.js +8 -15
- package/dist/lib/evaluation/index.d.ts +1 -1
- package/dist/lib/evaluation/index.js +1 -1
- package/dist/lib/evaluation/tui.js +1 -0
- package/dist/lib/evaluation/types.d.ts +1 -0
- package/dist/lib/schemas.d.ts +2 -0
- package/dist/lib/schemas.js +1 -0
- package/dist/lib/utils.d.ts +7 -0
- package/dist/lib/utils.js +21 -1
- package/oclif.manifest.json +1 -1
- package/package.json +3 -4
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Kradle's CLI for managing Minecraft challenges, evaluations, agents, and more!
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Installation
|
|
6
6
|
|
|
7
7
|
1. Install Kradle's CLI globally
|
|
8
8
|
```
|
|
@@ -48,7 +48,7 @@ KRADLE_API_KEY=your-api-key
|
|
|
48
48
|
KRADLE_CHALLENGES_PATH=~/Documents/kradle-studio/challenges
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
## Commands
|
|
51
|
+
## Challenge Commands
|
|
52
52
|
|
|
53
53
|
### Create Challenge
|
|
54
54
|
|
|
@@ -125,7 +125,7 @@ kradle challenge multi-upload
|
|
|
125
125
|
|
|
126
126
|
Provides an interactive UI to select multiple challenges and uploads them in parallel.
|
|
127
127
|
|
|
128
|
-
|
|
128
|
+
## Evaluations commands
|
|
129
129
|
|
|
130
130
|
Plan and execute batches of runs across challenges/agents, with resumable iterations and a TUI.
|
|
131
131
|
|
|
@@ -148,6 +148,23 @@ Features:
|
|
|
148
148
|
- Ink TUI: live status counts, elapsed times, scrollable run list; keys `q/Ctrl+C` quit, `↑/↓/j/k` move, `o` open run URL.
|
|
149
149
|
- Per-iteration manifest: generated from the evaluation `config.ts` into `manifest.json` before runs start.
|
|
150
150
|
|
|
151
|
+
## Publishing a New Version
|
|
152
|
+
|
|
153
|
+
The CLI uses GitHub Actions for automated releases. To publish a new version:
|
|
154
|
+
|
|
155
|
+
1. **Go to Actions** in the GitHub repository
|
|
156
|
+
2. **Select "Create Release PR"** workflow from the sidebar
|
|
157
|
+
3. **Click "Run workflow"** and choose the release type:
|
|
158
|
+
- `patch` - Bug fixes (0.0.5 → 0.0.6)
|
|
159
|
+
- `minor` - New features (0.0.5 → 0.1.0)
|
|
160
|
+
- `major` - Breaking changes (0.0.5 → 1.0.0)
|
|
161
|
+
4. **Review and merge** the automatically created PR
|
|
162
|
+
5. **Done!** The package is automatically published to npm when the PR is merged
|
|
163
|
+
|
|
164
|
+
### Setup (one-time)
|
|
165
|
+
|
|
166
|
+
For the publish workflow to work, we're using [NPM Trusted Publishers](https://docs.npmjs.com/trusted-publishers).
|
|
167
|
+
|
|
151
168
|
## Development
|
|
152
169
|
|
|
153
170
|
### Setup
|
package/dist/lib/api-client.js
CHANGED
|
@@ -12,7 +12,13 @@ const DEFAULT_CHALLENGE_SCHEMA = {
|
|
|
12
12
|
objective: {
|
|
13
13
|
fieldName: "success_rate",
|
|
14
14
|
direction: "maximize",
|
|
15
|
-
}
|
|
15
|
+
} /*
|
|
16
|
+
endStates: {
|
|
17
|
+
"red": "Red team only wins",
|
|
18
|
+
"blue": "Blue team only wins",
|
|
19
|
+
"both": "Both teams win",
|
|
20
|
+
"none": "No team wins",
|
|
21
|
+
},*/,
|
|
16
22
|
};
|
|
17
23
|
export class ApiClient {
|
|
18
24
|
config;
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { exec } from "node:child_process";
|
|
2
1
|
import fs from "node:fs/promises";
|
|
3
2
|
import path from "node:path";
|
|
4
|
-
import { executeNodeCommand } from "../utils.js";
|
|
3
|
+
import { executeNodeCommand, openInBrowser } from "../utils.js";
|
|
5
4
|
import { Runner } from "./runner.js";
|
|
6
5
|
import { TUI } from "./tui.js";
|
|
7
6
|
import { EvaluationMetadataSchema, ManifestSchema, ProgressSchema } from "./types.js";
|
|
@@ -195,7 +194,9 @@ export class Evaluator {
|
|
|
195
194
|
// Load manifest
|
|
196
195
|
const manifest = await this.loadManifest(iteration);
|
|
197
196
|
// We have 2 mandatory tags: "eval-<evaluation-name>" and "eval-<evaluation-name>-iteration-<iteration>"
|
|
198
|
-
const
|
|
197
|
+
const evaluationTag = `eval-${this.name}`;
|
|
198
|
+
const iterationTag = `${evaluationTag}-iteration-${iteration}`;
|
|
199
|
+
const tags = [evaluationTag, iterationTag, ...(manifest.tags ?? [])];
|
|
199
200
|
// Create runner
|
|
200
201
|
this.runner = new Runner(manifest.runs, this.api, this.config.WEB_URL, {
|
|
201
202
|
maxConcurrent: options.maxConcurrent,
|
|
@@ -232,6 +233,9 @@ export class Evaluator {
|
|
|
232
233
|
if (errors?.length > 0) {
|
|
233
234
|
throw new Error(`${errors.map((error) => error.error).join("\n\n")}`);
|
|
234
235
|
}
|
|
236
|
+
if (options.openMetabase ?? true) {
|
|
237
|
+
openInBrowser(`https://daunt-fair.metabaseapp.com/dashboard/10-runs-analysis&tags=${iterationTag}`);
|
|
238
|
+
}
|
|
235
239
|
}
|
|
236
240
|
/**
|
|
237
241
|
* Handle state change from runner
|
|
@@ -258,18 +262,7 @@ export class Evaluator {
|
|
|
258
262
|
openRun(index) {
|
|
259
263
|
const url = this.runner?.getRunUrl(index);
|
|
260
264
|
if (url) {
|
|
261
|
-
|
|
262
|
-
let command;
|
|
263
|
-
if (platform === "darwin") {
|
|
264
|
-
command = `open "${url}"`;
|
|
265
|
-
}
|
|
266
|
-
else if (platform === "win32") {
|
|
267
|
-
command = `start "${url}"`;
|
|
268
|
-
}
|
|
269
|
-
else {
|
|
270
|
-
command = `xdg-open "${url}"`;
|
|
271
|
-
}
|
|
272
|
-
exec(command);
|
|
265
|
+
openInBrowser(url);
|
|
273
266
|
}
|
|
274
267
|
}
|
|
275
268
|
}
|
|
@@ -35,6 +35,7 @@ const RenderRunLine = ({ state, total, isSelected, padding, }) => {
|
|
|
35
35
|
const agents = state.config.participants.map((p) => p.agent.split(":").pop() ?? p.agent).join(", ");
|
|
36
36
|
const summary = `${state.config.challenge_slug} (${agents})`;
|
|
37
37
|
const maxSummaryLength = getVisibleColumns() - indexLabel.length - statusLabel.length - (elapsedLabel ? elapsedLabel.length : 0) - 4; // 4 for the spaces and emoji
|
|
38
|
+
// biome-ignore lint/style/useTemplate: template literal would be less readable
|
|
38
39
|
const summaryText = summary.length > maxSummaryLength ? summary.slice(0, maxSummaryLength - 1) + "…" : summary;
|
|
39
40
|
return (_jsxs(Text, { inverse: isSelected, children: [_jsx(Text, { color: color, children: icon }), " ", indexLabel, " ", _jsx(Text, { color: color, children: statusLabel }), elapsedLabel ? (_jsxs(_Fragment, { children: [" ", _jsx(Text, { dimColor: true, children: elapsedLabel })] })) : null, " ", _jsx(Text, { dimColor: true, children: summaryText })] }));
|
|
40
41
|
};
|
|
@@ -120,6 +120,7 @@ export type EvaluationMetadata = z.infer<typeof EvaluationMetadataSchema>;
|
|
|
120
120
|
export interface EvaluationOptions {
|
|
121
121
|
new: boolean;
|
|
122
122
|
maxConcurrent: number;
|
|
123
|
+
openMetabase?: boolean;
|
|
123
124
|
}
|
|
124
125
|
export declare const STATUS_ICONS: Record<RunStatus, {
|
|
125
126
|
icon: string;
|
package/dist/lib/schemas.d.ts
CHANGED
|
@@ -35,6 +35,7 @@ export declare const ChallengeSchema: z.ZodObject<{
|
|
|
35
35
|
minimize: "minimize";
|
|
36
36
|
}>;
|
|
37
37
|
}, z.core.$strip>;
|
|
38
|
+
endStates: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
38
39
|
creationTime: z.ZodOptional<z.ZodString>;
|
|
39
40
|
updateTime: z.ZodOptional<z.ZodString>;
|
|
40
41
|
creator: z.ZodOptional<z.ZodString>;
|
|
@@ -76,6 +77,7 @@ export declare const ChallengesResponseSchema: z.ZodObject<{
|
|
|
76
77
|
minimize: "minimize";
|
|
77
78
|
}>;
|
|
78
79
|
}, z.core.$strip>;
|
|
80
|
+
endStates: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
79
81
|
creationTime: z.ZodOptional<z.ZodString>;
|
|
80
82
|
updateTime: z.ZodOptional<z.ZodString>;
|
|
81
83
|
creator: z.ZodOptional<z.ZodString>;
|
package/dist/lib/schemas.js
CHANGED
|
@@ -23,6 +23,7 @@ export const ChallengeSchema = z.object({
|
|
|
23
23
|
fieldName: z.string(),
|
|
24
24
|
direction: z.enum(["maximize", "minimize"]),
|
|
25
25
|
}),
|
|
26
|
+
endStates: z.record(z.string(), z.string()).optional(),
|
|
26
27
|
creationTime: z.string().optional(),
|
|
27
28
|
updateTime: z.string().optional(),
|
|
28
29
|
creator: z.string().optional(),
|
package/dist/lib/utils.d.ts
CHANGED
|
@@ -87,3 +87,10 @@ export declare function executeCommand(command: string, args: string[], options?
|
|
|
87
87
|
* @returns A promise that resolves with the stdout of the command.
|
|
88
88
|
*/
|
|
89
89
|
export declare function executeNodeCommand(args: string[], config: Config): Promise<string>;
|
|
90
|
+
/**
|
|
91
|
+
* Open a URL in the default browser.
|
|
92
|
+
* This is fire-and-forget, so we don't wait for it to complete.
|
|
93
|
+
*
|
|
94
|
+
* @param url The URL to open.
|
|
95
|
+
*/
|
|
96
|
+
export declare function openInBrowser(url: string): void;
|
package/dist/lib/utils.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { fork, spawn } from "node:child_process";
|
|
1
|
+
import { exec, fork, spawn } from "node:child_process";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import os from "node:os";
|
|
4
4
|
import path from "node:path";
|
|
@@ -168,3 +168,23 @@ export async function executeCommand(command, args, options) {
|
|
|
168
168
|
export async function executeNodeCommand(args, config) {
|
|
169
169
|
return executeCommand(process.execPath, args, { env: config });
|
|
170
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* Open a URL in the default browser.
|
|
173
|
+
* This is fire-and-forget, so we don't wait for it to complete.
|
|
174
|
+
*
|
|
175
|
+
* @param url The URL to open.
|
|
176
|
+
*/
|
|
177
|
+
export function openInBrowser(url) {
|
|
178
|
+
const platform = process.platform;
|
|
179
|
+
let command;
|
|
180
|
+
if (platform === "darwin") {
|
|
181
|
+
command = `open "${url}"`;
|
|
182
|
+
}
|
|
183
|
+
else if (platform === "win32") {
|
|
184
|
+
command = `start "${url}"`;
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
command = `xdg-open "${url}"`;
|
|
188
|
+
}
|
|
189
|
+
exec(command);
|
|
190
|
+
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kradle/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Kradle's CLI. Manage challenges, evaluations, agents and more!",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli"
|
|
@@ -24,11 +24,10 @@
|
|
|
24
24
|
"build": "rm -rf dist && tsc",
|
|
25
25
|
"watch": "rm -rf dist && tsc --watch",
|
|
26
26
|
"lint": "biome check .",
|
|
27
|
-
"
|
|
28
|
-
"format": "biome format --write .",
|
|
27
|
+
"format": "biome format --write . && biome check --write .",
|
|
29
28
|
"prepack": "sh scripts/prepack.sh",
|
|
30
29
|
"postpack": "sh scripts/postpack.sh",
|
|
31
|
-
"version": "oclif readme && git add README.md"
|
|
30
|
+
"version": "oclif manifest && oclif readme && git add README.md"
|
|
32
31
|
},
|
|
33
32
|
"dependencies": {
|
|
34
33
|
"@google-cloud/storage": "^7.17.3",
|