@byh3071/vhk 0.5.1 β†’ 0.5.2

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 +2 -2
  2. package/dist/index.js +259 -169
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  ---
2
2
  id: vhk-readme
3
3
  date: 2026-05-23
4
- tags: [vhk, cli, readme, v0.5.1]
4
+ tags: [vhk, cli, readme, v0.5.2]
5
5
  ---
6
6
 
7
7
  # πŸ”§ VHK β€” Vibe Harness Kit
8
8
 
9
- > AI μ½”λ”© μ—μ΄μ „νŠΈλ₯Ό λΆ€λ¦¬λŠ” μ‚¬λžŒμ„ μœ„ν•œ **ν•œκ΅­μ–΄ 풀사이클 CLI** (v0.5.1)
9
+ > AI μ½”λ”© μ—μ΄μ „νŠΈλ₯Ό λΆ€λ¦¬λŠ” μ‚¬λžŒμ„ μœ„ν•œ **ν•œκ΅­μ–΄ 풀사이클 CLI** (v0.5.2)
10
10
 
11
11
  λͺ…λ Ήμ–΄λ₯Ό μ™Έμš°μ§€ μ•Šμ•„λ„ λ©λ‹ˆλ‹€. `vhk`만 치면 메뉴가 λ‚˜μ˜€κ³ , ν•œκ΅­μ–΄λ‘œ 말해도 μ•Œμ•„λ“£μŠ΅λ‹ˆλ‹€.
12
12
 
package/dist/index.js CHANGED
@@ -485,8 +485,7 @@ var require_ignore = __commonJS({
485
485
 
486
486
  // src/index.ts
487
487
  import { Command, Help } from "commander";
488
- import chalk16 from "chalk";
489
- import inquirer7 from "inquirer";
488
+ import inquirer8 from "inquirer";
490
489
 
491
490
  // src/lib/nlp-router.ts
492
491
  function normalize(input) {
@@ -496,7 +495,7 @@ var NLP_KEYWORDS = {
496
495
  save: ["\uC800\uC7A5", "\uC138\uC774\uBE0C", "\uCEE4\uBC0B", "\uC62C\uB824", "\uC62C\uB9AC\uAE30", "\uD478\uC2DC", "push", "commit"],
497
496
  undo: ["\uB418\uB3CC\uB824", "\uB418\uB3CC\uB9AC\uAE30", "\uCDE8\uC18C", "\uC6D0\uB798\uB300\uB85C", "\uB864\uBC31", "\uB9AC\uC14B", "reset", "rollback"],
498
497
  status: ["\uC0C1\uD0DC", "\uD604\uD669", "\uC5B4\uB5BB\uAC8C", "\uC5B4\uB54C", "\uC9C0\uAE08"],
499
- diff: ["\uBCC0\uACBD", "\uBC14\uB010", "\uBB50\uBC14\uB01C", "\uCC28\uC774", "\uB2EC\uB77C\uC9C4", "\uC218\uC815\uB41C"]
498
+ diff: ["\uBCC0\uACBD", "\uBC14\uB010", "\uBB50\uBC14\uB01C", "\uBC14\uB00C\uC5C8", "\uCC28\uC774", "\uB2EC\uB77C\uC9C4", "\uC218\uC815\uB41C"]
500
499
  };
501
500
  function matchesKeywords(text, command) {
502
501
  const keywords = NLP_KEYWORDS[command];
@@ -546,7 +545,7 @@ var RULES = [
546
545
  command: "diff",
547
546
  explanation: "\uBCC0\uACBD\uC0AC\uD56D \uC694\uC57D (vhk diff)",
548
547
  confidence: "high",
549
- test: (t2) => (matchesKeywords(t2, "diff") || /^diff$/.test(t2) || /변경사항|μˆ˜μ •\s*λ‚΄μ—­|차이\s*보/.test(t2)) && !/μ €μž₯|컀밋|push|ν‘Έμ‹œ|μƒνƒœ|ν˜„ν™©|μ„Έμ΄λΈŒ|commit/.test(t2)
548
+ test: (t2) => (matchesKeywords(t2, "diff") || /^diff$/.test(t2) || /변경사항|μˆ˜μ •\s*λ‚΄μ—­|차이\s*보|뭐\s*λ°”λ€Œ/.test(t2)) && !/μ €μž₯|컀밋|push|ν‘Έμ‹œ|μƒνƒœ|ν˜„ν™©|μ„Έμ΄λΈŒ|commit/.test(t2)
550
549
  },
551
550
  {
552
551
  command: "undo",
@@ -611,6 +610,69 @@ function extractNotionUrl(input) {
611
610
  return m?.[0];
612
611
  }
613
612
 
613
+ // src/lib/cli-args.ts
614
+ var KNOWN_COMMAND_TOKENS = /* @__PURE__ */ new Set([
615
+ "gate",
616
+ "\uAC80\uC99D",
617
+ "\uC544\uC774\uB514\uC5B4",
618
+ "init",
619
+ "\uC2DC\uC791",
620
+ "\uB9CC\uB4E4\uAE30",
621
+ "recap",
622
+ "\uC815\uB9AC",
623
+ "\uC624\uB298",
624
+ "sync",
625
+ "\uB9DE\uCD94\uAE30",
626
+ "\uADDC\uCE59",
627
+ "check",
628
+ "\uC810\uAC80",
629
+ "\uB9B0\uD2B8",
630
+ "secure",
631
+ "\uBCF4\uC548",
632
+ "scan",
633
+ "\uC2A4\uCE94",
634
+ "ship",
635
+ "\uBC30\uD3EC",
636
+ "\uB9B4\uB9AC\uC988",
637
+ "doctor",
638
+ "\uD658\uACBD",
639
+ "\uC9C4\uB2E8",
640
+ "save",
641
+ "\uC800\uC7A5",
642
+ "undo",
643
+ "\uB418\uB3CC\uB9AC\uAE30",
644
+ "status",
645
+ "\uC0C1\uD0DC",
646
+ "\uD604\uD669",
647
+ "diff",
648
+ "\uBCC0\uACBD",
649
+ "\uCC28\uC774",
650
+ "help"
651
+ ]);
652
+ function isOptionToken(token) {
653
+ return token.startsWith("-");
654
+ }
655
+ function detectNaturalLanguageInput(argv) {
656
+ const rest = argv.slice(2);
657
+ if (rest.length === 0) return null;
658
+ const first = rest[0];
659
+ if (isOptionToken(first)) return null;
660
+ const input = rest.join(" ").trim();
661
+ if (!input) return null;
662
+ const firstIsKnown = KNOWN_COMMAND_TOKENS.has(first);
663
+ if (firstIsKnown && rest.length === 1) return null;
664
+ if (firstIsKnown && rest.slice(1).every(isOptionToken)) return null;
665
+ if (firstIsKnown && rest.length > 1) {
666
+ if (routeNaturalLanguage(input)) return input;
667
+ return null;
668
+ }
669
+ return input;
670
+ }
671
+
672
+ // src/lib/nlp-run.ts
673
+ import chalk16 from "chalk";
674
+ import inquirer7 from "inquirer";
675
+
614
676
  // src/i18n/ko.ts
615
677
  var ko = {
616
678
  status: {
@@ -3203,104 +3265,23 @@ ${t("undo.recentHeader")}`));
3203
3265
  }
3204
3266
  }
3205
3267
 
3206
- // src/commands/diff.ts
3207
- import { execFileSync as execFileSync4, execSync as execSync2 } from "child_process";
3268
+ // src/commands/status.ts
3269
+ import { execFileSync as execFileSync4 } from "child_process";
3270
+ import fs15 from "fs";
3271
+ import path14 from "path";
3208
3272
  import chalk14 from "chalk";
3209
- function gitOut2(args) {
3210
- try {
3211
- return execFileSync4("git", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
3212
- } catch {
3213
- return "";
3214
- }
3215
- }
3216
- function parseDiffStat(stat) {
3217
- const files = [];
3218
- const lines = stat.split("\n");
3219
- for (const line of lines) {
3220
- const match = line.match(/^\s*(.+?)\s*\|\s*(\d+)/);
3221
- if (!match) continue;
3222
- const name = match[1].trim();
3223
- if (name.includes("changed") || name.includes("file")) continue;
3224
- const plusMatch = line.match(/(\++)/);
3225
- const minusMatch = line.match(/(\-+)/);
3226
- files.push({
3227
- name,
3228
- additions: plusMatch ? plusMatch[1].length : 0,
3229
- deletions: minusMatch ? minusMatch[1].length : 0
3230
- });
3231
- }
3232
- return files;
3233
- }
3234
- function summarizeNumstat(numstat) {
3235
- let totalAdd = 0;
3236
- let totalDel = 0;
3237
- let fileCount = 0;
3238
- for (const line of numstat.split("\n").filter(Boolean)) {
3239
- const [add, del] = line.split(" ");
3240
- if (add === void 0 || del === void 0) continue;
3241
- totalAdd += parseInt(add, 10) || 0;
3242
- totalDel += parseInt(del, 10) || 0;
3243
- fileCount++;
3244
- }
3245
- return { fileCount, totalAdd, totalDel };
3246
- }
3247
- function printFile(f) {
3248
- const adds = f.additions > 0 ? chalk14.green(`+${f.additions}`) : "";
3249
- const dels = f.deletions > 0 ? chalk14.red(`-${f.deletions}`) : "";
3250
- const change = [adds, dels].filter(Boolean).join(" ");
3251
- console.log(` ${f.name} ${change}`);
3273
+
3274
+ // src/lib/read-json.ts
3275
+ import fs14 from "fs";
3276
+ function stripBom(text) {
3277
+ return text.charCodeAt(0) === 65279 ? text.slice(1) : text;
3252
3278
  }
3253
- async function diff() {
3254
- console.log(chalk14.bold(`
3255
- \u{1F50D} ${t("diff.title")}`));
3256
- console.log(chalk14.gray("\u2500".repeat(40)));
3257
- try {
3258
- execSync2("git rev-parse --is-inside-work-tree", { stdio: "pipe" });
3259
- } catch {
3260
- console.log(chalk14.red(`\u274C ${t("diff.notGitRepo")}`));
3261
- return;
3262
- }
3263
- const unstaged = gitOut2(["diff", "--stat"]);
3264
- const staged = gitOut2(["diff", "--cached", "--stat"]);
3265
- const untracked = gitOut2(["ls-files", "--others", "--exclude-standard"]);
3266
- if (!unstaged && !staged && !untracked) {
3267
- console.log(chalk14.green(`
3268
- \u2705 ${t("diff.noChanges")}`));
3269
- return;
3270
- }
3271
- if (staged) {
3272
- console.log(chalk14.cyan(`
3273
- ${t("diff.stagedHeader")}`));
3274
- parseDiffStat(staged).forEach((f) => printFile(f));
3275
- }
3276
- if (unstaged) {
3277
- console.log(chalk14.cyan(`
3278
- ${t("diff.unstagedHeader")}`));
3279
- parseDiffStat(unstaged).forEach((f) => printFile(f));
3280
- }
3281
- if (untracked) {
3282
- const files = untracked.split("\n").filter(Boolean);
3283
- console.log(chalk14.cyan(`
3284
- ${t("diff.untrackedHeader", files.length)}`));
3285
- files.forEach((f) => console.log(` ${chalk14.green("+")} ${f}`));
3286
- }
3287
- const numstat = gitOut2(["diff", "--numstat", "HEAD"]);
3288
- if (numstat) {
3289
- const { fileCount, totalAdd, totalDel } = summarizeNumstat(numstat);
3290
- console.log(chalk14.cyan(`
3291
- ${t("diff.summaryHeader")}`));
3292
- console.log(` ${t("diff.filesLine", fileCount)}`);
3293
- console.log(` \uCD94\uAC00: ${chalk14.green(`+${totalAdd}`)}\uC904`);
3294
- console.log(` \uC0AD\uC81C: ${chalk14.red(`-${totalDel}`)}\uC904`);
3295
- }
3296
- console.log("");
3279
+ function readJsonFile(filePath) {
3280
+ const raw = stripBom(fs14.readFileSync(filePath, "utf-8"));
3281
+ return JSON.parse(raw);
3297
3282
  }
3298
3283
 
3299
3284
  // src/commands/status.ts
3300
- import { execFileSync as execFileSync5 } from "child_process";
3301
- import fs14 from "fs";
3302
- import path14 from "path";
3303
- import chalk15 from "chalk";
3304
3285
  function countFileChanges(porcelain) {
3305
3286
  const lines = porcelain.split("\n").filter(Boolean);
3306
3287
  let staged = 0;
@@ -3339,9 +3320,9 @@ function parseRecentCommitLines(logOutput) {
3339
3320
  }
3340
3321
  function readProjectPackage(cwd = process.cwd()) {
3341
3322
  const pkgPath = path14.join(cwd, "package.json");
3342
- if (!fs14.existsSync(pkgPath)) return null;
3323
+ if (!fs15.existsSync(pkgPath)) return null;
3343
3324
  try {
3344
- const pkg = JSON.parse(fs14.readFileSync(pkgPath, "utf-8"));
3325
+ const pkg = readJsonFile(pkgPath);
3345
3326
  if (!pkg.name && !pkg.version) return null;
3346
3327
  return {
3347
3328
  name: pkg.name ?? "(no name)",
@@ -3360,15 +3341,15 @@ function getSyncCounts(gitRoot) {
3360
3341
  }
3361
3342
  }
3362
3343
  async function status() {
3363
- console.log(chalk15.bold(`
3344
+ console.log(chalk14.bold(`
3364
3345
  \u{1F4CA} ${t("status.title")}`));
3365
- console.log(chalk15.gray("\u2500".repeat(40)));
3346
+ console.log(chalk14.gray("\u2500".repeat(40)));
3366
3347
  let gitRoot;
3367
3348
  try {
3368
- execFileSync5("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3349
+ execFileSync4("git", ["rev-parse", "--is-inside-work-tree"], { stdio: "pipe" });
3369
3350
  gitRoot = getGitRoot();
3370
3351
  } catch {
3371
- console.log(chalk15.red(`\u274C ${t("status.notGitRepo")}`));
3352
+ console.log(chalk14.red(`\u274C ${t("status.notGitRepo")}`));
3372
3353
  return;
3373
3354
  }
3374
3355
  let branch;
@@ -3387,33 +3368,185 @@ async function status() {
3387
3368
  commits = [];
3388
3369
  }
3389
3370
  const pkg = readProjectPackage();
3390
- console.log(chalk15.cyan(`
3391
- \u{1F33F} ${t("status.branch")}`) + chalk15.white(` ${branch}`));
3371
+ console.log(chalk14.cyan(`
3372
+ \u{1F33F} ${t("status.branch")}`) + chalk14.white(` ${branch}`));
3392
3373
  console.log(
3393
- chalk15.cyan(`\u{1F4C1} ${t("status.changes")}`) + chalk15.white(
3374
+ chalk14.cyan(`\u{1F4C1} ${t("status.changes")}`) + chalk14.white(
3394
3375
  ` staged ${counts.staged} \xB7 unstaged ${counts.unstaged} \xB7 untracked ${counts.untracked}`
3395
3376
  )
3396
3377
  );
3397
- console.log(chalk15.cyan(`
3378
+ console.log(chalk14.cyan(`
3398
3379
  \u{1F4CB} ${t("status.recentCommits")}`));
3399
3380
  if (commits.length === 0) {
3400
- console.log(chalk15.dim(` ${t("status.noCommits")}`));
3381
+ console.log(chalk14.dim(` ${t("status.noCommits")}`));
3401
3382
  } else {
3402
- commits.forEach((c) => console.log(` ${chalk15.dim("\u2022")} ${c}`));
3383
+ commits.forEach((c) => console.log(` ${chalk14.dim("\u2022")} ${c}`));
3403
3384
  }
3404
3385
  console.log(
3405
- chalk15.cyan(`
3406
- \u{1F504} ${t("status.remote")}`) + chalk15.white(` ${formatSyncLabel(sync2)}`)
3386
+ chalk14.cyan(`
3387
+ \u{1F504} ${t("status.remote")}`) + chalk14.white(` ${formatSyncLabel(sync2)}`)
3407
3388
  );
3408
- console.log(chalk15.gray("\n" + "\u2500".repeat(40)));
3389
+ console.log(chalk14.gray("\n" + "\u2500".repeat(40)));
3409
3390
  if (pkg) {
3410
- console.log(chalk15.cyan(`\u{1F4E6} ${t("status.package")}`) + chalk15.white(` ${pkg.name} v${pkg.version}`));
3391
+ console.log(chalk14.cyan(`\u{1F4E6} ${t("status.package")}`) + chalk14.white(` ${pkg.name} v${pkg.version}`));
3411
3392
  } else {
3412
- console.log(chalk15.dim(`\u{1F4E6} ${t("status.noPackage")}`));
3393
+ console.log(chalk14.dim(`\u{1F4E6} ${t("status.noPackage")}`));
3413
3394
  }
3414
3395
  console.log("");
3415
3396
  }
3416
3397
 
3398
+ // src/commands/diff.ts
3399
+ import { execFileSync as execFileSync5, execSync as execSync2 } from "child_process";
3400
+ import chalk15 from "chalk";
3401
+ function gitOut2(args) {
3402
+ try {
3403
+ return execFileSync5("git", args, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
3404
+ } catch {
3405
+ return "";
3406
+ }
3407
+ }
3408
+ function parseDiffStat(stat) {
3409
+ const files = [];
3410
+ const lines = stat.split("\n");
3411
+ for (const line of lines) {
3412
+ const match = line.match(/^\s*(.+?)\s*\|\s*(\d+)/);
3413
+ if (!match) continue;
3414
+ const name = match[1].trim();
3415
+ if (name.includes("changed") || name.includes("file")) continue;
3416
+ const plusMatch = line.match(/(\++)/);
3417
+ const minusMatch = line.match(/(\-+)/);
3418
+ files.push({
3419
+ name,
3420
+ additions: plusMatch ? plusMatch[1].length : 0,
3421
+ deletions: minusMatch ? minusMatch[1].length : 0
3422
+ });
3423
+ }
3424
+ return files;
3425
+ }
3426
+ function summarizeNumstat(numstat) {
3427
+ let totalAdd = 0;
3428
+ let totalDel = 0;
3429
+ let fileCount = 0;
3430
+ for (const line of numstat.split("\n").filter(Boolean)) {
3431
+ const [add, del] = line.split(" ");
3432
+ if (add === void 0 || del === void 0) continue;
3433
+ totalAdd += parseInt(add, 10) || 0;
3434
+ totalDel += parseInt(del, 10) || 0;
3435
+ fileCount++;
3436
+ }
3437
+ return { fileCount, totalAdd, totalDel };
3438
+ }
3439
+ function printFile(f) {
3440
+ const adds = f.additions > 0 ? chalk15.green(`+${f.additions}`) : "";
3441
+ const dels = f.deletions > 0 ? chalk15.red(`-${f.deletions}`) : "";
3442
+ const change = [adds, dels].filter(Boolean).join(" ");
3443
+ console.log(` ${f.name} ${change}`);
3444
+ }
3445
+ async function diff() {
3446
+ console.log(chalk15.bold(`
3447
+ \u{1F50D} ${t("diff.title")}`));
3448
+ console.log(chalk15.gray("\u2500".repeat(40)));
3449
+ try {
3450
+ execSync2("git rev-parse --is-inside-work-tree", { stdio: "pipe" });
3451
+ } catch {
3452
+ console.log(chalk15.red(`\u274C ${t("diff.notGitRepo")}`));
3453
+ return;
3454
+ }
3455
+ const unstaged = gitOut2(["diff", "--stat"]);
3456
+ const staged = gitOut2(["diff", "--cached", "--stat"]);
3457
+ const untracked = gitOut2(["ls-files", "--others", "--exclude-standard"]);
3458
+ if (!unstaged && !staged && !untracked) {
3459
+ console.log(chalk15.green(`
3460
+ \u2705 ${t("diff.noChanges")}`));
3461
+ return;
3462
+ }
3463
+ if (staged) {
3464
+ console.log(chalk15.cyan(`
3465
+ ${t("diff.stagedHeader")}`));
3466
+ parseDiffStat(staged).forEach((f) => printFile(f));
3467
+ }
3468
+ if (unstaged) {
3469
+ console.log(chalk15.cyan(`
3470
+ ${t("diff.unstagedHeader")}`));
3471
+ parseDiffStat(unstaged).forEach((f) => printFile(f));
3472
+ }
3473
+ if (untracked) {
3474
+ const files = untracked.split("\n").filter(Boolean);
3475
+ console.log(chalk15.cyan(`
3476
+ ${t("diff.untrackedHeader", files.length)}`));
3477
+ files.forEach((f) => console.log(` ${chalk15.green("+")} ${f}`));
3478
+ }
3479
+ const numstat = gitOut2(["diff", "--numstat", "HEAD"]);
3480
+ if (numstat) {
3481
+ const { fileCount, totalAdd, totalDel } = summarizeNumstat(numstat);
3482
+ console.log(chalk15.cyan(`
3483
+ ${t("diff.summaryHeader")}`));
3484
+ console.log(` ${t("diff.filesLine", fileCount)}`);
3485
+ console.log(` \uCD94\uAC00: ${chalk15.green(`+${totalAdd}`)}\uC904`);
3486
+ console.log(` \uC0AD\uC81C: ${chalk15.red(`-${totalDel}`)}\uC904`);
3487
+ }
3488
+ console.log("");
3489
+ }
3490
+
3491
+ // src/lib/nlp-run.ts
3492
+ async function dispatchNlpRoute(route, input) {
3493
+ switch (route.command) {
3494
+ case "gate":
3495
+ return gate();
3496
+ case "init":
3497
+ return init({
3498
+ skipGate: route.args?.includes("--skip-gate"),
3499
+ fromNotion: route.args?.includes("--from-notion") ? extractNotionUrl(input) : void 0
3500
+ });
3501
+ case "recap":
3502
+ return recap({});
3503
+ case "sync":
3504
+ return sync();
3505
+ case "check":
3506
+ return check();
3507
+ case "secure":
3508
+ return secure();
3509
+ case "ship":
3510
+ return ship();
3511
+ case "doctor":
3512
+ return doctor();
3513
+ case "save":
3514
+ return save();
3515
+ case "undo":
3516
+ return undo();
3517
+ case "status":
3518
+ return status();
3519
+ case "diff":
3520
+ return diff();
3521
+ }
3522
+ }
3523
+ async function runNaturalLanguageRoute(input) {
3524
+ const route = routeNaturalLanguage(input);
3525
+ if (!route) {
3526
+ console.log(chalk16.yellow(`
3527
+ \u2753 "${input}" \u2014 ${ko.nlp.notMatched}
3528
+ `));
3529
+ return;
3530
+ }
3531
+ console.log("");
3532
+ console.log(chalk16.cyan(` \u{1F4AC} "${input}"`));
3533
+ console.log(chalk16.cyan(` \u2192 ${route.explanation}`));
3534
+ if (route.confidence === "low") {
3535
+ const { confirm } = await inquirer7.prompt([{
3536
+ type: "confirm",
3537
+ name: "confirm",
3538
+ message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
3539
+ default: true
3540
+ }]);
3541
+ if (!confirm) {
3542
+ console.log(chalk16.dim(` ${ko.nlp.menuHint}`));
3543
+ return;
3544
+ }
3545
+ }
3546
+ console.log("");
3547
+ await dispatchNlpRoute(route, input);
3548
+ }
3549
+
3417
3550
  // src/index.ts
3418
3551
  var program = new Command();
3419
3552
  var defaultHelp = new Help();
@@ -3431,7 +3564,7 @@ var KO_ALIASES = {
3431
3564
  status: "\uC0C1\uD0DC",
3432
3565
  diff: "\uBCC0\uACBD"
3433
3566
  };
3434
- program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.5.1");
3567
+ program.name("vhk").description("VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58 (\uD55C\uAD6D\uC5B4\uB85C \uC548\uB0B4\uD569\uB2C8\uB2E4)").version("0.5.2");
3435
3568
  program.configureHelp({
3436
3569
  formatHelp(cmd, helper) {
3437
3570
  if (cmd.parent) {
@@ -3472,62 +3605,14 @@ program.command("status").alias("\uC0C1\uD0DC").description("\uD504\uB85C\uC81D\
3472
3605
  });
3473
3606
  program.command("diff").alias("\uBCC0\uACBD").alias("\uCC28\uC774").description("Git \uBCC0\uACBD\uC0AC\uD56D \uD55C\uAD6D\uC5B4 \uC694\uC57D (staged / unstaged / \uC0C8 \uD30C\uC77C)").action(diff);
3474
3607
  program.on("command:*", async (operands) => {
3475
- const input = operands.join(" ");
3476
- const route = routeNaturalLanguage(input);
3477
- if (route) {
3478
- console.log("");
3479
- console.log(chalk16.cyan(` \u{1F4AC} "${input}"`));
3480
- console.log(chalk16.cyan(` \u2192 ${route.explanation}`));
3481
- if (route.confidence === "low") {
3482
- const { confirm } = await inquirer7.prompt([{
3483
- type: "confirm",
3484
- name: "confirm",
3485
- message: `${route.explanation} \u2014 ${ko.nlp.matched}`,
3486
- default: true
3487
- }]);
3488
- if (!confirm) {
3489
- console.log(chalk16.dim(` ${ko.nlp.menuHint}`));
3490
- return;
3491
- }
3492
- }
3493
- console.log("");
3494
- switch (route.command) {
3495
- case "gate":
3496
- return gate();
3497
- case "init":
3498
- return init({
3499
- skipGate: route.args?.includes("--skip-gate"),
3500
- fromNotion: route.args?.includes("--from-notion") ? extractNotionUrl(input) : void 0
3501
- });
3502
- case "recap":
3503
- return recap({});
3504
- case "sync":
3505
- return sync();
3506
- case "check":
3507
- return check();
3508
- case "secure":
3509
- return secure();
3510
- case "ship":
3511
- return ship();
3512
- case "doctor":
3513
- return doctor();
3514
- case "save":
3515
- return save();
3516
- case "undo":
3517
- return undo();
3518
- case "status":
3519
- return status();
3520
- case "diff":
3521
- return diff();
3522
- }
3523
- }
3524
- console.log(chalk16.yellow(`
3525
- \u2753 "${input}" \u2014 ${ko.nlp.notMatched}
3526
- `));
3608
+ const unknown = operands[0] ?? "";
3609
+ const rest = operands.slice(1);
3610
+ const input = [unknown, ...rest].join(" ").trim();
3611
+ await runNaturalLanguageRoute(input);
3527
3612
  });
3528
3613
  program.action(async () => {
3529
3614
  console.log("\n\u{1F3AF} VHK \u2014 \uBC14\uC774\uBE0C\uCF54\uB529 \uD504\uB85C\uC81D\uD2B8 \uCF54\uCE58\n");
3530
- const { choice } = await inquirer7.prompt([{
3615
+ const { choice } = await inquirer8.prompt([{
3531
3616
  type: "list",
3532
3617
  name: "choice",
3533
3618
  message: "\uBB58 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?",
@@ -3573,4 +3658,9 @@ program.action(async () => {
3573
3658
  return diff();
3574
3659
  }
3575
3660
  });
3576
- await program.parseAsync(process.argv);
3661
+ var nlInput = detectNaturalLanguageInput(process.argv);
3662
+ if (nlInput !== null) {
3663
+ await runNaturalLanguageRoute(nlInput);
3664
+ } else {
3665
+ await program.parseAsync(process.argv);
3666
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byh3071/vhk",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "description": "Vibe Harness Kit β€” λ°”μ΄λΈŒμ½”λ”© 풀사이클 CLI",
5
5
  "bin": {
6
6
  "vhk": "./dist/index.js"