ai-hero-cli 0.2.2 → 0.2.4

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 +548 -266
  2. package/package.json +1 -1
package/bin.cjs CHANGED
@@ -5593,8 +5593,8 @@ ${ctx.indent}`;
5593
5593
  const vs0 = valueStr[0];
5594
5594
  const nl0 = valueStr.indexOf("\n");
5595
5595
  const hasNewline = nl0 !== -1;
5596
- const flow3 = ctx.inFlow ?? value5.flow ?? value5.items.length === 0;
5597
- if (hasNewline || !flow3) {
5596
+ const flow2 = ctx.inFlow ?? value5.flow ?? value5.items.length === 0;
5597
+ if (hasNewline || !flow2) {
5598
5598
  let hasPropsLine = false;
5599
5599
  if (hasNewline && (vs0 === "&" || vs0 === "!")) {
5600
5600
  let sp0 = valueStr.indexOf(" ");
@@ -5812,8 +5812,8 @@ var require_stringifyCollection = __commonJS({
5812
5812
  var stringify2 = require_stringify();
5813
5813
  var stringifyComment = require_stringifyComment();
5814
5814
  function stringifyCollection(collection, ctx, options3) {
5815
- const flow3 = ctx.inFlow ?? collection.flow;
5816
- const stringify3 = flow3 ? stringifyFlowCollection : stringifyBlockCollection;
5815
+ const flow2 = ctx.inFlow ?? collection.flow;
5816
+ const stringify3 = flow2 ? stringifyFlowCollection : stringifyBlockCollection;
5817
5817
  return stringify3(collection, ctx, options3);
5818
5818
  }
5819
5819
  function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
@@ -7424,7 +7424,7 @@ var require_Document = __commonJS({
7424
7424
  options3 = replacer;
7425
7425
  replacer = void 0;
7426
7426
  }
7427
- const { aliasDuplicateObjects, anchorPrefix, flow: flow3, keepUndefined, onTagObj, tag: tag4 } = options3 ?? {};
7427
+ const { aliasDuplicateObjects, anchorPrefix, flow: flow2, keepUndefined, onTagObj, tag: tag4 } = options3 ?? {};
7428
7428
  const { onAnchor, setAnchors, sourceObjects } = anchors.createNodeAnchors(
7429
7429
  this,
7430
7430
  // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
@@ -7440,7 +7440,7 @@ var require_Document = __commonJS({
7440
7440
  sourceObjects
7441
7441
  };
7442
7442
  const node = createNode.createNode(value5, tag4, ctx);
7443
- if (flow3 && identity3.isCollection(node))
7443
+ if (flow2 && identity3.isCollection(node))
7444
7444
  node.flow = true;
7445
7445
  setAnchors();
7446
7446
  return node;
@@ -7686,7 +7686,7 @@ ${pointer}
7686
7686
  // node_modules/.pnpm/yaml@2.8.1/node_modules/yaml/dist/compose/resolve-props.js
7687
7687
  var require_resolve_props = __commonJS({
7688
7688
  "node_modules/.pnpm/yaml@2.8.1/node_modules/yaml/dist/compose/resolve-props.js"(exports) {
7689
- function resolveProps(tokens, { flow: flow3, indicator, next, offset, onError: onError4, parentIndent, startOnNewline }) {
7689
+ function resolveProps(tokens, { flow: flow2, indicator, next, offset, onError: onError4, parentIndent, startOnNewline }) {
7690
7690
  let spaceBefore = false;
7691
7691
  let atNewline = startOnNewline;
7692
7692
  let hasSpace = startOnNewline;
@@ -7715,7 +7715,7 @@ var require_resolve_props = __commonJS({
7715
7715
  }
7716
7716
  switch (token.type) {
7717
7717
  case "space":
7718
- if (!flow3 && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) {
7718
+ if (!flow2 && (indicator !== "doc-start" || next?.type !== "flow-collection") && token.source.includes(" ")) {
7719
7719
  tab = token;
7720
7720
  }
7721
7721
  hasSpace = true;
@@ -7771,15 +7771,15 @@ var require_resolve_props = __commonJS({
7771
7771
  if (anchor || tag4)
7772
7772
  onError4(token, "BAD_PROP_ORDER", `Anchors and tags must be after the ${token.source} indicator`);
7773
7773
  if (found)
7774
- onError4(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow3 ?? "collection"}`);
7774
+ onError4(token, "UNEXPECTED_TOKEN", `Unexpected ${token.source} in ${flow2 ?? "collection"}`);
7775
7775
  found = token;
7776
7776
  atNewline = indicator === "seq-item-ind" || indicator === "explicit-key-ind";
7777
7777
  hasSpace = false;
7778
7778
  break;
7779
7779
  case "comma":
7780
- if (flow3) {
7780
+ if (flow2) {
7781
7781
  if (comma3)
7782
- onError4(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow3}`);
7782
+ onError4(token, "UNEXPECTED_TOKEN", `Unexpected , in ${flow2}`);
7783
7783
  comma3 = token;
7784
7784
  atNewline = false;
7785
7785
  hasSpace = false;
@@ -11482,10 +11482,10 @@ var require_clear = __commonJS({
11482
11482
  var erase = _require.erase;
11483
11483
  var cursor = _require.cursor;
11484
11484
  var width3 = (str) => [...strip(str)].length;
11485
- module.exports = function(prompt6, perLine) {
11485
+ module.exports = function(prompt7, perLine) {
11486
11486
  if (!perLine) return erase.line + cursor.to(0);
11487
11487
  let rows = 0;
11488
- const lines4 = prompt6.split(/\r?\n/);
11488
+ const lines4 = prompt7.split(/\r?\n/);
11489
11489
  var _iterator = _createForOfIteratorHelper(lines4), _step;
11490
11490
  try {
11491
11491
  for (_iterator.s(); !(_step = _iterator.n()).done; ) {
@@ -13086,14 +13086,14 @@ Instructions:
13086
13086
  if (this.closed) return;
13087
13087
  if (this.firstRender) this.out.write(cursor.hide);
13088
13088
  super.render();
13089
- let prompt6 = [style.symbol(this.done, this.aborted), color3.bold(this.msg), style.delimiter(false), this.renderDoneOrInstructions()].join(" ");
13089
+ let prompt7 = [style.symbol(this.done, this.aborted), color3.bold(this.msg), style.delimiter(false), this.renderDoneOrInstructions()].join(" ");
13090
13090
  if (this.showMinError) {
13091
- prompt6 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
13091
+ prompt7 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
13092
13092
  this.showMinError = false;
13093
13093
  }
13094
- prompt6 += this.renderOptions(this.value);
13095
- this.out.write(this.clear + prompt6);
13096
- this.clear = clear3(prompt6, this.out.columns);
13094
+ prompt7 += this.renderOptions(this.value);
13095
+ this.out.write(this.clear + prompt7);
13096
+ this.clear = clear3(prompt7, this.out.columns);
13097
13097
  }
13098
13098
  };
13099
13099
  module.exports = MultiselectPrompt;
@@ -13498,14 +13498,14 @@ Filtered results for: ${this.inputValue ? this.inputValue : color3.gray("Enter s
13498
13498
  if (this.closed) return;
13499
13499
  if (this.firstRender) this.out.write(cursor.hide);
13500
13500
  super.render();
13501
- let prompt6 = [style.symbol(this.done, this.aborted), color3.bold(this.msg), style.delimiter(false), this.renderDoneOrInstructions()].join(" ");
13501
+ let prompt7 = [style.symbol(this.done, this.aborted), color3.bold(this.msg), style.delimiter(false), this.renderDoneOrInstructions()].join(" ");
13502
13502
  if (this.showMinError) {
13503
- prompt6 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
13503
+ prompt7 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
13504
13504
  this.showMinError = false;
13505
13505
  }
13506
- prompt6 += this.renderOptions(this.filteredOptions);
13507
- this.out.write(this.clear + prompt6);
13508
- this.clear = clear3(prompt6, this.out.columns);
13506
+ prompt7 += this.renderOptions(this.filteredOptions);
13507
+ this.out.write(this.clear + prompt7);
13508
+ this.clear = clear3(prompt7, this.out.columns);
13509
13509
  }
13510
13510
  };
13511
13511
  module.exports = AutocompleteMultiselectPrompt;
@@ -13785,7 +13785,7 @@ var require_dist2 = __commonJS({
13785
13785
  var passOn = ["suggest", "format", "onState", "validate", "onRender", "type"];
13786
13786
  var noop = () => {
13787
13787
  };
13788
- function prompt6() {
13788
+ function prompt7() {
13789
13789
  return _prompt.apply(this, arguments);
13790
13790
  }
13791
13791
  function _prompt() {
@@ -13794,7 +13794,7 @@ var require_dist2 = __commonJS({
13794
13794
  onCancel = noop
13795
13795
  } = {}) {
13796
13796
  const answers = {};
13797
- const override2 = prompt6._override || {};
13797
+ const override2 = prompt7._override || {};
13798
13798
  questions = [].concat(questions);
13799
13799
  let answer, question, quit, name, type2, lastPrompt;
13800
13800
  const getFormattedAnswer = /* @__PURE__ */ (function() {
@@ -13843,7 +13843,7 @@ var require_dist2 = __commonJS({
13843
13843
  }
13844
13844
  }
13845
13845
  try {
13846
- answer = prompt6._injected ? getInjectedAnswer(prompt6._injected, question.initial) : yield prompts[type2](question);
13846
+ answer = prompt7._injected ? getInjectedAnswer(prompt7._injected, question.initial) : yield prompts[type2](question);
13847
13847
  answers[name] = answer = yield getFormattedAnswer(question, answer, true);
13848
13848
  quit = yield onSubmit(question, answer, answers);
13849
13849
  } catch (err) {
@@ -13868,13 +13868,13 @@ var require_dist2 = __commonJS({
13868
13868
  return answer === void 0 ? deafultValue : answer;
13869
13869
  }
13870
13870
  function inject(answers) {
13871
- prompt6._injected = (prompt6._injected || []).concat(answers);
13871
+ prompt7._injected = (prompt7._injected || []).concat(answers);
13872
13872
  }
13873
13873
  function override(answers) {
13874
- prompt6._override = Object.assign({}, answers);
13874
+ prompt7._override = Object.assign({}, answers);
13875
13875
  }
13876
- module.exports = Object.assign(prompt6, {
13877
- prompt: prompt6,
13876
+ module.exports = Object.assign(prompt7, {
13877
+ prompt: prompt7,
13878
13878
  prompts,
13879
13879
  inject,
13880
13880
  override
@@ -13938,10 +13938,10 @@ var require_clear2 = __commonJS({
13938
13938
  var strip = require_strip2();
13939
13939
  var { erase, cursor } = require_src();
13940
13940
  var width3 = (str) => [...strip(str)].length;
13941
- module.exports = function(prompt6, perLine) {
13941
+ module.exports = function(prompt7, perLine) {
13942
13942
  if (!perLine) return erase.line + cursor.to(0);
13943
13943
  let rows = 0;
13944
- const lines4 = prompt6.split(/\r?\n/);
13944
+ const lines4 = prompt7.split(/\r?\n/);
13945
13945
  for (let line4 of lines4) {
13946
13946
  rows += 1 + Math.floor(Math.max(width3(line4) - 1, 0) / perLine);
13947
13947
  }
@@ -15380,19 +15380,19 @@ Instructions:
15380
15380
  if (this.closed) return;
15381
15381
  if (this.firstRender) this.out.write(cursor.hide);
15382
15382
  super.render();
15383
- let prompt6 = [
15383
+ let prompt7 = [
15384
15384
  style.symbol(this.done, this.aborted),
15385
15385
  color3.bold(this.msg),
15386
15386
  style.delimiter(false),
15387
15387
  this.renderDoneOrInstructions()
15388
15388
  ].join(" ");
15389
15389
  if (this.showMinError) {
15390
- prompt6 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
15390
+ prompt7 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
15391
15391
  this.showMinError = false;
15392
15392
  }
15393
- prompt6 += this.renderOptions(this.value);
15394
- this.out.write(this.clear + prompt6);
15395
- this.clear = clear3(prompt6, this.out.columns);
15393
+ prompt7 += this.renderOptions(this.value);
15394
+ this.out.write(this.clear + prompt7);
15395
+ this.clear = clear3(prompt7, this.out.columns);
15396
15396
  }
15397
15397
  };
15398
15398
  module.exports = MultiselectPrompt;
@@ -15754,19 +15754,19 @@ Filtered results for: ${this.inputValue ? this.inputValue : color3.gray("Enter s
15754
15754
  if (this.closed) return;
15755
15755
  if (this.firstRender) this.out.write(cursor.hide);
15756
15756
  super.render();
15757
- let prompt6 = [
15757
+ let prompt7 = [
15758
15758
  style.symbol(this.done, this.aborted),
15759
15759
  color3.bold(this.msg),
15760
15760
  style.delimiter(false),
15761
15761
  this.renderDoneOrInstructions()
15762
15762
  ].join(" ");
15763
15763
  if (this.showMinError) {
15764
- prompt6 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
15764
+ prompt7 += color3.red(`You must select a minimum of ${this.minSelected} choices.`);
15765
15765
  this.showMinError = false;
15766
15766
  }
15767
- prompt6 += this.renderOptions(this.filteredOptions);
15768
- this.out.write(this.clear + prompt6);
15769
- this.clear = clear3(prompt6, this.out.columns);
15767
+ prompt7 += this.renderOptions(this.filteredOptions);
15768
+ this.out.write(this.clear + prompt7);
15769
+ this.clear = clear3(prompt7, this.out.columns);
15770
15770
  }
15771
15771
  };
15772
15772
  module.exports = AutocompleteMultiselectPrompt;
@@ -15934,9 +15934,9 @@ var require_lib = __commonJS({
15934
15934
  var passOn = ["suggest", "format", "onState", "validate", "onRender", "type"];
15935
15935
  var noop = () => {
15936
15936
  };
15937
- async function prompt6(questions = [], { onSubmit = noop, onCancel = noop } = {}) {
15937
+ async function prompt7(questions = [], { onSubmit = noop, onCancel = noop } = {}) {
15938
15938
  const answers = {};
15939
- const override2 = prompt6._override || {};
15939
+ const override2 = prompt7._override || {};
15940
15940
  questions = [].concat(questions);
15941
15941
  let answer, question, quit, name, type2, lastPrompt;
15942
15942
  const getFormattedAnswer = async (question2, answer2, skipValidation = false) => {
@@ -15973,7 +15973,7 @@ var require_lib = __commonJS({
15973
15973
  }
15974
15974
  }
15975
15975
  try {
15976
- answer = prompt6._injected ? getInjectedAnswer(prompt6._injected, question.initial) : await prompts[type2](question);
15976
+ answer = prompt7._injected ? getInjectedAnswer(prompt7._injected, question.initial) : await prompts[type2](question);
15977
15977
  answers[name] = answer = await getFormattedAnswer(question, answer, true);
15978
15978
  quit = await onSubmit(question, answer, answers);
15979
15979
  } catch (err) {
@@ -15991,12 +15991,12 @@ var require_lib = __commonJS({
15991
15991
  return answer === void 0 ? deafultValue : answer;
15992
15992
  }
15993
15993
  function inject(answers) {
15994
- prompt6._injected = (prompt6._injected || []).concat(answers);
15994
+ prompt7._injected = (prompt7._injected || []).concat(answers);
15995
15995
  }
15996
15996
  function override(answers) {
15997
- prompt6._override = Object.assign({}, answers);
15997
+ prompt7._override = Object.assign({}, answers);
15998
15998
  }
15999
- module.exports = Object.assign(prompt6, { prompt: prompt6, prompts, inject, override });
15999
+ module.exports = Object.assign(prompt7, { prompt: prompt7, prompts, inject, override });
16000
16000
  }
16001
16001
  });
16002
16002
 
@@ -27360,7 +27360,7 @@ var require_mock_pool = __commonJS({
27360
27360
  var require_pending_interceptors_formatter = __commonJS({
27361
27361
  "node_modules/.pnpm/undici@7.13.0/node_modules/undici/lib/mock/pending-interceptors-formatter.js"(exports, module) {
27362
27362
  var { Transform } = __require("stream");
27363
- var { Console: Console3 } = __require("console");
27363
+ var { Console: Console2 } = __require("console");
27364
27364
  var PERSISTENT = process.versions.icu ? "\u2705" : "Y ";
27365
27365
  var NOT_PERSISTENT = process.versions.icu ? "\u274C" : "N ";
27366
27366
  module.exports = class PendingInterceptorsFormatter {
@@ -27370,7 +27370,7 @@ var require_pending_interceptors_formatter = __commonJS({
27370
27370
  cb(null, chunk4);
27371
27371
  }
27372
27372
  });
27373
- this.logger = new Console3({
27373
+ this.logger = new Console2({
27374
27374
  stdout: this.transform,
27375
27375
  inspectOptions: {
27376
27376
  colors: !disableColors && !process.env.CI
@@ -42029,7 +42029,7 @@ var require_lodash = __commonJS({
42029
42029
  function defaultTo(value5, defaultValue) {
42030
42030
  return value5 == null || value5 !== value5 ? defaultValue : value5;
42031
42031
  }
42032
- var flow3 = createFlow();
42032
+ var flow2 = createFlow();
42033
42033
  var flowRight = createFlow(true);
42034
42034
  function identity3(value5) {
42035
42035
  return value5;
@@ -42229,7 +42229,7 @@ var require_lodash = __commonJS({
42229
42229
  lodash.flattenDeep = flattenDeep;
42230
42230
  lodash.flattenDepth = flattenDepth;
42231
42231
  lodash.flip = flip3;
42232
- lodash.flow = flow3;
42232
+ lodash.flow = flow2;
42233
42233
  lodash.flowRight = flowRight;
42234
42234
  lodash.fromPairs = fromPairs;
42235
42235
  lodash.functions = functions;
@@ -75481,8 +75481,8 @@ var make59 = /* @__PURE__ */ fnUntraced2(function* (shouldQuit = defaultShouldQu
75481
75481
  readlineInterface.once("line", onLine);
75482
75482
  return sync5(() => readlineInterface.off("line", onLine));
75483
75483
  })), scoped2);
75484
- const display = (prompt6) => uninterruptible2(async2((resume2) => {
75485
- stdout3.write(prompt6, (err) => err ? resume2(fail9(new BadArgument({
75484
+ const display = (prompt7) => uninterruptible2(async2((resume2) => {
75485
+ stdout3.write(prompt7, (err) => err ? resume2(fail9(new BadArgument({
75486
75486
  module: "Terminal",
75487
75487
  method: "display",
75488
75488
  description: "Failed to write prompt to stdout",
@@ -77753,8 +77753,8 @@ var run5 = /* @__PURE__ */ fnUntraced2(function* (self2) {
77753
77753
  const input = yield* terminal.readInput;
77754
77754
  return yield* runWithInput(self2, terminal, input);
77755
77755
  }, /* @__PURE__ */ mapError2(() => new QuitException()), scoped2);
77756
- var runWithInput = (prompt6, terminal, input) => suspend4(() => {
77757
- const op = prompt6;
77756
+ var runWithInput = (prompt7, terminal, input) => suspend4(() => {
77757
+ const op = prompt7;
77758
77758
  switch (op._tag) {
77759
77759
  case "Loop": {
77760
77760
  return runLoop(op, terminal, input);
@@ -77967,8 +77967,8 @@ function eraseText(text11, columns) {
77967
77967
  }
77968
77968
  return eraseLines3(rows);
77969
77969
  }
77970
- function lines3(prompt6, columns) {
77971
- const lines4 = prompt6.split(/\r?\n/);
77970
+ function lines3(prompt7, columns) {
77971
+ const lines4 = prompt7.split(/\r?\n/);
77972
77972
  return columns === 0 ? lines4.length : pipe(map3(lines4, (line4) => Math.ceil(line4.length / columns)), reduce(0, (left3, right3) => left3 + right3));
77973
77973
  }
77974
77974
 
@@ -81031,11 +81031,11 @@ var withFallbackConfig3 = /* @__PURE__ */ dual(2, (self2, config3) => {
81031
81031
  }
81032
81032
  return makeWithFallback(self2, config3);
81033
81033
  });
81034
- var withFallbackPrompt = /* @__PURE__ */ dual(2, (self2, prompt6) => {
81034
+ var withFallbackPrompt = /* @__PURE__ */ dual(2, (self2, prompt7) => {
81035
81035
  if (isInstruction2(self2) && isWithDefault2(self2)) {
81036
- return makeWithDefault2(withFallbackPrompt(self2.options, prompt6), self2.fallback);
81036
+ return makeWithDefault2(withFallbackPrompt(self2.options, prompt7), self2.fallback);
81037
81037
  }
81038
- return makeWithFallback(self2, prompt6);
81038
+ return makeWithFallback(self2, prompt7);
81039
81039
  });
81040
81040
  var withDescription4 = /* @__PURE__ */ dual(2, (self2, desc) => modifySingle(self2, (single2) => {
81041
81041
  const description = sequence(single2.description, p(desc));
@@ -82178,12 +82178,12 @@ var make65 = (name, options3 = none14, args2 = none12) => {
82178
82178
  op.args = args2;
82179
82179
  return op;
82180
82180
  };
82181
- var prompt = (name, prompt6) => {
82181
+ var prompt = (name, prompt7) => {
82182
82182
  const op = Object.create(proto23);
82183
82183
  op._tag = "GetUserInput";
82184
82184
  op.name = name;
82185
82185
  op.description = empty39;
82186
- op.prompt = prompt6;
82186
+ op.prompt = prompt7;
82187
82187
  return op;
82188
82188
  };
82189
82189
  var getHelp7 = (self2, config3) => getHelpInternal4(self2, config3);
@@ -83024,7 +83024,7 @@ var getUsage6 = (self2) => getUsage5(self2.descriptor);
83024
83024
  var mapDescriptor = /* @__PURE__ */ dual(2, (self2, f) => makeDerive(self2, {
83025
83025
  descriptor: f(self2.descriptor)
83026
83026
  }));
83027
- var prompt2 = (name, prompt6, handler) => makeProto(map35(prompt(name, prompt6), (_) => _.value), handler, GenericTag(`@effect/cli/Prompt/${name}`));
83027
+ var prompt2 = (name, prompt7, handler) => makeProto(map35(prompt(name, prompt7), (_) => _.value), handler, GenericTag(`@effect/cli/Prompt/${name}`));
83028
83028
  var withHandler = /* @__PURE__ */ dual(2, (self2, handler) => makeDerive(self2, {
83029
83029
  handler,
83030
83030
  transform: identity
@@ -83125,18 +83125,194 @@ var make69 = make42;
83125
83125
  var makeWith2 = makeWith;
83126
83126
  var makeCacheStats2 = makeCacheStats;
83127
83127
  var makeEntryStats2 = makeEntryStats;
83128
- var NotAGitRepoError = class extends Data_exports.TaggedError(
83129
- "NotAGitRepoError"
83128
+
83129
+ // src/commit-utils.ts
83130
+ var import_prompts = __toESM(require_prompts3());
83131
+
83132
+ // src/prompt-utils.ts
83133
+ var PromptCancelledError = class extends Data_exports.TaggedError(
83134
+ "PromptCancelledError"
83130
83135
  ) {
83131
83136
  };
83137
+ var runPrompt = (promptFn) => {
83138
+ return Effect_exports.gen(function* () {
83139
+ const result = yield* Effect_exports.promise(() => promptFn());
83140
+ if (Object.keys(result).length === 0) {
83141
+ return yield* new PromptCancelledError();
83142
+ }
83143
+ return result;
83144
+ });
83145
+ };
83146
+
83147
+ // src/commit-utils.ts
83132
83148
  var CommitNotFoundError = class extends Data_exports.TaggedError(
83133
83149
  "CommitNotFoundError"
83134
83150
  ) {
83135
83151
  };
83152
+ var NoParentCommitError = class extends Data_exports.TaggedError(
83153
+ "NoParentCommitError"
83154
+ ) {
83155
+ };
83156
+ var parseCommits = (commitHistory) => {
83157
+ return commitHistory.trim().split("\n").filter(Boolean).map((line4) => {
83158
+ const [sha, ...messageParts] = line4.split(" ");
83159
+ const fullMessage = messageParts.join(" ");
83160
+ const lessonMatch = fullMessage.match(
83161
+ /^(\d+)[.-](\d+)[.-](\d+)\s*/
83162
+ );
83163
+ const extractedLessonId = lessonMatch ? `${lessonMatch[1].padStart(
83164
+ 2,
83165
+ "0"
83166
+ )}.${lessonMatch[2].padStart(
83167
+ 2,
83168
+ "0"
83169
+ )}.${lessonMatch[3].padStart(2, "0")}` : null;
83170
+ const message = lessonMatch ? fullMessage.slice(lessonMatch[0].length).trim() : fullMessage;
83171
+ return {
83172
+ sha,
83173
+ message,
83174
+ lessonId: extractedLessonId
83175
+ };
83176
+ });
83177
+ };
83178
+ var selectLessonCommit = ({
83179
+ branch,
83180
+ cwd,
83181
+ excludeCurrentBranch,
83182
+ lessonId,
83183
+ promptMessage
83184
+ }) => Effect_exports.gen(function* () {
83185
+ let commits;
83186
+ if (excludeCurrentBranch) {
83187
+ const currentBranchCommand = Command_exports.make(
83188
+ "git",
83189
+ "log",
83190
+ "HEAD",
83191
+ "--oneline"
83192
+ ).pipe(Command_exports.workingDirectory(cwd));
83193
+ const currentBranchHistory = yield* Command_exports.string(
83194
+ currentBranchCommand
83195
+ );
83196
+ const currentBranchCommits = parseCommits(currentBranchHistory);
83197
+ const currentLessonIds = new Set(
83198
+ currentBranchCommits.filter((c) => c.lessonId !== null).map((c) => c.lessonId)
83199
+ );
83200
+ const targetBranchCommand = Command_exports.make(
83201
+ "git",
83202
+ "log",
83203
+ branch,
83204
+ "--oneline"
83205
+ ).pipe(Command_exports.workingDirectory(cwd));
83206
+ const targetBranchHistory = yield* Command_exports.string(
83207
+ targetBranchCommand
83208
+ );
83209
+ const allTargetCommits = parseCommits(targetBranchHistory);
83210
+ commits = allTargetCommits.filter(
83211
+ (c) => !c.lessonId || !currentLessonIds.has(c.lessonId)
83212
+ );
83213
+ } else {
83214
+ const gitLogCommand = Command_exports.make(
83215
+ "git",
83216
+ "log",
83217
+ branch,
83218
+ "--oneline"
83219
+ ).pipe(Command_exports.workingDirectory(cwd));
83220
+ const commitHistory = yield* Command_exports.string(gitLogCommand);
83221
+ commits = parseCommits(commitHistory);
83222
+ }
83223
+ let selectedLessonId;
83224
+ if (Option_exports.isSome(lessonId)) {
83225
+ selectedLessonId = lessonId.value;
83226
+ yield* Console_exports.log(
83227
+ `Searching for lesson ${selectedLessonId} on branch ${branch}...`
83228
+ );
83229
+ } else {
83230
+ const commitsWithLessonIds = commits.filter(
83231
+ (commit) => commit.lessonId !== null
83232
+ );
83233
+ if (commitsWithLessonIds.length === 0) {
83234
+ return yield* Effect_exports.fail(
83235
+ new CommitNotFoundError({
83236
+ lessonId: "any",
83237
+ branch
83238
+ })
83239
+ );
83240
+ }
83241
+ const sortedCommits = commitsWithLessonIds.sort((a, b) => {
83242
+ return a.lessonId.localeCompare(b.lessonId);
83243
+ });
83244
+ const { lesson } = yield* runPrompt(
83245
+ () => (0, import_prompts.default)([
83246
+ {
83247
+ type: "autocomplete",
83248
+ name: "lesson",
83249
+ message: promptMessage,
83250
+ choices: sortedCommits.map((commit) => ({
83251
+ title: commit.lessonId,
83252
+ value: commit.lessonId,
83253
+ description: commit.message
83254
+ })),
83255
+ suggest: async (input, choices) => {
83256
+ return choices.filter((choice6) => {
83257
+ const searchText = `${choice6.title} ${choice6.description}`;
83258
+ return searchText.toLowerCase().includes(input.toLowerCase());
83259
+ });
83260
+ }
83261
+ }
83262
+ ])
83263
+ );
83264
+ selectedLessonId = lesson;
83265
+ }
83266
+ const matchingCommits = commits.filter(
83267
+ (commit) => commit.lessonId === selectedLessonId
83268
+ );
83269
+ if (matchingCommits.length === 0) {
83270
+ return yield* new CommitNotFoundError({
83271
+ lessonId: selectedLessonId,
83272
+ branch
83273
+ });
83274
+ }
83275
+ const targetCommit = matchingCommits[matchingCommits.length - 1];
83276
+ yield* Console_exports.log(
83277
+ `Found commit: ${targetCommit.sha} ${targetCommit.message}`
83278
+ );
83279
+ return {
83280
+ commit: targetCommit,
83281
+ lessonId: selectedLessonId
83282
+ };
83283
+ });
83284
+ var getParentCommit = ({
83285
+ commitSha,
83286
+ cwd
83287
+ }) => Effect_exports.gen(function* () {
83288
+ const gitRevParseCommand = Command_exports.make(
83289
+ "git",
83290
+ "rev-parse",
83291
+ `${commitSha}^`
83292
+ ).pipe(Command_exports.workingDirectory(cwd));
83293
+ const parentSha = yield* Command_exports.string(
83294
+ gitRevParseCommand
83295
+ ).pipe(
83296
+ Effect_exports.mapError(() => new NoParentCommitError({ commitSha }))
83297
+ );
83298
+ return parentSha.trim();
83299
+ });
83300
+
83301
+ // src/cherry-pick.ts
83302
+ var NotAGitRepoError = class extends Data_exports.TaggedError(
83303
+ "NotAGitRepoError"
83304
+ ) {
83305
+ };
83306
+ var InvalidBranchOperationError = class extends Data_exports.TaggedError(
83307
+ "InvalidBranchOperationError"
83308
+ ) {
83309
+ };
83136
83310
  var cherryPick = Command_exports2.make(
83137
83311
  "cherry-pick",
83138
83312
  {
83139
- lessonId: Args_exports.text({ name: "lesson-id" }),
83313
+ lessonId: Args_exports.text({ name: "lesson-id" }).pipe(
83314
+ Args_exports.optional
83315
+ ),
83140
83316
  branch: Options_exports.text("branch").pipe(
83141
83317
  Options_exports.withDescription(
83142
83318
  "Branch to search for the lesson commit"
@@ -83154,49 +83330,51 @@ var cherryPick = Command_exports2.make(
83154
83330
  })
83155
83331
  );
83156
83332
  }
83157
- yield* Console_exports.log(
83158
- `Searching for lesson ${lessonId} on branch ${branch}...`
83159
- );
83160
- const gitLogCommand = Command_exports.make(
83333
+ const gitFetchCommand = Command_exports.make(
83161
83334
  "git",
83162
- "log",
83335
+ "fetch",
83336
+ "origin"
83337
+ ).pipe(
83338
+ Command_exports.workingDirectory(cwd),
83339
+ Command_exports.stdout("inherit"),
83340
+ Command_exports.stderr("inherit")
83341
+ );
83342
+ const fetchExitCode = yield* Command_exports.exitCode(
83343
+ gitFetchCommand
83344
+ );
83345
+ if (fetchExitCode !== 0) {
83346
+ yield* Console_exports.error("Failed to fetch branch");
83347
+ process.exitCode = 1;
83348
+ return;
83349
+ }
83350
+ const {
83351
+ commit: targetCommit,
83352
+ lessonId: selectedLessonId
83353
+ } = yield* selectLessonCommit({
83354
+ cwd,
83163
83355
  branch,
83164
- "--oneline",
83165
- "--all"
83166
- ).pipe(Command_exports.workingDirectory(cwd));
83167
- const commitHistory = yield* Command_exports.string(gitLogCommand);
83168
- const commits = commitHistory.trim().split("\n").filter(Boolean).map((line4) => {
83169
- const [sha, ...messageParts] = line4.split(" ");
83170
- const message = messageParts.join(" ");
83171
- const lessonMatch = message.match(
83172
- /^(\d+)[.-](\d+)[.-](\d+)/
83173
- );
83174
- const extractedLessonId = lessonMatch ? `${lessonMatch[1].padStart(
83175
- 2,
83176
- "0"
83177
- )}.${lessonMatch[2].padStart(
83178
- 2,
83179
- "0"
83180
- )}.${lessonMatch[3].padStart(2, "0")}` : null;
83181
- return {
83182
- sha,
83183
- message,
83184
- lessonId: extractedLessonId
83185
- };
83356
+ lessonId,
83357
+ promptMessage: "Which lesson do you want to cherry-pick? (type to search)",
83358
+ excludeCurrentBranch: true
83186
83359
  });
83187
- const matchingCommits = commits.filter(
83188
- (commit) => commit.lessonId === lessonId
83189
- );
83190
- if (matchingCommits.length === 0) {
83191
- return yield* new CommitNotFoundError({
83192
- lessonId,
83193
- branch
83360
+ const currentBranchCommand = Command_exports.make(
83361
+ "git",
83362
+ "branch",
83363
+ "--show-current"
83364
+ ).pipe(Command_exports.workingDirectory(cwd));
83365
+ const currentBranch = (yield* Command_exports.string(
83366
+ currentBranchCommand
83367
+ )).trim();
83368
+ if (currentBranch === branch) {
83369
+ return yield* new InvalidBranchOperationError({
83370
+ message: `Cannot cherry-pick when on target branch "${branch}"`
83371
+ });
83372
+ }
83373
+ if (currentBranch === "main") {
83374
+ return yield* new InvalidBranchOperationError({
83375
+ message: `Cannot cherry-pick when on "main" branch`
83194
83376
  });
83195
83377
  }
83196
- const targetCommit = matchingCommits[matchingCommits.length - 1];
83197
- yield* Console_exports.log(
83198
- `Found commit: ${targetCommit.sha} ${targetCommit.message}`
83199
- );
83200
83378
  yield* Console_exports.log(
83201
83379
  `Cherry-picking ${targetCommit.sha} onto current branch...
83202
83380
  `
@@ -83220,7 +83398,7 @@ var cherryPick = Command_exports2.make(
83220
83398
  }
83221
83399
  yield* Console_exports.log(
83222
83400
  `
83223
- \u2713 Successfully cherry-picked lesson ${lessonId}`
83401
+ \u2713 Successfully cherry-picked lesson ${selectedLessonId}`
83224
83402
  );
83225
83403
  }).pipe(
83226
83404
  Effect_exports.catchTags({
@@ -83237,6 +83415,18 @@ var cherryPick = Command_exports2.make(
83237
83415
  );
83238
83416
  process.exitCode = 1;
83239
83417
  });
83418
+ },
83419
+ InvalidBranchOperationError: (error4) => {
83420
+ return Effect_exports.gen(function* () {
83421
+ yield* Console_exports.error(`Error: ${error4.message}`);
83422
+ process.exitCode = 1;
83423
+ });
83424
+ },
83425
+ PromptCancelledError: () => {
83426
+ return Effect_exports.gen(function* () {
83427
+ yield* Console_exports.log("Operation cancelled");
83428
+ process.exitCode = 0;
83429
+ });
83240
83430
  }
83241
83431
  }),
83242
83432
  Effect_exports.catchAll((error4) => {
@@ -83253,7 +83443,7 @@ var cherryPick = Command_exports2.make(
83253
83443
  );
83254
83444
 
83255
83445
  // src/exercise.ts
83256
- var import_prompts = __toESM(require_prompts3());
83446
+ var import_prompts2 = __toESM(require_prompts3());
83257
83447
 
83258
83448
  // node_modules/.pnpm/@effect+platform-node@0.95.0_@effect+cluster@0.47.0_@effect+platform@0.90.2_effect@3.17_717c1c3b02c892e86f9e65866f1c696c/node_modules/@effect/platform-node/dist/esm/Undici.js
83259
83449
  var Undici_exports = {};
@@ -83489,19 +83679,6 @@ var envFilePathOption = Options_exports.text("env-file").pipe(
83489
83679
  );
83490
83680
 
83491
83681
  // src/exercise.ts
83492
- var PromptCancelledError = class extends Data_exports.TaggedError(
83493
- "PromptCancelledError"
83494
- ) {
83495
- };
83496
- var runPrompt = (prompt6) => {
83497
- return Effect_exports.gen(function* () {
83498
- const result = yield* Effect_exports.promise(() => prompt6());
83499
- if (!result) {
83500
- return yield* new PromptCancelledError();
83501
- }
83502
- return result;
83503
- });
83504
- };
83505
83682
  var LessonNotFoundError = class extends Data_exports.TaggedError(
83506
83683
  "LessonNotFoundError"
83507
83684
  ) {
@@ -83634,7 +83811,7 @@ var runLesson = Effect_exports.fn("runLesson")(function* (opts) {
83634
83811
  lowercase: "exercise"
83635
83812
  };
83636
83813
  const { choice: choice6 } = yield* runPrompt(
83637
- () => (0, import_prompts.default)([
83814
+ () => (0, import_prompts2.default)([
83638
83815
  {
83639
83816
  type: "select",
83640
83817
  name: "choice",
@@ -83723,7 +83900,7 @@ var chooseLessonAndRunIt = (opts) => Effect_exports.gen(function* () {
83723
83900
  );
83724
83901
  yield* Console_exports.clear;
83725
83902
  const { lesson: lessonNumber } = yield* runPrompt(
83726
- () => (0, import_prompts.default)([
83903
+ () => (0, import_prompts2.default)([
83727
83904
  {
83728
83905
  type: "autocomplete",
83729
83906
  name: "lesson",
@@ -83823,7 +84000,7 @@ var selectSubfolderIndex = Effect_exports.fn("selectSubfolder")(
83823
84000
  });
83824
84001
  }
83825
84002
  const result = yield* runPrompt(
83826
- () => (0, import_prompts.default)([
84003
+ () => (0, import_prompts2.default)([
83827
84004
  {
83828
84005
  type: "select",
83829
84006
  name: "subfolderIndex",
@@ -84495,10 +84672,10 @@ var MissingExerciseFolderError = class extends Data_exports.TaggedError(
84495
84672
  "DiffGenerationError"
84496
84673
  ) {
84497
84674
  });
84498
- var DirtyWorkingTreeError = class extends Data_exports.TaggedError(
84675
+ (class extends Data_exports.TaggedError(
84499
84676
  "DirtyWorkingTreeError"
84500
84677
  ) {
84501
- };
84678
+ });
84502
84679
  var NoExerciseFoundError = class extends Data_exports.TaggedError(
84503
84680
  "NoExerciseFoundError"
84504
84681
  ) {
@@ -84512,9 +84689,7 @@ var getDiffs = Command_exports2.make(
84512
84689
  )
84513
84690
  ),
84514
84691
  branch: Options_exports.text("branch").pipe(
84515
- Options_exports.withDescription(
84516
- "Branch to checkout before getting diffs"
84517
- )
84692
+ Options_exports.withDescription("Branch to get diffs from")
84518
84693
  ),
84519
84694
  root: Options_exports.text("root").pipe(
84520
84695
  Options_exports.withDescription(
@@ -84542,39 +84717,24 @@ var getDiffs = Command_exports2.make(
84542
84717
  })
84543
84718
  );
84544
84719
  }
84545
- const gitStatusCommand = Command_exports.make(
84720
+ yield* Console_exports.log("Fetching latest from origin...");
84721
+ const gitFetchCommand = Command_exports.make(
84546
84722
  "git",
84547
- "status",
84548
- "--porcelain"
84723
+ "fetch",
84724
+ "origin"
84549
84725
  ).pipe(Command_exports.workingDirectory(projectRepo));
84550
- const statusOutput = yield* Command_exports.string(
84551
- gitStatusCommand
84552
- );
84553
- if (statusOutput.trim() !== "") {
84554
- return yield* Effect_exports.fail(
84555
- new DirtyWorkingTreeError({
84556
- path: projectRepo,
84557
- message: `Working tree has uncommitted changes. Commit or stash changes before running get-diffs`
84558
- })
84559
- );
84560
- }
84561
- const gitCheckoutCommand = Command_exports.make(
84562
- "git",
84563
- "checkout",
84564
- branch
84565
- ).pipe(Command_exports.workingDirectory(projectRepo));
84566
- const checkoutExitCode = yield* Command_exports.exitCode(
84567
- gitCheckoutCommand
84726
+ const fetchExitCode = yield* Command_exports.exitCode(
84727
+ gitFetchCommand
84568
84728
  ).pipe(Effect_exports.catchAll(() => Effect_exports.succeed(1)));
84569
- if (checkoutExitCode !== 0) {
84729
+ if (fetchExitCode !== 0) {
84570
84730
  return yield* Effect_exports.fail(
84571
84731
  new InvalidProjectRepoError({
84572
84732
  path: projectRepo,
84573
- message: `Failed to checkout branch: ${branch}`
84733
+ message: `Failed to fetch from origin`
84574
84734
  })
84575
84735
  );
84576
84736
  }
84577
- yield* Console_exports.log(`\u2713 Checked out branch: ${branch}`);
84737
+ yield* Console_exports.log(`\u2713 Fetched latest from origin`);
84578
84738
  yield* Console_exports.log(
84579
84739
  `\u2713 Validated project repo: ${projectRepo}`
84580
84740
  );
@@ -84586,7 +84746,7 @@ var getDiffs = Command_exports2.make(
84586
84746
  "--oneline",
84587
84747
  "--reverse",
84588
84748
  // Chronological order (oldest first)
84589
- "--all"
84749
+ branch
84590
84750
  ).pipe(Command_exports.workingDirectory(projectRepo));
84591
84751
  const commitHistory = yield* Command_exports.string(gitLogCommand);
84592
84752
  const commits = commitHistory.trim().split("\n").filter(Boolean).map((line4) => {
@@ -84786,12 +84946,6 @@ var getDiffs = Command_exports2.make(
84786
84946
  process.exitCode = 1;
84787
84947
  });
84788
84948
  },
84789
- DirtyWorkingTreeError: (error4) => {
84790
- return Effect_exports.gen(function* () {
84791
- yield* Console_exports.error(`Error: ${error4.message}`);
84792
- process.exitCode = 1;
84793
- });
84794
- },
84795
84949
  NoExerciseFoundError: (error4) => {
84796
84950
  return Effect_exports.gen(function* () {
84797
84951
  yield* Console_exports.error(
@@ -84871,39 +85025,43 @@ var internal = Command_exports2.make("internal").pipe(
84871
85025
  );
84872
85026
 
84873
85027
  // src/reset.ts
84874
- var import_prompts2 = __toESM(require_prompts3());
85028
+ var import_prompts3 = __toESM(require_prompts3());
84875
85029
  var NotAGitRepoError2 = class extends Data_exports.TaggedError(
84876
85030
  "NotAGitRepoError"
84877
85031
  ) {
84878
85032
  };
84879
- var CommitNotFoundError2 = class extends Data_exports.TaggedError(
84880
- "CommitNotFoundError"
84881
- ) {
84882
- };
84883
- var PromptCancelledError2 = class extends Data_exports.TaggedError(
84884
- "PromptCancelledError"
85033
+ var InvalidBranchOperationError2 = class extends Data_exports.TaggedError(
85034
+ "InvalidBranchOperationError"
84885
85035
  ) {
84886
85036
  };
84887
- var runPrompt2 = (promptFn) => {
84888
- return Effect_exports.gen(function* () {
84889
- const result = yield* Effect_exports.promise(() => promptFn());
84890
- if (!result) {
84891
- return yield* new PromptCancelledError2();
84892
- }
84893
- return result;
84894
- });
84895
- };
84896
85037
  var reset2 = Command_exports2.make(
84897
85038
  "reset",
84898
85039
  {
84899
- lessonId: Args_exports.text({ name: "lesson-id" }),
85040
+ lessonId: Args_exports.text({ name: "lesson-id" }).pipe(
85041
+ Args_exports.optional
85042
+ ),
84900
85043
  branch: Options_exports.text("branch").pipe(
84901
85044
  Options_exports.withDescription(
84902
85045
  "Branch to search for the lesson commit"
84903
85046
  )
85047
+ ),
85048
+ problem: Options_exports.boolean("problem").pipe(
85049
+ Options_exports.withAlias("p"),
85050
+ Options_exports.withDescription(
85051
+ "Reset to problem state (start the exercise)"
85052
+ )
85053
+ ),
85054
+ solution: Options_exports.boolean("solution").pipe(
85055
+ Options_exports.withAlias("s"),
85056
+ Options_exports.withDescription(
85057
+ "Reset to solution state (final code)"
85058
+ )
85059
+ ),
85060
+ demo: Options_exports.boolean("demo").pipe(
85061
+ Options_exports.withAlias("d")
84904
85062
  )
84905
85063
  },
84906
- ({ branch, lessonId }) => Effect_exports.gen(function* () {
85064
+ ({ branch, demo, lessonId, problem, solution }) => Effect_exports.gen(function* () {
84907
85065
  const cwd = process.cwd();
84908
85066
  const gitDirPath = path5__namespace.join(cwd, ".git");
84909
85067
  if (!NFS.existsSync(gitDirPath)) {
@@ -84914,71 +85072,133 @@ var reset2 = Command_exports2.make(
84914
85072
  })
84915
85073
  );
84916
85074
  }
84917
- yield* Console_exports.log(
84918
- `Searching for lesson ${lessonId} on branch ${branch}...`
84919
- );
84920
- const gitLogCommand = Command_exports.make(
85075
+ const gitFetchCommand = Command_exports.make(
84921
85076
  "git",
84922
- "log",
85077
+ "fetch",
85078
+ "origin"
85079
+ ).pipe(
85080
+ Command_exports.workingDirectory(cwd),
85081
+ Command_exports.stdout("inherit"),
85082
+ Command_exports.stderr("inherit")
85083
+ );
85084
+ const fetchExitCode = yield* Command_exports.exitCode(
85085
+ gitFetchCommand
85086
+ );
85087
+ if (fetchExitCode !== 0) {
85088
+ yield* Console_exports.error("Failed to fetch branch");
85089
+ process.exitCode = 1;
85090
+ return;
85091
+ }
85092
+ const {
85093
+ commit: targetCommit,
85094
+ lessonId: selectedLessonId
85095
+ } = yield* selectLessonCommit({
85096
+ cwd,
84923
85097
  branch,
84924
- "--oneline",
84925
- "--all"
84926
- ).pipe(Command_exports.workingDirectory(cwd));
84927
- const commitHistory = yield* Command_exports.string(gitLogCommand);
84928
- const commits = commitHistory.trim().split("\n").filter(Boolean).map((line4) => {
84929
- const [sha, ...messageParts] = line4.split(" ");
84930
- const message = messageParts.join(" ");
84931
- const lessonMatch = message.match(
84932
- /^(\d+)[.-](\d+)[.-](\d+) /
84933
- );
84934
- const extractedLessonId = lessonMatch ? `${lessonMatch[1].padStart(
84935
- 2,
84936
- "0"
84937
- )}.${lessonMatch[2].padStart(
84938
- 2,
84939
- "0"
84940
- )}.${lessonMatch[3].padStart(2, "0")}` : null;
84941
- return {
84942
- sha,
84943
- message,
84944
- lessonId: extractedLessonId
84945
- };
85098
+ lessonId,
85099
+ promptMessage: "Which lesson do you want to reset to? (type to search)",
85100
+ excludeCurrentBranch: false
84946
85101
  });
84947
- const matchingCommits = commits.filter(
84948
- (commit) => commit.lessonId === lessonId
84949
- );
84950
- if (matchingCommits.length === 0) {
84951
- return yield* new CommitNotFoundError2({
84952
- lessonId,
84953
- branch
85102
+ let commitToUse = targetCommit.sha;
85103
+ let stateDescription = "final code";
85104
+ if (problem && solution) {
85105
+ return yield* Effect_exports.fail(
85106
+ new InvalidBranchOperationError2({
85107
+ message: "Cannot use both --problem and --solution flags"
85108
+ })
85109
+ );
85110
+ }
85111
+ if (demo && (problem || solution)) {
85112
+ return yield* Effect_exports.fail(
85113
+ new InvalidBranchOperationError2({
85114
+ message: "Cannot use --demo with --problem or --solution flags"
85115
+ })
85116
+ );
85117
+ }
85118
+ if (!problem && !solution && !demo) {
85119
+ const { state } = yield* runPrompt(
85120
+ () => (0, import_prompts3.default)([
85121
+ {
85122
+ type: "select",
85123
+ name: "state",
85124
+ message: "Start the exercise or view final code?",
85125
+ choices: [
85126
+ {
85127
+ title: "Start the exercise",
85128
+ value: "problem",
85129
+ description: "Reset to problem state (commit before solution)"
85130
+ },
85131
+ {
85132
+ title: "Final code",
85133
+ value: "solution",
85134
+ description: "Reset to solution state (completed exercise)"
85135
+ }
85136
+ ]
85137
+ }
85138
+ ])
85139
+ );
85140
+ if (state === "problem") {
85141
+ commitToUse = yield* getParentCommit({
85142
+ commitSha: targetCommit.sha,
85143
+ cwd
85144
+ });
85145
+ stateDescription = "problem state";
85146
+ }
85147
+ } else if (problem) {
85148
+ commitToUse = yield* getParentCommit({
85149
+ commitSha: targetCommit.sha,
85150
+ cwd
84954
85151
  });
85152
+ stateDescription = "problem state";
85153
+ }
85154
+ const currentBranchCommand = Command_exports.make(
85155
+ "git",
85156
+ "branch",
85157
+ "--show-current"
85158
+ ).pipe(Command_exports.workingDirectory(cwd));
85159
+ const currentBranch = (yield* Command_exports.string(
85160
+ currentBranchCommand
85161
+ )).trim();
85162
+ let action;
85163
+ if (demo) {
85164
+ action = "reset-current";
85165
+ } else {
85166
+ const result = yield* runPrompt(
85167
+ () => (0, import_prompts3.default)([
85168
+ {
85169
+ type: "select",
85170
+ name: "action",
85171
+ message: "How would you like to proceed?",
85172
+ choices: [
85173
+ {
85174
+ title: `Reset current branch (${currentBranch})`,
85175
+ value: "reset-current"
85176
+ },
85177
+ {
85178
+ title: "Create new branch from commit",
85179
+ value: "create-branch"
85180
+ }
85181
+ ]
85182
+ }
85183
+ ])
85184
+ );
85185
+ action = result.action;
85186
+ }
85187
+ if (action === "reset-current") {
85188
+ if (currentBranch === branch) {
85189
+ return yield* new InvalidBranchOperationError2({
85190
+ message: `Cannot reset current branch when on target branch "${branch}"`
85191
+ });
85192
+ }
85193
+ if (currentBranch === "main") {
85194
+ return yield* new InvalidBranchOperationError2({
85195
+ message: `Cannot reset current branch when on "main" branch`
85196
+ });
85197
+ }
84955
85198
  }
84956
- const targetCommit = matchingCommits[matchingCommits.length - 1];
84957
- yield* Console_exports.log(
84958
- `Found commit: ${targetCommit.sha} ${targetCommit.message}`
84959
- );
84960
- const { action } = yield* runPrompt2(
84961
- () => (0, import_prompts2.default)([
84962
- {
84963
- type: "select",
84964
- name: "action",
84965
- message: "How would you like to proceed?",
84966
- choices: [
84967
- {
84968
- title: "Reset current branch",
84969
- value: "reset-current"
84970
- },
84971
- {
84972
- title: "Create new branch from commit",
84973
- value: "create-branch"
84974
- }
84975
- ]
84976
- }
84977
- ])
84978
- );
84979
85199
  if (action === "create-branch") {
84980
- const { branchName } = yield* runPrompt2(
84981
- () => (0, import_prompts2.default)([
85200
+ const { branchName } = yield* runPrompt(
85201
+ () => (0, import_prompts3.default)([
84982
85202
  {
84983
85203
  type: "text",
84984
85204
  name: "branchName",
@@ -84987,14 +85207,14 @@ var reset2 = Command_exports2.make(
84987
85207
  ])
84988
85208
  );
84989
85209
  yield* Console_exports.log(
84990
- `Creating branch ${branchName} from ${targetCommit.sha}...`
85210
+ `Creating branch ${branchName} from ${commitToUse} (${stateDescription})...`
84991
85211
  );
84992
85212
  const createBranchCommand = Command_exports.make(
84993
85213
  "git",
84994
85214
  "checkout",
84995
85215
  "-b",
84996
85216
  branchName,
84997
- targetCommit.sha
85217
+ commitToUse
84998
85218
  ).pipe(
84999
85219
  Command_exports.workingDirectory(cwd),
85000
85220
  Command_exports.stdout("inherit"),
@@ -85013,40 +85233,44 @@ var reset2 = Command_exports2.make(
85013
85233
  );
85014
85234
  return;
85015
85235
  }
85016
- const gitStatusCommand = Command_exports.make(
85017
- "git",
85018
- "status",
85019
- "--porcelain"
85020
- ).pipe(Command_exports.workingDirectory(cwd));
85021
- const statusOutput = yield* Command_exports.string(
85022
- gitStatusCommand
85023
- );
85024
- if (statusOutput.trim() !== "") {
85025
- yield* Console_exports.log(
85026
- "\nWarning: You have uncommitted changes:"
85027
- );
85028
- yield* Console_exports.log(statusOutput);
85029
- const { confirm } = yield* runPrompt2(
85030
- () => (0, import_prompts2.default)([
85031
- {
85032
- type: "confirm",
85033
- name: "confirm",
85034
- message: "This will lose all uncommitted work. Continue?",
85035
- initial: false
85036
- }
85037
- ])
85236
+ if (!demo) {
85237
+ const gitStatusCommand = Command_exports.make(
85238
+ "git",
85239
+ "status",
85240
+ "--porcelain"
85241
+ ).pipe(Command_exports.workingDirectory(cwd));
85242
+ const statusOutput = yield* Command_exports.string(
85243
+ gitStatusCommand
85038
85244
  );
85039
- if (!confirm) {
85040
- yield* Console_exports.log("Reset cancelled");
85041
- return;
85245
+ if (statusOutput.trim() !== "") {
85246
+ yield* Console_exports.log(
85247
+ "\nWarning: You have uncommitted changes:"
85248
+ );
85249
+ yield* Console_exports.log(statusOutput);
85250
+ const { confirm } = yield* runPrompt(
85251
+ () => (0, import_prompts3.default)([
85252
+ {
85253
+ type: "confirm",
85254
+ name: "confirm",
85255
+ message: "This will lose all uncommitted work. Continue?",
85256
+ initial: false
85257
+ }
85258
+ ])
85259
+ );
85260
+ if (!confirm) {
85261
+ yield* Console_exports.log("Reset cancelled");
85262
+ return;
85263
+ }
85042
85264
  }
85043
85265
  }
85044
- yield* Console_exports.log(`Resetting to ${targetCommit.sha}...`);
85266
+ yield* Console_exports.log(
85267
+ `Resetting to ${commitToUse} (${stateDescription})...`
85268
+ );
85045
85269
  const resetCommand = Command_exports.make(
85046
85270
  "git",
85047
85271
  "reset",
85048
85272
  "--hard",
85049
- targetCommit.sha
85273
+ commitToUse
85050
85274
  ).pipe(
85051
85275
  Command_exports.workingDirectory(cwd),
85052
85276
  Command_exports.stdout("inherit"),
@@ -85060,9 +85284,61 @@ var reset2 = Command_exports2.make(
85060
85284
  process.exitCode = 1;
85061
85285
  return;
85062
85286
  }
85063
- yield* Console_exports.log(`\u2713 Reset to lesson ${lessonId}`);
85287
+ if (demo) {
85288
+ yield* Console_exports.log("Undoing commit and unstaging changes...");
85289
+ const undoCommand = Command_exports.make(
85290
+ "git",
85291
+ "reset",
85292
+ "HEAD^"
85293
+ ).pipe(
85294
+ Command_exports.workingDirectory(cwd),
85295
+ Command_exports.stdout("inherit"),
85296
+ Command_exports.stderr("inherit")
85297
+ );
85298
+ const undoExitCode = yield* Command_exports.exitCode(
85299
+ undoCommand
85300
+ ).pipe(Effect_exports.catchAll(() => Effect_exports.succeed(1)));
85301
+ if (undoExitCode !== 0) {
85302
+ yield* Console_exports.error("Failed to undo commit");
85303
+ process.exitCode = 1;
85304
+ return;
85305
+ }
85306
+ const unstageCommand = Command_exports.make(
85307
+ "git",
85308
+ "restore",
85309
+ "--staged",
85310
+ "."
85311
+ ).pipe(
85312
+ Command_exports.workingDirectory(cwd),
85313
+ Command_exports.stdout("inherit"),
85314
+ Command_exports.stderr("inherit")
85315
+ );
85316
+ const unstageExitCode = yield* Command_exports.exitCode(
85317
+ unstageCommand
85318
+ ).pipe(Effect_exports.catchAll(() => Effect_exports.succeed(1)));
85319
+ if (unstageExitCode !== 0) {
85320
+ yield* Console_exports.error("Failed to unstage changes");
85321
+ process.exitCode = 1;
85322
+ return;
85323
+ }
85324
+ yield* Console_exports.log(
85325
+ `\u2713 Demo mode: Reset to lesson ${selectedLessonId} with unstaged changes`
85326
+ );
85327
+ } else {
85328
+ yield* Console_exports.log(
85329
+ `\u2713 Reset to lesson ${selectedLessonId} (${stateDescription})`
85330
+ );
85331
+ }
85064
85332
  }).pipe(
85065
85333
  Effect_exports.catchTags({
85334
+ NoParentCommitError: (error4) => {
85335
+ return Effect_exports.gen(function* () {
85336
+ yield* Console_exports.error(
85337
+ `Error: Commit ${error4.commitSha} has no parent commit. Repository may be in an invalid state.`
85338
+ );
85339
+ process.exitCode = 1;
85340
+ });
85341
+ },
85066
85342
  NotAGitRepoError: (error4) => {
85067
85343
  return Effect_exports.gen(function* () {
85068
85344
  yield* Console_exports.error(`Error: ${error4.message}`);
@@ -85082,6 +85358,12 @@ var reset2 = Command_exports2.make(
85082
85358
  yield* Console_exports.log("Operation cancelled");
85083
85359
  process.exitCode = 0;
85084
85360
  });
85361
+ },
85362
+ InvalidBranchOperationError: (error4) => {
85363
+ return Effect_exports.gen(function* () {
85364
+ yield* Console_exports.error(`Error: ${error4.message}`);
85365
+ process.exitCode = 1;
85366
+ });
85085
85367
  }
85086
85368
  }),
85087
85369
  Effect_exports.catchAll((error4) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-hero-cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "type": "module",
5
5
  "description": "The CLI used to run exercises for the AI Hero course",
6
6
  "bin": "bin.cjs",