ai-hero-cli 0.0.25 → 0.1.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.
Files changed (2) hide show
  1. package/bin.cjs +43 -324
  2. package/package.json +1 -1
package/bin.cjs CHANGED
@@ -8,7 +8,6 @@ var OS = require('os');
8
8
  var path4 = require('path');
9
9
  var NodeUrl = require('url');
10
10
  var readline = require('readline');
11
- var readline2 = require('readline/promises');
12
11
  var util = require('util');
13
12
 
14
13
  function _interopNamespace(e) {
@@ -36,7 +35,6 @@ var OS__namespace = /*#__PURE__*/_interopNamespace(OS);
36
35
  var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
37
36
  var NodeUrl__namespace = /*#__PURE__*/_interopNamespace(NodeUrl);
38
37
  var readline__namespace = /*#__PURE__*/_interopNamespace(readline);
39
- var readline2__namespace = /*#__PURE__*/_interopNamespace(readline2);
40
38
 
41
39
  var __create = Object.create;
42
40
  var __defProp = Object.defineProperty;
@@ -11646,7 +11644,7 @@ var require_util = __commonJS({
11646
11644
  // node_modules/.pnpm/prompts@2.4.2/node_modules/prompts/dist/elements/prompt.js
11647
11645
  var require_prompt = __commonJS({
11648
11646
  "node_modules/.pnpm/prompts@2.4.2/node_modules/prompts/dist/elements/prompt.js"(exports, module) {
11649
- var readline3 = __require("readline");
11647
+ var readline2 = __require("readline");
11650
11648
  var _require = require_util();
11651
11649
  var action = _require.action;
11652
11650
  var EventEmitter = __require("events");
@@ -11661,11 +11659,11 @@ var require_prompt = __commonJS({
11661
11659
  this.in = opts.stdin || process.stdin;
11662
11660
  this.out = opts.stdout || process.stdout;
11663
11661
  this.onRender = (opts.onRender || (() => void 0)).bind(this);
11664
- const rl = readline3.createInterface({
11662
+ const rl = readline2.createInterface({
11665
11663
  input: this.in,
11666
11664
  escapeCodeTimeout: 50
11667
11665
  });
11668
- readline3.emitKeypressEvents(this.in, rl);
11666
+ readline2.emitKeypressEvents(this.in, rl);
11669
11667
  if (this.in.isTTY) this.in.setRawMode(true);
11670
11668
  const isSelect = ["SelectPrompt", "MultiselectPrompt"].indexOf(this.constructor.name) > -1;
11671
11669
  const keypress = (str, key) => {
@@ -14080,7 +14078,7 @@ var require_util2 = __commonJS({
14080
14078
  // node_modules/.pnpm/prompts@2.4.2/node_modules/prompts/lib/elements/prompt.js
14081
14079
  var require_prompt2 = __commonJS({
14082
14080
  "node_modules/.pnpm/prompts@2.4.2/node_modules/prompts/lib/elements/prompt.js"(exports, module) {
14083
- var readline3 = __require("readline");
14081
+ var readline2 = __require("readline");
14084
14082
  var { action } = require_util2();
14085
14083
  var EventEmitter = __require("events");
14086
14084
  var { beep: beep4, cursor } = require_src();
@@ -14092,8 +14090,8 @@ var require_prompt2 = __commonJS({
14092
14090
  this.in = opts.stdin || process.stdin;
14093
14091
  this.out = opts.stdout || process.stdout;
14094
14092
  this.onRender = (opts.onRender || (() => void 0)).bind(this);
14095
- const rl = readline3.createInterface({ input: this.in, escapeCodeTimeout: 50 });
14096
- readline3.emitKeypressEvents(this.in, rl);
14093
+ const rl = readline2.createInterface({ input: this.in, escapeCodeTimeout: 50 });
14094
+ readline2.emitKeypressEvents(this.in, rl);
14097
14095
  if (this.in.isTTY) this.in.setRawMode(true);
14098
14096
  const isSelect = ["SelectPrompt", "MultiselectPrompt"].indexOf(this.constructor.name) > -1;
14099
14097
  const keypress = (str, key) => {
@@ -51999,8 +51997,8 @@ var require_main = __commonJS({
51999
51997
  const shortPaths = [];
52000
51998
  for (const filePath of optionPaths) {
52001
51999
  try {
52002
- const relative2 = path11.relative(process.cwd(), filePath);
52003
- shortPaths.push(relative2);
52000
+ const relative3 = path11.relative(process.cwd(), filePath);
52001
+ shortPaths.push(relative3);
52004
52002
  } catch (e) {
52005
52003
  if (debug3) {
52006
52004
  _debug(`Failed to load ${filePath} ${e.message}`);
@@ -83386,306 +83384,8 @@ var LessonEntrypointNotFoundError = class extends Data_exports.TaggedError(
83386
83384
  "LessonEntrypointNotFoundError"
83387
83385
  ) {
83388
83386
  };
83389
- var shortcuts = {
83390
- enter: "Choose a new exercise to run",
83391
- n: "Go to the next exercise",
83392
- p: "Go to the previous exercise",
83393
- q: "Quit the exercise"
83394
- };
83395
83387
  var runLesson = Effect_exports.fn("runLesson")(function* (opts) {
83396
- if (opts.simple) {
83397
- return yield* runLessonSimple(opts);
83398
- }
83399
- const { cwd, envFilePath, lesson, root } = opts;
83400
- const service2 = yield* LessonParserService;
83401
- const lessons = yield* service2.getLessonsFromRepo(root);
83402
- const foundLessonIndex = lessons.findIndex(
83403
- (l) => l.num === lesson
83404
- );
83405
- if (foundLessonIndex === -1) {
83406
- return yield* new LessonNotFoundError({
83407
- lesson,
83408
- message: `Lesson ${lesson} not found`
83409
- });
83410
- }
83411
- const foundLesson = lessons[foundLessonIndex];
83412
- const previousLesson = lessons[foundLessonIndex - 1];
83413
- const nextLesson = lessons[foundLessonIndex + 1];
83414
- const subfolders = yield* foundLesson.subfolders();
83415
- if (subfolders.length === 0) {
83416
- return yield* new LessonEntrypointNotFoundError({
83417
- lesson,
83418
- message: `No subfolders found for lesson ${lesson}`
83419
- });
83420
- }
83421
- let subfolderIndex = opts.forceSubfolderIndex;
83422
- if (subfolderIndex === void 0) {
83423
- if (subfolders.length === 1) {
83424
- subfolderIndex = 0;
83425
- } else {
83426
- const result = yield* selectSubfolderIndex({
83427
- lesson: foundLesson
83428
- });
83429
- subfolderIndex = result.subfolderIndex;
83430
- }
83431
- }
83432
- const subfolder = subfolders[subfolderIndex];
83433
- let nextExerciseToRun;
83434
- const nextSubfolder = subfolders[subfolderIndex + 1];
83435
- if (nextSubfolder) {
83436
- nextExerciseToRun = {
83437
- lessonNumber: foundLesson.num,
83438
- lessonName: foundLesson.name,
83439
- subfolderIndex: subfolderIndex + 1,
83440
- subfolder: nextSubfolder
83441
- };
83442
- } else if (nextLesson) {
83443
- nextExerciseToRun = {
83444
- lessonNumber: nextLesson.num,
83445
- lessonName: nextLesson.name,
83446
- subfolderIndex: 0,
83447
- subfolder: (yield* nextLesson.subfolders())[0]
83448
- };
83449
- } else {
83450
- nextExerciseToRun = void 0;
83451
- }
83452
- let previousExerciseToRun;
83453
- if (subfolderIndex > 0) {
83454
- previousExerciseToRun = {
83455
- lessonNumber: foundLesson.num,
83456
- lessonName: foundLesson.name,
83457
- subfolderIndex: subfolderIndex - 1,
83458
- subfolder: subfolders[subfolderIndex - 1]
83459
- };
83460
- } else if (previousLesson) {
83461
- const previousLessonSubfolders = yield* previousLesson.subfolders();
83462
- const previousLessonLastSubfolderIndex = previousLessonSubfolders.length - 1;
83463
- previousExerciseToRun = {
83464
- lessonNumber: previousLesson.num,
83465
- lessonName: previousLesson.name,
83466
- subfolderIndex: previousLessonLastSubfolderIndex,
83467
- subfolder: previousLessonSubfolders[previousLessonLastSubfolderIndex]
83468
- };
83469
- } else {
83470
- previousExerciseToRun = void 0;
83471
- }
83472
- const { mainFile, readmeFile } = yield* getMainAndReadmeFiles({
83473
- lesson: foundLesson,
83474
- subfolder
83475
- });
83476
- yield* Console_exports.clear;
83477
- yield* Console_exports.log(
83478
- util.styleText(
83479
- "bold",
83480
- `Running ${foundLesson.num} ${subfolder}...`
83481
- )
83482
- );
83483
- yield* Console_exports.log(
83484
- util.styleText(
83485
- "dim",
83486
- " Press n + enter to go to the next exercise"
83487
- )
83488
- );
83489
- yield* Console_exports.log(
83490
- util.styleText("dim", " Press h + enter for more shortcuts\n")
83491
- );
83492
- if (readmeFile) {
83493
- yield* logReadmeFile({ readmeFile });
83494
- }
83495
- const command2 = Command_exports.make(
83496
- "pnpm",
83497
- "tsx",
83498
- "--env-file",
83499
- envFilePath,
83500
- mainFile
83501
- ).pipe(
83502
- Command_exports.stdout("inherit"),
83503
- Command_exports.stderr("inherit"),
83504
- Command_exports.workingDirectory(cwd)
83505
- );
83506
- const processOutcome = yield* Effect_exports.raceAll([
83507
- Effect_exports.gen(function* () {
83508
- const proc = yield* Command_exports.start(command2);
83509
- const killWithLogging = () => Effect_exports.gen(function* () {
83510
- if (yield* proc.isRunning) {
83511
- return yield* proc.kill();
83512
- }
83513
- }).pipe(
83514
- Effect_exports.catchAll(
83515
- (e) => Effect_exports.logDebug(
83516
- `Error occurred when killing child process.`,
83517
- e
83518
- )
83519
- )
83520
- );
83521
- yield* Effect_exports.addFinalizer(() => killWithLogging());
83522
- const killAsCallback = () => killWithLogging().pipe(Effect_exports.runPromise);
83523
- yield* Effect_exports.fork(
83524
- Effect_exports.sync(() => {
83525
- process.on("SIGINT", killAsCallback);
83526
- })
83527
- );
83528
- yield* Effect_exports.fork(
83529
- Effect_exports.sync(() => {
83530
- process.on("SIGTERM", killAsCallback);
83531
- })
83532
- );
83533
- yield* Effect_exports.addFinalizer(() => {
83534
- return Effect_exports.sync(
83535
- () => process.removeListener("SIGINT", killAsCallback)
83536
- );
83537
- });
83538
- yield* Effect_exports.addFinalizer(() => {
83539
- return Effect_exports.sync(
83540
- () => process.removeListener("SIGTERM", killAsCallback)
83541
- );
83542
- });
83543
- const result = yield* proc.exitCode;
83544
- return result === 0 ? "exit" : "failed";
83545
- }),
83546
- Effect_exports.gen(function* () {
83547
- const rl = readline2__namespace.createInterface({
83548
- input: process.stdin
83549
- });
83550
- yield* Effect_exports.addFinalizer(() => {
83551
- return Effect_exports.succeed(rl.close());
83552
- });
83553
- while (true) {
83554
- const line4 = yield* Effect_exports.promise(async (signal) => {
83555
- const result = await rl.question("", { signal });
83556
- rl.close();
83557
- return result;
83558
- });
83559
- if (line4 === "h") {
83560
- yield* Console_exports.log(util.styleText("bold", "Shortcuts:"));
83561
- for (const [key, value5] of Object.entries(shortcuts)) {
83562
- yield* Console_exports.log(
83563
- ` ${key} ${util.styleText("dim", `- ${value5}`)}`
83564
- );
83565
- }
83566
- } else if (line4 === "q") {
83567
- return "quit";
83568
- } else if (line4 === "n") {
83569
- return "next";
83570
- } else if (line4 === "p") {
83571
- return "previous";
83572
- } else if (line4.trim() === "") {
83573
- return "choose-exercise";
83574
- }
83575
- }
83576
- })
83577
- ]).pipe(Effect_exports.scoped);
83578
- yield* Console_exports.log("");
83579
- if (processOutcome === "next" && nextExerciseToRun) {
83580
- return yield* runLesson({
83581
- simple: opts.simple,
83582
- lesson: nextExerciseToRun.lessonNumber,
83583
- root,
83584
- envFilePath,
83585
- cwd,
83586
- forceSubfolderIndex: nextExerciseToRun.subfolderIndex
83587
- });
83588
- } else if (processOutcome === "previous" && previousExerciseToRun) {
83589
- return yield* runLesson({
83590
- simple: opts.simple,
83591
- lesson: previousExerciseToRun.lessonNumber,
83592
- root,
83593
- envFilePath,
83594
- cwd,
83595
- forceSubfolderIndex: previousExerciseToRun.subfolderIndex
83596
- });
83597
- } else if (processOutcome === "choose-exercise") {
83598
- return yield* chooseLessonAndRunIt({
83599
- simple: opts.simple,
83600
- root,
83601
- envFilePath,
83602
- cwd
83603
- });
83604
- }
83605
- const isExplainer = yield* foundLesson.isExplainer();
83606
- if (isExplainer && readmeFile) {
83607
- yield* logReadmeFile({ readmeFile });
83608
- }
83609
- const lessonNoun = isExplainer ? {
83610
- successMessage: `Explainer executed! Once you've read the readme and understand the code, you can go to the next exercise.`,
83611
- failureMessage: `Looks like the explainer errored! Want to try again?`,
83612
- lowercase: "explainer"
83613
- } : {
83614
- successMessage: "Exercise complete! What's next?",
83615
- failureMessage: `Looks like the exercise errored! Want to try again?`,
83616
- lowercase: "exercise"
83617
- };
83618
- const { choice: choice6 } = yield* runPrompt(
83619
- () => (0, import_prompts.default)([
83620
- {
83621
- type: "select",
83622
- name: "choice",
83623
- message: processOutcome === "exit" ? lessonNoun.successMessage : lessonNoun.failureMessage,
83624
- choices: [
83625
- {
83626
- title: processOutcome === "failed" ? `\u{1F504} Run the ${lessonNoun.lowercase} again` : `\u{1F504} Try the ${lessonNoun.lowercase} again`,
83627
- value: "run-again"
83628
- },
83629
- ...nextExerciseToRun ? [
83630
- {
83631
- title: `\u27A1\uFE0F Run the next exercise: ${nextExerciseToRun?.lessonNumber}-${nextExerciseToRun?.lessonName} ${nextExerciseToRun?.subfolder}`,
83632
- value: "next-exercise"
83633
- }
83634
- ] : [],
83635
- ...previousExerciseToRun ? [
83636
- {
83637
- title: `\u2B05\uFE0F Run the previous exercise: ${previousExerciseToRun?.lessonNumber}-${previousExerciseToRun?.lessonName} ${previousExerciseToRun?.subfolder}`,
83638
- value: "previous-exercise"
83639
- }
83640
- ] : [],
83641
- {
83642
- title: "\u{1F4CB} Choose a new exercise",
83643
- value: "choose-exercise"
83644
- },
83645
- {
83646
- title: "\u2705 Finish",
83647
- value: "finish"
83648
- }
83649
- ]
83650
- }
83651
- ])
83652
- );
83653
- if (choice6 === "run-again") {
83654
- return yield* runLesson({
83655
- lesson,
83656
- root,
83657
- envFilePath,
83658
- cwd,
83659
- // Run the same exercise again, with the same subfolder index
83660
- forceSubfolderIndex: subfolderIndex,
83661
- simple: opts.simple
83662
- });
83663
- } else if (choice6 === "choose-exercise") {
83664
- return yield* chooseLessonAndRunIt({
83665
- root,
83666
- envFilePath,
83667
- cwd,
83668
- simple: opts.simple
83669
- });
83670
- } else if (choice6 === "next-exercise" && nextExerciseToRun) {
83671
- return yield* runLesson({
83672
- lesson: nextExerciseToRun.lessonNumber,
83673
- root,
83674
- envFilePath,
83675
- cwd,
83676
- forceSubfolderIndex: nextExerciseToRun.subfolderIndex,
83677
- simple: opts.simple
83678
- });
83679
- } else if (choice6 === "previous-exercise" && previousExerciseToRun) {
83680
- return yield* runLesson({
83681
- lesson: previousExerciseToRun.lessonNumber,
83682
- root,
83683
- envFilePath,
83684
- cwd,
83685
- forceSubfolderIndex: previousExerciseToRun.subfolderIndex,
83686
- simple: opts.simple
83687
- });
83688
- }
83388
+ return yield* runLessonSimple(opts);
83689
83389
  });
83690
83390
  var logReadmeFile = Effect_exports.fn("logReadmeFile")(
83691
83391
  function* (opts) {
@@ -83699,6 +83399,9 @@ var logReadmeFile = Effect_exports.fn("logReadmeFile")(
83699
83399
  );
83700
83400
  }
83701
83401
  );
83402
+ var normalizeExerciseNumber = (str) => {
83403
+ return str.replace(/\b0+(\d)/g, "$1");
83404
+ };
83702
83405
  var chooseLessonAndRunIt = (opts) => Effect_exports.gen(function* () {
83703
83406
  const lessonService = yield* LessonParserService;
83704
83407
  const lessons = yield* lessonService.getLessonsFromRepo(
@@ -83717,11 +83420,12 @@ var chooseLessonAndRunIt = (opts) => Effect_exports.gen(function* () {
83717
83420
  description: lesson.name
83718
83421
  })),
83719
83422
  suggest: async (input, choices) => {
83720
- return choices.filter(
83721
- (choice6) => `${choice6.title}-${choice6.description}`.includes(
83722
- input
83723
- )
83724
- );
83423
+ const normalizedInput = normalizeExerciseNumber(input);
83424
+ return choices.filter((choice6) => {
83425
+ const searchText = `${choice6.title}-${choice6.description}`;
83426
+ const normalizedSearchText = normalizeExerciseNumber(searchText);
83427
+ return searchText.includes(input) || normalizedSearchText.includes(normalizedInput);
83428
+ });
83725
83429
  }
83726
83430
  }
83727
83431
  ])
@@ -83734,8 +83438,7 @@ var chooseLessonAndRunIt = (opts) => Effect_exports.gen(function* () {
83734
83438
  root: opts.root,
83735
83439
  envFilePath: opts.envFilePath,
83736
83440
  cwd: opts.cwd,
83737
- forceSubfolderIndex: void 0,
83738
- simple: opts.simple
83441
+ forceSubfolderIndex: void 0
83739
83442
  });
83740
83443
  }).pipe(Effect_exports.catchAll(Console_exports.log));
83741
83444
  var exercise = Command_exports2.make(
@@ -83762,14 +83465,24 @@ var exercise = Command_exports2.make(
83762
83465
  },
83763
83466
  ({ cwd, debug: debug3, envFilePath, lesson, root, simple: simple3 }) => {
83764
83467
  return Effect_exports.gen(function* () {
83468
+ if (simple3) {
83469
+ return yield* Effect_exports.fail(
83470
+ new Error(
83471
+ "Simple is now the default mode, so you no longer need to include the --simple flag"
83472
+ )
83473
+ );
83474
+ }
83475
+ const resolvedEnvFilePath = path4__namespace.relative(
83476
+ cwd,
83477
+ envFilePath
83478
+ );
83765
83479
  if (Option_exports.isSome(lesson)) {
83766
83480
  return yield* runLesson({
83767
83481
  lesson: lesson.value,
83768
83482
  root,
83769
- envFilePath,
83483
+ envFilePath: resolvedEnvFilePath,
83770
83484
  cwd,
83771
- forceSubfolderIndex: void 0,
83772
- simple: simple3
83485
+ forceSubfolderIndex: void 0
83773
83486
  }).pipe(
83774
83487
  Logger_exports.withMinimumLogLevel(
83775
83488
  debug3 ? LogLevel_exports.Debug : LogLevel_exports.Info
@@ -83778,9 +83491,8 @@ var exercise = Command_exports2.make(
83778
83491
  }
83779
83492
  return yield* chooseLessonAndRunIt({
83780
83493
  root,
83781
- envFilePath,
83782
- cwd,
83783
- simple: simple3
83494
+ envFilePath: resolvedEnvFilePath,
83495
+ cwd
83784
83496
  }).pipe(
83785
83497
  Logger_exports.withMinimumLogLevel(
83786
83498
  debug3 ? LogLevel_exports.Debug : LogLevel_exports.Info
@@ -83876,7 +83588,7 @@ var runLessonSimple = (opts) => Effect_exports.gen(function* () {
83876
83588
  util.styleText("bold", `Running ${lesson} ${subfolder}...`)
83877
83589
  );
83878
83590
  ChildProcess.execSync(
83879
- `pnpm tsx --env-file "${envFilePath}" "${mainFile}"`,
83591
+ `pnpm tsx --env-file="${envFilePath}" "${mainFile}"`,
83880
83592
  {
83881
83593
  stdio: "inherit",
83882
83594
  cwd
@@ -84214,6 +83926,12 @@ var lint = Command_exports2.make(
84214
83926
  ".gitkeep file found in the exercise."
84215
83927
  );
84216
83928
  }
83929
+ if (files.some((file6) => file6.includes("speaker-notes.md"))) {
83930
+ errorTracker.addError(
83931
+ lesson,
83932
+ "speaker-notes.md file found in the exercise. This should not be exposed to users."
83933
+ );
83934
+ }
84217
83935
  }
84218
83936
  const readmeContents = allReadmeContents.join("\n");
84219
83937
  const referenceLessons = lessons.filter(
@@ -84519,7 +84237,8 @@ var upgradePackages = Command_exports2.make(
84519
84237
  "ai@latest",
84520
84238
  "@ai-sdk/*@latest",
84521
84239
  "ai-hero-cli@latest",
84522
- "evalite@latest"
84240
+ "evalite@latest",
84241
+ "vitest@latest"
84523
84242
  ).pipe(
84524
84243
  verbose ? Command_exports.stdout("inherit") : Command_exports.stdout("pipe"),
84525
84244
  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.25",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "description": "The CLI used to run exercises for the AI Hero course",
6
6
  "bin": "bin.cjs",