@snelusha/noto 1.1.0 → 1.1.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 +12 -1
  2. package/dist/index.js +194 -90
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -105,7 +105,18 @@ Switch between branches in you git repo with an interactive prompt:
105
105
  ```bash
106
106
  noto checkout
107
107
  ```
108
-
108
+
109
+ To copy the selected branch to your clipboard immediately after choosing it, use the new `-c` flag:
110
+
111
+ ```bash
112
+ noto branch
113
+ ```
114
+
115
+ To list all branches, including remote branches, use the -r flag
116
+
117
+ ```bash
118
+ noto branch -r
119
+ ```
109
120
 
110
121
  ## Pro Tips
111
122
 
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // src/index.ts
2
- import * as p7 from "@clack/prompts";
3
- import color8 from "picocolors";
2
+ import * as p8 from "@clack/prompts";
3
+ import color9 from "picocolors";
4
4
 
5
5
  // src/utils/parser.ts
6
6
  import arg from "arg";
@@ -12,21 +12,21 @@ var parse = (schema, raw) => {
12
12
  };
13
13
  };
14
14
  var safeParse = (schema, raw) => {
15
- let current = { ...schema };
15
+ let current2 = { ...schema };
16
16
  let iterations = 0;
17
- const maxIterations = Object.keys(current).filter(
18
- (key2) => current[key2] === String
17
+ const maxIterations = Object.keys(current2).filter(
18
+ (key2) => current2[key2] === String
19
19
  ).length;
20
20
  while (iterations++ < maxIterations) {
21
21
  try {
22
- return parse(current, raw);
22
+ return parse(current2, raw);
23
23
  } catch (error) {
24
24
  if (error.code === "ARG_MISSING_REQUIRED_LONGARG") {
25
25
  const match = error.message.match(/(--\w[\w-]*)/);
26
26
  if (match) {
27
27
  const missingFlag = match[0];
28
- if (current[missingFlag] === String) {
29
- current[missingFlag] = Boolean;
28
+ if (current2[missingFlag] === String) {
29
+ current2[missingFlag] = Boolean;
30
30
  continue;
31
31
  }
32
32
  }
@@ -34,7 +34,7 @@ var safeParse = (schema, raw) => {
34
34
  throw error;
35
35
  }
36
36
  }
37
- return parse(current, raw);
37
+ return parse(current2, raw);
38
38
  };
39
39
 
40
40
  // src/commands/noto.ts
@@ -62,9 +62,7 @@ var AvailableModelsSchema = z.enum([
62
62
  "gemini-1.5-flash-8b-latest",
63
63
  "gemini-1.5-pro",
64
64
  "gemini-1.5-pro-latest",
65
- "gemini-2.0-flash-lite-preview-02-05",
66
- "gemini-2.0-flash-exp",
67
- "gemini-2.0-pro-exp-02-05",
65
+ "gemini-2.0-flash-001",
68
66
  "gemini-2.5-pro-exp-03-25"
69
67
  ]);
70
68
 
@@ -208,12 +206,10 @@ var getCurrentBranch = async () => {
208
206
  return null;
209
207
  }
210
208
  };
211
- var getBranches = async () => {
209
+ var getBranches = async (remote) => {
212
210
  try {
213
211
  const branches = await git.branch();
214
- return Object.keys(branches.branches).filter(
215
- (b) => !b.startsWith("remotes/")
216
- );
212
+ return remote ? branches.all : Object.keys(branches.branches).filter((b) => !b.startsWith("remotes/"));
217
213
  } catch {
218
214
  return null;
219
215
  }
@@ -276,7 +272,7 @@ var NotoError = class _NotoError extends Error {
276
272
  var google = createGoogleGenerativeAI({
277
273
  apiKey: (await StorageManager.get()).llm?.apiKey ?? "api-key"
278
274
  });
279
- var defaultModel = "gemini-2.0-pro-exp-02-05";
275
+ var defaultModel = "gemini-2.0-flash-001";
280
276
  var models = {
281
277
  "gemini-1.5-flash": google("gemini-1.5-flash"),
282
278
  "gemini-1.5-flash-latest": google("gemini-1.5-flash-latest"),
@@ -284,22 +280,18 @@ var models = {
284
280
  "gemini-1.5-flash-8b-latest": google("gemini-1.5-flash-8b-latest"),
285
281
  "gemini-1.5-pro": google("gemini-1.5-pro"),
286
282
  "gemini-1.5-pro-latest": google("gemini-1.5-pro-latest"),
287
- "gemini-2.0-flash-lite-preview-02-05": google(
288
- "gemini-2.0-flash-lite-preview-02-05"
289
- ),
290
- "gemini-2.0-flash-exp": google("gemini-2.0-flash-exp"),
291
- "gemini-2.0-pro-exp-02-05": google("gemini-2.0-pro-exp-02-05"),
283
+ "gemini-2.0-flash-001": google("gemini-2.0-flash-001"),
292
284
  "gemini-2.5-pro-exp-03-25": google("gemini-2.5-pro-exp-03-25")
293
285
  };
294
286
  var availableModels = Object.keys(models);
295
287
  var getModel = async () => {
296
288
  let model2 = (await StorageManager.get()).llm?.model;
297
- if (!model2) {
289
+ if (!model2 || model2 === "gemini-2.0-pro-exp-02-05") {
298
290
  model2 = defaultModel;
299
- await StorageManager.update((current) => ({
300
- ...current,
291
+ await StorageManager.update((current2) => ({
292
+ ...current2,
301
293
  llm: {
302
- ...current.llm,
294
+ ...current2.llm,
303
295
  model: model2
304
296
  }
305
297
  }));
@@ -443,8 +435,8 @@ var command = {
443
435
  message = editedMessage;
444
436
  p3.log.step(color3.green(message));
445
437
  }
446
- await StorageManager.update((current) => ({
447
- ...current,
438
+ await StorageManager.update((current2) => ({
439
+ ...current2,
448
440
  lastGeneratedMessage: message
449
441
  }));
450
442
  if (options["--copy"]) {
@@ -541,8 +533,8 @@ var command2 = {
541
533
  return await exit(1);
542
534
  }
543
535
  lastGeneratedMessage = editedMessage;
544
- await StorageManager.update((current) => ({
545
- ...current,
536
+ await StorageManager.update((current2) => ({
537
+ ...current2,
546
538
  lastGeneratedMessage: editedMessage
547
539
  }));
548
540
  p4.log.step(color4.green(lastGeneratedMessage));
@@ -583,14 +575,59 @@ var command2 = {
583
575
  };
584
576
  var prev_default = command2;
585
577
 
586
- // src/commands/checkout.ts
578
+ // src/commands/branch.ts
587
579
  import * as p5 from "@clack/prompts";
588
580
  import color5 from "picocolors";
581
+ import clipboard3 from "clipboardy";
589
582
  import dedent5 from "dedent";
583
+ var current = {
584
+ name: "current",
585
+ description: "get current branch",
586
+ usage: "branch current",
587
+ options: [
588
+ {
589
+ type: Boolean,
590
+ flag: "--copy",
591
+ alias: "-c",
592
+ description: "copy the selected branch to clipboard"
593
+ }
594
+ ],
595
+ execute: withRepository(
596
+ async (options) => {
597
+ if (!options.isRepo) {
598
+ p5.log.error(
599
+ dedent5`${color5.red("no git repository found in cwd.")}
600
+ ${color5.dim(`run ${color5.cyan("`git init`")} to initialize a new repository.`)}`
601
+ );
602
+ return await exit(1);
603
+ }
604
+ const branch = await getCurrentBranch();
605
+ if (!branch) {
606
+ p5.log.error("failed to fetch current branch");
607
+ return await exit(1);
608
+ }
609
+ p5.log.success(`current branch: ${color5.bold(branch)}`);
610
+ if (options["--copy"]) {
611
+ clipboard3.writeSync(branch);
612
+ p5.log.success(`${color5.green("copied to clipboard!")}`);
613
+ }
614
+ await exit(0);
615
+ },
616
+ { enabled: false }
617
+ )
618
+ };
590
619
  var command3 = {
591
- name: "checkout",
592
- description: "checkout a branch",
593
- usage: "checkout [options]",
620
+ name: "branch",
621
+ description: "list branches",
622
+ usage: "branch [options]",
623
+ options: [
624
+ {
625
+ type: Boolean,
626
+ flag: "--remote",
627
+ alias: "-r",
628
+ description: "list branches including remotes"
629
+ }
630
+ ],
594
631
  execute: withRepository(
595
632
  async (options) => {
596
633
  if (!options.isRepo) {
@@ -600,14 +637,15 @@ var command3 = {
600
637
  );
601
638
  return await exit(1);
602
639
  }
603
- const branches = await getBranches();
640
+ const remote = options["--remote"];
641
+ const branches = await getBranches(remote);
604
642
  if (!branches) {
605
643
  p5.log.error("failed to fetch branches");
606
644
  return await exit(1);
607
645
  }
608
646
  const currentBranch = await getCurrentBranch();
609
647
  const branch = await p5.select({
610
- message: "select a branch to checkout",
648
+ message: "select a branch",
611
649
  options: branches.map((branch2) => ({
612
650
  value: branch2,
613
651
  label: color5.bold(
@@ -625,59 +663,125 @@ var command3 = {
625
663
  p5.log.error("no branch selected");
626
664
  return await exit(1);
627
665
  }
666
+ clipboard3.writeSync(branch);
667
+ p5.log.success(`${color5.green("copied to clipboard!")}`);
668
+ await exit(0);
669
+ },
670
+ { enabled: false }
671
+ ),
672
+ subCommands: [current]
673
+ };
674
+ var branch_default = command3;
675
+
676
+ // src/commands/checkout.ts
677
+ import * as p6 from "@clack/prompts";
678
+ import color6 from "picocolors";
679
+ import clipboard4 from "clipboardy";
680
+ import dedent6 from "dedent";
681
+ var command4 = {
682
+ name: "checkout",
683
+ description: "checkout a branch",
684
+ usage: "checkout [options]",
685
+ options: [
686
+ {
687
+ type: Boolean,
688
+ flag: "--copy",
689
+ alias: "-c",
690
+ description: "copy the selected branch to clipboard"
691
+ }
692
+ ],
693
+ execute: withRepository(
694
+ async (options) => {
695
+ if (!options.isRepo) {
696
+ p6.log.error(
697
+ dedent6`${color6.red("no git repository found in cwd.")}
698
+ ${color6.dim(`run ${color6.cyan("`git init`")} to initialize a new repository.`)}`
699
+ );
700
+ return await exit(1);
701
+ }
702
+ const branches = await getBranches();
703
+ if (!branches) {
704
+ p6.log.error("failed to fetch branches");
705
+ return await exit(1);
706
+ }
707
+ const currentBranch = await getCurrentBranch();
708
+ const branch = await p6.select({
709
+ message: "select a branch to checkout",
710
+ options: branches.map((branch2) => ({
711
+ value: branch2,
712
+ label: color6.bold(
713
+ branch2 === currentBranch ? color6.green(branch2) : branch2
714
+ ),
715
+ hint: branch2 === currentBranch ? "current branch" : void 0
716
+ })),
717
+ initialValue: currentBranch
718
+ });
719
+ if (p6.isCancel(branch)) {
720
+ p6.log.error("nothing selected!");
721
+ return await exit(1);
722
+ }
723
+ if (!branch) {
724
+ p6.log.error("no branch selected");
725
+ return await exit(1);
726
+ }
727
+ if (options["--copy"]) {
728
+ clipboard4.writeSync(branch);
729
+ p6.log.success(`copied ${color6.green(branch)} to clipboard`);
730
+ return await exit(0);
731
+ }
628
732
  if (branch === currentBranch) {
629
- p5.log.error(`${color5.red("already on branch")}`);
733
+ p6.log.error(`${color6.red("already on branch")}`);
630
734
  return await exit(1);
631
735
  }
632
736
  const result = await checkout(branch);
633
737
  if (!result) {
634
- p5.log.error(`failed to checkout ${color5.bold(branch)}`);
738
+ p6.log.error(`failed to checkout ${color6.bold(branch)}`);
635
739
  return await exit(1);
636
740
  }
637
- p5.log.success(`checked out ${color5.green(branch)}`);
741
+ p6.log.success(`checked out ${color6.green(branch)}`);
638
742
  await exit(0);
639
743
  },
640
744
  { enabled: false }
641
745
  )
642
746
  };
643
- var checkout_default = command3;
747
+ var checkout_default = command4;
644
748
 
645
749
  // src/commands/config.ts
646
- import * as p6 from "@clack/prompts";
647
- import color6 from "picocolors";
750
+ import * as p7 from "@clack/prompts";
751
+ import color7 from "picocolors";
648
752
  var key = {
649
753
  name: "key",
650
754
  description: "configure api key",
651
755
  usage: "noto config key [options]",
652
756
  execute: async (options) => {
653
757
  if ((await StorageManager.get()).llm?.apiKey) {
654
- const confirm2 = await p6.confirm({
758
+ const confirm2 = await p7.confirm({
655
759
  message: "noto api key already configured, do you want to update it?"
656
760
  });
657
- if (p6.isCancel(confirm2) || !confirm2) {
658
- p6.log.error(color6.red("nothing changed!"));
761
+ if (p7.isCancel(confirm2) || !confirm2) {
762
+ p7.log.error(color7.red("nothing changed!"));
659
763
  return await exit(1);
660
764
  }
661
765
  }
662
766
  let apiKey = options._[0];
663
767
  if (!apiKey) {
664
- const result = await p6.text({
768
+ const result = await p7.text({
665
769
  message: "enter your noto api key"
666
770
  });
667
- if (p6.isCancel(result)) {
668
- p6.log.error(color6.red("nothing changed!"));
771
+ if (p7.isCancel(result)) {
772
+ p7.log.error(color7.red("nothing changed!"));
669
773
  return await exit(1);
670
774
  }
671
775
  apiKey = result;
672
776
  }
673
- await StorageManager.update((current) => ({
674
- ...current,
777
+ await StorageManager.update((current2) => ({
778
+ ...current2,
675
779
  llm: {
676
- ...current.llm,
780
+ ...current2.llm,
677
781
  apiKey
678
782
  }
679
783
  }));
680
- p6.log.success(color6.green("noto api key configured!"));
784
+ p7.log.success(color7.green("noto api key configured!"));
681
785
  console.log();
682
786
  }
683
787
  };
@@ -685,8 +789,8 @@ var model = {
685
789
  name: "model",
686
790
  description: "configure model",
687
791
  usage: "noto config model [options]",
688
- execute: async (options) => {
689
- const model2 = await p6.select({
792
+ execute: async () => {
793
+ const model2 = await p7.select({
690
794
  message: "select a model",
691
795
  initialValue: (await StorageManager.get()).llm?.model,
692
796
  options: Object.keys(models).map((model3) => ({
@@ -694,27 +798,27 @@ var model = {
694
798
  value: model3
695
799
  }))
696
800
  });
697
- if (p6.isCancel(model2)) {
698
- p6.log.error(color6.red("nothing changed!"));
801
+ if (p7.isCancel(model2)) {
802
+ p7.log.error(color7.red("nothing changed!"));
699
803
  return await exit(1);
700
804
  }
701
805
  if (model2 === "gemini-2.5-pro-exp-03-25") {
702
- const confirm2 = await p6.confirm({
806
+ const confirm2 = await p7.confirm({
703
807
  message: "this model has a rate limit of 5 RPM (requests per minute) 50 requests per day, do you want to continue?"
704
808
  });
705
- if (p6.isCancel(confirm2) || !confirm2) {
706
- p6.log.error(color6.red("nothing changed!"));
809
+ if (p7.isCancel(confirm2) || !confirm2) {
810
+ p7.log.error(color7.red("nothing changed!"));
707
811
  return await exit(1);
708
812
  }
709
813
  }
710
- await StorageManager.update((current) => ({
711
- ...current,
814
+ await StorageManager.update((current2) => ({
815
+ ...current2,
712
816
  llm: {
713
- ...current.llm,
817
+ ...current2.llm,
714
818
  model: model2
715
819
  }
716
820
  }));
717
- p6.log.success(color6.green("model configured!"));
821
+ p7.log.success(color7.green("model configured!"));
718
822
  console.log();
719
823
  }
720
824
  };
@@ -723,37 +827,37 @@ var reset = {
723
827
  description: "reset configuration",
724
828
  usage: "noto config reset",
725
829
  execute: async () => {
726
- const confirm2 = await p6.confirm({
830
+ const confirm2 = await p7.confirm({
727
831
  message: "are you sure you want to reset the configuration?"
728
832
  });
729
- if (p6.isCancel(confirm2) || !confirm2) {
730
- p6.log.error(color6.red("nothing changed!"));
833
+ if (p7.isCancel(confirm2) || !confirm2) {
834
+ p7.log.error(color7.red("nothing changed!"));
731
835
  return await exit(1);
732
836
  }
733
837
  await StorageManager.clear();
734
- p6.log.success(color6.green("configuration reset!"));
838
+ p7.log.success(color7.green("configuration reset!"));
735
839
  console.log();
736
840
  }
737
841
  };
738
842
  var subCommands = [key, model, reset];
739
- var command4 = {
843
+ var command5 = {
740
844
  name: "config",
741
845
  description: "configure noto",
742
846
  usage: "noto config [subcommand]",
743
847
  execute: async (options) => {
744
- const command5 = await p6.select({
848
+ const command6 = await p7.select({
745
849
  message: "Select a subcommand",
746
850
  options: subCommands.map((cmd2) => ({
747
851
  label: cmd2.description,
748
852
  value: cmd2.name
749
853
  }))
750
854
  });
751
- if (p6.isCancel(command5)) {
855
+ if (p7.isCancel(command6)) {
752
856
  return await exit(1);
753
857
  }
754
- const cmd = getCommand(command5, subCommands);
858
+ const cmd = getCommand(command6, subCommands);
755
859
  if (!cmd) {
756
- p6.log.error(color6.red("unknown config command"));
860
+ p7.log.error(color7.red("unknown config command"));
757
861
  return await exit(1);
758
862
  }
759
863
  options._ = options._.slice(1);
@@ -761,34 +865,34 @@ var command4 = {
761
865
  },
762
866
  subCommands
763
867
  };
764
- var config_default = command4;
868
+ var config_default = command5;
765
869
 
766
870
  // src/commands/help.ts
767
- import color7 from "picocolors";
871
+ import color8 from "picocolors";
768
872
  var help = {
769
873
  name: "help",
770
874
  description: "show help",
771
875
  usage: "noto help [command]",
772
876
  execute: async (options) => {
773
- const command5 = getCommand(options._[0]);
774
- if (command5) {
877
+ const command6 = getCommand(options._[0]);
878
+ if (command6 && command6.name !== "help") {
775
879
  console.log();
776
- console.log(color7.bold("Usage"));
777
- console.log(` ${command5.usage}`);
880
+ console.log(color8.bold("Usage"));
881
+ console.log(` ${command6.usage}`);
778
882
  console.log();
779
- console.log(color7.bold("Description"));
780
- console.log(` ${command5.description}`);
883
+ console.log(color8.bold("Description"));
884
+ console.log(` ${command6.description}`);
781
885
  console.log();
782
886
  } else {
783
887
  const commands2 = listCommand();
784
888
  console.log();
785
- console.log(color7.bold("Usage"));
889
+ console.log(color8.bold("Usage"));
786
890
  console.log(` noto [command] [options]`);
787
891
  console.log();
788
- console.log(color7.bold("Commands"));
789
- commands2.forEach((command6) => {
892
+ console.log(color8.bold("Commands"));
893
+ commands2.forEach((command7) => {
790
894
  console.log(
791
- ` ${color7.bold(command6.name)} ${color7.dim(command6.description)}`
895
+ ` ${color8.bold(command7.name)} ${color8.dim(command7.description)}`
792
896
  );
793
897
  });
794
898
  console.log();
@@ -798,7 +902,7 @@ var help = {
798
902
  var help_default = help;
799
903
 
800
904
  // src/commands/index.ts
801
- var commands = [noto_default, prev_default, checkout_default, config_default, help_default];
905
+ var commands = [noto_default, prev_default, branch_default, checkout_default, config_default, help_default];
802
906
  var getCommand = (name, cmds = commands) => {
803
907
  return cmds.find((cmd) => cmd.name === name);
804
908
  };
@@ -807,7 +911,7 @@ var listCommand = () => {
807
911
  };
808
912
 
809
913
  // package.json
810
- var version = "1.1.0";
914
+ var version = "1.1.2";
811
915
 
812
916
  // src/index.ts
813
917
  var globalSpec = {
@@ -818,15 +922,15 @@ var globalSpec = {
818
922
  };
819
923
  function main() {
820
924
  const args = process.argv.slice(2);
821
- const { command: command5, options: globalOptions } = parse(globalSpec, args);
925
+ const { command: command6, options: globalOptions } = parse(globalSpec, args);
822
926
  console.log();
823
- p7.intro(`${color8.bgCyan(color8.black(" @snelusha/noto "))}`);
824
- if (globalOptions["--version"]) return p7.outro(version);
927
+ p8.intro(`${color9.bgCyan(color9.black(" @snelusha/noto "))}`);
928
+ if (globalOptions["--version"]) return p8.outro(version);
825
929
  if (globalOptions["--help"]) {
826
930
  getCommand("help")?.execute(globalOptions);
827
931
  return;
828
932
  }
829
- const cmd = getCommand(command5) ?? getCommand("noto");
933
+ const cmd = getCommand(command6) ?? getCommand("noto");
830
934
  if (!cmd) return getCommand("noto")?.execute(globalOptions);
831
935
  let commandArgs = args;
832
936
  let selectedCommand = cmd;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@snelusha/noto",
3
- "version": "1.1.0",
3
+ "version": "1.1.2",
4
4
  "description": "Generate clean commit messages in a snap! ✨",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,9 +48,9 @@
48
48
  "vitest": "^3.1.1"
49
49
  },
50
50
  "dependencies": {
51
- "@ai-sdk/google": "^1.2.7",
52
- "@clack/prompts": "^0.10.0",
53
- "ai": "^4.3.2",
51
+ "@ai-sdk/google": "^1.2.10",
52
+ "@clack/prompts": "^0.10.1",
53
+ "ai": "^4.3.4",
54
54
  "arg": "^5.0.2",
55
55
  "clipboardy": "^4.0.0",
56
56
  "dedent": "^1.5.3",