ai-hero-cli 0.0.24 → 0.0.26

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.
Files changed (2) hide show
  1. package/bin.cjs +118 -85
  2. package/package.json +1 -1
package/bin.cjs CHANGED
@@ -5595,8 +5595,8 @@ ${ctx.indent}`;
5595
5595
  const vs0 = valueStr[0];
5596
5596
  const nl0 = valueStr.indexOf("\n");
5597
5597
  const hasNewline = nl0 !== -1;
5598
- const flow2 = ctx.inFlow ?? value5.flow ?? value5.items.length === 0;
5599
- if (hasNewline || !flow2) {
5598
+ const flow3 = ctx.inFlow ?? value5.flow ?? value5.items.length === 0;
5599
+ if (hasNewline || !flow3) {
5600
5600
  let hasPropsLine = false;
5601
5601
  if (hasNewline && (vs0 === "&" || vs0 === "!")) {
5602
5602
  let sp0 = valueStr.indexOf(" ");
@@ -5814,8 +5814,8 @@ var require_stringifyCollection = __commonJS({
5814
5814
  var stringify2 = require_stringify();
5815
5815
  var stringifyComment = require_stringifyComment();
5816
5816
  function stringifyCollection(collection, ctx, options3) {
5817
- const flow2 = ctx.inFlow ?? collection.flow;
5818
- const stringify3 = flow2 ? stringifyFlowCollection : stringifyBlockCollection;
5817
+ const flow3 = ctx.inFlow ?? collection.flow;
5818
+ const stringify3 = flow3 ? stringifyFlowCollection : stringifyBlockCollection;
5819
5819
  return stringify3(collection, ctx, options3);
5820
5820
  }
5821
5821
  function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
@@ -7426,7 +7426,7 @@ var require_Document = __commonJS({
7426
7426
  options3 = replacer;
7427
7427
  replacer = void 0;
7428
7428
  }
7429
- const { aliasDuplicateObjects, anchorPrefix, flow: flow2, keepUndefined, onTagObj, tag: tag4 } = options3 ?? {};
7429
+ const { aliasDuplicateObjects, anchorPrefix, flow: flow3, keepUndefined, onTagObj, tag: tag4 } = options3 ?? {};
7430
7430
  const { onAnchor, setAnchors, sourceObjects } = anchors.createNodeAnchors(
7431
7431
  this,
7432
7432
  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
@@ -7442,7 +7442,7 @@ var require_Document = __commonJS({
7442
7442
  sourceObjects
7443
7443
  };
7444
7444
  const node = createNode.createNode(value5, tag4, ctx);
7445
- if (flow2 && identity3.isCollection(node))
7445
+ if (flow3 && identity3.isCollection(node))
7446
7446
  node.flow = true;
7447
7447
  setAnchors();
7448
7448
  return node;
@@ -7688,7 +7688,7 @@ ${pointer}
7688
7688
  // node_modules/.pnpm/yaml@2.8.1/node_modules/yaml/dist/compose/resolve-props.js
7689
7689
  var require_resolve_props = __commonJS({
7690
7690
  "node_modules/.pnpm/yaml@2.8.1/node_modules/yaml/dist/compose/resolve-props.js"(exports) {
7691
- function resolveProps(tokens, { flow: flow2, indicator, next, offset, onError: onError4, parentIndent, startOnNewline }) {
7691
+ function resolveProps(tokens, { flow: flow3, indicator, next, offset, onError: onError4, parentIndent, startOnNewline }) {
7692
7692
  let spaceBefore = false;
7693
7693
  let atNewline = startOnNewline;
7694
7694
  let hasSpace = startOnNewline;
@@ -7717,7 +7717,7 @@ var require_resolve_props = __commonJS({
7717
7717
  }
7718
7718
  switch (token.type) {
7719
7719
  case "space":
7720
- if (!flow2 && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) {
7720
+ if (!flow3 && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) {
7721
7721
  tab = token;
7722
7722
  }
7723
7723
  hasSpace = true;
@@ -7773,15 +7773,15 @@ var require_resolve_props = __commonJS({
7773
7773
  if (anchor || tag4)
7774
7774
  onError4(token, "BAD_PROP_ORDER", `Anchors and tags must be after the ${token.source} indicator`);
7775
7775
  if (found)
7776
- onError4(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow2 ?? "collection"}`);
7776
+ onError4(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow3 ?? "collection"}`);
7777
7777
  found = token;
7778
7778
  atNewline = indicator === "seq-item-ind" || indicator === "explicit-key-ind";
7779
7779
  hasSpace = false;
7780
7780
  break;
7781
7781
  case "comma":
7782
- if (flow2) {
7782
+ if (flow3) {
7783
7783
  if (comma3)
7784
- onError4(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow2}`);
7784
+ onError4(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow3}`);
7785
7785
  comma3 = token;
7786
7786
  atNewline = false;
7787
7787
  hasSpace = false;
@@ -42031,7 +42031,7 @@ var require_lodash = __commonJS({
42031
42031
  function defaultTo(value5, defaultValue) {
42032
42032
  return value5 == null || value5 !== value5 ? defaultValue : value5;
42033
42033
  }
42034
- var flow2 = createFlow();
42034
+ var flow3 = createFlow();
42035
42035
  var flowRight = createFlow(true);
42036
42036
  function identity3(value5) {
42037
42037
  return value5;
@@ -42231,7 +42231,7 @@ var require_lodash = __commonJS({
42231
42231
  lodash.flattenDeep = flattenDeep;
42232
42232
  lodash.flattenDepth = flattenDepth;
42233
42233
  lodash.flip = flip3;
42234
- lodash.flow = flow2;
42234
+ lodash.flow = flow3;
42235
42235
  lodash.flowRight = flowRight;
42236
42236
  lodash.fromPairs = fromPairs;
42237
42237
  lodash.functions = functions;
@@ -51999,8 +51999,8 @@ var require_main = __commonJS({
51999
51999
  const shortPaths = [];
52000
52000
  for (const filePath of optionPaths) {
52001
52001
  try {
52002
- const relative2 = path11.relative(process.cwd(), filePath);
52003
- shortPaths.push(relative2);
52002
+ const relative3 = path11.relative(process.cwd(), filePath);
52003
+ shortPaths.push(relative3);
52004
52004
  } catch (e) {
52005
52005
  if (debug3) {
52006
52006
  _debug(`Failed to load ${filePath} ${e.message}`);
@@ -83495,7 +83495,7 @@ var runLesson = Effect_exports.fn("runLesson")(function* (opts) {
83495
83495
  const command2 = Command_exports.make(
83496
83496
  "pnpm",
83497
83497
  "tsx",
83498
- "--env-file",
83498
+ `--env-file`,
83499
83499
  envFilePath,
83500
83500
  mainFile
83501
83501
  ).pipe(
@@ -83699,6 +83699,9 @@ var logReadmeFile = Effect_exports.fn("logReadmeFile")(
83699
83699
  );
83700
83700
  }
83701
83701
  );
83702
+ var normalizeExerciseNumber = (str) => {
83703
+ return str.replace(/\b0+(\d)/g, "$1");
83704
+ };
83702
83705
  var chooseLessonAndRunIt = (opts) => Effect_exports.gen(function* () {
83703
83706
  const lessonService = yield* LessonParserService;
83704
83707
  const lessons = yield* lessonService.getLessonsFromRepo(
@@ -83717,11 +83720,12 @@ var chooseLessonAndRunIt = (opts) => Effect_exports.gen(function* () {
83717
83720
  description: lesson.name
83718
83721
  })),
83719
83722
  suggest: async (input, choices) => {
83720
- return choices.filter(
83721
- (choice6) => `${choice6.title}-${choice6.description}`.includes(
83722
- input
83723
- )
83724
- );
83723
+ const normalizedInput = normalizeExerciseNumber(input);
83724
+ return choices.filter((choice6) => {
83725
+ const searchText = `${choice6.title}-${choice6.description}`;
83726
+ const normalizedSearchText = normalizeExerciseNumber(searchText);
83727
+ return searchText.includes(input) || normalizedSearchText.includes(normalizedInput);
83728
+ });
83725
83729
  }
83726
83730
  }
83727
83731
  ])
@@ -83762,11 +83766,15 @@ var exercise = Command_exports2.make(
83762
83766
  },
83763
83767
  ({ cwd, debug: debug3, envFilePath, lesson, root, simple: simple3 }) => {
83764
83768
  return Effect_exports.gen(function* () {
83769
+ const resolvedEnvFilePath = path4__namespace.relative(
83770
+ cwd,
83771
+ envFilePath
83772
+ );
83765
83773
  if (Option_exports.isSome(lesson)) {
83766
83774
  return yield* runLesson({
83767
83775
  lesson: lesson.value,
83768
83776
  root,
83769
- envFilePath,
83777
+ envFilePath: resolvedEnvFilePath,
83770
83778
  cwd,
83771
83779
  forceSubfolderIndex: void 0,
83772
83780
  simple: simple3
@@ -83778,7 +83786,7 @@ var exercise = Command_exports2.make(
83778
83786
  }
83779
83787
  return yield* chooseLessonAndRunIt({
83780
83788
  root,
83781
- envFilePath,
83789
+ envFilePath: resolvedEnvFilePath,
83782
83790
  cwd,
83783
83791
  simple: simple3
83784
83792
  }).pipe(
@@ -83876,7 +83884,7 @@ var runLessonSimple = (opts) => Effect_exports.gen(function* () {
83876
83884
  util.styleText("bold", `Running ${lesson} ${subfolder}...`)
83877
83885
  );
83878
83886
  ChildProcess.execSync(
83879
- `pnpm tsx --env-file "${envFilePath}" "${mainFile}"`,
83887
+ `pnpm tsx --env-file="${envFilePath}" "${mainFile}"`,
83880
83888
  {
83881
83889
  stdio: "inherit",
83882
83890
  cwd
@@ -84214,6 +84222,12 @@ var lint = Command_exports2.make(
84214
84222
  ".gitkeep file found in the exercise."
84215
84223
  );
84216
84224
  }
84225
+ if (files.some((file6) => file6.includes("speaker-notes.md"))) {
84226
+ errorTracker.addError(
84227
+ lesson,
84228
+ "speaker-notes.md file found in the exercise. This should not be exposed to users."
84229
+ );
84230
+ }
84217
84231
  }
84218
84232
  const readmeContents = allReadmeContents.join("\n");
84219
84233
  const referenceLessons = lessons.filter(
@@ -84350,11 +84364,7 @@ var ImageUploadError = class extends Data_exports.TaggedError(
84350
84364
  var uploadToCloudinary = Command_exports2.make(
84351
84365
  "upload-to-cloudinary",
84352
84366
  {
84353
- filePath: Options_exports.text("file-path").pipe(
84354
- Options_exports.withDescription(
84355
- "The markdown file to extract images from"
84356
- )
84357
- ),
84367
+ root: rootOption,
84358
84368
  cwd: Options_exports.text("cwd").pipe(
84359
84369
  Options_exports.withDescription("The working directory"),
84360
84370
  Options_exports.withDefault(process.cwd())
@@ -84364,7 +84374,7 @@ var uploadToCloudinary = Command_exports2.make(
84364
84374
  Effect_exports.fn("upload-to-cloudinary")(function* ({
84365
84375
  cwd,
84366
84376
  envFilePath,
84367
- filePath
84377
+ root
84368
84378
  }) {
84369
84379
  const fs = yield* FileSystem_exports.FileSystem;
84370
84380
  const envConfig = dotenv.config({
@@ -84394,66 +84404,87 @@ var uploadToCloudinary = Command_exports2.make(
84394
84404
  api_secret: apiSecret,
84395
84405
  cloud_name: cloudName
84396
84406
  });
84397
- const fileContent5 = yield* fs.readFileString(filePath);
84398
- const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
84399
- const imageMatches = Array.from(
84400
- fileContent5.matchAll(imageRegex)
84401
- );
84402
- if (imageMatches.length === 0) {
84403
- return yield* new NoImagesFoundError({
84404
- message: "No images found in the markdown file"
84405
- });
84407
+ const lessonParserService = yield* LessonParserService;
84408
+ const lessons = yield* lessonParserService.getLessonsFromRepo(root);
84409
+ const readmeFiles = [];
84410
+ for (const lesson of lessons) {
84411
+ const allFiles = yield* lesson.allFiles();
84412
+ const foundReadmes = allFiles.filter(
84413
+ (file6) => file6.includes("readme.md")
84414
+ );
84415
+ for (const readmeFile of foundReadmes) {
84416
+ readmeFiles.push(readmeFile);
84417
+ }
84406
84418
  }
84407
- let updatedContent = fileContent5;
84408
- const markdownDir = path4__namespace.dirname(filePath);
84409
- for (const [fullMatch, altText, imagePath] of imageMatches) {
84410
- let resolvedImagePath;
84411
- if (imagePath.startsWith("/")) {
84412
- resolvedImagePath = path4__namespace.resolve(
84413
- cwd,
84414
- // Remove the leading slash
84415
- imagePath.slice(1)
84416
- );
84417
- } else if (imagePath.startsWith("http")) {
84418
- continue;
84419
- } else {
84420
- resolvedImagePath = path4__namespace.resolve(markdownDir, imagePath);
84419
+ for (const readmeFile of readmeFiles) {
84420
+ const fileContent5 = yield* fs.readFileString(readmeFile);
84421
+ const imageRegex = /!\[([^\]]*)\]\(([^)]+)\)/g;
84422
+ const imageMatches = Array.from(
84423
+ fileContent5.matchAll(imageRegex)
84424
+ );
84425
+ if (imageMatches.length === 0) {
84426
+ return yield* new NoImagesFoundError({
84427
+ message: "No images found in the markdown file"
84428
+ });
84421
84429
  }
84422
- const imageExists = yield* fs.exists(resolvedImagePath);
84423
- if (!imageExists) {
84430
+ let updatedContent = fileContent5;
84431
+ const markdownDir = path4__namespace.dirname(readmeFile);
84432
+ for (const [
84433
+ fullMatch,
84434
+ altText,
84435
+ imagePath
84436
+ ] of imageMatches) {
84437
+ let resolvedImagePath;
84438
+ if (imagePath.startsWith("/")) {
84439
+ resolvedImagePath = path4__namespace.resolve(
84440
+ cwd,
84441
+ // Remove the leading slash
84442
+ imagePath.slice(1)
84443
+ );
84444
+ } else if (imagePath.startsWith("http")) {
84445
+ continue;
84446
+ } else {
84447
+ resolvedImagePath = path4__namespace.resolve(
84448
+ markdownDir,
84449
+ imagePath
84450
+ );
84451
+ }
84452
+ const imageExists = yield* fs.exists(resolvedImagePath);
84453
+ if (!imageExists) {
84454
+ yield* Console_exports.log(
84455
+ `Warning: Image file not found: ${resolvedImagePath}`
84456
+ );
84457
+ continue;
84458
+ }
84459
+ yield* Console_exports.log(`Uploading: ${resolvedImagePath}`);
84460
+ const uploadResult = yield* Effect_exports.tryPromise({
84461
+ try: () => {
84462
+ return import_cloudinary.v2.uploader.upload(
84463
+ resolvedImagePath,
84464
+ {
84465
+ resource_type: "auto",
84466
+ folder: "ai-hero-images"
84467
+ // Optional: organize uploads in a folder
84468
+ }
84469
+ );
84470
+ },
84471
+ catch: (error4) => {
84472
+ return new ImageUploadError({
84473
+ message: `Error uploading ${imagePath}`,
84474
+ cause: error4
84475
+ });
84476
+ }
84477
+ });
84478
+ updatedContent = updatedContent.replace(
84479
+ fullMatch,
84480
+ `![${altText}](${uploadResult.secure_url})`
84481
+ );
84424
84482
  yield* Console_exports.log(
84425
- `Warning: Image file not found: ${resolvedImagePath}`
84483
+ `\u2713 Uploaded: ${uploadResult.secure_url}`
84426
84484
  );
84427
- continue;
84428
84485
  }
84429
- yield* Console_exports.log(`Uploading: ${resolvedImagePath}`);
84430
- const uploadResult = yield* Effect_exports.tryPromise({
84431
- try: () => {
84432
- return import_cloudinary.v2.uploader.upload(resolvedImagePath, {
84433
- resource_type: "auto",
84434
- folder: "ai-hero-images"
84435
- // Optional: organize uploads in a folder
84436
- });
84437
- },
84438
- catch: (error4) => {
84439
- return new ImageUploadError({
84440
- message: `Error uploading ${imagePath}`,
84441
- cause: error4
84442
- });
84443
- }
84444
- });
84445
- updatedContent = updatedContent.replace(
84446
- fullMatch,
84447
- `![${altText}](${uploadResult.secure_url})`
84448
- );
84449
- yield* Console_exports.log(
84450
- `\u2713 Uploaded: ${uploadResult.secure_url}`
84451
- );
84486
+ yield* fs.writeFileString(readmeFile, updatedContent);
84452
84487
  }
84453
- yield* fs.writeFileString(filePath, updatedContent);
84454
- yield* Console_exports.log(
84455
- "\u2713 Markdown file updated with Cloudinary URLs"
84456
- );
84457
84488
  })
84458
84489
  ).pipe(
84459
84490
  Command_exports2.withDescription(
@@ -84501,7 +84532,9 @@ var upgradePackages = Command_exports2.make(
84501
84532
  "upgrade",
84502
84533
  "ai@latest",
84503
84534
  "@ai-sdk/*@latest",
84504
- "ai-hero-cli@latest"
84535
+ "ai-hero-cli@latest",
84536
+ "evalite@latest",
84537
+ "vitest@latest"
84505
84538
  ).pipe(
84506
84539
  verbose ? Command_exports.stdout("inherit") : Command_exports.stdout("pipe"),
84507
84540
  verbose ? Command_exports.stderr("inherit") : Command_exports.stderr("pipe"),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-hero-cli",
3
- "version": "0.0.24",
3
+ "version": "0.0.26",
4
4
  "type": "module",
5
5
  "description": "The CLI used to run exercises for the AI Hero course",
6
6
  "bin": "bin.cjs",