aicommit2 2.4.27 → 2.4.28
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.
- package/README.md +125 -348
- package/dist/cli.mjs +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,29 @@
|
|
|
21
21
|
|
|
22
22
|
______________________________________________________________________
|
|
23
23
|
|
|
24
|
+
## Table of Contents
|
|
25
|
+
|
|
26
|
+
- [Quick start](#quick-start)
|
|
27
|
+
- [Introduction](#introduction)
|
|
28
|
+
- [Key features](#key-features)
|
|
29
|
+
- [Supported providers](#supported-providers)
|
|
30
|
+
- [Setup](#setup)
|
|
31
|
+
- [How it works](#how-it-works)
|
|
32
|
+
- [Version Control Systems](#version-control-systems)
|
|
33
|
+
- [Usage](#usage)
|
|
34
|
+
- [Integrations](#integrations)
|
|
35
|
+
- [LazyGit](#lazygit)
|
|
36
|
+
- [Git Hooks](#git-hooks)
|
|
37
|
+
- [Configuration](#configuration)
|
|
38
|
+
- [General Settings](#general-settings)
|
|
39
|
+
- [Logging](#logging)
|
|
40
|
+
- [Custom Prompt Template](#custom-prompt-template)
|
|
41
|
+
- [Watch Commit Mode](#watch-commit-mode)
|
|
42
|
+
- [Upgrading](#upgrading)
|
|
43
|
+
- [Contributing](#contributing)
|
|
44
|
+
|
|
45
|
+
______________________________________________________________________
|
|
46
|
+
|
|
24
47
|
## Quick start
|
|
25
48
|
|
|
26
49
|
```bash
|
|
@@ -44,7 +67,7 @@ aicommit2
|
|
|
44
67
|
|
|
45
68
|
## Introduction
|
|
46
69
|
|
|
47
|
-
|
|
70
|
+
_aicommit2_ automatically generates commit messages using AI. It supports [Git](https://git-scm.com/), [YADM](https://yadm.io/) (Yet Another Dotfiles Manager), and [Jujutsu](https://github.com/jj-vcs/jj) (jj) repositories with automatic detection. [AICommits](https://github.com/Nutlope/aicommits) inspired the core functionalities and architecture of this project.
|
|
48
71
|
|
|
49
72
|
## Key features
|
|
50
73
|
|
|
@@ -52,7 +75,7 @@ AICommit2 automatically generates commit messages using AI. It supports [Git](ht
|
|
|
52
75
|
- **[Multi-AI Support](#cloud-ai-services)**: Integrates with OpenAI, Anthropic Claude, Google Gemini, Mistral AI, Cohere, Groq, Ollama and more
|
|
53
76
|
- **[OpenAI API Compatibility](docs/providers/compatible.md)**: Support for any service that implements the OpenAI API specification
|
|
54
77
|
- **[Reactive CLI](#usage)**: Enables simultaneous requests to multiple AIs and selection of the best commit message
|
|
55
|
-
- **[Git Hook Integration](#git-
|
|
78
|
+
- **[Git Hook Integration](#git-hooks)**: Can be used as a prepare-commit-msg hook
|
|
56
79
|
- **[Custom Prompt](#custom-prompt-template)**: Supports user-defined system prompt templates
|
|
57
80
|
|
|
58
81
|
## Supported providers
|
|
@@ -80,12 +103,12 @@ AICommit2 automatically generates commit messages using AI. It supports [Git](ht
|
|
|
80
103
|
1. Install _aicommit2_:
|
|
81
104
|
|
|
82
105
|
**Via Homebrew (recommended for macOS/Linux):**
|
|
83
|
-
```
|
|
106
|
+
```bash
|
|
84
107
|
brew install aicommit2
|
|
85
108
|
```
|
|
86
109
|
|
|
87
110
|
**Via npm:**
|
|
88
|
-
```
|
|
111
|
+
```bash
|
|
89
112
|
npm install -g aicommit2
|
|
90
113
|
```
|
|
91
114
|
|
|
@@ -93,7 +116,7 @@ npm install -g aicommit2
|
|
|
93
116
|
|
|
94
117
|
2. Set up API keys (**at least ONE key must be set**):
|
|
95
118
|
|
|
96
|
-
```
|
|
119
|
+
```bash
|
|
97
120
|
aicommit2 config set OPENAI.key=<your key>
|
|
98
121
|
aicommit2 config set ANTHROPIC.key=<your key>
|
|
99
122
|
# ... (similar commands for other providers)
|
|
@@ -101,7 +124,7 @@ aicommit2 config set ANTHROPIC.key=<your key>
|
|
|
101
124
|
|
|
102
125
|
3. Run _aicommit2_ in your Git or Jujutsu repository:
|
|
103
126
|
|
|
104
|
-
```
|
|
127
|
+
```bash
|
|
105
128
|
# For Git repositories
|
|
106
129
|
git add <files...>
|
|
107
130
|
aicommit2
|
|
@@ -118,7 +141,7 @@ aicommit2
|
|
|
118
141
|
|
|
119
142
|
If you use the Nix package manager, aicommit2 can be installed directly using the provided flake:
|
|
120
143
|
|
|
121
|
-
```
|
|
144
|
+
```bash
|
|
122
145
|
# Install temporarily in your current shell
|
|
123
146
|
nix run github:tak-bro/aicommit2
|
|
124
147
|
|
|
@@ -157,7 +180,7 @@ Add aicommit2 to your flake inputs:
|
|
|
157
180
|
|
|
158
181
|
To enter a development shell with all dependencies:
|
|
159
182
|
|
|
160
|
-
```
|
|
183
|
+
```bash
|
|
161
184
|
nix develop github:tak-bro/aicommit2
|
|
162
185
|
```
|
|
163
186
|
|
|
@@ -165,7 +188,7 @@ After setting up with Nix, you'll still need to configure API keys as described
|
|
|
165
188
|
|
|
166
189
|
#### From Source
|
|
167
190
|
|
|
168
|
-
```
|
|
191
|
+
```bash
|
|
169
192
|
git clone https://github.com/tak-bro/aicommit2.git
|
|
170
193
|
cd aicommit2
|
|
171
194
|
npm run build
|
|
@@ -205,7 +228,7 @@ aicommit2
|
|
|
205
228
|
|
|
206
229
|
### YADM Support
|
|
207
230
|
|
|
208
|
-
|
|
231
|
+
_aicommit2_ supports [YADM (Yet Another Dotfiles Manager)](https://yadm.io/) for managing dotfiles:
|
|
209
232
|
|
|
210
233
|
```bash
|
|
211
234
|
# Standard YADM workflow
|
|
@@ -240,7 +263,7 @@ yadm clone <url>
|
|
|
240
263
|
|
|
241
264
|
### Jujutsu Support
|
|
242
265
|
|
|
243
|
-
|
|
266
|
+
_aicommit2_ also supports [Jujutsu (jj)](https://github.com/jj-vcs/jj) repositories:
|
|
244
267
|
|
|
245
268
|
```bash
|
|
246
269
|
# Automatic jj detection (no staging needed)
|
|
@@ -261,7 +284,7 @@ aicommit2 config set forceGit=true
|
|
|
261
284
|
|
|
262
285
|
**jj new Behavior:**
|
|
263
286
|
|
|
264
|
-
By default,
|
|
287
|
+
By default, _aicommit2_ only runs `jj describe` to set the commit message, without creating a new changeset. This matches the workflow of many Jujutsu users who prefer to manually control when to run `jj new`.
|
|
265
288
|
|
|
266
289
|
To automatically run `jj new` after describing (mimics `jj commit` behavior):
|
|
267
290
|
|
|
@@ -324,16 +347,16 @@ aicommit2 --jj
|
|
|
324
347
|
|
|
325
348
|
You can call `aicommit2` directly to generate a commit message for your staged changes:
|
|
326
349
|
|
|
327
|
-
```
|
|
350
|
+
```bash
|
|
328
351
|
git add <files...>
|
|
329
352
|
aicommit2
|
|
330
353
|
```
|
|
331
354
|
|
|
332
355
|
`aicommit2` passes down unknown flags to `git commit`, so you can pass in [`commit` flags](https://git-scm.com/docs/git-commit).
|
|
333
356
|
|
|
334
|
-
For example, you can stage all changes in tracked files
|
|
357
|
+
For example, you can stage all changes in tracked files as you commit:
|
|
335
358
|
|
|
336
|
-
```
|
|
359
|
+
```bash
|
|
337
360
|
aicommit2 --all # or -a
|
|
338
361
|
```
|
|
339
362
|
|
|
@@ -368,7 +391,7 @@ aicommit2 --all # or -a
|
|
|
368
391
|
- Useful when working with custom commit conventions that require specific casing
|
|
369
392
|
- `--hook-mode`: Run as a Git hook, typically used with [`prepare-commit-msg` hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks#_committing_workflow_hooks) hook (default: **false**)
|
|
370
393
|
- This mode is automatically enabled when running through the Git hook system
|
|
371
|
-
- See [Git
|
|
394
|
+
- See [Git Hooks](#git-hooks) section for more details
|
|
372
395
|
- `--pre-commit`: Run in [pre-commit](https://pre-commit.com/) framework mode (default: **false**)
|
|
373
396
|
- This option is specifically for use with the pre-commit framework
|
|
374
397
|
- See [Integration with pre-commit framework](#integration-with-pre-commit-framework) section for setup instructions
|
|
@@ -379,12 +402,12 @@ aicommit2 --all # or -a
|
|
|
379
402
|
- `--output` or `-o`: Output format for non-interactive mode (default: **none**)
|
|
380
403
|
- Use `--output json` for JSON Lines format (one JSON object per line)
|
|
381
404
|
- Outputs `{"subject":"...","body":"..."}` for each generated message
|
|
382
|
-
- Designed for integration with tools like [LazyGit](#lazygit
|
|
405
|
+
- Designed for integration with tools like [LazyGit](#lazygit)
|
|
383
406
|
- Skips TUI and exits after outputting messages
|
|
384
407
|
|
|
385
408
|
Examples:
|
|
386
409
|
|
|
387
|
-
```
|
|
410
|
+
```bash
|
|
388
411
|
# Generate multiple commit messages with clipboard and file exclusions
|
|
389
412
|
aicommit2 --locale "jp" --all --type "conventional" --generate 3 --clipboard --exclude "*.json" --exclude "*.ts"
|
|
390
413
|
|
|
@@ -401,15 +424,17 @@ aicommit2 -d -c
|
|
|
401
424
|
aicommit2 --verbose # or -v
|
|
402
425
|
```
|
|
403
426
|
|
|
404
|
-
|
|
427
|
+
## Integrations
|
|
405
428
|
|
|
406
|
-
|
|
429
|
+
### LazyGit
|
|
430
|
+
|
|
431
|
+
_aicommit2_ supports non-interactive JSON output mode for seamless integration with [LazyGit](https://github.com/jesseduffield/lazygit).
|
|
407
432
|
|
|
408
433
|
#### Setup
|
|
409
434
|
|
|
410
435
|
Use the `--output json` flag to get AI-generated commit messages in JSON Lines format:
|
|
411
436
|
|
|
412
|
-
```
|
|
437
|
+
```bash
|
|
413
438
|
aicommit2 --output json
|
|
414
439
|
# Output: {"subject":"feat: add user authentication","body":""}
|
|
415
440
|
# Output: {"subject":"fix: resolve login bug","body":"Fixes issue with session handling"}
|
|
@@ -468,23 +493,23 @@ customCommands:
|
|
|
468
493
|
|
|
469
494
|
> **Note:** The editable mode (`Shift+A`) currently supports editing the subject only. The AI-generated body is not carried over to the edit prompt.
|
|
470
495
|
|
|
471
|
-
### Git
|
|
496
|
+
### Git Hooks
|
|
472
497
|
|
|
473
|
-
You can
|
|
498
|
+
You can integrate _aicommit2_ with Git via the [`prepare-commit-msg`](https://git-scm.com/docs/githooks#_prepare_commit_msg) hook. This lets you use Git like you normally would, and edit the commit message before committing.
|
|
474
499
|
|
|
475
500
|
#### Automatic Installation
|
|
476
501
|
|
|
477
502
|
In the Git repository you want to install the hook in:
|
|
478
503
|
|
|
479
|
-
```
|
|
504
|
+
```bash
|
|
480
505
|
aicommit2 hook install
|
|
481
506
|
```
|
|
482
507
|
|
|
483
508
|
#### Manual Installation
|
|
484
509
|
|
|
485
|
-
|
|
510
|
+
If you prefer to set up the hook manually, create or edit the `.git/hooks/prepare-commit-msg` file:
|
|
486
511
|
|
|
487
|
-
```
|
|
512
|
+
```bash
|
|
488
513
|
#!/bin/sh
|
|
489
514
|
# your-other-hook "$@"
|
|
490
515
|
aicommit2 --hook-mode "$@"
|
|
@@ -492,13 +517,13 @@ aicommit2 --hook-mode "$@"
|
|
|
492
517
|
|
|
493
518
|
Make the hook executable:
|
|
494
519
|
|
|
495
|
-
```
|
|
520
|
+
```bash
|
|
496
521
|
chmod +x .git/hooks/prepare-commit-msg
|
|
497
522
|
```
|
|
498
523
|
|
|
499
524
|
##### Use with a custom `core.hooksPath`
|
|
500
525
|
|
|
501
|
-
If you are using [`husky`](https://typicode.github.io/husky/)
|
|
526
|
+
If you are using [`husky`](https://typicode.github.io/husky/) or have configured a custom [`core.hooksPath`](https://git-scm.com/docs/git-config#Documentation/git-config.txt-corehooksPath), update the corresponding hooks file instead. For Husky users, this file is `.husky/prepare-commit-message`.
|
|
502
527
|
|
|
503
528
|
#### Integration with pre-commit Framework
|
|
504
529
|
|
|
@@ -522,19 +547,19 @@ Make sure you have:
|
|
|
522
547
|
2. Installed aicommit2 globally: `npm install -g aicommit2`
|
|
523
548
|
3. Run `pre-commit install --hook-type prepare-commit-msg` to set up the hook
|
|
524
549
|
|
|
525
|
-
> **Note
|
|
550
|
+
> **Note:** The `--pre-commit` flag is specifically designed for use with the pre-commit framework and ensures proper integration with other pre-commit hooks.
|
|
526
551
|
|
|
527
552
|
#### Uninstall
|
|
528
553
|
|
|
529
554
|
In the Git repository you want to uninstall the hook from:
|
|
530
555
|
|
|
531
|
-
```
|
|
556
|
+
```bash
|
|
532
557
|
aicommit2 hook uninstall
|
|
533
558
|
```
|
|
534
559
|
|
|
535
560
|
Or manually delete the `.git/hooks/prepare-commit-msg` file.
|
|
536
561
|
|
|
537
|
-
|
|
562
|
+
## Configuration
|
|
538
563
|
|
|
539
564
|
aicommit2 supports configuration via command-line arguments, environment variables, and a configuration file. Settings are resolved in the following order of precedence:
|
|
540
565
|
|
|
@@ -543,7 +568,7 @@ aicommit2 supports configuration via command-line arguments, environment variabl
|
|
|
543
568
|
3. Configuration file
|
|
544
569
|
4. Default values
|
|
545
570
|
|
|
546
|
-
|
|
571
|
+
### Configuration File Location
|
|
547
572
|
|
|
548
573
|
aicommit2 follows the [XDG Base Directory Specification](https://specifications.freedesktop.org/basedir-spec/latest/index.html) for its configuration file. The configuration file is named `config.ini` and is in INI format. It is resolved in the following order of precedence:
|
|
549
574
|
|
|
@@ -555,11 +580,11 @@ The first existing file found in this order will be used. If no configuration fi
|
|
|
555
580
|
|
|
556
581
|
You can find the path of the currently loaded configuration file using the `config path` command:
|
|
557
582
|
|
|
558
|
-
```
|
|
583
|
+
```bash
|
|
559
584
|
aicommit2 config path
|
|
560
585
|
```
|
|
561
586
|
|
|
562
|
-
|
|
587
|
+
### Environment Variable Expansion in Config File
|
|
563
588
|
|
|
564
589
|
You can use environment variables in your configuration file values. Both `$VAR` and `${VAR}` syntax are supported.
|
|
565
590
|
|
|
@@ -571,7 +596,7 @@ key=$OPENAI_API_KEY
|
|
|
571
596
|
url=${CUSTOM_API_URL}/v1
|
|
572
597
|
```
|
|
573
598
|
|
|
574
|
-
|
|
599
|
+
### Reading and Setting Configuration
|
|
575
600
|
|
|
576
601
|
- READ: `aicommit2 config get [<key> [<key> ...]]`
|
|
577
602
|
- SET: `aicommit2 config set <key>=<value>`
|
|
@@ -579,7 +604,7 @@ url=${CUSTOM_API_URL}/v1
|
|
|
579
604
|
|
|
580
605
|
Example:
|
|
581
606
|
|
|
582
|
-
```
|
|
607
|
+
```bash
|
|
583
608
|
# Get all configurations
|
|
584
609
|
aicommit2 config get
|
|
585
610
|
|
|
@@ -596,7 +621,7 @@ aicommit2 config del GEMINI
|
|
|
596
621
|
aicommit2 config del timeout
|
|
597
622
|
```
|
|
598
623
|
|
|
599
|
-
|
|
624
|
+
### Environment Variables
|
|
600
625
|
|
|
601
626
|
You can configure API keys using environment variables. This is particularly useful for CI/CD environments or when you don't want to store keys in the configuration file.
|
|
602
627
|
|
|
@@ -621,20 +646,20 @@ DEEPSEEK_API_KEY="your-deepseek-key"
|
|
|
621
646
|
|
|
622
647
|
Usage Example:
|
|
623
648
|
|
|
624
|
-
```
|
|
649
|
+
```bash
|
|
625
650
|
OPENAI_API_KEY="your-openai-key" ANTHROPIC_API_KEY="your-anthropic-key" aicommit2
|
|
626
651
|
```
|
|
627
652
|
|
|
628
653
|
> **Note**: Environment variables take precedence over configuration file settings.
|
|
629
654
|
|
|
630
|
-
|
|
655
|
+
### How to Configure in detail
|
|
631
656
|
|
|
632
657
|
_aicommit2_ offers flexible configuration options for all AI services, including support for specifying multiple models. You can configure settings via command-line arguments, environment variables, or a configuration file.
|
|
633
658
|
|
|
634
659
|
1. **Command-line arguments**: Use the format `--[Model].[Key]=value`.
|
|
635
660
|
To specify multiple models, use the `--[Model].model=model1,model2` format.
|
|
636
661
|
|
|
637
|
-
```
|
|
662
|
+
```bash
|
|
638
663
|
aicommit2 --OPENAI.locale="jp" --GEMINI.temperature="0.5" --OPENAI.model="gpt-4o-mini,gpt-3.5-turbo"
|
|
639
664
|
```
|
|
640
665
|
|
|
@@ -669,282 +694,61 @@ _aicommit2_ offers flexible configuration options for all AI services, including
|
|
|
669
694
|
|
|
670
695
|
> The priority of settings is: **Command-line Arguments > Environment Variables > Model-Specific Settings > General Settings > Default Values**.
|
|
671
696
|
|
|
697
|
+
### Configuration Examples
|
|
698
|
+
|
|
699
|
+
```bash
|
|
700
|
+
aicommit2 config set \
|
|
701
|
+
generate=2 \
|
|
702
|
+
topP=0.8 \
|
|
703
|
+
maxTokens=1024 \
|
|
704
|
+
temperature=0.7 \
|
|
705
|
+
OPENAI.key="sk-..." OPENAI.model="gpt-4o-mini" OPENAI.temperature=0.5 \
|
|
706
|
+
ANTHROPIC.key="sk-..." ANTHROPIC.model="claude-3-5-haiku-20241022" ANTHROPIC.maxTokens=2000 \
|
|
707
|
+
MISTRAL.key="your-key" MISTRAL.model="mistral-small-latest" \
|
|
708
|
+
OLLAMA.model="llama3.2" OLLAMA.numCtx=4096 OLLAMA.watchMode=true
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
> 🔍 **Detailed Support Info**: Check each provider's documentation for specific limits and behaviors:
|
|
712
|
+
>
|
|
713
|
+
> - [OpenAI](docs/providers/openai.md)
|
|
714
|
+
> - [Anthropic Claude](docs/providers/anthropic.md)
|
|
715
|
+
> - [Gemini](docs/providers/gemini.md)
|
|
716
|
+
> - [Mistral & Codestral](docs/providers/mistral.md)
|
|
717
|
+
> - [Cohere](docs/providers/cohere.md)
|
|
718
|
+
> - [Groq](docs/providers/groq.md)
|
|
719
|
+
> - [Perplexity](docs/providers/perplexity.md)
|
|
720
|
+
> - [DeepSeek](docs/providers/deepseek.md)
|
|
721
|
+
> - [GitHub Models](docs/providers/github-models.md)
|
|
722
|
+
> - [OpenAI API Compatibility](docs/providers/compatible.md)
|
|
723
|
+
> - [Ollama](docs/providers/ollama.md)
|
|
724
|
+
|
|
672
725
|
## General Settings
|
|
673
726
|
|
|
674
|
-
|
|
675
|
-
Please check the documentation for each specific model to confirm which settings are supported.
|
|
727
|
+
For detailed information about all available settings, see the [General Settings documentation](docs/settings.md).
|
|
676
728
|
|
|
677
729
|
| Setting | Description | Default |
|
|
678
730
|
| ---------------------- | ------------------------------------------------------------------- | ------------ |
|
|
679
|
-
| `envKey` | Custom environment variable name for the API key | - |
|
|
680
|
-
| `systemPrompt` | System Prompt text | - |
|
|
681
|
-
| `systemPromptPath` | Path to system prompt file | - |
|
|
682
|
-
| `exclude` | Files to exclude from AI analysis | - |
|
|
683
|
-
| `type` | Type of commit message to generate | conventional |
|
|
684
731
|
| `locale` | Locale for the generated commit messages | en |
|
|
685
732
|
| `generate` | Number of commit messages to generate | 1 |
|
|
686
|
-
| `
|
|
687
|
-
| `
|
|
688
|
-
| `maxLength` | Maximum character length of the Subject of generated commit message | 50 |
|
|
689
|
-
| `disableLowerCase` | Disable automatic lowercase conversion of commit messages | false |
|
|
733
|
+
| `type` | Type of commit message (`conventional` / `gitmoji`) | conventional |
|
|
734
|
+
| `maxLength` | Maximum character length of the commit subject | 50 |
|
|
690
735
|
| `timeout` | Request timeout (milliseconds) | 10000 |
|
|
691
736
|
| `temperature` | Model's creativity (0.0 - 2.0) | 0.7 |
|
|
692
737
|
| `maxTokens` | Maximum number of tokens to generate | 1024 |
|
|
693
|
-
| `
|
|
694
|
-
| `codeReview` |
|
|
695
|
-
| `
|
|
696
|
-
| `disabled` | Whether a specific model is enabled or disabled | false |
|
|
697
|
-
|
|
698
|
-
> 👉 **Tip:** To set the General Settings for each model, use the following command.
|
|
699
|
-
>
|
|
700
|
-
> ```shell
|
|
701
|
-
> aicommit2 config set OPENAI.locale="jp"
|
|
702
|
-
> aicommit2 config set CODESTRAL.type="gitmoji"
|
|
703
|
-
> aicommit2 config set GEMINI.includeBody=true
|
|
704
|
-
> ```
|
|
705
|
-
|
|
706
|
-
##### envKey
|
|
707
|
-
|
|
708
|
-
- Allows users to specify a custom environment variable name for their API key.
|
|
709
|
-
- If `envKey` is not explicitly set, the system defaults to using an environment variable named after the service, followed by `_API_KEY` (e.g., `OPENAI_API_KEY` for OpenAI, `GEMINI_API_KEY` for Gemini).
|
|
710
|
-
- This setting provides flexibility for managing API keys, especially when multiple services are used or when specific naming conventions are required.
|
|
711
|
-
|
|
712
|
-
```sh
|
|
713
|
-
aicommit2 config set OPENAI.envKey="MY_CUSTOM_OPENAI_KEY"
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
> `envKey` is used to retrieve the API key from your system's environment variables. Ensure the specified environment variable is set with your API key.
|
|
717
|
-
|
|
718
|
-
##### systemPrompt
|
|
719
|
-
|
|
720
|
-
- Allow users to specify a custom system prompt
|
|
721
|
-
|
|
722
|
-
```sh
|
|
723
|
-
aicommit2 config set systemPrompt="Generate git commit message."
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
> `systemPrompt` takes precedence over `systemPromptPath` and does not apply at the same time.
|
|
727
|
-
|
|
728
|
-
##### systemPromptPath
|
|
729
|
-
|
|
730
|
-
- Allow users to specify a custom file path for their own system prompt template
|
|
731
|
-
- Please see [Custom Prompt Template](#custom-prompt-template)
|
|
732
|
-
- **Note**: Paths can be absolute or relative to the configuration file location.
|
|
733
|
-
|
|
734
|
-
```sh
|
|
735
|
-
aicommit2 config set systemPromptPath="/path/to/user/prompt.txt"
|
|
736
|
-
```
|
|
737
|
-
|
|
738
|
-
##### exclude
|
|
739
|
-
|
|
740
|
-
- Files to exclude from AI analysis
|
|
741
|
-
- It is applied with the `--exclude` option of the CLI option. All files excluded through `--exclude` in CLI and `exclude` general setting.
|
|
742
|
-
|
|
743
|
-
```sh
|
|
744
|
-
aicommit2 config set exclude="*.ts"
|
|
745
|
-
aicommit2 config set exclude="*.ts,*.json"
|
|
746
|
-
```
|
|
747
|
-
|
|
748
|
-
> NOTE: `exclude` option does not support per model. It is **only** supported by General Settings.
|
|
749
|
-
|
|
750
|
-
##### forceGit
|
|
751
|
-
|
|
752
|
-
Default: `false`
|
|
753
|
-
|
|
754
|
-
Force Git detection even in Jujutsu repositories (useful when you have both `.jj` and `.git` directories):
|
|
755
|
-
|
|
756
|
-
```sh
|
|
757
|
-
aicommit2 config set forceGit=true
|
|
758
|
-
```
|
|
759
|
-
|
|
760
|
-
This is equivalent to using the `FORCE_GIT=true` environment variable, but persistent across sessions.
|
|
761
|
-
|
|
762
|
-
##### type
|
|
763
|
-
|
|
764
|
-
Default: `conventional`
|
|
765
|
-
|
|
766
|
-
Supported: `conventional`, `gitmoji`
|
|
767
|
-
|
|
768
|
-
The type of commit message to generate:
|
|
769
|
-
|
|
770
|
-
**Conventional Commits**: Follow the [Conventional Commits](https://conventionalcommits.org/) specification:
|
|
771
|
-
|
|
772
|
-
```sh
|
|
773
|
-
aicommit2 config set type="conventional"
|
|
774
|
-
```
|
|
775
|
-
|
|
776
|
-
**Gitmoji**: Use [Gitmoji](https://gitmoji.dev/) emojis in commit messages:
|
|
777
|
-
|
|
778
|
-
```sh
|
|
779
|
-
aicommit2 config set type="gitmoji"
|
|
780
|
-
```
|
|
781
|
-
|
|
782
|
-
##### locale
|
|
783
|
-
|
|
784
|
-
Default: `en`
|
|
785
|
-
|
|
786
|
-
The locale to use for the generated commit messages. Consult the list of codes in: https://wikipedia.org/wiki/List_of_ISO_639_language_codes.
|
|
787
|
-
|
|
788
|
-
```sh
|
|
789
|
-
aicommit2 config set locale="jp"
|
|
790
|
-
```
|
|
791
|
-
|
|
792
|
-
##### generate
|
|
793
|
-
|
|
794
|
-
Default: `1`
|
|
795
|
-
|
|
796
|
-
The number of commit messages to generate to pick from.
|
|
797
|
-
|
|
798
|
-
Note, this will use more tokens as it generates more results.
|
|
799
|
-
|
|
800
|
-
```sh
|
|
801
|
-
aicommit2 config set generate=2
|
|
802
|
-
```
|
|
803
|
-
|
|
804
|
-
##### logging
|
|
805
|
-
|
|
806
|
-
Default: `true`
|
|
807
|
-
|
|
808
|
-
This boolean option controls whether the application generates log files. When enabled, both the general application logs and the AI request/response logs are written to their respective paths. For a detailed explanation of all logging settings, including how to enable/disable logging and manage log files, please refer to the main [Logging](#main-logging-section) section.
|
|
809
|
-
|
|
810
|
-
- **Log File Example**:
|
|
811
|
-

|
|
812
|
-
|
|
813
|
-
##### includeBody
|
|
814
|
-
|
|
815
|
-
Default: `false`
|
|
816
|
-
|
|
817
|
-
This option determines whether the commit message includes body. If you want to include body in message, you can set it to `true`.
|
|
818
|
-
|
|
819
|
-
```sh
|
|
820
|
-
aicommit2 config set includeBody="true"
|
|
821
|
-
```
|
|
822
|
-
|
|
823
|
-

|
|
824
|
-
|
|
825
|
-
```sh
|
|
826
|
-
aicommit2 config set includeBody="false"
|
|
827
|
-
```
|
|
828
|
-
|
|
829
|
-

|
|
830
|
-
|
|
831
|
-
##### maxLength
|
|
832
|
-
|
|
833
|
-
The maximum character length of the Subject of generated commit message
|
|
834
|
-
|
|
835
|
-
Default: `50`
|
|
836
|
-
|
|
837
|
-
```sh
|
|
838
|
-
aicommit2 config set maxLength=100
|
|
839
|
-
```
|
|
840
|
-
|
|
841
|
-
##### disableLowerCase
|
|
842
|
-
|
|
843
|
-
Disable automatic lowercase conversion of commit messages
|
|
844
|
-
|
|
845
|
-
Default: `false`
|
|
846
|
-
|
|
847
|
-
By default, AICommit2 converts the first character of commit types and descriptions to lowercase to follow conventional commit standards. Set this to `true` to preserve the original casing.
|
|
848
|
-
|
|
849
|
-
```sh
|
|
850
|
-
aicommit2 config set disableLowerCase=true
|
|
851
|
-
```
|
|
852
|
-
|
|
853
|
-
You can also use the CLI flag:
|
|
854
|
-
|
|
855
|
-
```sh
|
|
856
|
-
aicommit2 --disable-lowercase
|
|
857
|
-
```
|
|
858
|
-
|
|
859
|
-
##### timeout
|
|
860
|
-
|
|
861
|
-
The timeout for network requests in milliseconds.
|
|
862
|
-
|
|
863
|
-
Default: `10_000` (10 seconds)
|
|
864
|
-
|
|
865
|
-
```sh
|
|
866
|
-
aicommit2 config set timeout=20000 # 20s
|
|
867
|
-
```
|
|
868
|
-
|
|
869
|
-
> **Note**: Each AI provider has its own default timeout value, and if the configured timeout is less than the provider's default, the setting will be ignored.
|
|
870
|
-
|
|
871
|
-
##### temperature
|
|
872
|
-
|
|
873
|
-
The temperature (0.0-2.0) is used to control the randomness of the output
|
|
874
|
-
|
|
875
|
-
Default: `0.7`
|
|
876
|
-
|
|
877
|
-
```sh
|
|
878
|
-
aicommit2 config set temperature=0.3
|
|
879
|
-
```
|
|
880
|
-
|
|
881
|
-
##### maxTokens
|
|
882
|
-
|
|
883
|
-
The maximum number of tokens that the AI models can generate.
|
|
884
|
-
|
|
885
|
-
Default: `1024`
|
|
886
|
-
|
|
887
|
-
```sh
|
|
888
|
-
aicommit2 config set maxTokens=3000
|
|
889
|
-
```
|
|
890
|
-
|
|
891
|
-
##### topP
|
|
892
|
-
|
|
893
|
-
Default: `0.9`
|
|
894
|
-
|
|
895
|
-
Nucleus sampling, where the model considers the results of the tokens with top_p probability mass.
|
|
896
|
-
|
|
897
|
-
> **Note**: Claude 4.x models do not support using `temperature` and `top_p` simultaneously. For these models, `top_p` is automatically excluded.
|
|
898
|
-
|
|
899
|
-
```sh
|
|
900
|
-
aicommit2 config set topP=0.2
|
|
901
|
-
```
|
|
902
|
-
|
|
903
|
-
##### disabled
|
|
904
|
-
|
|
905
|
-
Default: `false`
|
|
906
|
-
|
|
907
|
-
This option determines whether a specific model is enabled or disabled. If you want to disable a particular model, you can set this option to `true`.
|
|
908
|
-
|
|
909
|
-
To disable a model, use the following commands:
|
|
910
|
-
|
|
911
|
-
```sh
|
|
912
|
-
aicommit2 config set GEMINI.disabled="true"
|
|
913
|
-
aicommit2 config set GROQ.disabled="true"
|
|
914
|
-
```
|
|
915
|
-
|
|
916
|
-
##### codeReview
|
|
917
|
-
|
|
918
|
-
Default: `false`
|
|
919
|
-
|
|
920
|
-
The `codeReview` parameter determines whether to include an automated code review in the process.
|
|
738
|
+
| `includeBody` | Whether the commit message includes body | false |
|
|
739
|
+
| `codeReview` | Enable automated code review | false |
|
|
740
|
+
| `systemPromptPath` | Path to custom system prompt file | - |
|
|
921
741
|
|
|
922
|
-
```
|
|
923
|
-
|
|
742
|
+
```bash
|
|
743
|
+
# Example: Set settings for a specific model
|
|
744
|
+
aicommit2 config set OPENAI.locale="jp"
|
|
745
|
+
aicommit2 config set GEMINI.temperature=0.5
|
|
746
|
+
aicommit2 config set ANTHROPIC.includeBody=true
|
|
924
747
|
```
|
|
925
748
|
|
|
926
|
-
>
|
|
927
|
-
|
|
928
|
-
<img src="https://github.com/tak-bro/aicommit2/blob/main/img/code_review.gif?raw=true" alt="CODE_REVIEW" />
|
|
929
|
-
|
|
930
|
-
⚠️ **CAUTION**
|
|
749
|
+
> 👉 For all settings and detailed explanations, see [docs/settings.md](docs/settings.md)
|
|
931
750
|
|
|
932
|
-
|
|
933
|
-
- This feature performs a code review before generating commit messages.
|
|
934
|
-
- Using this feature will significantly increase the overall processing time.
|
|
935
|
-
- It may significantly impact performance and cost.
|
|
936
|
-
- **The code review process consumes a large number of tokens.**
|
|
937
|
-
|
|
938
|
-
##### codeReviewPromptPath
|
|
939
|
-
|
|
940
|
-
- Allow users to specify a custom file path for code review
|
|
941
|
-
- **Note**: Paths can be absolute or relative to the configuration file location.
|
|
942
|
-
|
|
943
|
-
```sh
|
|
944
|
-
aicommit2 config set codeReviewPromptPath="/path/to/user/prompt.txt"
|
|
945
|
-
```
|
|
946
|
-
|
|
947
|
-
## Available General Settings by Model
|
|
751
|
+
### Available Settings by Model
|
|
948
752
|
|
|
949
753
|
| | timeout | temperature | maxTokens | topP |
|
|
950
754
|
| :-----------------------: | :-----: | :---------: | :-------: | :--: |
|
|
@@ -961,39 +765,7 @@ aicommit2 config set codeReviewPromptPath="/path/to/user/prompt.txt"
|
|
|
961
765
|
| **Ollama** | ✓ | ✓ | | ✓ |
|
|
962
766
|
| **OpenAI API-Compatible** | ✓ | ✓ | ✓ | ✓ |
|
|
963
767
|
|
|
964
|
-
|
|
965
|
-
>
|
|
966
|
-
> - systemPrompt, systemPromptPath, codeReview, codeReviewPromptPath, exclude, type, locale, generate, logging, includeBody, maxLength, disableLowerCase
|
|
967
|
-
|
|
968
|
-
## Configuration Examples
|
|
969
|
-
|
|
970
|
-
```
|
|
971
|
-
aicommit2 config set \
|
|
972
|
-
generate=2 \
|
|
973
|
-
topP=0.8 \
|
|
974
|
-
maxTokens=1024 \
|
|
975
|
-
temperature=0.7 \
|
|
976
|
-
OPENAI.key="sk-..." OPENAI.model="gpt-4o-mini" OPENAI.temperature=0.5 \
|
|
977
|
-
ANTHROPIC.key="sk-..." ANTHROPIC.model="claude-3-5-haiku-20241022" ANTHROPIC.maxTokens=2000 \
|
|
978
|
-
MISTRAL.key="your-key" MISTRAL.model="mistral-small-latest" \
|
|
979
|
-
OLLAMA.model="llama3.2" OLLAMA.numCtx=4096 OLLAMA.watchMode=true
|
|
980
|
-
```
|
|
981
|
-
|
|
982
|
-
> 🔍 **Detailed Support Info**: Check each provider's documentation for specific limits and behaviors:
|
|
983
|
-
>
|
|
984
|
-
> - [OpenAI](docs/providers/openai.md)
|
|
985
|
-
> - [Anthropic Claude](docs/providers/anthropic.md)
|
|
986
|
-
> - [Gemini](docs/providers/gemini.md)
|
|
987
|
-
> - [Mistral & Codestral](docs/providers/mistral.md)
|
|
988
|
-
> - [Cohere](docs/providers/cohere.md)
|
|
989
|
-
> - [Groq](docs/providers/groq.md)
|
|
990
|
-
> - [Perplexity](docs/providers/perplexity.md)
|
|
991
|
-
> - [DeepSeek](docs/providers/deepseek.md)
|
|
992
|
-
> - [GitHub Models](docs/providers/github-models.md)
|
|
993
|
-
> - [OpenAI API Compatibility](docs/providers/compatible.md)
|
|
994
|
-
> - [Ollama](docs/providers/ollama.md)
|
|
995
|
-
|
|
996
|
-
## <a id="main-logging-section"></a>Logging
|
|
768
|
+
## Logging
|
|
997
769
|
|
|
998
770
|
The application utilizes two distinct logging systems to provide comprehensive insights into its operations:
|
|
999
771
|
|
|
@@ -1037,7 +809,7 @@ _aicommit2_ generates detailed logs for debugging and tracking AI requests. You
|
|
|
1037
809
|
|
|
1038
810
|
#### View Log Files
|
|
1039
811
|
|
|
1040
|
-
```
|
|
812
|
+
```bash
|
|
1041
813
|
# List all log files with details
|
|
1042
814
|
aicommit2 log list
|
|
1043
815
|
|
|
@@ -1047,14 +819,14 @@ aicommit2 log path
|
|
|
1047
819
|
|
|
1048
820
|
#### Open Log Directory
|
|
1049
821
|
|
|
1050
|
-
```
|
|
822
|
+
```bash
|
|
1051
823
|
# Open logs directory in your file manager
|
|
1052
824
|
aicommit2 log open
|
|
1053
825
|
```
|
|
1054
826
|
|
|
1055
827
|
#### Clean Up Logs
|
|
1056
828
|
|
|
1057
|
-
```
|
|
829
|
+
```bash
|
|
1058
830
|
# Remove all log files
|
|
1059
831
|
aicommit2 log removeAll
|
|
1060
832
|
```
|
|
@@ -1074,7 +846,7 @@ _aicommit2_ supports custom prompt templates through the `systemPromptPath` opti
|
|
|
1074
846
|
|
|
1075
847
|
To use a custom prompt template, specify the path to your template file when running the tool:
|
|
1076
848
|
|
|
1077
|
-
```
|
|
849
|
+
```bash
|
|
1078
850
|
aicommit2 config set systemPromptPath="/path/to/user/prompt.txt"
|
|
1079
851
|
aicommit2 config set OPENAI.systemPromptPath="/path/to/another-prompt.txt"
|
|
1080
852
|
```
|
|
@@ -1088,10 +860,10 @@ For the above command, OpenAI uses the prompt in the `another-prompt.txt` file,
|
|
|
1088
860
|
Your custom template can include placeholders for various commit options.
|
|
1089
861
|
Use curly braces `{}` to denote these placeholders for options. The following placeholders are supported:
|
|
1090
862
|
|
|
1091
|
-
-
|
|
1092
|
-
-
|
|
1093
|
-
-
|
|
1094
|
-
-
|
|
863
|
+
- `{locale}`: The language for the commit message (default: **en**)
|
|
864
|
+
- `{maxLength}`: The maximum length for the commit message (default: **50**)
|
|
865
|
+
- `{type}`: The type of the commit message (**conventional** or **gitmoji**)
|
|
866
|
+
- `{generate}`: The number of commit messages to generate (default: **1**)
|
|
1095
867
|
|
|
1096
868
|
#### Example Template
|
|
1097
869
|
|
|
@@ -1138,7 +910,7 @@ This ensures that the output is consistently formatted as a JSON array, regardle
|
|
|
1138
910
|
|
|
1139
911
|
Watch Commit mode allows you to monitor Git commits in real-time and automatically perform AI code reviews using the `--watch-commit` flag.
|
|
1140
912
|
|
|
1141
|
-
```
|
|
913
|
+
```bash
|
|
1142
914
|
aicommit2 --watch-commit
|
|
1143
915
|
```
|
|
1144
916
|
|
|
@@ -1148,7 +920,7 @@ This feature only works within Git repository directories and automatically trig
|
|
|
1148
920
|
2. Performs AI code review
|
|
1149
921
|
3. Displays results in real-time
|
|
1150
922
|
|
|
1151
|
-
> For detailed configuration of the code review feature, please refer to the [codeReview](#codereview) section. The settings in that section are shared with this feature.
|
|
923
|
+
> For detailed configuration of the code review feature, please refer to the [codeReview](docs/settings.md#codereview) section. The settings in that section are shared with this feature.
|
|
1152
924
|
|
|
1153
925
|
⚠️ **CAUTION**
|
|
1154
926
|
|
|
@@ -1158,7 +930,7 @@ This feature only works within Git repository directories and automatically trig
|
|
|
1158
930
|
- It is recommended to **carefully monitor your token usage** when using this feature
|
|
1159
931
|
- To use this feature, you must enable watch mode for at least one AI model:
|
|
1160
932
|
|
|
1161
|
-
```
|
|
933
|
+
```bash
|
|
1162
934
|
aicommit2 config set [MODEL].watchMode="true"
|
|
1163
935
|
```
|
|
1164
936
|
|
|
@@ -1166,13 +938,17 @@ aicommit2 config set [MODEL].watchMode="true"
|
|
|
1166
938
|
|
|
1167
939
|
Check the installed version with:
|
|
1168
940
|
|
|
1169
|
-
```
|
|
941
|
+
```bash
|
|
1170
942
|
aicommit2 --version
|
|
1171
943
|
```
|
|
1172
944
|
|
|
1173
945
|
If it's not the [latest version](https://github.com/tak-bro/aicommit2/releases/latest), run:
|
|
1174
946
|
|
|
1175
|
-
```
|
|
947
|
+
```bash
|
|
948
|
+
# Via Homebrew
|
|
949
|
+
brew upgrade aicommit2
|
|
950
|
+
|
|
951
|
+
# Via npm
|
|
1176
952
|
npm update -g aicommit2
|
|
1177
953
|
```
|
|
1178
954
|
|
|
@@ -1215,6 +991,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d
|
|
|
1215
991
|
</tr>
|
|
1216
992
|
<tr>
|
|
1217
993
|
<td align="center"><a href="https://github.com/jaytaylor"><img src="https://avatars.githubusercontent.com/jaytaylor" width="100px;" alt=""/><br /><sub><b>@jaytaylor</b></sub></a><br /><a href="https://github.com/tak-bro/aicommit2/commits?author=jaytaylor" title="Code">💻</a></td>
|
|
994
|
+
<td align="center"><a href="https://github.com/denniswebb"><img src="https://avatars.githubusercontent.com/denniswebb" width="100px;" alt=""/><br /><sub><b>@denniswebb</b></sub></a><br /><a href="https://github.com/tak-bro/aicommit2/commits?author=denniswebb" title="Code">💻</a></td>
|
|
1218
995
|
</tr>
|
|
1219
996
|
</table>
|
|
1220
997
|
<!-- markdownlint-restore -->
|
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{command as de,cli as Mn}from"cleye";import{createRequire as Rn}from"module";import Dn from"crypto";import X from"fs";import Fe from"os";import x from"path";import{Buffer as Tr}from"node:buffer";import ge from"node:path";import Rt,{ChildProcess as jr,exec as On}from"node:child_process";import ae from"node:process";import Nn,{execSync as Ze,exec as Fn}from"child_process";import{fileURLToPath as Br}from"node:url";import _n,{constants as Gr}from"node:os";import Hr from"assert";import Ur from"events";import{createWriteStream as Ln,createReadStream as Tn,readFileSync as jn}from"node:fs";import Bn from"buffer";import Dt from"stream";import zr,{promisify as Gn}from"util";import{debuglog as Hn,promisify as Un}from"node:util";import et from"inquirer";import{of as Ot,concatMap as F,from as D,map as O,catchError as N,mergeMap as Kr,BehaviorSubject as Wr,ReplaySubject as zn,Subscription as Nt,lastValueFrom as Ft,toArray as _t,filter as Yr,Subject as Lt}from"rxjs";import _ from"fs/promises";import C from"chalk";import Kn from"@anthropic-ai/sdk";import{fromPromise as L}from"rxjs/internal/observable/innerFrom";import{xxh64 as Jr}from"@pacote/xxhash";import U from"winston";import"winston-daily-rotate-file";import Vr from"https";import Wn from"axios";import{CohereClientV2 as Yn}from"cohere-ai";import qr from"openai";import{GoogleGenerativeAI as Jn,HarmCategory as tt,HarmBlockThreshold as rt}from"@google/generative-ai";import Vn from"http";import qn from"net";import Xn from"tls";import Qn,{fileURLToPath as Zn,pathToFileURL as es}from"url";import Xr from"tty";import ts from"groq-sdk";import{Ollama as rs}from"ollama";import{fetch as os,Agent as ns}from"undici";import ot from"readline";import Qr from"figlet";import ss from"gradient-string";import Zr from"ora";import is from"inquirer-reactive-list-prompt";import{readdir as eo,stat as as,rm as cs}from"node:fs/promises";import ls from"chokidar";import{takeUntil as to,finalize as ro}from"rxjs/operators";var us="aicommit2",oo="2.4.27",ds="A Reactive CLI that generates commit messages for Git and Jujutsu with various AI",ms=["cli","ai","git","jujutsu","jj","vcs","version-control","commit","git-commit","jujutsu-commit","command-line","commandline","aipick","aicommit","aicommits","aicommit2","openai","huggingface","anthropic","claude","claude3","gemini","gemini-pro","generative-ai","mistral","ollama","llama3","llama3.2","llama3.3","gemma","llm","chatgpt","cohere","groq","codestral","perplexity","deepseek","deepseek-r1","pre-commit"],fs="MIT",ps="tak-bro/aicommit2",hs="Hyungtak Jin(@tak-bro)",gs="module",ys=["dist"],ws={aicommit2:"./dist/cli.mjs",aic2:"./dist/cli.mjs"},vs={prepare:"simple-git-hooks",build:"pkgroll --minify",lint:"eslint --cache .","type-check":"tsc",test:"tsx tests",prepack:"pnpm build && clean-pkg-json",prettier:"prettier"},Cs={"@anthropic-ai/sdk":"^0.39.0","@aws-sdk/client-bedrock-runtime":"^3.678.0","@aws-sdk/credential-providers":"^3.678.0","@dqbd/tiktoken":"^1.0.21","@google/generative-ai":"^0.24.1","@inquirer/prompts":"^3.3.2","@pacote/xxhash":"^0.3.2","@types/winston":"^2.4.4",axios:"^1.9.0",chalk:"^5.4.1",chokidar:"^4.0.3",cleye:"^1.3.4","cohere-ai":"^7.19.0","copy-paste":"^1.5.3",figlet:"^1.8.1","formdata-node":"^6.0.3","gradient-string":"^3.0.0","groq-sdk":"^0.7.0",inquirer:"9.2.8","inquirer-reactive-list-prompt":"^1.0.16",ollama:"^0.5.15",openai:"^6.3.0",ora:"^8.2.0",readline:"^1.3.0",rxjs:"^7.8.2",undici:"^7.10.0",uuid:"^9.0.1",winston:"^3.17.0","winston-daily-rotate-file":"^5.0.0"},bs={"@pvtnbr/eslint-config":"^0.33.0","@semantic-release/changelog":"^6.0.3","@semantic-release/commit-analyzer":"^12.0.0","@semantic-release/git":"^10.0.1","@semantic-release/github":"^10.3.5","@semantic-release/npm":"^12.0.1","@semantic-release/release-notes-generator":"^13.0.0","@types/figlet":"^1.7.0","@types/ini":"^1.3.34","@types/inquirer":"^9.0.8","@types/node":"^18.19.103","@types/uuid":"^9.0.8","@typescript-eslint/eslint-plugin":"^6.21.0","@typescript-eslint/parser":"^6.21.0","clean-pkg-json":"^1.3.0","conventional-changelog-conventionalcommits":"^7.0.2","conventional-commits-parser":"^5.0.0",eslint:"^8.57.1","eslint-config-prettier":"^8.10.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","eslint-plugin-jsonc":"^2.20.1","eslint-plugin-no-use-extend-native":"^0.5.0","eslint-plugin-promise":"^6.6.0","eslint-plugin-unicorn":"^49.0.0","eslint-plugin-unused-imports":"^3.2.0",execa:"^7.2.0","fs-fixture":"^1.2.0","https-proxy-agent":"^5.0.1",ini:"^3.0.1","lint-staged":"^13.3.0",manten:"^0.7.0",pkgroll:"^1.11.1",prettier:"^3.5.3","semantic-release":"^23.1.1","simple-git-hooks":"^2.13.0",tsx:"^3.14.0",typescript:"^4.9.5","undici-types":"^7.10.0"},Es={extends:["@pvtnbr","prettier"],rules:{"unicorn/no-process-exit":"off"},overrides:[{files:"./src/commands/prepare-commit-msg-hook.ts",rules:{"unicorn/prevent-abbreviations":"off"}}]},Ps={branches:["main"],plugins:[["@semantic-release/commit-analyzer",{preset:"conventionalcommits",releaseRules:[{type:"refactor",release:"patch"},{type:"chore",release:"patch"},{type:"feat",release:"patch"},{scope:"major",release:"major"},{scope:"minor",release:"minor"},{scope:"patch",release:"patch"}]}],"@semantic-release/release-notes-generator",["@semantic-release/changelog",{changelogFile:"CHANGELOG.md"}],"@semantic-release/github",["@semantic-release/git",{assets:["CHANGELOG.md"],message:"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}],"@semantic-release/npm"]},$s={name:us,version:oo,description:ds,keywords:ms,license:fs,repository:ps,author:hs,type:gs,files:ys,bin:ws,scripts:vs,"simple-git-hooks":{"pre-commit":"pnpm lint-staged"},"lint-staged":{"*.ts":["prettier --config ./.prettierrc --write","eslint --fix"]},dependencies:Cs,devDependencies:bs,eslintConfig:Es,release:Ps},As=Rn(import.meta.url),H=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Ee(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Pe={exports:{}},Tt,no;function ks(){if(no)return Tt;no=1,Tt=o,o.sync=n;var t=X;function e(s,i){var l=i.pathExt!==void 0?i.pathExt:process.env.PATHEXT;if(!l||(l=l.split(";"),l.indexOf("")!==-1))return!0;for(var a=0;a<l.length;a++){var d=l[a].toLowerCase();if(d&&s.substr(-d.length).toLowerCase()===d)return!0}return!1}function r(s,i,l){return!s.isSymbolicLink()&&!s.isFile()?!1:e(i,l)}function o(s,i,l){t.stat(s,function(a,d){l(a,a?!1:r(d,s,i))})}function n(s,i){return r(t.statSync(s),s,i)}return Tt}var jt,so;function Ss(){if(so)return jt;so=1,jt=e,e.sync=r;var t=X;function e(s,i,l){t.stat(s,function(a,d){l(a,a?!1:o(d,i))})}function r(s,i){return o(t.statSync(s),i)}function o(s,i){return s.isFile()&&n(s,i)}function n(s,i){var l=s.mode,a=s.uid,d=s.gid,c=i.uid!==void 0?i.uid:process.getuid&&process.getuid(),u=i.gid!==void 0?i.gid:process.getgid&&process.getgid(),f=parseInt("100",8),p=parseInt("010",8),h=parseInt("001",8),g=f|p,y=l&h||l&p&&d===u||l&f&&a===c||l&g&&c===0;return y}return jt}var nt;process.platform==="win32"||H.TESTING_WINDOWS?nt=ks():nt=Ss();var xs=Bt;Bt.sync=Is;function Bt(t,e,r){if(typeof e=="function"&&(r=e,e={}),!r){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(o,n){Bt(t,e||{},function(s,i){s?n(s):o(i)})})}nt(t,e||{},function(o,n){o&&(o.code==="EACCES"||e&&e.ignoreErrors)&&(o=null,n=!1),r(o,n)})}function Is(t,e){try{return nt.sync(t,e||{})}catch(r){if(e&&e.ignoreErrors||r.code==="EACCES")return!1;throw r}}const $e=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",io=x,Ms=$e?";":":",ao=xs,co=t=>Object.assign(new Error(`not found: ${t}`),{code:"ENOENT"}),lo=(t,e)=>{const r=e.colon||Ms,o=t.match(/\//)||$e&&t.match(/\\/)?[""]:[...$e?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(r)],n=$e?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=$e?n.split(r):[""];return $e&&t.indexOf(".")!==-1&&s[0]!==""&&s.unshift(""),{pathEnv:o,pathExt:s,pathExtExe:n}},uo=(t,e,r)=>{typeof e=="function"&&(r=e,e={}),e||(e={});const{pathEnv:o,pathExt:n,pathExtExe:s}=lo(t,e),i=[],l=d=>new Promise((c,u)=>{if(d===o.length)return e.all&&i.length?c(i):u(co(t));const f=o[d],p=/^".*"$/.test(f)?f.slice(1,-1):f,h=io.join(p,t),g=!p&&/^\.[\\\/]/.test(t)?t.slice(0,2)+h:h;c(a(g,d,0))}),a=(d,c,u)=>new Promise((f,p)=>{if(u===n.length)return f(l(c+1));const h=n[u];ao(d+h,{pathExt:s},(g,y)=>{if(!g&&y)if(e.all)i.push(d+h);else return f(d+h);return f(a(d,c,u+1))})});return r?l(0).then(d=>r(null,d),r):l(0)},Rs=(t,e)=>{e=e||{};const{pathEnv:r,pathExt:o,pathExtExe:n}=lo(t,e),s=[];for(let i=0;i<r.length;i++){const l=r[i],a=/^".*"$/.test(l)?l.slice(1,-1):l,d=io.join(a,t),c=!a&&/^\.[\\\/]/.test(t)?t.slice(0,2)+d:d;for(let u=0;u<o.length;u++){const f=c+o[u];try{if(ao.sync(f,{pathExt:n}))if(e.all)s.push(f);else return f}catch{}}}if(e.all&&s.length)return s;if(e.nothrow)return null;throw co(t)};var Ds=uo;uo.sync=Rs;var Gt={exports:{}};const mo=(t={})=>{const e=t.env||process.env;return(t.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(o=>o.toUpperCase()==="PATH")||"Path"};Gt.exports=mo,Gt.exports.default=mo;var Os=Gt.exports;const fo=x,Ns=Ds,Fs=Os;function po(t,e){const r=t.options.env||process.env,o=process.cwd(),n=t.options.cwd!=null,s=n&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(t.options.cwd)}catch{}let i;try{i=Ns.sync(t.command,{path:r[Fs({env:r})],pathExt:e?fo.delimiter:void 0})}catch{}finally{s&&process.chdir(o)}return i&&(i=fo.resolve(n?t.options.cwd:"",i)),i}function _s(t){return po(t)||po(t,!0)}var Ls=_s,Ht={};const Ut=/([()\][%!^"`<>&|;, *?])/g;function Ts(t){return t=t.replace(Ut,"^$1"),t}function js(t,e){return t=`${t}`,t=t.replace(/(?=(\\+?)?)\1"/g,'$1$1\\"'),t=t.replace(/(?=(\\+?)?)\1$/,"$1$1"),t=`"${t}"`,t=t.replace(Ut,"^$1"),e&&(t=t.replace(Ut,"^$1")),t}Ht.command=Ts,Ht.argument=js;var Bs=/^#!(.*)/;const Gs=Bs;var Hs=(t="")=>{const e=t.match(Gs);if(!e)return null;const[r,o]=e[0].replace(/#! ?/,"").split(" "),n=r.split("/").pop();return n==="env"?o:o?`${n} ${o}`:n};const zt=X,Us=Hs;function zs(t){const r=Buffer.alloc(150);let o;try{o=zt.openSync(t,"r"),zt.readSync(o,r,0,150,0),zt.closeSync(o)}catch{}return Us(r.toString())}var Ks=zs;const Ws=x,ho=Ls,go=Ht,Ys=Ks,Js=process.platform==="win32",Vs=/\.(?:com|exe)$/i,qs=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function Xs(t){t.file=ho(t);const e=t.file&&Ys(t.file);return e?(t.args.unshift(t.file),t.command=e,ho(t)):t.file}function Qs(t){if(!Js)return t;const e=Xs(t),r=!Vs.test(e);if(t.options.forceShell||r){const o=qs.test(e);t.command=Ws.normalize(t.command),t.command=go.command(t.command),t.args=t.args.map(s=>go.argument(s,o));const n=[t.command].concat(t.args).join(" ");t.args=["/d","/s","/c",`"${n}"`],t.command=process.env.comspec||"cmd.exe",t.options.windowsVerbatimArguments=!0}return t}function Zs(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[],r=Object.assign({},r);const o={command:t,args:e,options:r,file:void 0,original:{command:t,args:e}};return r.shell?o:Qs(o)}var ei=Zs;const Kt=process.platform==="win32";function Wt(t,e){return Object.assign(new Error(`${e} ${t.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${t.command}`,path:t.command,spawnargs:t.args})}function ti(t,e){if(!Kt)return;const r=t.emit;t.emit=function(o,n){if(o==="exit"){const s=yo(n,e);if(s)return r.call(t,"error",s)}return r.apply(t,arguments)}}function yo(t,e){return Kt&&t===1&&!e.file?Wt(e.original,"spawn"):null}function ri(t,e){return Kt&&t===1&&!e.file?Wt(e.original,"spawnSync"):null}var oi={hookChildProcess:ti,verifyENOENT:yo,verifyENOENTSync:ri,notFoundError:Wt};const wo=Nn,Yt=ei,Jt=oi;function vo(t,e,r){const o=Yt(t,e,r),n=wo.spawn(o.command,o.args,o.options);return Jt.hookChildProcess(n,o),n}function ni(t,e,r){const o=Yt(t,e,r),n=wo.spawnSync(o.command,o.args,o.options);return n.error=n.error||Jt.verifyENOENTSync(n.status,o),n}Pe.exports=vo,Pe.exports.spawn=vo,Pe.exports.sync=ni,Pe.exports._parse=Yt,Pe.exports._enoent=Jt;var si=Pe.exports,ii=Ee(si);function ai(t){const e=typeof t=="string"?`
|
|
2
|
+
import{command as de,cli as Mn}from"cleye";import{createRequire as Rn}from"module";import Dn from"crypto";import X from"fs";import Fe from"os";import x from"path";import{Buffer as Tr}from"node:buffer";import ge from"node:path";import Rt,{ChildProcess as jr,exec as On}from"node:child_process";import ae from"node:process";import Nn,{execSync as Ze,exec as Fn}from"child_process";import{fileURLToPath as Br}from"node:url";import _n,{constants as Gr}from"node:os";import Hr from"assert";import Ur from"events";import{createWriteStream as Ln,createReadStream as Tn,readFileSync as jn}from"node:fs";import Bn from"buffer";import Dt from"stream";import zr,{promisify as Gn}from"util";import{debuglog as Hn,promisify as Un}from"node:util";import et from"inquirer";import{of as Ot,concatMap as F,from as D,map as O,catchError as N,mergeMap as Kr,BehaviorSubject as Wr,ReplaySubject as zn,Subscription as Nt,lastValueFrom as Ft,toArray as _t,filter as Yr,Subject as Lt}from"rxjs";import _ from"fs/promises";import C from"chalk";import Kn from"@anthropic-ai/sdk";import{fromPromise as L}from"rxjs/internal/observable/innerFrom";import{xxh64 as Jr}from"@pacote/xxhash";import U from"winston";import"winston-daily-rotate-file";import Vr from"https";import Wn from"axios";import{CohereClientV2 as Yn}from"cohere-ai";import qr from"openai";import{GoogleGenerativeAI as Jn,HarmCategory as tt,HarmBlockThreshold as rt}from"@google/generative-ai";import Vn from"http";import qn from"net";import Xn from"tls";import Qn,{fileURLToPath as Zn,pathToFileURL as es}from"url";import Xr from"tty";import ts from"groq-sdk";import{Ollama as rs}from"ollama";import{fetch as os,Agent as ns}from"undici";import ot from"readline";import Qr from"figlet";import ss from"gradient-string";import Zr from"ora";import is from"inquirer-reactive-list-prompt";import{readdir as eo,stat as as,rm as cs}from"node:fs/promises";import ls from"chokidar";import{takeUntil as to,finalize as ro}from"rxjs/operators";var us="aicommit2",oo="2.4.28",ds="A Reactive CLI that generates commit messages for Git and Jujutsu with various AI",ms=["cli","ai","git","jujutsu","jj","vcs","version-control","commit","git-commit","jujutsu-commit","command-line","commandline","aipick","aicommit","aicommits","aicommit2","openai","huggingface","anthropic","claude","claude3","gemini","gemini-pro","generative-ai","mistral","ollama","llama3","llama3.2","llama3.3","gemma","llm","chatgpt","cohere","groq","codestral","perplexity","deepseek","deepseek-r1","pre-commit"],fs="MIT",ps="tak-bro/aicommit2",hs="Hyungtak Jin(@tak-bro)",gs="module",ys=["dist"],ws={aicommit2:"./dist/cli.mjs",aic2:"./dist/cli.mjs"},vs={prepare:"simple-git-hooks",build:"pkgroll --minify",lint:"eslint --cache .","type-check":"tsc",test:"tsx tests",prepack:"pnpm build && clean-pkg-json",prettier:"prettier"},Cs={"@anthropic-ai/sdk":"^0.39.0","@aws-sdk/client-bedrock-runtime":"^3.678.0","@aws-sdk/credential-providers":"^3.678.0","@dqbd/tiktoken":"^1.0.21","@google/generative-ai":"^0.24.1","@inquirer/prompts":"^3.3.2","@pacote/xxhash":"^0.3.2","@types/winston":"^2.4.4",axios:"^1.9.0",chalk:"^5.4.1",chokidar:"^4.0.3",cleye:"^1.3.4","cohere-ai":"^7.19.0","copy-paste":"^1.5.3",figlet:"^1.8.1","formdata-node":"^6.0.3","gradient-string":"^3.0.0","groq-sdk":"^0.7.0",inquirer:"9.2.8","inquirer-reactive-list-prompt":"^1.0.16",ollama:"^0.5.15",openai:"^6.3.0",ora:"^8.2.0",readline:"^1.3.0",rxjs:"^7.8.2",undici:"^7.10.0",uuid:"^9.0.1",winston:"^3.17.0","winston-daily-rotate-file":"^5.0.0"},bs={"@pvtnbr/eslint-config":"^0.33.0","@semantic-release/changelog":"^6.0.3","@semantic-release/commit-analyzer":"^12.0.0","@semantic-release/git":"^10.0.1","@semantic-release/github":"^10.3.5","@semantic-release/npm":"^12.0.1","@semantic-release/release-notes-generator":"^13.0.0","@types/figlet":"^1.7.0","@types/ini":"^1.3.34","@types/inquirer":"^9.0.8","@types/node":"^18.19.103","@types/uuid":"^9.0.8","@typescript-eslint/eslint-plugin":"^6.21.0","@typescript-eslint/parser":"^6.21.0","clean-pkg-json":"^1.3.0","conventional-changelog-conventionalcommits":"^7.0.2","conventional-commits-parser":"^5.0.0",eslint:"^8.57.1","eslint-config-prettier":"^8.10.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","eslint-plugin-jsonc":"^2.20.1","eslint-plugin-no-use-extend-native":"^0.5.0","eslint-plugin-promise":"^6.6.0","eslint-plugin-unicorn":"^49.0.0","eslint-plugin-unused-imports":"^3.2.0",execa:"^7.2.0","fs-fixture":"^1.2.0","https-proxy-agent":"^5.0.1",ini:"^3.0.1","lint-staged":"^13.3.0",manten:"^0.7.0",pkgroll:"^1.11.1",prettier:"^3.5.3","semantic-release":"^23.1.1","simple-git-hooks":"^2.13.0",tsx:"^3.14.0",typescript:"^4.9.5","undici-types":"^7.10.0"},Es={extends:["@pvtnbr","prettier"],rules:{"unicorn/no-process-exit":"off"},overrides:[{files:"./src/commands/prepare-commit-msg-hook.ts",rules:{"unicorn/prevent-abbreviations":"off"}}]},Ps={branches:["main"],plugins:[["@semantic-release/commit-analyzer",{preset:"conventionalcommits",releaseRules:[{type:"refactor",release:"patch"},{type:"chore",release:"patch"},{type:"feat",release:"patch"},{scope:"major",release:"major"},{scope:"minor",release:"minor"},{scope:"patch",release:"patch"}]}],"@semantic-release/release-notes-generator",["@semantic-release/changelog",{changelogFile:"CHANGELOG.md"}],"@semantic-release/github",["@semantic-release/git",{assets:["CHANGELOG.md"],message:"chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"}],"@semantic-release/npm"]},$s={name:us,version:oo,description:ds,keywords:ms,license:fs,repository:ps,author:hs,type:gs,files:ys,bin:ws,scripts:vs,"simple-git-hooks":{"pre-commit":"pnpm lint-staged"},"lint-staged":{"*.ts":["prettier --config ./.prettierrc --write","eslint --fix"]},dependencies:Cs,devDependencies:bs,eslintConfig:Es,release:Ps},As=Rn(import.meta.url),H=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function Ee(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var Pe={exports:{}},Tt,no;function ks(){if(no)return Tt;no=1,Tt=o,o.sync=n;var t=X;function e(s,i){var l=i.pathExt!==void 0?i.pathExt:process.env.PATHEXT;if(!l||(l=l.split(";"),l.indexOf("")!==-1))return!0;for(var a=0;a<l.length;a++){var d=l[a].toLowerCase();if(d&&s.substr(-d.length).toLowerCase()===d)return!0}return!1}function r(s,i,l){return!s.isSymbolicLink()&&!s.isFile()?!1:e(i,l)}function o(s,i,l){t.stat(s,function(a,d){l(a,a?!1:r(d,s,i))})}function n(s,i){return r(t.statSync(s),s,i)}return Tt}var jt,so;function Ss(){if(so)return jt;so=1,jt=e,e.sync=r;var t=X;function e(s,i,l){t.stat(s,function(a,d){l(a,a?!1:o(d,i))})}function r(s,i){return o(t.statSync(s),i)}function o(s,i){return s.isFile()&&n(s,i)}function n(s,i){var l=s.mode,a=s.uid,d=s.gid,c=i.uid!==void 0?i.uid:process.getuid&&process.getuid(),u=i.gid!==void 0?i.gid:process.getgid&&process.getgid(),f=parseInt("100",8),p=parseInt("010",8),h=parseInt("001",8),g=f|p,y=l&h||l&p&&d===u||l&f&&a===c||l&g&&c===0;return y}return jt}var nt;process.platform==="win32"||H.TESTING_WINDOWS?nt=ks():nt=Ss();var xs=Bt;Bt.sync=Is;function Bt(t,e,r){if(typeof e=="function"&&(r=e,e={}),!r){if(typeof Promise!="function")throw new TypeError("callback not provided");return new Promise(function(o,n){Bt(t,e||{},function(s,i){s?n(s):o(i)})})}nt(t,e||{},function(o,n){o&&(o.code==="EACCES"||e&&e.ignoreErrors)&&(o=null,n=!1),r(o,n)})}function Is(t,e){try{return nt.sync(t,e||{})}catch(r){if(e&&e.ignoreErrors||r.code==="EACCES")return!1;throw r}}const $e=process.platform==="win32"||process.env.OSTYPE==="cygwin"||process.env.OSTYPE==="msys",io=x,Ms=$e?";":":",ao=xs,co=t=>Object.assign(new Error(`not found: ${t}`),{code:"ENOENT"}),lo=(t,e)=>{const r=e.colon||Ms,o=t.match(/\//)||$e&&t.match(/\\/)?[""]:[...$e?[process.cwd()]:[],...(e.path||process.env.PATH||"").split(r)],n=$e?e.pathExt||process.env.PATHEXT||".EXE;.CMD;.BAT;.COM":"",s=$e?n.split(r):[""];return $e&&t.indexOf(".")!==-1&&s[0]!==""&&s.unshift(""),{pathEnv:o,pathExt:s,pathExtExe:n}},uo=(t,e,r)=>{typeof e=="function"&&(r=e,e={}),e||(e={});const{pathEnv:o,pathExt:n,pathExtExe:s}=lo(t,e),i=[],l=d=>new Promise((c,u)=>{if(d===o.length)return e.all&&i.length?c(i):u(co(t));const f=o[d],p=/^".*"$/.test(f)?f.slice(1,-1):f,h=io.join(p,t),g=!p&&/^\.[\\\/]/.test(t)?t.slice(0,2)+h:h;c(a(g,d,0))}),a=(d,c,u)=>new Promise((f,p)=>{if(u===n.length)return f(l(c+1));const h=n[u];ao(d+h,{pathExt:s},(g,y)=>{if(!g&&y)if(e.all)i.push(d+h);else return f(d+h);return f(a(d,c,u+1))})});return r?l(0).then(d=>r(null,d),r):l(0)},Rs=(t,e)=>{e=e||{};const{pathEnv:r,pathExt:o,pathExtExe:n}=lo(t,e),s=[];for(let i=0;i<r.length;i++){const l=r[i],a=/^".*"$/.test(l)?l.slice(1,-1):l,d=io.join(a,t),c=!a&&/^\.[\\\/]/.test(t)?t.slice(0,2)+d:d;for(let u=0;u<o.length;u++){const f=c+o[u];try{if(ao.sync(f,{pathExt:n}))if(e.all)s.push(f);else return f}catch{}}}if(e.all&&s.length)return s;if(e.nothrow)return null;throw co(t)};var Ds=uo;uo.sync=Rs;var Gt={exports:{}};const mo=(t={})=>{const e=t.env||process.env;return(t.platform||process.platform)!=="win32"?"PATH":Object.keys(e).reverse().find(o=>o.toUpperCase()==="PATH")||"Path"};Gt.exports=mo,Gt.exports.default=mo;var Os=Gt.exports;const fo=x,Ns=Ds,Fs=Os;function po(t,e){const r=t.options.env||process.env,o=process.cwd(),n=t.options.cwd!=null,s=n&&process.chdir!==void 0&&!process.chdir.disabled;if(s)try{process.chdir(t.options.cwd)}catch{}let i;try{i=Ns.sync(t.command,{path:r[Fs({env:r})],pathExt:e?fo.delimiter:void 0})}catch{}finally{s&&process.chdir(o)}return i&&(i=fo.resolve(n?t.options.cwd:"",i)),i}function _s(t){return po(t)||po(t,!0)}var Ls=_s,Ht={};const Ut=/([()\][%!^"`<>&|;, *?])/g;function Ts(t){return t=t.replace(Ut,"^$1"),t}function js(t,e){return t=`${t}`,t=t.replace(/(?=(\\+?)?)\1"/g,'$1$1\\"'),t=t.replace(/(?=(\\+?)?)\1$/,"$1$1"),t=`"${t}"`,t=t.replace(Ut,"^$1"),e&&(t=t.replace(Ut,"^$1")),t}Ht.command=Ts,Ht.argument=js;var Bs=/^#!(.*)/;const Gs=Bs;var Hs=(t="")=>{const e=t.match(Gs);if(!e)return null;const[r,o]=e[0].replace(/#! ?/,"").split(" "),n=r.split("/").pop();return n==="env"?o:o?`${n} ${o}`:n};const zt=X,Us=Hs;function zs(t){const r=Buffer.alloc(150);let o;try{o=zt.openSync(t,"r"),zt.readSync(o,r,0,150,0),zt.closeSync(o)}catch{}return Us(r.toString())}var Ks=zs;const Ws=x,ho=Ls,go=Ht,Ys=Ks,Js=process.platform==="win32",Vs=/\.(?:com|exe)$/i,qs=/node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;function Xs(t){t.file=ho(t);const e=t.file&&Ys(t.file);return e?(t.args.unshift(t.file),t.command=e,ho(t)):t.file}function Qs(t){if(!Js)return t;const e=Xs(t),r=!Vs.test(e);if(t.options.forceShell||r){const o=qs.test(e);t.command=Ws.normalize(t.command),t.command=go.command(t.command),t.args=t.args.map(s=>go.argument(s,o));const n=[t.command].concat(t.args).join(" ");t.args=["/d","/s","/c",`"${n}"`],t.command=process.env.comspec||"cmd.exe",t.options.windowsVerbatimArguments=!0}return t}function Zs(t,e,r){e&&!Array.isArray(e)&&(r=e,e=null),e=e?e.slice(0):[],r=Object.assign({},r);const o={command:t,args:e,options:r,file:void 0,original:{command:t,args:e}};return r.shell?o:Qs(o)}var ei=Zs;const Kt=process.platform==="win32";function Wt(t,e){return Object.assign(new Error(`${e} ${t.command} ENOENT`),{code:"ENOENT",errno:"ENOENT",syscall:`${e} ${t.command}`,path:t.command,spawnargs:t.args})}function ti(t,e){if(!Kt)return;const r=t.emit;t.emit=function(o,n){if(o==="exit"){const s=yo(n,e);if(s)return r.call(t,"error",s)}return r.apply(t,arguments)}}function yo(t,e){return Kt&&t===1&&!e.file?Wt(e.original,"spawn"):null}function ri(t,e){return Kt&&t===1&&!e.file?Wt(e.original,"spawnSync"):null}var oi={hookChildProcess:ti,verifyENOENT:yo,verifyENOENTSync:ri,notFoundError:Wt};const wo=Nn,Yt=ei,Jt=oi;function vo(t,e,r){const o=Yt(t,e,r),n=wo.spawn(o.command,o.args,o.options);return Jt.hookChildProcess(n,o),n}function ni(t,e,r){const o=Yt(t,e,r),n=wo.spawnSync(o.command,o.args,o.options);return n.error=n.error||Jt.verifyENOENTSync(n.status,o),n}Pe.exports=vo,Pe.exports.spawn=vo,Pe.exports.sync=ni,Pe.exports._parse=Yt,Pe.exports._enoent=Jt;var si=Pe.exports,ii=Ee(si);function ai(t){const e=typeof t=="string"?`
|
|
3
3
|
`:`
|
|
4
4
|
`.charCodeAt(),r=typeof t=="string"?"\r":"\r".charCodeAt();return t[t.length-1]===e&&(t=t.slice(0,-1)),t[t.length-1]===r&&(t=t.slice(0,-1)),t}function Co(t={}){const{env:e=process.env,platform:r=process.platform}=t;return r!=="win32"?"PATH":Object.keys(e).reverse().find(o=>o.toUpperCase()==="PATH")||"Path"}const ci=({cwd:t=ae.cwd(),path:e=ae.env[Co()],preferLocal:r=!0,execPath:o=ae.execPath,addExecPath:n=!0}={})=>{const s=t instanceof URL?Br(t):t,i=ge.resolve(s),l=[];return r&&li(l,i),n&&ui(l,o,i),[...l,e].join(ge.delimiter)},li=(t,e)=>{let r;for(;r!==e;)t.push(ge.join(e,"node_modules/.bin")),r=e,e=ge.resolve(e,"..")},ui=(t,e,r)=>{const o=e instanceof URL?Br(e):e;t.push(ge.resolve(r,o,".."))},di=({env:t=ae.env,...e}={})=>{t={...t};const r=Co({env:t});return e.path=t[r],t[r]=ci(e),t},mi=(t,e,r,o)=>{if(r==="length"||r==="prototype"||r==="arguments"||r==="caller")return;const n=Object.getOwnPropertyDescriptor(t,r),s=Object.getOwnPropertyDescriptor(e,r);!fi(n,s)&&o||Object.defineProperty(t,r,s)},fi=function(t,e){return t===void 0||t.configurable||t.writable===e.writable&&t.enumerable===e.enumerable&&t.configurable===e.configurable&&(t.writable||t.value===e.value)},pi=(t,e)=>{const r=Object.getPrototypeOf(e);r!==Object.getPrototypeOf(t)&&Object.setPrototypeOf(t,r)},hi=(t,e)=>`/* Wrapped ${t}*/
|
|
5
5
|
${e}`,gi=Object.getOwnPropertyDescriptor(Function.prototype,"toString"),yi=Object.getOwnPropertyDescriptor(Function.prototype.toString,"name"),wi=(t,e,r)=>{const o=r===""?"":`with ${r.trim()}() `,n=hi.bind(null,o,e.toString());Object.defineProperty(n,"name",yi),Object.defineProperty(t,"toString",{...gi,value:n})};function vi(t,e,{ignoreNonConfigurable:r=!1}={}){const{name:o}=t;for(const n of Reflect.ownKeys(e))mi(t,e,n,r);return pi(t,e),wi(t,e,o),t}const st=new WeakMap,bo=(t,e={})=>{if(typeof t!="function")throw new TypeError("Expected a function");let r,o=0;const n=t.displayName||t.name||"<anonymous>",s=function(...i){if(st.set(s,++o),o===1)r=t.apply(this,i),t=null;else if(e.throw===!0)throw new Error(`Function \`${n}\` can only be called once`);return r};return vi(s,t),st.set(s,o),s};bo.callCount=t=>{if(!st.has(t))throw new Error(`The given function \`${t.name}\` is not wrapped by the \`onetime\` package`);return st.get(t)};const Ci=()=>{const t=Po-Eo+1;return Array.from({length:t},bi)},bi=(t,e)=>({name:`SIGRT${e+1}`,number:Eo+e,action:"terminate",description:"Application-specific signal (realtime)",standard:"posix"}),Eo=34,Po=64,Ei=[{name:"SIGHUP",number:1,action:"terminate",description:"Terminal closed",standard:"posix"},{name:"SIGINT",number:2,action:"terminate",description:"User interruption with CTRL-C",standard:"ansi"},{name:"SIGQUIT",number:3,action:"core",description:"User interruption with CTRL-\\",standard:"posix"},{name:"SIGILL",number:4,action:"core",description:"Invalid machine instruction",standard:"ansi"},{name:"SIGTRAP",number:5,action:"core",description:"Debugger breakpoint",standard:"posix"},{name:"SIGABRT",number:6,action:"core",description:"Aborted",standard:"ansi"},{name:"SIGIOT",number:6,action:"core",description:"Aborted",standard:"bsd"},{name:"SIGBUS",number:7,action:"core",description:"Bus error due to misaligned, non-existing address or paging error",standard:"bsd"},{name:"SIGEMT",number:7,action:"terminate",description:"Command should be emulated but is not implemented",standard:"other"},{name:"SIGFPE",number:8,action:"core",description:"Floating point arithmetic error",standard:"ansi"},{name:"SIGKILL",number:9,action:"terminate",description:"Forced termination",standard:"posix",forced:!0},{name:"SIGUSR1",number:10,action:"terminate",description:"Application-specific signal",standard:"posix"},{name:"SIGSEGV",number:11,action:"core",description:"Segmentation fault",standard:"ansi"},{name:"SIGUSR2",number:12,action:"terminate",description:"Application-specific signal",standard:"posix"},{name:"SIGPIPE",number:13,action:"terminate",description:"Broken pipe or socket",standard:"posix"},{name:"SIGALRM",number:14,action:"terminate",description:"Timeout or timer",standard:"posix"},{name:"SIGTERM",number:15,action:"terminate",description:"Termination",standard:"ansi"},{name:"SIGSTKFLT",number:16,action:"terminate",description:"Stack is empty or overflowed",standard:"other"},{name:"SIGCHLD",number:17,action:"ignore",description:"Child process terminated, paused or unpaused",standard:"posix"},{name:"SIGCLD",number:17,action:"ignore",description:"Child process terminated, paused or unpaused",standard:"other"},{name:"SIGCONT",number:18,action:"unpause",description:"Unpaused",standard:"posix",forced:!0},{name:"SIGSTOP",number:19,action:"pause",description:"Paused",standard:"posix",forced:!0},{name:"SIGTSTP",number:20,action:"pause",description:'Paused using CTRL-Z or "suspend"',standard:"posix"},{name:"SIGTTIN",number:21,action:"pause",description:"Background process cannot read terminal input",standard:"posix"},{name:"SIGBREAK",number:21,action:"terminate",description:"User interruption with CTRL-BREAK",standard:"other"},{name:"SIGTTOU",number:22,action:"pause",description:"Background process cannot write to terminal output",standard:"posix"},{name:"SIGURG",number:23,action:"ignore",description:"Socket received out-of-band data",standard:"bsd"},{name:"SIGXCPU",number:24,action:"core",description:"Process timed out",standard:"bsd"},{name:"SIGXFSZ",number:25,action:"core",description:"File too big",standard:"bsd"},{name:"SIGVTALRM",number:26,action:"terminate",description:"Timeout or timer",standard:"bsd"},{name:"SIGPROF",number:27,action:"terminate",description:"Timeout or timer",standard:"bsd"},{name:"SIGWINCH",number:28,action:"ignore",description:"Terminal window size changed",standard:"bsd"},{name:"SIGIO",number:29,action:"terminate",description:"I/O is available",standard:"other"},{name:"SIGPOLL",number:29,action:"terminate",description:"Watched event",standard:"other"},{name:"SIGINFO",number:29,action:"ignore",description:"Request for process information",standard:"other"},{name:"SIGPWR",number:30,action:"terminate",description:"Device running out of power",standard:"systemv"},{name:"SIGSYS",number:31,action:"core",description:"Invalid system call",standard:"other"},{name:"SIGUNUSED",number:31,action:"terminate",description:"Invalid system call",standard:"other"}],$o=()=>{const t=Ci();return[...Ei,...t].map(Pi)},Pi=({name:t,number:e,description:r,action:o,forced:n=!1,standard:s})=>{const{signals:{[t]:i}}=Gr,l=i!==void 0;return{name:t,number:l?i:e,description:r,supported:l,action:o,forced:n,standard:s}},$i=()=>{const t=$o();return Object.fromEntries(t.map(Ai))},Ai=({name:t,number:e,description:r,supported:o,action:n,forced:s,standard:i})=>[t,{name:t,number:e,description:r,supported:o,action:n,forced:s,standard:i}],ki=$i(),Si=()=>{const t=$o(),e=Po+1,r=Array.from({length:e},(o,n)=>xi(n,t));return Object.assign({},...r)},xi=(t,e)=>{const r=Ii(t,e);if(r===void 0)return{};const{name:o,description:n,supported:s,action:i,forced:l,standard:a}=r;return{[t]:{name:o,number:t,description:n,supported:s,action:i,forced:l,standard:a}}},Ii=(t,e)=>{const r=e.find(({name:o})=>Gr.signals[o]===t);return r!==void 0?r:e.find(o=>o.number===t)};Si();const Mi=({timedOut:t,timeout:e,errorCode:r,signal:o,signalDescription:n,exitCode:s,isCanceled:i})=>t?`timed out after ${e} milliseconds`:i?"was canceled":r!==void 0?`failed with ${r}`:o!==void 0?`was killed with ${o} (${n})`:s!==void 0?`failed with exit code ${s}`:"failed",it=({stdout:t,stderr:e,all:r,error:o,signal:n,exitCode:s,command:i,escapedCommand:l,timedOut:a,isCanceled:d,killed:c,parsed:{options:{timeout:u,cwd:f=ae.cwd()}}})=>{s=s===null?void 0:s,n=n===null?void 0:n;const p=n===void 0?void 0:ki[n].description,h=o&&o.code,y=`Command ${Mi({timedOut:a,timeout:u,errorCode:h,signal:n,signalDescription:p,exitCode:s,isCanceled:d})}: ${i}`,v=Object.prototype.toString.call(o)==="[object Error]",E=v?`${y}
|
|
@@ -123,7 +123,7 @@ Please install Jujutsu:
|
|
|
123
123
|
- macOS: brew install jj
|
|
124
124
|
- Linux: cargo install jj-cli
|
|
125
125
|
- Windows: cargo install jj-cli
|
|
126
|
-
- See: https://github.com/
|
|
126
|
+
- See: https://github.com/jj-vcs/jj#installation`):new w(`Failed to execute jj command: ${r.message}`)}try{const{stdout:e,stderr:r}=await S("jj",["workspace","root"],{reject:!0}),o=e.trim();if(!o)throw new w("jj workspace root returned empty path");const n=x.join(o,".jj");if(!X.existsSync(n))throw new w(`Jujutsu repository directory not found at ${n}
|
|
127
127
|
|
|
128
128
|
Initialize a jj repository with: jj init`);return o}catch(e){if(e instanceof w)throw e;const r=e;throw r.stderr?r.stderr.includes("not in a jj repo")?new w(`Not in a Jujutsu repository!
|
|
129
129
|
|