kradle 0.3.1 → 0.3.3

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.
@@ -72,8 +72,7 @@ export default class Init extends Command {
72
72
  // this.log(pc.green("Using Kradle's production environment."));
73
73
  // }
74
74
  this.log();
75
- this.log(pc.yellow("Cloud Analytics are only available in the development environment for now. Development environment will be used."));
76
- const useDev = true;
75
+ const useDev = false;
77
76
  const domain = useDev ? "dev.kradle.ai" : "kradle.ai";
78
77
  let apiKey;
79
78
  if (flags["api-key"]) {
@@ -1,5 +1,5 @@
1
1
  import type z from "zod";
2
- import { type AgentSchemaType, type ChallengeConfigSchemaType, type ChallengeSchemaType, type DownloadUrlResponse, HumanSchema, type RecordingMetadata, type RunStatusSchemaType, type WorldConfigSchemaType, type WorldSchemaType } from "./schemas.js";
2
+ import { type AgentSchemaType, type ChallengeConfigSchemaType, type ChallengeSchemaType, type DashboardUrlResponse, type DownloadUrlResponse, HumanSchema, type RecordingMetadata, type RunStatusSchemaType, type WorldConfigSchemaType, type WorldSchemaType } from "./schemas.js";
3
3
  export declare class ApiClient {
4
4
  private apiUrl;
5
5
  private kradleApiKey;
@@ -130,4 +130,9 @@ export declare class ApiClient {
130
130
  getWorldUploadUrl(slug: string): Promise<string>;
131
131
  getWorldDownloadUrl(slug: string): Promise<DownloadUrlResponse>;
132
132
  uploadWorldFile(slug: string, tarballPath: string): Promise<void>;
133
+ /**
134
+ * Get the dashboard URL for the current environment.
135
+ * @returns The dashboard URL.
136
+ */
137
+ getDashboardUrl(): Promise<DashboardUrlResponse>;
133
138
  }
@@ -1,6 +1,6 @@
1
1
  import { existsSync } from "node:fs";
2
2
  import fs from "node:fs/promises";
3
- import { AgentsResponseSchema, ChallengeSchema, ChallengesResponseSchema, DownloadUrlResponseSchema, HumanSchema, JobResponseSchema, RecordingsListResponseSchema, RunStatusSchema, UploadUrlResponseSchema, WorldSchema, WorldsResponseSchema, } from "./schemas.js";
3
+ import { AgentsResponseSchema, ChallengeSchema, ChallengesResponseSchema, DashboardUrlResponseSchema, DownloadUrlResponseSchema, HumanSchema, JobResponseSchema, RecordingsListResponseSchema, RunStatusSchema, UploadUrlResponseSchema, WorldSchema, WorldsResponseSchema, } from "./schemas.js";
4
4
  const DEFAULT_PAGE_SIZE = 30;
5
5
  const DEFAULT_CHALLENGE_SCHEMA = {
6
6
  slug: "",
@@ -343,4 +343,11 @@ export class ApiClient {
343
343
  throw new Error(`Failed to upload world: ${response.statusText}`);
344
344
  }
345
345
  }
346
+ /**
347
+ * Get the dashboard URL for the current environment.
348
+ * @returns The dashboard URL.
349
+ */
350
+ async getDashboardUrl() {
351
+ return this.get("dashboard", {}, DashboardUrlResponseSchema);
352
+ }
346
353
  }
@@ -144,8 +144,14 @@ export class Experimenter {
144
144
  async loadManifest(version) {
145
145
  const paths = this.getVersionPaths(version);
146
146
  const content = await fs.readFile(paths.manifestPath, "utf-8");
147
- const data = JSON.parse(content);
148
- return ManifestSchema.parse(data);
147
+ try {
148
+ const data = JSON.parse(content);
149
+ return ManifestSchema.parse(data);
150
+ }
151
+ catch (error) {
152
+ console.error(pc.red(`Error loading manifest for version ${version}: ${error instanceof Error ? error.message : String(error)}`));
153
+ throw error;
154
+ }
149
155
  }
150
156
  /**
151
157
  * Load progress from version
@@ -191,7 +197,20 @@ export class Experimenter {
191
197
  "--experimental-transform-types",
192
198
  "--no-warnings",
193
199
  "-e",
194
- `console.log(JSON.stringify(require("${configPath}").main()));`,
200
+ `
201
+ // Disable stdout and stderr
202
+ const oldLog = console.log;
203
+ console.log = () => {};
204
+ console.error = () => {};
205
+ const module = require("${configPath}");
206
+ const manifest = module.main();
207
+
208
+ // Restore stdout
209
+ console.log = oldLog;
210
+
211
+ // Log the manifest
212
+ console.log(JSON.stringify(manifest));
213
+ `,
195
214
  ], {});
196
215
  return JSON.parse(stdout.trim());
197
216
  }
@@ -250,7 +269,14 @@ export class Experimenter {
250
269
  console.log("");
251
270
  }
252
271
  if (options.openMetabase ?? true) {
253
- openInBrowser(`https://daunt-fair.metabaseapp.com/dashboard/10-runs-analysis?run_tags=${versionTag}`);
272
+ try {
273
+ const { url } = await this.api.getDashboardUrl();
274
+ console.log(pc.blackBright(`\nOpening dashboard URL: ${url}?run_tags=${versionTag}`));
275
+ await openInBrowser(`${url}?run_tags=${versionTag}`);
276
+ }
277
+ catch (error) {
278
+ console.error(pc.yellow(`Warning: Failed to fetch dashboard URL: ${error instanceof Error ? error.message : String(error)}`));
279
+ }
254
280
  }
255
281
  const errors = this.runner?.getAllStates().filter((state) => state.status === "error");
256
282
  if (errors?.length > 0) {
@@ -1,6 +1,14 @@
1
1
  const DEFAULT_MAX_CONCURRENT = 5;
2
- const RATE_LIMIT_BACKOFF_MS = 15000;
3
2
  const STATUS_POLL_INTERVAL_MS = 2000;
3
+ const MAX_START_RUN_TRIES = 10;
4
+ /**
5
+ * Exponential backoff time in milliseconds. Starts at 1 second and doubles each attempt.
6
+ * @param currentAttempt - The current attempt number
7
+ * @returns The backoff time in milliseconds
8
+ */
9
+ function getBackoffTime(currentAttempt) {
10
+ return 1000 * 1.5 ** currentAttempt;
11
+ }
4
12
  export class Runner {
5
13
  runs;
6
14
  api;
@@ -139,8 +147,8 @@ export class Runner {
139
147
  * Start a single run
140
148
  */
141
149
  async startRun(index, tries = 0) {
142
- if (tries > 5) {
143
- this.updateState(index, { status: "error", error: "Failed to start run after 3 tries" });
150
+ if (tries > MAX_START_RUN_TRIES) {
151
+ this.updateState(index, { status: "error", error: `Failed to start run after ${MAX_START_RUN_TRIES} tries` });
144
152
  this.completedRuns.add(index);
145
153
  this.activeRuns.delete(index);
146
154
  return;
@@ -182,7 +190,7 @@ export class Runner {
182
190
  // Re-queue for later
183
191
  this.updateState(index, { status: "queued", error: undefined });
184
192
  this.activeRuns.delete(index);
185
- await this.delay(RATE_LIMIT_BACKOFF_MS);
193
+ await this.delay(getBackoffTime(tries));
186
194
  await this.startRun(index, tries + 1);
187
195
  return;
188
196
  }
@@ -225,6 +225,9 @@ export declare const WorldsResponseSchema: z.ZodObject<{
225
225
  }, z.core.$strip>>;
226
226
  nextPageToken: z.ZodOptional<z.ZodString>;
227
227
  }, z.core.$strip>;
228
+ export declare const DashboardUrlResponseSchema: z.ZodObject<{
229
+ url: z.ZodString;
230
+ }, z.core.$strip>;
228
231
  export type ChallengeSchemaType = z.infer<typeof ChallengeSchema>;
229
232
  export type ChallengeConfigSchemaType = z.infer<typeof ChallengeConfigSchema>;
230
233
  export type ChallengesResponseType = z.infer<typeof ChallengesResponseSchema>;
@@ -240,3 +243,4 @@ export type DownloadUrlResponse = z.infer<typeof DownloadUrlResponseSchema>;
240
243
  export type WorldSchemaType = z.infer<typeof WorldSchema>;
241
244
  export type WorldConfigSchemaType = z.infer<typeof WorldConfigSchema>;
242
245
  export type WorldsResponseType = z.infer<typeof WorldsResponseSchema>;
246
+ export type DashboardUrlResponse = z.infer<typeof DashboardUrlResponseSchema>;
@@ -110,3 +110,6 @@ export const WorldsResponseSchema = z.object({
110
110
  worlds: z.array(WorldSchema),
111
111
  nextPageToken: z.string().optional(),
112
112
  });
113
+ export const DashboardUrlResponseSchema = z.object({
114
+ url: z.string(),
115
+ });
@@ -86,62 +86,6 @@
86
86
  "list.js"
87
87
  ]
88
88
  },
89
- "ai-docs:challenges-sdk": {
90
- "aliases": [],
91
- "args": {
92
- "version": {
93
- "description": "SDK version to fetch docs for. If not specified, the locally installed version will be used if available, otherwise the latest version will be used.",
94
- "name": "version",
95
- "required": false
96
- }
97
- },
98
- "description": "Output the @kradle/challenges-sdk API reference documentation for LLMs",
99
- "examples": [
100
- "<%= config.bin %> <%= command.id %>",
101
- "<%= config.bin %> <%= command.id %> 0.2.1",
102
- "<%= config.bin %> <%= command.id %> latest"
103
- ],
104
- "flags": {},
105
- "hasDynamicHelp": false,
106
- "hiddenAliases": [],
107
- "id": "ai-docs:challenges-sdk",
108
- "pluginAlias": "kradle",
109
- "pluginName": "kradle",
110
- "pluginType": "core",
111
- "strict": true,
112
- "enableJsonFlag": false,
113
- "isESM": true,
114
- "relativePath": [
115
- "dist",
116
- "commands",
117
- "ai-docs",
118
- "challenges-sdk.js"
119
- ]
120
- },
121
- "ai-docs:cli": {
122
- "aliases": [],
123
- "args": {},
124
- "description": "Output the Kradle CLI reference documentation for LLMs",
125
- "examples": [
126
- "<%= config.bin %> <%= command.id %>"
127
- ],
128
- "flags": {},
129
- "hasDynamicHelp": false,
130
- "hiddenAliases": [],
131
- "id": "ai-docs:cli",
132
- "pluginAlias": "kradle",
133
- "pluginName": "kradle",
134
- "pluginType": "core",
135
- "strict": true,
136
- "enableJsonFlag": false,
137
- "isESM": true,
138
- "relativePath": [
139
- "dist",
140
- "commands",
141
- "ai-docs",
142
- "cli.js"
143
- ]
144
- },
145
89
  "challenge:build": {
146
90
  "aliases": [],
147
91
  "args": {
@@ -1161,7 +1105,63 @@
1161
1105
  "world",
1162
1106
  "push.js"
1163
1107
  ]
1108
+ },
1109
+ "ai-docs:challenges-sdk": {
1110
+ "aliases": [],
1111
+ "args": {
1112
+ "version": {
1113
+ "description": "SDK version to fetch docs for. If not specified, the locally installed version will be used if available, otherwise the latest version will be used.",
1114
+ "name": "version",
1115
+ "required": false
1116
+ }
1117
+ },
1118
+ "description": "Output the @kradle/challenges-sdk API reference documentation for LLMs",
1119
+ "examples": [
1120
+ "<%= config.bin %> <%= command.id %>",
1121
+ "<%= config.bin %> <%= command.id %> 0.2.1",
1122
+ "<%= config.bin %> <%= command.id %> latest"
1123
+ ],
1124
+ "flags": {},
1125
+ "hasDynamicHelp": false,
1126
+ "hiddenAliases": [],
1127
+ "id": "ai-docs:challenges-sdk",
1128
+ "pluginAlias": "kradle",
1129
+ "pluginName": "kradle",
1130
+ "pluginType": "core",
1131
+ "strict": true,
1132
+ "enableJsonFlag": false,
1133
+ "isESM": true,
1134
+ "relativePath": [
1135
+ "dist",
1136
+ "commands",
1137
+ "ai-docs",
1138
+ "challenges-sdk.js"
1139
+ ]
1140
+ },
1141
+ "ai-docs:cli": {
1142
+ "aliases": [],
1143
+ "args": {},
1144
+ "description": "Output the Kradle CLI reference documentation for LLMs",
1145
+ "examples": [
1146
+ "<%= config.bin %> <%= command.id %>"
1147
+ ],
1148
+ "flags": {},
1149
+ "hasDynamicHelp": false,
1150
+ "hiddenAliases": [],
1151
+ "id": "ai-docs:cli",
1152
+ "pluginAlias": "kradle",
1153
+ "pluginName": "kradle",
1154
+ "pluginType": "core",
1155
+ "strict": true,
1156
+ "enableJsonFlag": false,
1157
+ "isESM": true,
1158
+ "relativePath": [
1159
+ "dist",
1160
+ "commands",
1161
+ "ai-docs",
1162
+ "cli.js"
1163
+ ]
1164
1164
  }
1165
1165
  },
1166
- "version": "0.3.1"
1166
+ "version": "0.3.3"
1167
1167
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kradle",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Kradle's CLI. Manage challenges, experiments, agents and more!",
5
5
  "keywords": [
6
6
  "cli"
@@ -1,5 +1,5 @@
1
- KRADLE_API_URL=https://api.kradle.ai/v0 #https://dev-api.kradle.ai/v0
2
- KRADLE_WEB_URL=https://kradle.ai #https://dev.kradle.ai
1
+ KRADLE_API_URL=https://api.kradle.ai/v0
2
+ KRADLE_WEB_URL=https://kradle.ai
3
3
  KRADLE_STUDIO_API_URL=http://localhost:2999/api/v0
4
- KRADLE_STUDIO_URL=kradle://open #kradle-dev://open
5
- KRADLE_CHALLENGES_PATH=~/Documents/kradle-studio/challenges
4
+ KRADLE_STUDIO_URL=kradle://open
5
+ KRADLE_CHALLENGES_PATH=~/Documents/kradle-studio/challenges