ai-hero-cli 0.2.3 → 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 +516 -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,9 +83330,6 @@ 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
83333
  const gitFetchCommand = Command_exports.make(
83161
83334
  "git",
83162
83335
  "fetch",
@@ -83174,45 +83347,34 @@ var cherryPick = Command_exports2.make(
83174
83347
  process.exitCode = 1;
83175
83348
  return;
83176
83349
  }
83177
- const gitLogCommand = Command_exports.make(
83178
- "git",
83179
- "log",
83350
+ const {
83351
+ commit: targetCommit,
83352
+ lessonId: selectedLessonId
83353
+ } = yield* selectLessonCommit({
83354
+ cwd,
83180
83355
  branch,
83181
- "--oneline"
83182
- ).pipe(Command_exports.workingDirectory(cwd));
83183
- const commitHistory = yield* Command_exports.string(gitLogCommand);
83184
- const commits = commitHistory.trim().split("\n").filter(Boolean).map((line4) => {
83185
- const [sha, ...messageParts] = line4.split(" ");
83186
- const message = messageParts.join(" ");
83187
- const lessonMatch = message.match(
83188
- /^(\d+)[.-](\d+)[.-](\d+)/
83189
- );
83190
- const extractedLessonId = lessonMatch ? `${lessonMatch[1].padStart(
83191
- 2,
83192
- "0"
83193
- )}.${lessonMatch[2].padStart(
83194
- 2,
83195
- "0"
83196
- )}.${lessonMatch[3].padStart(2, "0")}` : null;
83197
- return {
83198
- sha,
83199
- message,
83200
- lessonId: extractedLessonId
83201
- };
83356
+ lessonId,
83357
+ promptMessage: "Which lesson do you want to cherry-pick? (type to search)",
83358
+ excludeCurrentBranch: true
83202
83359
  });
83203
- const matchingCommits = commits.filter(
83204
- (commit) => commit.lessonId === lessonId
83205
- );
83206
- if (matchingCommits.length === 0) {
83207
- return yield* new CommitNotFoundError({
83208
- lessonId,
83209
- 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`
83210
83376
  });
83211
83377
  }
83212
- const targetCommit = matchingCommits[matchingCommits.length - 1];
83213
- yield* Console_exports.log(
83214
- `Found commit: ${targetCommit.sha} ${targetCommit.message}`
83215
- );
83216
83378
  yield* Console_exports.log(
83217
83379
  `Cherry-picking ${targetCommit.sha} onto current branch...
83218
83380
  `
@@ -83236,7 +83398,7 @@ var cherryPick = Command_exports2.make(
83236
83398
  }
83237
83399
  yield* Console_exports.log(
83238
83400
  `
83239
- \u2713 Successfully cherry-picked lesson ${lessonId}`
83401
+ \u2713 Successfully cherry-picked lesson ${selectedLessonId}`
83240
83402
  );
83241
83403
  }).pipe(
83242
83404
  Effect_exports.catchTags({
@@ -83253,6 +83415,18 @@ var cherryPick = Command_exports2.make(
83253
83415
  );
83254
83416
  process.exitCode = 1;
83255
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
+ });
83256
83430
  }
83257
83431
  }),
83258
83432
  Effect_exports.catchAll((error4) => {
@@ -83269,7 +83443,7 @@ var cherryPick = Command_exports2.make(
83269
83443
  );
83270
83444
 
83271
83445
  // src/exercise.ts
83272
- var import_prompts = __toESM(require_prompts3());
83446
+ var import_prompts2 = __toESM(require_prompts3());
83273
83447
 
83274
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
83275
83449
  var Undici_exports = {};
@@ -83505,19 +83679,6 @@ var envFilePathOption = Options_exports.text("env-file").pipe(
83505
83679
  );
83506
83680
 
83507
83681
  // src/exercise.ts
83508
- var PromptCancelledError = class extends Data_exports.TaggedError(
83509
- "PromptCancelledError"
83510
- ) {
83511
- };
83512
- var runPrompt = (prompt6) => {
83513
- return Effect_exports.gen(function* () {
83514
- const result = yield* Effect_exports.promise(() => prompt6());
83515
- if (!result) {
83516
- return yield* new PromptCancelledError();
83517
- }
83518
- return result;
83519
- });
83520
- };
83521
83682
  var LessonNotFoundError = class extends Data_exports.TaggedError(
83522
83683
  "LessonNotFoundError"
83523
83684
  ) {
@@ -83650,7 +83811,7 @@ var runLesson = Effect_exports.fn("runLesson")(function* (opts) {
83650
83811
  lowercase: "exercise"
83651
83812
  };
83652
83813
  const { choice: choice6 } = yield* runPrompt(
83653
- () => (0, import_prompts.default)([
83814
+ () => (0, import_prompts2.default)([
83654
83815
  {
83655
83816
  type: "select",
83656
83817
  name: "choice",
@@ -83739,7 +83900,7 @@ var chooseLessonAndRunIt = (opts) => Effect_exports.gen(function* () {
83739
83900
  );
83740
83901
  yield* Console_exports.clear;
83741
83902
  const { lesson: lessonNumber } = yield* runPrompt(
83742
- () => (0, import_prompts.default)([
83903
+ () => (0, import_prompts2.default)([
83743
83904
  {
83744
83905
  type: "autocomplete",
83745
83906
  name: "lesson",
@@ -83839,7 +84000,7 @@ var selectSubfolderIndex = Effect_exports.fn("selectSubfolder")(
83839
84000
  });
83840
84001
  }
83841
84002
  const result = yield* runPrompt(
83842
- () => (0, import_prompts.default)([
84003
+ () => (0, import_prompts2.default)([
83843
84004
  {
83844
84005
  type: "select",
83845
84006
  name: "subfolderIndex",
@@ -84511,10 +84672,10 @@ var MissingExerciseFolderError = class extends Data_exports.TaggedError(
84511
84672
  "DiffGenerationError"
84512
84673
  ) {
84513
84674
  });
84514
- var DirtyWorkingTreeError = class extends Data_exports.TaggedError(
84675
+ (class extends Data_exports.TaggedError(
84515
84676
  "DirtyWorkingTreeError"
84516
84677
  ) {
84517
- };
84678
+ });
84518
84679
  var NoExerciseFoundError = class extends Data_exports.TaggedError(
84519
84680
  "NoExerciseFoundError"
84520
84681
  ) {
@@ -84528,9 +84689,7 @@ var getDiffs = Command_exports2.make(
84528
84689
  )
84529
84690
  ),
84530
84691
  branch: Options_exports.text("branch").pipe(
84531
- Options_exports.withDescription(
84532
- "Branch to checkout before getting diffs"
84533
- )
84692
+ Options_exports.withDescription("Branch to get diffs from")
84534
84693
  ),
84535
84694
  root: Options_exports.text("root").pipe(
84536
84695
  Options_exports.withDescription(
@@ -84558,39 +84717,24 @@ var getDiffs = Command_exports2.make(
84558
84717
  })
84559
84718
  );
84560
84719
  }
84561
- const gitStatusCommand = Command_exports.make(
84562
- "git",
84563
- "status",
84564
- "--porcelain"
84565
- ).pipe(Command_exports.workingDirectory(projectRepo));
84566
- const statusOutput = yield* Command_exports.string(
84567
- gitStatusCommand
84568
- );
84569
- if (statusOutput.trim() !== "") {
84570
- return yield* Effect_exports.fail(
84571
- new DirtyWorkingTreeError({
84572
- path: projectRepo,
84573
- message: `Working tree has uncommitted changes. Commit or stash changes before running get-diffs`
84574
- })
84575
- );
84576
- }
84577
- const gitCheckoutCommand = Command_exports.make(
84720
+ yield* Console_exports.log("Fetching latest from origin...");
84721
+ const gitFetchCommand = Command_exports.make(
84578
84722
  "git",
84579
- "checkout",
84580
- branch
84723
+ "fetch",
84724
+ "origin"
84581
84725
  ).pipe(Command_exports.workingDirectory(projectRepo));
84582
- const checkoutExitCode = yield* Command_exports.exitCode(
84583
- gitCheckoutCommand
84726
+ const fetchExitCode = yield* Command_exports.exitCode(
84727
+ gitFetchCommand
84584
84728
  ).pipe(Effect_exports.catchAll(() => Effect_exports.succeed(1)));
84585
- if (checkoutExitCode !== 0) {
84729
+ if (fetchExitCode !== 0) {
84586
84730
  return yield* Effect_exports.fail(
84587
84731
  new InvalidProjectRepoError({
84588
84732
  path: projectRepo,
84589
- message: `Failed to checkout branch: ${branch}`
84733
+ message: `Failed to fetch from origin`
84590
84734
  })
84591
84735
  );
84592
84736
  }
84593
- yield* Console_exports.log(`\u2713 Checked out branch: ${branch}`);
84737
+ yield* Console_exports.log(`\u2713 Fetched latest from origin`);
84594
84738
  yield* Console_exports.log(
84595
84739
  `\u2713 Validated project repo: ${projectRepo}`
84596
84740
  );
@@ -84602,7 +84746,7 @@ var getDiffs = Command_exports2.make(
84602
84746
  "--oneline",
84603
84747
  "--reverse",
84604
84748
  // Chronological order (oldest first)
84605
- "--all"
84749
+ branch
84606
84750
  ).pipe(Command_exports.workingDirectory(projectRepo));
84607
84751
  const commitHistory = yield* Command_exports.string(gitLogCommand);
84608
84752
  const commits = commitHistory.trim().split("\n").filter(Boolean).map((line4) => {
@@ -84802,12 +84946,6 @@ var getDiffs = Command_exports2.make(
84802
84946
  process.exitCode = 1;
84803
84947
  });
84804
84948
  },
84805
- DirtyWorkingTreeError: (error4) => {
84806
- return Effect_exports.gen(function* () {
84807
- yield* Console_exports.error(`Error: ${error4.message}`);
84808
- process.exitCode = 1;
84809
- });
84810
- },
84811
84949
  NoExerciseFoundError: (error4) => {
84812
84950
  return Effect_exports.gen(function* () {
84813
84951
  yield* Console_exports.error(
@@ -84887,39 +85025,43 @@ var internal = Command_exports2.make("internal").pipe(
84887
85025
  );
84888
85026
 
84889
85027
  // src/reset.ts
84890
- var import_prompts2 = __toESM(require_prompts3());
85028
+ var import_prompts3 = __toESM(require_prompts3());
84891
85029
  var NotAGitRepoError2 = class extends Data_exports.TaggedError(
84892
85030
  "NotAGitRepoError"
84893
85031
  ) {
84894
85032
  };
84895
- var CommitNotFoundError2 = class extends Data_exports.TaggedError(
84896
- "CommitNotFoundError"
84897
- ) {
84898
- };
84899
- var PromptCancelledError2 = class extends Data_exports.TaggedError(
84900
- "PromptCancelledError"
85033
+ var InvalidBranchOperationError2 = class extends Data_exports.TaggedError(
85034
+ "InvalidBranchOperationError"
84901
85035
  ) {
84902
85036
  };
84903
- var runPrompt2 = (promptFn) => {
84904
- return Effect_exports.gen(function* () {
84905
- const result = yield* Effect_exports.promise(() => promptFn());
84906
- if (!result) {
84907
- return yield* new PromptCancelledError2();
84908
- }
84909
- return result;
84910
- });
84911
- };
84912
85037
  var reset2 = Command_exports2.make(
84913
85038
  "reset",
84914
85039
  {
84915
- lessonId: Args_exports.text({ name: "lesson-id" }),
85040
+ lessonId: Args_exports.text({ name: "lesson-id" }).pipe(
85041
+ Args_exports.optional
85042
+ ),
84916
85043
  branch: Options_exports.text("branch").pipe(
84917
85044
  Options_exports.withDescription(
84918
85045
  "Branch to search for the lesson commit"
84919
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")
84920
85062
  )
84921
85063
  },
84922
- ({ branch, lessonId }) => Effect_exports.gen(function* () {
85064
+ ({ branch, demo, lessonId, problem, solution }) => Effect_exports.gen(function* () {
84923
85065
  const cwd = process.cwd();
84924
85066
  const gitDirPath = path5__namespace.join(cwd, ".git");
84925
85067
  if (!NFS.existsSync(gitDirPath)) {
@@ -84947,70 +85089,116 @@ var reset2 = Command_exports2.make(
84947
85089
  process.exitCode = 1;
84948
85090
  return;
84949
85091
  }
84950
- yield* Console_exports.log(
84951
- `Searching for lesson ${lessonId} on branch ${branch}...`
84952
- );
84953
- const gitLogCommand = Command_exports.make(
84954
- "git",
84955
- "log",
85092
+ const {
85093
+ commit: targetCommit,
85094
+ lessonId: selectedLessonId
85095
+ } = yield* selectLessonCommit({
85096
+ cwd,
84956
85097
  branch,
84957
- "--oneline"
84958
- ).pipe(Command_exports.workingDirectory(cwd));
84959
- const commitHistory = yield* Command_exports.string(gitLogCommand);
84960
- const commits = commitHistory.trim().split("\n").filter(Boolean).map((line4) => {
84961
- const [sha, ...messageParts] = line4.split(" ");
84962
- const message = messageParts.join(" ");
84963
- const lessonMatch = message.match(
84964
- /^(\d+)[.-](\d+)[.-](\d+) /
84965
- );
84966
- const extractedLessonId = lessonMatch ? `${lessonMatch[1].padStart(
84967
- 2,
84968
- "0"
84969
- )}.${lessonMatch[2].padStart(
84970
- 2,
84971
- "0"
84972
- )}.${lessonMatch[3].padStart(2, "0")}` : null;
84973
- return {
84974
- sha,
84975
- message,
84976
- lessonId: extractedLessonId
84977
- };
85098
+ lessonId,
85099
+ promptMessage: "Which lesson do you want to reset to? (type to search)",
85100
+ excludeCurrentBranch: false
84978
85101
  });
84979
- const matchingCommits = commits.filter(
84980
- (commit) => commit.lessonId === lessonId
84981
- );
84982
- if (matchingCommits.length === 0) {
84983
- return yield* new CommitNotFoundError2({
84984
- lessonId,
84985
- 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
84986
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
+ }
84987
85198
  }
84988
- const targetCommit = matchingCommits[matchingCommits.length - 1];
84989
- yield* Console_exports.log(
84990
- `Found commit: ${targetCommit.sha} ${targetCommit.message}`
84991
- );
84992
- const { action } = yield* runPrompt2(
84993
- () => (0, import_prompts2.default)([
84994
- {
84995
- type: "select",
84996
- name: "action",
84997
- message: "How would you like to proceed?",
84998
- choices: [
84999
- {
85000
- title: "Reset current branch",
85001
- value: "reset-current"
85002
- },
85003
- {
85004
- title: "Create new branch from commit",
85005
- value: "create-branch"
85006
- }
85007
- ]
85008
- }
85009
- ])
85010
- );
85011
85199
  if (action === "create-branch") {
85012
- const { branchName } = yield* runPrompt2(
85013
- () => (0, import_prompts2.default)([
85200
+ const { branchName } = yield* runPrompt(
85201
+ () => (0, import_prompts3.default)([
85014
85202
  {
85015
85203
  type: "text",
85016
85204
  name: "branchName",
@@ -85019,14 +85207,14 @@ var reset2 = Command_exports2.make(
85019
85207
  ])
85020
85208
  );
85021
85209
  yield* Console_exports.log(
85022
- `Creating branch ${branchName} from ${targetCommit.sha}...`
85210
+ `Creating branch ${branchName} from ${commitToUse} (${stateDescription})...`
85023
85211
  );
85024
85212
  const createBranchCommand = Command_exports.make(
85025
85213
  "git",
85026
85214
  "checkout",
85027
85215
  "-b",
85028
85216
  branchName,
85029
- targetCommit.sha
85217
+ commitToUse
85030
85218
  ).pipe(
85031
85219
  Command_exports.workingDirectory(cwd),
85032
85220
  Command_exports.stdout("inherit"),
@@ -85045,40 +85233,44 @@ var reset2 = Command_exports2.make(
85045
85233
  );
85046
85234
  return;
85047
85235
  }
85048
- const gitStatusCommand = Command_exports.make(
85049
- "git",
85050
- "status",
85051
- "--porcelain"
85052
- ).pipe(Command_exports.workingDirectory(cwd));
85053
- const statusOutput = yield* Command_exports.string(
85054
- gitStatusCommand
85055
- );
85056
- if (statusOutput.trim() !== "") {
85057
- yield* Console_exports.log(
85058
- "\nWarning: You have uncommitted changes:"
85059
- );
85060
- yield* Console_exports.log(statusOutput);
85061
- const { confirm } = yield* runPrompt2(
85062
- () => (0, import_prompts2.default)([
85063
- {
85064
- type: "confirm",
85065
- name: "confirm",
85066
- message: "This will lose all uncommitted work. Continue?",
85067
- initial: false
85068
- }
85069
- ])
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
85070
85244
  );
85071
- if (!confirm) {
85072
- yield* Console_exports.log("Reset cancelled");
85073
- 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
+ }
85074
85264
  }
85075
85265
  }
85076
- yield* Console_exports.log(`Resetting to ${targetCommit.sha}...`);
85266
+ yield* Console_exports.log(
85267
+ `Resetting to ${commitToUse} (${stateDescription})...`
85268
+ );
85077
85269
  const resetCommand = Command_exports.make(
85078
85270
  "git",
85079
85271
  "reset",
85080
85272
  "--hard",
85081
- targetCommit.sha
85273
+ commitToUse
85082
85274
  ).pipe(
85083
85275
  Command_exports.workingDirectory(cwd),
85084
85276
  Command_exports.stdout("inherit"),
@@ -85092,9 +85284,61 @@ var reset2 = Command_exports2.make(
85092
85284
  process.exitCode = 1;
85093
85285
  return;
85094
85286
  }
85095
- 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
+ }
85096
85332
  }).pipe(
85097
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
+ },
85098
85342
  NotAGitRepoError: (error4) => {
85099
85343
  return Effect_exports.gen(function* () {
85100
85344
  yield* Console_exports.error(`Error: ${error4.message}`);
@@ -85114,6 +85358,12 @@ var reset2 = Command_exports2.make(
85114
85358
  yield* Console_exports.log("Operation cancelled");
85115
85359
  process.exitCode = 0;
85116
85360
  });
85361
+ },
85362
+ InvalidBranchOperationError: (error4) => {
85363
+ return Effect_exports.gen(function* () {
85364
+ yield* Console_exports.error(`Error: ${error4.message}`);
85365
+ process.exitCode = 1;
85366
+ });
85117
85367
  }
85118
85368
  }),
85119
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.3",
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",