chofex-cli 0.1.113 → 0.1.115

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 (3) hide show
  1. package/README.md +8 -0
  2. package/dist/index.js +249 -47
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -11,6 +11,7 @@ npm install --global chofex-cli@latest
11
11
  The installed command is `chofex`:
12
12
 
13
13
  ```sh
14
+ chofex
14
15
  chofex whoami
15
16
  chofex register
16
17
  chofex status
@@ -32,6 +33,13 @@ never decide admission or block an application submission.
32
33
 
33
34
  The public ranking is read-only at `https://andes.crafter.run/challenges`.
34
35
 
36
+ Run `chofex` for a compact retro welcome screen with a pixel Sacred Valley and
37
+ the main commands. Run `chofex --help` for the full command reference. The
38
+ landscape uses colored terminal cells, with readable text that works with your
39
+ terminal's line spacing. It adapts to the terminal width and has a plain ASCII
40
+ fallback when color is disabled with `NO_COLOR`. JSON output and individual
41
+ command results omit the welcome screen.
42
+
35
43
  For agent or script input, `chofex schema --stage application` and
36
44
  `chofex schema --stage acceptance` print complete templates containing every
37
45
  accepted JSON key. Validate a completed input file locally before submitting it:
package/dist/index.js CHANGED
@@ -51213,35 +51213,17 @@ var withTime = /* @__PURE__ */ dual((args2) => isEffect(args2[0]), (self, label)
51213
51213
  }), () => self, () => sync(() => {
51214
51214
  console2.timeEnd(label);
51215
51215
  }))));
51216
- // ../../node_modules/effect/dist/unstable/cli/Command.js
51217
- var exports_Command = {};
51218
- __export(exports_Command, {
51219
- wizard: () => wizard,
51220
- withSubcommands: () => withSubcommands,
51221
- withShortDescription: () => withShortDescription,
51222
- withSharedFlags: () => withSharedFlags,
51223
- withHandler: () => withHandler,
51224
- withGlobalFlags: () => withGlobalFlags,
51225
- withExamples: () => withExamples,
51226
- withDescription: () => withDescription3,
51227
- withAlias: () => withAlias3,
51228
- unlisted: () => unlisted,
51229
- runWith: () => runWith2,
51230
- run: () => run5,
51231
- provideSync: () => provideSync,
51232
- provideEffectDiscard: () => provideEffectDiscard,
51233
- provideEffect: () => provideEffect,
51234
- provide: () => provide6,
51235
- make: () => make37,
51236
- isCommand: () => isCommand,
51237
- annotateMerge: () => annotateMerge,
51238
- annotate: () => annotate4
51239
- });
51240
-
51241
51216
  // ../../node_modules/effect/dist/unstable/cli/CliOutput.js
51217
+ var exports_CliOutput = {};
51218
+ __export(exports_CliOutput, {
51219
+ layer: () => layer13,
51220
+ defaultFormatter: () => defaultFormatter2,
51221
+ Formatter: () => Formatter2
51222
+ });
51242
51223
  var Formatter2 = /* @__PURE__ */ Reference("effect/cli/CliOutput", {
51243
51224
  defaultValue: () => defaultFormatter2()
51244
51225
  });
51226
+ var layer13 = (formatter) => succeed5(Formatter2)(formatter);
51245
51227
  var escapeControlCharacters = (text) => text.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F]/g, (character) => `\\x${character.charCodeAt(0).toString(16).padStart(2, "0")}`);
51246
51228
  var defaultFormatter2 = (options) => {
51247
51229
  const globalProcess = globalThis.process;
@@ -51436,6 +51418,30 @@ var formatHelpDocImpl = (doc, colors2) => {
51436
51418
  return sections.join(`
51437
51419
  `);
51438
51420
  };
51421
+ // ../../node_modules/effect/dist/unstable/cli/Command.js
51422
+ var exports_Command = {};
51423
+ __export(exports_Command, {
51424
+ wizard: () => wizard,
51425
+ withSubcommands: () => withSubcommands,
51426
+ withShortDescription: () => withShortDescription,
51427
+ withSharedFlags: () => withSharedFlags,
51428
+ withHandler: () => withHandler,
51429
+ withGlobalFlags: () => withGlobalFlags,
51430
+ withExamples: () => withExamples,
51431
+ withDescription: () => withDescription3,
51432
+ withAlias: () => withAlias3,
51433
+ unlisted: () => unlisted,
51434
+ runWith: () => runWith2,
51435
+ run: () => run5,
51436
+ provideSync: () => provideSync,
51437
+ provideEffectDiscard: () => provideEffectDiscard,
51438
+ provideEffect: () => provideEffect,
51439
+ provide: () => provide6,
51440
+ make: () => make37,
51441
+ isCommand: () => isCommand,
51442
+ annotateMerge: () => annotateMerge,
51443
+ annotate: () => annotate4
51444
+ });
51439
51445
 
51440
51446
  // ../../node_modules/effect/dist/unstable/cli/internal/completions/bash.js
51441
51447
  var escapeForBash = (s) => s.replace(/'/g, "'\\''");
@@ -58383,7 +58389,7 @@ var mapHandler = (self, f) => {
58383
58389
  handle: (input, path4) => f(impl.handle(input, path4), input)
58384
58390
  });
58385
58391
  };
58386
- var provide6 = /* @__PURE__ */ dual((args2) => isCommand(args2[0]), (self, layer13, options) => mapHandler(self, (handler, input) => provide4(handler, typeof layer13 === "function" ? layer13(input) : layer13, options)));
58392
+ var provide6 = /* @__PURE__ */ dual((args2) => isCommand(args2[0]), (self, layer14, options) => mapHandler(self, (handler, input) => provide4(handler, typeof layer14 === "function" ? layer14(input) : layer14, options)));
58387
58393
  var provideSync = /* @__PURE__ */ dual(3, (self, service3, implementation) => mapHandler(self, (handler, input) => provideService2(handler, service3, typeof implementation === "function" ? implementation(input) : implementation)));
58388
58394
  var provideEffect = /* @__PURE__ */ dual(3, (self, service3, effect2) => mapHandler(self, (handler, input) => provideServiceEffect2(handler, service3, typeof effect2 === "function" ? effect2(input) : effect2)));
58389
58395
  var provideEffectDiscard = /* @__PURE__ */ dual(2, (self, effect2) => mapHandler(self, (handler, input) => andThen4(typeof effect2 === "function" ? effect2(input) : effect2, handler)));
@@ -58557,7 +58563,7 @@ var challengeCatalog = [
58557
58563
  coreSkill: "Reverse engineering & experimentation",
58558
58564
  format: "accuracy",
58559
58565
  formatLabel: "Accuracy score",
58560
- opensAt: "2026-09-18T05:00:00.000Z",
58566
+ opensAt: "2026-09-17T05:00:00.000Z",
58561
58567
  queryLimit: 25,
58562
58568
  evaluationLimit: 3,
58563
58569
  hiddenSampleSize: 1000,
@@ -58634,6 +58640,35 @@ var challengeCatalog = [
58634
58640
  }
58635
58641
  ];
58636
58642
  var playableChallenges = challengeCatalog.filter((challenge) => challenge.playable);
58643
+ var challengeBySlug = (slug) => challengeCatalog.find((challenge) => challenge.slug === slug);
58644
+ var challengeTimeZoneOffsetMs = 5 * 60 * 60 * 1000;
58645
+ var monthNames = [
58646
+ "January",
58647
+ "February",
58648
+ "March",
58649
+ "April",
58650
+ "May",
58651
+ "June",
58652
+ "July",
58653
+ "August",
58654
+ "September",
58655
+ "October",
58656
+ "November",
58657
+ "December"
58658
+ ];
58659
+ var formatChallengeOpeningInPeru = (opensAt) => {
58660
+ const localTime = new Date(Date.parse(opensAt) - challengeTimeZoneOffsetMs);
58661
+ const month = monthNames[localTime.getUTCMonth()];
58662
+ if (!month || Number.isNaN(localTime.getTime())) {
58663
+ throw new Error("Challenge opening time is invalid");
58664
+ }
58665
+ const day = localTime.getUTCDate();
58666
+ const year = localTime.getUTCFullYear();
58667
+ const hour = String(localTime.getUTCHours()).padStart(2, "0");
58668
+ const minute = String(localTime.getUTCMinutes()).padStart(2, "0");
58669
+ return `${month} ${day}, ${year} at ${hour}:${minute} (UTC-5)`;
58670
+ };
58671
+ var challengeOpeningNotice = (title, opensAt) => `${title} opens ${formatChallengeOpeningInPeru(opensAt)}. Queries and evaluations are disabled until then; no attempts will be consumed.`;
58637
58672
  var ChallengeSlugSchema = exports_Schema.Literals([
58638
58673
  "black-box",
58639
58674
  "last-mile",
@@ -59649,12 +59684,18 @@ var remainingBar = (used, limit) => {
59649
59684
  return `${"█".repeat(filled)}${"░".repeat(width - filled)}`;
59650
59685
  };
59651
59686
  var percent = (value3) => `${(value3 * 100).toFixed(2)}%`;
59687
+ var challengeLaunchNotice = (title, opensAt, now3 = new Date) => {
59688
+ if (now3.getTime() >= Date.parse(opensAt))
59689
+ return;
59690
+ return challengeOpeningNotice(title, opensAt);
59691
+ };
59652
59692
  var challengeListText = (catalog) => {
59653
59693
  const lines2 = ["Hack the Andes challenges", ""];
59654
59694
  for (const challenge of catalog.challenges) {
59655
59695
  let state = "open";
59656
- if (!challenge.open)
59657
- state = `opens ${challenge.opensAt.slice(0, 10)}`;
59696
+ if (!challenge.open) {
59697
+ state = `opens ${formatChallengeOpeningInPeru(challenge.opensAt)}`;
59698
+ }
59658
59699
  const playable = challenge.playable ? "" : " (coming later)";
59659
59700
  lines2.push(`${challenge.code} ${challenge.theme} — ${challenge.title}${playable}`);
59660
59701
  lines2.push(` ${challenge.coreSkill} · ${challenge.formatLabel} · ${state}`);
@@ -60134,21 +60175,17 @@ var challengeQuickstart = {
60134
60175
  ],
60135
60176
  helpCommand: "chofex challenge query --help"
60136
60177
  };
60137
- var challengeQuickstartText = () => {
60138
- const lines2 = [
60139
- challengeQuickstart.title,
60140
- "",
60141
- ...challengeQuickstart.story,
60142
- "",
60143
- "YOUR MISSION",
60144
- challengeQuickstart.mission,
60145
- "",
60146
- "RULES OF THE GAME",
60147
- ...challengeQuickstart.rules.map((rule) => `• ${rule}`),
60148
- "",
60149
- "FIELD GUIDE",
60150
- ""
60151
- ];
60178
+ var launchNoticeFor = (slug) => {
60179
+ const challenge = challengeBySlug(slug);
60180
+ if (!challenge)
60181
+ return;
60182
+ return challengeLaunchNotice(challenge.theme, challenge.opensAt);
60183
+ };
60184
+ var challengeQuickstartText = (launchNotice) => {
60185
+ const lines2 = [challengeQuickstart.title];
60186
+ if (launchNotice)
60187
+ lines2.push("", "LAUNCH NOTICE", launchNotice);
60188
+ lines2.push("", ...challengeQuickstart.story, "", "YOUR MISSION", challengeQuickstart.mission, "", "RULES OF THE GAME", ...challengeQuickstart.rules.map((rule) => `• ${rule}`), "", "FIELD GUIDE", "");
60152
60189
  for (const item of challengeQuickstart.workflow) {
60153
60190
  lines2.push(`${item.step}. ${item.action}`);
60154
60191
  lines2.push(` ${item.command}`);
@@ -60334,16 +60371,22 @@ var rankingCommand = exports_Command.make("ranking", { challenge: challengeFlag
60334
60371
  ]));
60335
60372
  var challengeCommand = exports_Command.make("challenge", {}, exports_Effect.fn("challengeQuickstartCommand")(function* () {
60336
60373
  const options = yield* root;
60374
+ const launchNotice = launchNoticeFor(defaultChallengeSlug);
60337
60375
  if (options.output === "json") {
60376
+ const data = {
60377
+ ...challengeQuickstart
60378
+ };
60379
+ if (launchNotice)
60380
+ data.notice = launchNotice;
60338
60381
  yield* printJson({
60339
60382
  version: 1,
60340
60383
  ok: true,
60341
60384
  requestId: crypto.randomUUID(),
60342
- data: challengeQuickstart
60385
+ data
60343
60386
  });
60344
60387
  return;
60345
60388
  }
60346
- yield* exports_Console.log(challengeQuickstartText());
60389
+ yield* exports_Console.log(challengeQuickstartText(launchNotice));
60347
60390
  })).pipe(exports_Command.withDescription("Play mini technical challenges. Start here: learn the Black Box workflow from first query to leaderboard. Run without a subcommand for the guided quickstart."), exports_Command.withExamples([
60348
60391
  {
60349
60392
  command: "chofex challenge",
@@ -62649,6 +62692,161 @@ var command = root.pipe(exports_Command.withSubcommands([
62649
62692
  challengeCommand
62650
62693
  ]));
62651
62694
 
62695
+ // src/welcome.ts
62696
+ var valley = [
62697
+ " 11 55 ",
62698
+ " 11 1111 5555 11 ",
62699
+ " 1111 111111 11 55 1111 ",
62700
+ " 11112222111111 111111 111111 ",
62701
+ "111222222211111111111111111122221111",
62702
+ "112223333222111111111111112223332222",
62703
+ "222333333322211114411111222333333333",
62704
+ "333333333332222144442222233333333333",
62705
+ "333333333333322244422223333333333333"
62706
+ ];
62707
+ var palette = {
62708
+ sky: "12;24;24",
62709
+ distant: "28;62;61",
62710
+ ridge: "44;101;85",
62711
+ terrace: "84;143;111",
62712
+ river: "141;200;190",
62713
+ sun: "234;183;108",
62714
+ border: "66;101;85",
62715
+ text: "243;241;217",
62716
+ muted: "183;201;181",
62717
+ accent: "214;255;0"
62718
+ };
62719
+ var pixels = {
62720
+ " ": { color: palette.sky, character: " " },
62721
+ "1": { color: palette.distant, character: "." },
62722
+ "2": { color: palette.ridge, character: ":" },
62723
+ "3": { color: palette.terrace, character: "#" },
62724
+ "4": { color: palette.river, character: "~" },
62725
+ "5": { color: palette.sun, character: "o" }
62726
+ };
62727
+ var wrap = (text2, width) => {
62728
+ const lines2 = [];
62729
+ let line = "";
62730
+ for (const word of text2.split(" ")) {
62731
+ if (line && line.length + word.length + 1 > width) {
62732
+ lines2.push(line);
62733
+ line = "";
62734
+ }
62735
+ line = line ? `${line} ${word}` : word;
62736
+ while (line.length > width) {
62737
+ lines2.push(line.slice(0, width));
62738
+ line = line.slice(width);
62739
+ }
62740
+ }
62741
+ if (line)
62742
+ lines2.push(line);
62743
+ return lines2;
62744
+ };
62745
+ var center = (text2, width) => (" ".repeat(Math.max(0, Math.floor((width - text2.length) / 2))) + text2).padEnd(width);
62746
+ var renderWelcome = ({
62747
+ columns = 80,
62748
+ colors: colors2 = false
62749
+ } = {}) => {
62750
+ const width = Math.max(1, Math.min(Math.floor(columns), 72));
62751
+ if (width < 24) {
62752
+ return [
62753
+ "The Andes Hackathon",
62754
+ "by Chofex",
62755
+ "S/8,000 in prizes",
62756
+ "Only for the best engineers from Peru."
62757
+ ].flatMap((line) => wrap(line, width)).join(`
62758
+ `);
62759
+ }
62760
+ const innerWidth = width - 4;
62761
+ const paint = (text2, foreground = palette.text, background = palette.sky, bold2 = false) => {
62762
+ if (!colors2)
62763
+ return text2;
62764
+ const weight = bold2 ? "1;" : "";
62765
+ return `\x1B[${weight}38;2;${foreground};48;2;${background}m${text2}\x1B[0m`;
62766
+ };
62767
+ let horizontal = "-";
62768
+ let vertical = "|";
62769
+ let corners = ["+", "+", "+", "+"];
62770
+ if (colors2) {
62771
+ horizontal = "─";
62772
+ vertical = "│";
62773
+ corners = ["╭", "╮", "╰", "╯"];
62774
+ }
62775
+ const frame = (content) => ` ${paint(vertical, palette.border)}${content}${paint(vertical, palette.border)}`;
62776
+ const rule = (left, right) => ` ${paint(left + horizontal.repeat(innerWidth) + right, palette.border)}`;
62777
+ const label = (text2, foreground, bold2 = false) => frame(paint(center(text2, innerWidth), foreground, palette.sky, bold2));
62778
+ const sourceWidth = Math.max(...valley.map((row) => row.length));
62779
+ const scene = valley.map((row, y) => {
62780
+ const cells = Array.from({ length: innerWidth }, (_, x) => {
62781
+ const sourceX = Math.floor(x / innerWidth * sourceWidth);
62782
+ return row[sourceX] ?? " ";
62783
+ });
62784
+ let heading = "";
62785
+ let foreground = palette.text;
62786
+ if (y === 3)
62787
+ heading = "The Andes Hackathon";
62788
+ if (y === 4) {
62789
+ heading = "by Chofex";
62790
+ foreground = palette.sun;
62791
+ }
62792
+ const headingStart = Math.floor((innerWidth - heading.length) / 2);
62793
+ let rendered = "";
62794
+ for (let x = 0;x < cells.length; x += 1) {
62795
+ if (heading && x >= headingStart - 1 && x <= headingStart + heading.length) {
62796
+ const character = heading[x - headingStart] ?? " ";
62797
+ rendered += paint(character, foreground, palette.sky, y === 3);
62798
+ continue;
62799
+ }
62800
+ const pixel = pixels[cells[x] ?? " "] ?? pixels[" "];
62801
+ if (!pixel)
62802
+ continue;
62803
+ if (colors2) {
62804
+ rendered += paint(" ", pixel.color, pixel.color);
62805
+ } else {
62806
+ rendered += pixel.character;
62807
+ }
62808
+ }
62809
+ return frame(rendered);
62810
+ });
62811
+ return [
62812
+ "",
62813
+ rule(corners[0] ?? "+", corners[1] ?? "+"),
62814
+ ...scene,
62815
+ label("", palette.text),
62816
+ label("S/8,000 in prizes", palette.accent, true),
62817
+ ...wrap("Only for the best engineers from Peru.", innerWidth - 2).map((line) => label(line, palette.muted)),
62818
+ rule(corners[2] ?? "+", corners[3] ?? "+"),
62819
+ ""
62820
+ ].join(`
62821
+ `);
62822
+ };
62823
+ var welcomeFormatter = (options) => {
62824
+ const formatter = exports_CliOutput.defaultFormatter({ colors: options.colors });
62825
+ return {
62826
+ ...formatter,
62827
+ formatHelpDoc: (doc) => {
62828
+ const help = formatter.formatHelpDoc(doc);
62829
+ if (!doc.subcommands?.length)
62830
+ return help;
62831
+ const welcome = renderWelcome(options);
62832
+ if (!options.home)
62833
+ return `${welcome}
62834
+ ${help}`;
62835
+ const width = Math.max(1, Math.min(options.columns ?? 80, 72));
62836
+ const shortcuts = [
62837
+ "chofex login Sign in",
62838
+ "chofex register Apply",
62839
+ "chofex status Check your application",
62840
+ "chofex --help All commands"
62841
+ ];
62842
+ return `${welcome}
62843
+ ${shortcuts.flatMap((line) => wrap(line, width)).join(`
62844
+ `)}
62845
+ `;
62846
+ }
62847
+ };
62848
+ };
62849
+
62652
62850
  // src/index.ts
62653
62851
  var packageMetadata = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
62654
62852
  var cliVersion = packageMetadata.version;
@@ -62670,7 +62868,11 @@ var quietConsole = Object.assign(Object.create(console), {
62670
62868
  return;
62671
62869
  }
62672
62870
  });
62673
- var commandProgram = command.pipe(exports_Command.run({ version: cliVersion, renderErrors: !jsonMode }), exports_Effect.catch((error2) => {
62871
+ var commandProgram = command.pipe(exports_Command.run({ version: cliVersion, renderErrors: !jsonMode }), exports_Effect.provide(exports_CliOutput.layer(welcomeFormatter({
62872
+ home: arguments_.length === 0,
62873
+ columns: process.stdout.columns ?? 80,
62874
+ colors: process.stdout.isTTY === true && process.env.NO_COLOR === undefined && process.env.TERM !== "dumb"
62875
+ }))), exports_Effect.catch((error2) => {
62674
62876
  if (!jsonMode)
62675
62877
  return exports_Effect.fail(error2);
62676
62878
  if (error2._tag === "ShowHelp" && error2.errors.length === 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chofex-cli",
3
- "version": "0.1.113",
3
+ "version": "0.1.115",
4
4
  "description": "Command-line client for the Chofex Hackathon",
5
5
  "type": "module",
6
6
  "bin": {