@kud/ai-conventional-commit-cli 0.5.0 → 0.7.0
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 +47 -18
- package/dist/chunk-DCGUX6KW.js +95 -0
- package/dist/config-Q7AKJSO4.js +12 -0
- package/dist/index.js +291 -111
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
<a href="https://www.conventionalcommits.org"><img alt="Conventional Commits" src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-yellow.svg" /></a>
|
|
14
14
|
</p>
|
|
15
15
|
|
|
16
|
-
> TL;DR: Stage your changes, run `ai-conventional-commit` (or `split` for multiple commits), accept, done. Add `--gitmoji` if you like emoji. Refine later with `refine`.
|
|
16
|
+
> TL;DR: Stage your changes, run `ai-conventional-commit` (or `split` for multiple commits), accept, done. Add `--style gitmoji` if you like emoji. Refine later with `refine`.
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
@@ -101,11 +101,11 @@ ai-conventional-commit
|
|
|
101
101
|
# Propose multiple commits (interactive confirm + real selective staging)
|
|
102
102
|
ai-conventional-commit split
|
|
103
103
|
|
|
104
|
-
# Add emoji decorations
|
|
105
|
-
ai-conventional-commit --gitmoji
|
|
104
|
+
# Add emoji decorations (gitmoji)
|
|
105
|
+
ai-conventional-commit --style gitmoji
|
|
106
106
|
|
|
107
107
|
# Pure emoji style (emoji: subject)
|
|
108
|
-
ai-conventional-commit --gitmoji-pure
|
|
108
|
+
ai-conventional-commit --style gitmoji-pure
|
|
109
109
|
|
|
110
110
|
# Refine previous session's first commit (shorter wording)
|
|
111
111
|
ai-conventional-commit refine --shorter
|
|
@@ -113,20 +113,23 @@ ai-conventional-commit refine --shorter
|
|
|
113
113
|
|
|
114
114
|
## Command Reference
|
|
115
115
|
|
|
116
|
-
| Command
|
|
117
|
-
|
|
|
118
|
-
| `ai-conventional-commit`
|
|
119
|
-
| `ai-conventional-commit generate`
|
|
120
|
-
| `ai-conventional-commit split`
|
|
121
|
-
| `ai-conventional-commit refine`
|
|
116
|
+
| Command | Purpose |
|
|
117
|
+
| ------------------------------------ | ------------------------------------------- |
|
|
118
|
+
| `ai-conventional-commit` | Generate single commit suggestion (default) |
|
|
119
|
+
| `ai-conventional-commit generate` | Explicit alias of root |
|
|
120
|
+
| `ai-conventional-commit split` | Propose & execute multiple commits |
|
|
121
|
+
| `ai-conventional-commit refine` | Refine last session (or indexed) commit |
|
|
122
|
+
| `ai-conventional-commit models` | List / pick models, save default |
|
|
123
|
+
| `ai-conventional-commit config show` | Show merged config + sources |
|
|
124
|
+
| `ai-conventional-commit config get` | Get a single config value |
|
|
125
|
+
| `ai-conventional-commit config set` | Persist a global config value |
|
|
122
126
|
|
|
123
127
|
Helpful flags:
|
|
124
128
|
|
|
125
|
-
- `--
|
|
129
|
+
- `--style <standard|gitmoji|gitmoji-pure>`
|
|
126
130
|
- `--model <provider/name>` (override)
|
|
127
131
|
- `--scope <scope>` (refine)
|
|
128
132
|
- `--shorter` / `--longer`
|
|
129
|
-
- `--emoji` (add appropriate emoji in refine)
|
|
130
133
|
|
|
131
134
|
## Examples
|
|
132
135
|
|
|
@@ -163,7 +166,7 @@ $ ai-conventional-commit refine --scope cli --shorter
|
|
|
163
166
|
| gitmoji | `✨ feat: add search box` | Emoji + type retained |
|
|
164
167
|
| gitmoji-pure | `✨: add search box` | Type removed; emoji acts as category |
|
|
165
168
|
|
|
166
|
-
Enable via CLI
|
|
169
|
+
Enable via CLI flag `--style gitmoji|gitmoji-pure` or config `"style": "gitmoji"` / `"style": "gitmoji-pure"`.
|
|
167
170
|
|
|
168
171
|
## Privacy Modes
|
|
169
172
|
|
|
@@ -181,10 +184,9 @@ Resolves via cosmiconfig (JSON/YAML/etc). Example:
|
|
|
181
184
|
|
|
182
185
|
```json
|
|
183
186
|
{
|
|
184
|
-
"model": "github-copilot/gpt-
|
|
187
|
+
"model": "github-copilot/gpt-4.1",
|
|
185
188
|
"privacy": "low",
|
|
186
|
-
"
|
|
187
|
-
"gitmojiMode": "gitmoji",
|
|
189
|
+
"style": "gitmoji",
|
|
188
190
|
"styleSamples": 120,
|
|
189
191
|
"plugins": ["./src/sample-plugin/example-plugin.ts"],
|
|
190
192
|
"maxTokens": 512
|
|
@@ -192,12 +194,39 @@ Resolves via cosmiconfig (JSON/YAML/etc). Example:
|
|
|
192
194
|
```
|
|
193
195
|
|
|
194
196
|
Environment overrides (prefix `AICC_`):
|
|
195
|
-
|
|
197
|
+
|
|
198
|
+
### Configuration Precedence
|
|
199
|
+
|
|
200
|
+
Lowest to highest (later wins):
|
|
201
|
+
|
|
202
|
+
1. Built-in defaults
|
|
203
|
+
2. Global config file: `~/.config/ai-conventional-commit-cli/aicc.json` (or `$XDG_CONFIG_HOME`)
|
|
204
|
+
3. Project config (.aiccrc via cosmiconfig)
|
|
205
|
+
4. Environment variables (`AICC_*`)
|
|
206
|
+
5. CLI flags (e.g. `--model`, `--style`)
|
|
207
|
+
|
|
208
|
+
View the resolved configuration:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
ai-conventional-commit config show
|
|
212
|
+
ai-conventional-commit config show --json | jq
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Manage models:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
ai-conventional-commit models # list (opencode pass-through)
|
|
219
|
+
ai-conventional-commit models --interactive # interactive picker
|
|
220
|
+
ai-conventional-commit models --interactive --save # pick + persist globally
|
|
221
|
+
ai-conventional-commit models --current # show active model + source
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
`MODEL`, `PRIVACY`, `STYLE`, `STYLE_SAMPLES`, `MAX_TOKENS`, `VERBOSE`, `MODEL_TIMEOUT_MS`, `DEBUG`, `PRINT_LOGS`, `DEBUG_PROVIDER=mock`.
|
|
196
225
|
|
|
197
226
|
## Refinement Workflow
|
|
198
227
|
|
|
199
228
|
1. Generate (`ai-conventional-commit` or `split`) – session cached under `.git/.aicc-cache/last-session.json`.
|
|
200
|
-
2. Run `refine` with flags (`--shorter`, `--longer`, `--scope=ui
|
|
229
|
+
2. Run `refine` with flags (`--shorter`, `--longer`, `--scope=ui`).
|
|
201
230
|
3. Accept or reject; refined output does _not_ auto‑amend history until you use it.
|
|
202
231
|
|
|
203
232
|
## Plugin API
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
import { cosmiconfig } from "cosmiconfig";
|
|
3
|
+
import { resolve, dirname, join } from "path";
|
|
4
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
5
|
+
import { homedir } from "os";
|
|
6
|
+
var DEFAULTS = {
|
|
7
|
+
model: process.env.AICC_MODEL || "github-copilot/gpt-4.1",
|
|
8
|
+
privacy: process.env.AICC_PRIVACY || "low",
|
|
9
|
+
style: process.env.AICC_STYLE || "standard",
|
|
10
|
+
styleSamples: parseInt(process.env.AICC_STYLE_SAMPLES || "120", 10),
|
|
11
|
+
maxTokens: parseInt(process.env.AICC_MAX_TOKENS || "512", 10),
|
|
12
|
+
cacheDir: ".git/.aicc-cache",
|
|
13
|
+
plugins: [],
|
|
14
|
+
verbose: process.env.AICC_VERBOSE === "true"
|
|
15
|
+
};
|
|
16
|
+
function getGlobalConfigPath() {
|
|
17
|
+
const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
|
|
18
|
+
return resolve(base, "ai-conventional-commit-cli", "aicc.json");
|
|
19
|
+
}
|
|
20
|
+
function saveGlobalConfig(partial) {
|
|
21
|
+
const filePath = getGlobalConfigPath();
|
|
22
|
+
const dir = dirname(filePath);
|
|
23
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
24
|
+
let existing = {};
|
|
25
|
+
if (existsSync(filePath)) {
|
|
26
|
+
try {
|
|
27
|
+
existing = JSON.parse(readFileSync(filePath, "utf8")) || {};
|
|
28
|
+
} catch (e) {
|
|
29
|
+
if (process.env.AICC_VERBOSE === "true") {
|
|
30
|
+
console.error("[ai-cc] Failed to parse existing global config, overwriting.");
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const merged = { ...existing, ...partial };
|
|
35
|
+
writeFileSync(filePath, JSON.stringify(merged, null, 2) + "\n", "utf8");
|
|
36
|
+
return filePath;
|
|
37
|
+
}
|
|
38
|
+
async function loadConfig(cwd = process.cwd()) {
|
|
39
|
+
return (await loadConfigDetailed(cwd)).config;
|
|
40
|
+
}
|
|
41
|
+
async function loadConfigDetailed(cwd = process.cwd()) {
|
|
42
|
+
let globalCfg = {};
|
|
43
|
+
const globalPath = getGlobalConfigPath();
|
|
44
|
+
if (existsSync(globalPath)) {
|
|
45
|
+
try {
|
|
46
|
+
globalCfg = JSON.parse(readFileSync(globalPath, "utf8")) || {};
|
|
47
|
+
} catch (e) {
|
|
48
|
+
if (process.env.AICC_VERBOSE === "true") {
|
|
49
|
+
console.error("[ai-cc] Failed to parse global config, ignoring.");
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
const explorer = cosmiconfig("aicc");
|
|
54
|
+
const result = await explorer.search(cwd);
|
|
55
|
+
const projectCfg = result?.config || {};
|
|
56
|
+
const envCfg = {};
|
|
57
|
+
if (process.env.AICC_MODEL) envCfg.model = process.env.AICC_MODEL;
|
|
58
|
+
if (process.env.AICC_PRIVACY) envCfg.privacy = process.env.AICC_PRIVACY;
|
|
59
|
+
if (process.env.AICC_STYLE) envCfg.style = process.env.AICC_STYLE;
|
|
60
|
+
if (process.env.AICC_STYLE_SAMPLES)
|
|
61
|
+
envCfg.styleSamples = parseInt(process.env.AICC_STYLE_SAMPLES, 10);
|
|
62
|
+
if (process.env.AICC_MAX_TOKENS) envCfg.maxTokens = parseInt(process.env.AICC_MAX_TOKENS, 10);
|
|
63
|
+
if (process.env.AICC_VERBOSE) envCfg.verbose = process.env.AICC_VERBOSE === "true";
|
|
64
|
+
const merged = {
|
|
65
|
+
...DEFAULTS,
|
|
66
|
+
...globalCfg,
|
|
67
|
+
...projectCfg,
|
|
68
|
+
...envCfg
|
|
69
|
+
};
|
|
70
|
+
merged.plugins = (merged.plugins || []).filter((p) => {
|
|
71
|
+
const abs = resolve(cwd, p);
|
|
72
|
+
return existsSync(abs);
|
|
73
|
+
});
|
|
74
|
+
const sources = Object.keys(merged).reduce((acc, key) => {
|
|
75
|
+
const k = key;
|
|
76
|
+
let src = "default";
|
|
77
|
+
if (k in globalCfg) src = "global";
|
|
78
|
+
if (k in projectCfg) src = "project";
|
|
79
|
+
if (k in envCfg) src = "env";
|
|
80
|
+
acc[k] = src;
|
|
81
|
+
return acc;
|
|
82
|
+
}, {});
|
|
83
|
+
const withMeta = Object.assign(merged, { _sources: sources });
|
|
84
|
+
return {
|
|
85
|
+
config: withMeta,
|
|
86
|
+
raw: { defaults: DEFAULTS, global: globalCfg, project: projectCfg, env: envCfg }
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export {
|
|
91
|
+
getGlobalConfigPath,
|
|
92
|
+
saveGlobalConfig,
|
|
93
|
+
loadConfig,
|
|
94
|
+
loadConfigDetailed
|
|
95
|
+
};
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadConfig
|
|
4
|
+
} from "./chunk-DCGUX6KW.js";
|
|
2
5
|
|
|
3
6
|
// src/index.ts
|
|
4
7
|
import { Cli, Command, Option } from "clipanion";
|
|
@@ -195,7 +198,7 @@ var buildGenerationMessages = (opts) => {
|
|
|
195
198
|
);
|
|
196
199
|
specLines.push("Length Rule: Entire title line (including type/scope) must be <= 72 chars.");
|
|
197
200
|
specLines.push(
|
|
198
|
-
"Emoji Rule: " + (config.gitmoji ? "OPTIONAL single leading gitmoji BEFORE the type only if confidently adds clarity; do not invent or stack; omit if unsure." : "Disallow all emojis and gitmoji codes; output must start directly with the type.")
|
|
201
|
+
"Emoji Rule: " + (config.style === "gitmoji" || config.style === "gitmoji-pure" ? "OPTIONAL single leading gitmoji BEFORE the type only if confidently adds clarity; do not invent or stack; omit if unsure." : "Disallow all emojis and gitmoji codes; output must start directly with the type.")
|
|
199
202
|
);
|
|
200
203
|
specLines.push(
|
|
201
204
|
"Forbidden: breaking changes notation, exclamation mark after type unless truly semver-major (avoid unless diff clearly indicates)."
|
|
@@ -244,7 +247,7 @@ var buildRefineMessages = (opts) => {
|
|
|
244
247
|
spec.push("Title Format: <type>(<optional-scope>): <subject> (<=72 chars)");
|
|
245
248
|
spec.push("Subject: imperative, present tense, no trailing period.");
|
|
246
249
|
spec.push(
|
|
247
|
-
"Emoji Rule: " + (config.gitmoji ? "OPTIONAL single leading gitmoji BEFORE type if it adds clarity; omit if unsure." : "Disallow all emojis; start directly with the type.")
|
|
250
|
+
"Emoji Rule: " + (config.style === "gitmoji" || config.style === "gitmoji-pure" ? "OPTIONAL single leading gitmoji BEFORE type if it adds clarity; omit if unsure." : "Disallow all emojis; start directly with the type.")
|
|
248
251
|
);
|
|
249
252
|
spec.push("Preserve semantic meaning; only improve clarity, scope, brevity, conformity.");
|
|
250
253
|
spec.push("If instructions request scope or emoji, incorporate only if justified by content.");
|
|
@@ -266,7 +269,7 @@ Refine now.`
|
|
|
266
269
|
import { z } from "zod";
|
|
267
270
|
import { execa } from "execa";
|
|
268
271
|
var OpenCodeProvider = class {
|
|
269
|
-
constructor(model = "github-copilot/gpt-
|
|
272
|
+
constructor(model = "github-copilot/gpt-4.1") {
|
|
270
273
|
this.model = model;
|
|
271
274
|
}
|
|
272
275
|
name() {
|
|
@@ -275,7 +278,7 @@ var OpenCodeProvider = class {
|
|
|
275
278
|
async chat(messages, _opts) {
|
|
276
279
|
const debug = process.env.AICC_DEBUG === "true";
|
|
277
280
|
const mockMode = process.env.AICC_DEBUG_PROVIDER === "mock";
|
|
278
|
-
const timeoutMs = parseInt(process.env.AICC_MODEL_TIMEOUT_MS || "
|
|
281
|
+
const timeoutMs = parseInt(process.env.AICC_MODEL_TIMEOUT_MS || "100000", 10);
|
|
279
282
|
const eager = process.env.AICC_EAGER_PARSE !== "false";
|
|
280
283
|
const userAggregate = messages.map((m) => `${m.role.toUpperCase()}: ${m.content}`).join("\n\n");
|
|
281
284
|
const command = `Generate high-quality commit message candidates based on the staged git diff.`;
|
|
@@ -298,7 +301,7 @@ ${userAggregate}`;
|
|
|
298
301
|
});
|
|
299
302
|
}
|
|
300
303
|
const start = Date.now();
|
|
301
|
-
return await new Promise((
|
|
304
|
+
return await new Promise((resolve2, reject) => {
|
|
302
305
|
let resolved = false;
|
|
303
306
|
let acc = "";
|
|
304
307
|
const includeLogs = process.env.AICC_PRINT_LOGS === "true";
|
|
@@ -318,7 +321,7 @@ ${userAggregate}`;
|
|
|
318
321
|
`[ai-cc][provider] model=${this.model} elapsedMs=${elapsed} promptChars=${fullPrompt.length} bytesOut=${value.length}`
|
|
319
322
|
);
|
|
320
323
|
}
|
|
321
|
-
|
|
324
|
+
resolve2(value);
|
|
322
325
|
};
|
|
323
326
|
const tryEager = () => {
|
|
324
327
|
if (!eager) return;
|
|
@@ -562,9 +565,12 @@ import inquirer from "inquirer";
|
|
|
562
565
|
|
|
563
566
|
// src/workflow/ui.ts
|
|
564
567
|
import chalk from "chalk";
|
|
565
|
-
function animateHeaderBase(text = "ai-conventional-commit") {
|
|
568
|
+
function animateHeaderBase(text = "ai-conventional-commit", modelSegment) {
|
|
569
|
+
const mainText = text;
|
|
570
|
+
const modelSeg = modelSegment ? ` (using ${modelSegment})` : "";
|
|
566
571
|
if (!process.stdout.isTTY || process.env.AICC_NO_ANIMATION) {
|
|
567
|
-
console.log("\n\u250C " + chalk.bold(
|
|
572
|
+
if (modelSeg) console.log("\n\u250C " + chalk.bold(mainText) + chalk.dim(modelSeg));
|
|
573
|
+
else console.log("\n\u250C " + chalk.bold(mainText));
|
|
568
574
|
return Promise.resolve();
|
|
569
575
|
}
|
|
570
576
|
const palette = [
|
|
@@ -582,8 +588,9 @@ function animateHeaderBase(text = "ai-conventional-commit") {
|
|
|
582
588
|
process.stdout.write("\n");
|
|
583
589
|
return palette.reduce(async (p, color) => {
|
|
584
590
|
await p;
|
|
585
|
-
const frame = chalk.bold.hex(color)(
|
|
586
|
-
process.stdout.write("\r\u250C " + frame);
|
|
591
|
+
const frame = chalk.bold.hex(color)(mainText);
|
|
592
|
+
if (modelSeg) process.stdout.write("\r\u250C " + frame + chalk.dim(modelSeg));
|
|
593
|
+
else process.stdout.write("\r\u250C " + frame);
|
|
587
594
|
await new Promise((r) => setTimeout(r, 60));
|
|
588
595
|
}, Promise.resolve()).then(() => process.stdout.write("\n"));
|
|
589
596
|
}
|
|
@@ -714,7 +721,7 @@ async function runGenerate(config) {
|
|
|
714
721
|
return;
|
|
715
722
|
}
|
|
716
723
|
if (process.stdout.isTTY) {
|
|
717
|
-
await animateHeaderBase(
|
|
724
|
+
await animateHeaderBase("ai-conventional-commit", config.model);
|
|
718
725
|
borderLine();
|
|
719
726
|
}
|
|
720
727
|
sectionTitle("Files");
|
|
@@ -756,8 +763,8 @@ async function runGenerate(config) {
|
|
|
756
763
|
candidates = candidates.map((c) => ({
|
|
757
764
|
...c,
|
|
758
765
|
title: formatCommitTitle(c.title, {
|
|
759
|
-
allowGitmoji:
|
|
760
|
-
mode: config.
|
|
766
|
+
allowGitmoji: config.style === "gitmoji" || config.style === "gitmoji-pure",
|
|
767
|
+
mode: config.style
|
|
761
768
|
})
|
|
762
769
|
}));
|
|
763
770
|
const chosen = candidates[0];
|
|
@@ -866,7 +873,7 @@ async function runSplit(config, desired) {
|
|
|
866
873
|
return;
|
|
867
874
|
}
|
|
868
875
|
if (process.stdout.isTTY) {
|
|
869
|
-
await animateHeaderBase(
|
|
876
|
+
await animateHeaderBase("ai-conventional-commit", config.model);
|
|
870
877
|
borderLine();
|
|
871
878
|
}
|
|
872
879
|
sectionTitle("Files");
|
|
@@ -907,8 +914,8 @@ async function runSplit(config, desired) {
|
|
|
907
914
|
candidates = candidates.map((c) => ({
|
|
908
915
|
...c,
|
|
909
916
|
title: formatCommitTitle(c.title, {
|
|
910
|
-
allowGitmoji:
|
|
911
|
-
mode: config.
|
|
917
|
+
allowGitmoji: config.style === "gitmoji" || config.style === "gitmoji-pure",
|
|
918
|
+
mode: config.style
|
|
912
919
|
})
|
|
913
920
|
}));
|
|
914
921
|
const fancy = candidates.length > 1;
|
|
@@ -1029,7 +1036,7 @@ async function runRefine(config, options) {
|
|
|
1029
1036
|
return;
|
|
1030
1037
|
}
|
|
1031
1038
|
if (process.stdout.isTTY) {
|
|
1032
|
-
await animateHeaderBase(
|
|
1039
|
+
await animateHeaderBase("ai-conventional-commit", config.model);
|
|
1033
1040
|
borderLine();
|
|
1034
1041
|
}
|
|
1035
1042
|
sectionTitle("Original");
|
|
@@ -1047,7 +1054,6 @@ async function runRefine(config, options) {
|
|
|
1047
1054
|
if (options.shorter) instructions.push("Make the title shorter but keep meaning.");
|
|
1048
1055
|
if (options.longer) instructions.push("Add more specificity to the title.");
|
|
1049
1056
|
if (options.scope) instructions.push(`Add or adjust scope to: ${options.scope}`);
|
|
1050
|
-
if (options.emoji) instructions.push("Add a relevant emoji prefix.");
|
|
1051
1057
|
if (!instructions.length) {
|
|
1052
1058
|
const add = await prompt("No refinement flags given. Enter custom instruction: ");
|
|
1053
1059
|
if (add.trim()) instructions.push(add.trim());
|
|
@@ -1069,8 +1075,8 @@ async function runRefine(config, options) {
|
|
|
1069
1075
|
);
|
|
1070
1076
|
const refinedPlan = await runStep("Parsing response", async () => extractJSON(raw));
|
|
1071
1077
|
refinedPlan.commits[0].title = formatCommitTitle(refinedPlan.commits[0].title, {
|
|
1072
|
-
allowGitmoji:
|
|
1073
|
-
mode: config.
|
|
1078
|
+
allowGitmoji: config.style === "gitmoji" || config.style === "gitmoji-pure",
|
|
1079
|
+
mode: config.style
|
|
1074
1080
|
});
|
|
1075
1081
|
phased.phase("Suggested commit");
|
|
1076
1082
|
phased.stop();
|
|
@@ -1104,39 +1110,10 @@ async function runRefine(config, options) {
|
|
|
1104
1110
|
finalSuccess({ count: 1, startedAt });
|
|
1105
1111
|
}
|
|
1106
1112
|
|
|
1107
|
-
// src/config.ts
|
|
1108
|
-
import { cosmiconfig } from "cosmiconfig";
|
|
1109
|
-
import { resolve as resolve2 } from "path";
|
|
1110
|
-
import { existsSync as existsSync4 } from "fs";
|
|
1111
|
-
var DEFAULTS = {
|
|
1112
|
-
model: process.env.AICC_MODEL || "github-copilot/gpt-5",
|
|
1113
|
-
privacy: process.env.AICC_PRIVACY || "low",
|
|
1114
|
-
gitmoji: process.env.AICC_GITMOJI === "true",
|
|
1115
|
-
gitmojiMode: "standard",
|
|
1116
|
-
styleSamples: parseInt(process.env.AICC_STYLE_SAMPLES || "120", 10),
|
|
1117
|
-
maxTokens: parseInt(process.env.AICC_MAX_TOKENS || "512", 10),
|
|
1118
|
-
cacheDir: ".git/.aicc-cache",
|
|
1119
|
-
plugins: [],
|
|
1120
|
-
verbose: process.env.AICC_VERBOSE === "true"
|
|
1121
|
-
};
|
|
1122
|
-
async function loadConfig(cwd = process.cwd()) {
|
|
1123
|
-
const explorer = cosmiconfig("aicc");
|
|
1124
|
-
const result = await explorer.search(cwd);
|
|
1125
|
-
const cfg = {
|
|
1126
|
-
...DEFAULTS,
|
|
1127
|
-
...result?.config || {}
|
|
1128
|
-
};
|
|
1129
|
-
cfg.plugins = (cfg.plugins || []).filter((p) => {
|
|
1130
|
-
const abs = resolve2(cwd, p);
|
|
1131
|
-
return existsSync4(abs);
|
|
1132
|
-
});
|
|
1133
|
-
return cfg;
|
|
1134
|
-
}
|
|
1135
|
-
|
|
1136
1113
|
// package.json
|
|
1137
1114
|
var package_default = {
|
|
1138
1115
|
name: "@kud/ai-conventional-commit-cli",
|
|
1139
|
-
version: "0.
|
|
1116
|
+
version: "0.7.0",
|
|
1140
1117
|
type: "module",
|
|
1141
1118
|
description: "Opinionated, style-aware AI assistant for crafting and splitting git commits (opencode-based, provider-agnostic).",
|
|
1142
1119
|
bin: {
|
|
@@ -1206,32 +1183,87 @@ var package_default = {
|
|
|
1206
1183
|
};
|
|
1207
1184
|
|
|
1208
1185
|
// src/index.ts
|
|
1186
|
+
import { execa as execa2 } from "execa";
|
|
1187
|
+
import inquirer4 from "inquirer";
|
|
1209
1188
|
var pkgVersion = package_default.version || "0.0.0";
|
|
1189
|
+
var RootCommand = class extends Command {
|
|
1190
|
+
static paths = [[]];
|
|
1191
|
+
static usage = Command.Usage({
|
|
1192
|
+
description: "Generate a conventional commit message (default command).",
|
|
1193
|
+
details: `Commands:
|
|
1194
|
+
|
|
1195
|
+
\u22C5 generate: Generate a single commit (default)
|
|
1196
|
+
|
|
1197
|
+
\u22C5 split: Plan & apply multiple smaller commits
|
|
1198
|
+
|
|
1199
|
+
\u22C5 refine: Refine last (or indexed) commit
|
|
1200
|
+
|
|
1201
|
+
\u22C5 models: List or pick AI models (opencode)
|
|
1202
|
+
|
|
1203
|
+
\u22C5 config show: Show merged config + sources
|
|
1204
|
+
|
|
1205
|
+
\u22C5 config get <key>: Get a single config value
|
|
1206
|
+
|
|
1207
|
+
\u22C5 config set <k> <v>: Persist a global config value
|
|
1208
|
+
|
|
1209
|
+
Refine Options:
|
|
1210
|
+
|
|
1211
|
+
\u22C5 --shorter: Make message more concise
|
|
1212
|
+
|
|
1213
|
+
\u22C5 --longer: Expand message with detail
|
|
1214
|
+
|
|
1215
|
+
\u22C5 --scope <scope>: Add or replace scope
|
|
1216
|
+
|
|
1217
|
+
\u22C5 --index <n>: Target commit from previous split`,
|
|
1218
|
+
examples: [
|
|
1219
|
+
["Generate with gitmoji style", "ai-conventional-commit --style gitmoji"],
|
|
1220
|
+
["Split staged changes", "ai-conventional-commit split --max 3"],
|
|
1221
|
+
["Pick & save default model", "ai-conventional-commit models -i --save"],
|
|
1222
|
+
["Set style globally", "ai-conventional-commit config set style gitmoji"],
|
|
1223
|
+
["Show config JSON", "ai-conventional-commit config show --json"]
|
|
1224
|
+
]
|
|
1225
|
+
});
|
|
1226
|
+
style = Option.String("--style", {
|
|
1227
|
+
required: false,
|
|
1228
|
+
description: "Title style: standard | gitmoji | gitmoji-pure"
|
|
1229
|
+
});
|
|
1230
|
+
model = Option.String("-m,--model", {
|
|
1231
|
+
required: false,
|
|
1232
|
+
description: "Model provider/name (e.g. github-copilot/gpt-4.1)"
|
|
1233
|
+
});
|
|
1234
|
+
async execute() {
|
|
1235
|
+
const config = await loadConfig();
|
|
1236
|
+
if (this.style) config.style = this.style;
|
|
1237
|
+
if (this.model) config.model = this.model;
|
|
1238
|
+
await runGenerate(config);
|
|
1239
|
+
}
|
|
1240
|
+
};
|
|
1210
1241
|
var GenerateCommand = class extends Command {
|
|
1211
|
-
static paths = [[`generate`]
|
|
1242
|
+
static paths = [[`generate`]];
|
|
1212
1243
|
static usage = Command.Usage({
|
|
1213
1244
|
description: "Generate a conventional commit message for staged changes.",
|
|
1214
|
-
details: `
|
|
1215
|
-
Add --gitmoji[-pure] to enable emoji styles.`,
|
|
1245
|
+
details: `Generate a single conventional commit using AI with style rules, guardrails, and optional model override. Uses staged changes. Add --style gitmoji or --style gitmoji-pure for emoji modes.`,
|
|
1216
1246
|
examples: [
|
|
1217
|
-
["
|
|
1247
|
+
["Basic usage (standard style)", "ai-conventional-commit generate"],
|
|
1248
|
+
["Force gitmoji style", "ai-conventional-commit generate --style gitmoji"],
|
|
1249
|
+
[
|
|
1250
|
+
"Override model for this run",
|
|
1251
|
+
"ai-conventional-commit generate --model github-copilot/gpt-4.1"
|
|
1252
|
+
]
|
|
1218
1253
|
]
|
|
1219
1254
|
});
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
gitmojiPure = Option.Boolean("--gitmoji-pure", false, {
|
|
1224
|
-
description: "Pure gitmoji mode (vs --gitmoji): emoji only (emoji: subject)"
|
|
1255
|
+
style = Option.String("--style", {
|
|
1256
|
+
required: false,
|
|
1257
|
+
description: "Title style: standard | gitmoji | gitmoji-pure"
|
|
1225
1258
|
});
|
|
1226
1259
|
model = Option.String("-m,--model", {
|
|
1227
1260
|
required: false,
|
|
1228
|
-
description: "Model provider/name (e.g. github-copilot/gpt-
|
|
1261
|
+
description: "Model provider/name (e.g. github-copilot/gpt-4.1)"
|
|
1229
1262
|
});
|
|
1230
1263
|
async execute() {
|
|
1231
1264
|
const config = await loadConfig();
|
|
1232
|
-
if (this.
|
|
1233
|
-
config.
|
|
1234
|
-
config.gitmojiMode = this.gitmojiPure ? "gitmoji-pure" : "gitmoji";
|
|
1265
|
+
if (this.style) {
|
|
1266
|
+
config.style = this.style;
|
|
1235
1267
|
}
|
|
1236
1268
|
if (this.model) config.model = this.model;
|
|
1237
1269
|
await runGenerate(config);
|
|
@@ -1241,21 +1273,19 @@ var SplitCommand = class extends Command {
|
|
|
1241
1273
|
static paths = [[`split`]];
|
|
1242
1274
|
static usage = Command.Usage({
|
|
1243
1275
|
description: "Propose multiple smaller conventional commits for current staged diff.",
|
|
1244
|
-
details: `
|
|
1245
|
-
Use --max to limit the number of proposals.`,
|
|
1276
|
+
details: `Analyze staged changes, group them logically, and propose multiple conventional commit titles + bodies. Use --max to limit proposals. Each proposal obeys style + guardrails.`,
|
|
1246
1277
|
examples: [
|
|
1278
|
+
["Default split (standard style)", "ai-conventional-commit split"],
|
|
1247
1279
|
[
|
|
1248
|
-
"
|
|
1249
|
-
"ai-conventional-commit split --max 3 --gitmoji"
|
|
1280
|
+
"Limit to 3 proposals with gitmoji style",
|
|
1281
|
+
"ai-conventional-commit split --max 3 --style gitmoji"
|
|
1250
1282
|
]
|
|
1251
1283
|
]
|
|
1252
1284
|
});
|
|
1253
1285
|
max = Option.String("--max", { description: "Max proposed commits", required: false });
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
gitmojiPure = Option.Boolean("--gitmoji-pure", false, {
|
|
1258
|
-
description: "Pure gitmoji mode (vs --gitmoji): emoji only"
|
|
1286
|
+
style = Option.String("--style", {
|
|
1287
|
+
required: false,
|
|
1288
|
+
description: "Title style: standard | gitmoji | gitmoji-pure"
|
|
1259
1289
|
});
|
|
1260
1290
|
model = Option.String("-m,--model", {
|
|
1261
1291
|
required: false,
|
|
@@ -1263,10 +1293,7 @@ Use --max to limit the number of proposals.`,
|
|
|
1263
1293
|
});
|
|
1264
1294
|
async execute() {
|
|
1265
1295
|
const config = await loadConfig();
|
|
1266
|
-
if (this.
|
|
1267
|
-
config.gitmoji = true;
|
|
1268
|
-
config.gitmojiMode = this.gitmojiPure ? "gitmoji-pure" : "gitmoji";
|
|
1269
|
-
}
|
|
1296
|
+
if (this.style) config.style = this.style;
|
|
1270
1297
|
if (this.model) config.model = this.model;
|
|
1271
1298
|
await runSplit(config, this.max ? parseInt(this.max, 10) : void 0);
|
|
1272
1299
|
}
|
|
@@ -1275,7 +1302,7 @@ var RefineCommand = class extends Command {
|
|
|
1275
1302
|
static paths = [[`refine`]];
|
|
1276
1303
|
static usage = Command.Usage({
|
|
1277
1304
|
description: "Refine the last (or chosen) commit message with style rules.",
|
|
1278
|
-
details: `
|
|
1305
|
+
details: `Targeted improvements to an existing commit: shorter/longer length, inject or replace scope, or refine a specific index from a previous split.`,
|
|
1279
1306
|
examples: [
|
|
1280
1307
|
["Shorten the last commit message", "ai-conventional-commit refine --shorter"],
|
|
1281
1308
|
["Add a scope to the last commit", "ai-conventional-commit refine --scope ui"]
|
|
@@ -1284,7 +1311,10 @@ var RefineCommand = class extends Command {
|
|
|
1284
1311
|
shorter = Option.Boolean("--shorter", false, { description: "Make message more concise" });
|
|
1285
1312
|
longer = Option.Boolean("--longer", false, { description: "Expand message with detail" });
|
|
1286
1313
|
scope = Option.String("--scope", { description: "Override/add scope (e.g. ui, api)" });
|
|
1287
|
-
|
|
1314
|
+
style = Option.String("--style", {
|
|
1315
|
+
required: false,
|
|
1316
|
+
description: "Title style: standard | gitmoji | gitmoji-pure"
|
|
1317
|
+
});
|
|
1288
1318
|
index = Option.String("--index", {
|
|
1289
1319
|
description: "Select commit index if multiple were generated"
|
|
1290
1320
|
});
|
|
@@ -1294,50 +1324,196 @@ var RefineCommand = class extends Command {
|
|
|
1294
1324
|
});
|
|
1295
1325
|
async execute() {
|
|
1296
1326
|
const config = await loadConfig();
|
|
1327
|
+
if (this.style) config.style = this.style;
|
|
1297
1328
|
if (this.model) config.model = this.model;
|
|
1298
1329
|
await runRefine(config, {
|
|
1299
1330
|
shorter: this.shorter,
|
|
1300
1331
|
longer: this.longer,
|
|
1301
1332
|
scope: this.scope,
|
|
1302
|
-
emoji: this.emoji,
|
|
1303
1333
|
index: this.index ? parseInt(this.index, 10) : void 0
|
|
1304
1334
|
});
|
|
1305
1335
|
}
|
|
1306
1336
|
};
|
|
1307
|
-
var
|
|
1308
|
-
static paths = [[
|
|
1309
|
-
|
|
1337
|
+
var ModelsCommand = class extends Command {
|
|
1338
|
+
static paths = [[`models`]];
|
|
1339
|
+
static usage = Command.Usage({
|
|
1340
|
+
description: "List available models via opencode CLI.",
|
|
1341
|
+
details: `Wrapper around "opencode models". Use --interactive (or -i) for a picker; prints the selected model id for piping or quick copy. Add --save with --interactive to persist globally in aicc.json (XDG config).`,
|
|
1342
|
+
examples: [
|
|
1343
|
+
["List models", "ai-conventional-commit models"],
|
|
1344
|
+
["Interactively pick a model", "ai-conventional-commit models --interactive"],
|
|
1345
|
+
["Pick & save globally", "ai-conventional-commit models --interactive --save"]
|
|
1346
|
+
]
|
|
1347
|
+
});
|
|
1348
|
+
interactive = Option.Boolean("-i,--interactive", false, {
|
|
1349
|
+
description: "Interactive model selection"
|
|
1350
|
+
});
|
|
1351
|
+
save = Option.Boolean("--save", false, {
|
|
1352
|
+
description: "Persist selected model globally (requires --interactive)"
|
|
1353
|
+
});
|
|
1354
|
+
current = Option.Boolean("--current", false, {
|
|
1355
|
+
description: "Print current default model and its source"
|
|
1356
|
+
});
|
|
1357
|
+
async execute() {
|
|
1358
|
+
if (this.current) {
|
|
1359
|
+
const { loadConfigDetailed } = await import("./config-Q7AKJSO4.js");
|
|
1360
|
+
const { config } = await loadConfigDetailed();
|
|
1361
|
+
this.context.stdout.write(`${config.model} (source: ${config._sources.model})
|
|
1362
|
+
`);
|
|
1363
|
+
return;
|
|
1364
|
+
}
|
|
1365
|
+
try {
|
|
1366
|
+
const { stdout } = await execa2("opencode", ["models"]).catch(async (err) => {
|
|
1367
|
+
if (err.shortMessage && /ENOENT/.test(err.shortMessage)) {
|
|
1368
|
+
this.context.stderr.write(
|
|
1369
|
+
"opencode CLI not found in PATH. Install it from https://github.com/opencodejs/opencode or ensure the binary is available.\n"
|
|
1370
|
+
);
|
|
1371
|
+
}
|
|
1372
|
+
throw err;
|
|
1373
|
+
});
|
|
1374
|
+
const useInteractive = this.interactive;
|
|
1375
|
+
if (!useInteractive) {
|
|
1376
|
+
this.context.stdout.write(stdout.trim() + "\n");
|
|
1377
|
+
return;
|
|
1378
|
+
}
|
|
1379
|
+
if (!process.stdout.isTTY) {
|
|
1380
|
+
this.context.stdout.write(stdout.trim() + "\n");
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
const candidates = Array.from(
|
|
1384
|
+
new Set(
|
|
1385
|
+
stdout.split("\n").map((l) => l.trim()).filter((l) => /^[a-z0-9_.-]+\/[A-Za-z0-9_.:-]+$/.test(l))
|
|
1386
|
+
)
|
|
1387
|
+
);
|
|
1388
|
+
if (candidates.length === 0) {
|
|
1389
|
+
this.context.stdout.write(stdout.trim() + "\n");
|
|
1390
|
+
return;
|
|
1391
|
+
}
|
|
1392
|
+
const { model } = await inquirer4.prompt([
|
|
1393
|
+
{
|
|
1394
|
+
name: "model",
|
|
1395
|
+
type: "list",
|
|
1396
|
+
message: "Select a model",
|
|
1397
|
+
choices: candidates
|
|
1398
|
+
}
|
|
1399
|
+
]);
|
|
1400
|
+
this.context.stdout.write(model + "\n");
|
|
1401
|
+
if (this.save) {
|
|
1402
|
+
try {
|
|
1403
|
+
const { saveGlobalConfig } = await import("./config-Q7AKJSO4.js");
|
|
1404
|
+
const path = saveGlobalConfig({ model });
|
|
1405
|
+
this.context.stdout.write(`Saved as default model in ${path}
|
|
1406
|
+
`);
|
|
1407
|
+
} catch (e) {
|
|
1408
|
+
this.context.stderr.write(`Failed to save global config: ${e?.message || e}
|
|
1409
|
+
`);
|
|
1410
|
+
}
|
|
1411
|
+
}
|
|
1412
|
+
this.context.stdout.write(
|
|
1413
|
+
`
|
|
1414
|
+
Use it now:
|
|
1415
|
+
ai-conventional-commit generate --model ${model}
|
|
1416
|
+
`
|
|
1417
|
+
);
|
|
1418
|
+
} catch (e) {
|
|
1419
|
+
this.context.stderr.write(
|
|
1420
|
+
`Failed to list models via "opencode models": ${e?.message || e}
|
|
1421
|
+
`
|
|
1422
|
+
);
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
};
|
|
1426
|
+
var ConfigShowCommand = class extends Command {
|
|
1427
|
+
static paths = [[`config`, `show`]];
|
|
1428
|
+
static usage = Command.Usage({
|
|
1429
|
+
description: "Show effective configuration with source metadata.",
|
|
1430
|
+
details: "Outputs merged config fields, their values, and source precedence info. Use --json for raw JSON including _sources.",
|
|
1431
|
+
examples: [
|
|
1432
|
+
["Human readable", "ai-conventional-commit config show"],
|
|
1433
|
+
["JSON with sources", "ai-conventional-commit config show --json"]
|
|
1434
|
+
]
|
|
1435
|
+
});
|
|
1436
|
+
json = Option.Boolean("--json", false, { description: "Output JSON including _sources" });
|
|
1310
1437
|
async execute() {
|
|
1311
|
-
|
|
1438
|
+
const { loadConfigDetailed } = await import("./config-Q7AKJSO4.js");
|
|
1439
|
+
const { config, raw } = await loadConfigDetailed();
|
|
1440
|
+
if (this.json) {
|
|
1441
|
+
this.context.stdout.write(JSON.stringify({ config, raw }, null, 2) + "\n");
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
const sources = config._sources;
|
|
1445
|
+
const lines = Object.entries(config).filter(([k]) => k !== "_sources").map(([k, v]) => `${k} = ${JSON.stringify(v)} (${sources[k]})`);
|
|
1446
|
+
this.context.stdout.write(lines.join("\n") + "\n");
|
|
1447
|
+
}
|
|
1448
|
+
};
|
|
1449
|
+
var ConfigGetCommand = class extends Command {
|
|
1450
|
+
static paths = [[`config`, `get`]];
|
|
1451
|
+
static usage = Command.Usage({
|
|
1452
|
+
description: "Get a single configuration value (effective).",
|
|
1453
|
+
details: "Returns the effective value after merging sources. Optionally show its source.",
|
|
1454
|
+
examples: [
|
|
1455
|
+
["Get model", "ai-conventional-commit config get model"],
|
|
1456
|
+
["Get style", "ai-conventional-commit config get style"],
|
|
1457
|
+
["Get model with source", "ai-conventional-commit config get model --with-source"]
|
|
1458
|
+
]
|
|
1459
|
+
});
|
|
1460
|
+
key = Option.String();
|
|
1461
|
+
withSource = Option.Boolean("--with-source", false, { description: "Append source label" });
|
|
1462
|
+
async execute() {
|
|
1463
|
+
const { loadConfigDetailed } = await import("./config-Q7AKJSO4.js");
|
|
1464
|
+
const { config } = await loadConfigDetailed();
|
|
1465
|
+
const key = this.key;
|
|
1466
|
+
if (!(key in config)) {
|
|
1467
|
+
this.context.stderr.write(`Unknown config key: ${this.key}
|
|
1468
|
+
`);
|
|
1469
|
+
process.exitCode = 1;
|
|
1470
|
+
return;
|
|
1471
|
+
}
|
|
1472
|
+
if (this.withSource) {
|
|
1473
|
+
const src = config._sources?.[key];
|
|
1474
|
+
this.context.stdout.write(`${JSON.stringify(config[key])} (${src})
|
|
1475
|
+
`);
|
|
1476
|
+
} else {
|
|
1477
|
+
this.context.stdout.write(JSON.stringify(config[key]) + "\n");
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
};
|
|
1481
|
+
var ConfigSetCommand = class extends Command {
|
|
1482
|
+
static paths = [[`config`, `set`]];
|
|
1483
|
+
static usage = Command.Usage({
|
|
1484
|
+
description: "Set and persist a global configuration key.",
|
|
1485
|
+
details: "Writes to the global aicc.json (XDG config). Accepts JSON for complex values. Only allowed keys: model, style, privacy, styleSamples, maxTokens, verbose.",
|
|
1486
|
+
examples: [
|
|
1487
|
+
["Set default model", "ai-conventional-commit config set model github-copilot/gpt-4.1"],
|
|
1488
|
+
["Set style to gitmoji", "ai-conventional-commit config set style gitmoji"],
|
|
1489
|
+
["Enable verbose mode", "ai-conventional-commit config set verbose true"]
|
|
1490
|
+
]
|
|
1491
|
+
});
|
|
1492
|
+
key = Option.String();
|
|
1493
|
+
value = Option.String();
|
|
1494
|
+
async execute() {
|
|
1495
|
+
const allowed = /* @__PURE__ */ new Set(["model", "style", "privacy", "styleSamples", "maxTokens", "verbose"]);
|
|
1496
|
+
if (!allowed.has(this.key)) {
|
|
1497
|
+
this.context.stderr.write(`Cannot set key: ${this.key}
|
|
1498
|
+
`);
|
|
1499
|
+
process.exitCode = 1;
|
|
1500
|
+
return;
|
|
1501
|
+
}
|
|
1502
|
+
let parsed = this.value;
|
|
1503
|
+
if (/^(true|false)$/i.test(this.value)) parsed = this.value.toLowerCase() === "true";
|
|
1504
|
+
else if (/^[0-9]+$/.test(this.value)) parsed = parseInt(this.value, 10);
|
|
1505
|
+
else if (/^[\[{]/.test(this.value)) {
|
|
1506
|
+
try {
|
|
1507
|
+
parsed = JSON.parse(this.value);
|
|
1508
|
+
} catch {
|
|
1509
|
+
}
|
|
1510
|
+
}
|
|
1511
|
+
const { saveGlobalConfig } = await import("./config-Q7AKJSO4.js");
|
|
1512
|
+
const path = saveGlobalConfig({ [this.key]: parsed });
|
|
1513
|
+
this.context.stdout.write(`Saved ${this.key} to ${path}
|
|
1514
|
+
`);
|
|
1312
1515
|
}
|
|
1313
1516
|
};
|
|
1314
|
-
function globalHelp() {
|
|
1315
|
-
return `ai-conventional-commit v${pkgVersion}
|
|
1316
|
-
|
|
1317
|
-
Usage:
|
|
1318
|
-
ai-conventional-commit [generate] [options] Generate a commit (default)
|
|
1319
|
-
ai-conventional-commit split [options] Propose multiple commits
|
|
1320
|
-
ai-conventional-commit refine [options] Refine last or indexed commit
|
|
1321
|
-
|
|
1322
|
-
Global Options:
|
|
1323
|
-
-m, --model <provider/name> Override model provider/name
|
|
1324
|
-
--gitmoji[-pure] Gitmoji modes: emoji + type (default) or pure emoji only
|
|
1325
|
-
-h, --help Show this help
|
|
1326
|
-
-V, --version Show version
|
|
1327
|
-
|
|
1328
|
-
Refine Options:
|
|
1329
|
-
--shorter / --longer Adjust message length
|
|
1330
|
-
--scope <scope> Add or replace scope
|
|
1331
|
-
--emoji Add suitable gitmoji
|
|
1332
|
-
--index <n> Select commit index
|
|
1333
|
-
|
|
1334
|
-
Examples:
|
|
1335
|
-
ai-conventional-commit --gitmoji
|
|
1336
|
-
ai-conventional-commit --gitmoji-pure
|
|
1337
|
-
ai-conventional-commit split --max 3 --gitmoji
|
|
1338
|
-
ai-conventional-commit refine --scope api --emoji
|
|
1339
|
-
`;
|
|
1340
|
-
}
|
|
1341
1517
|
var VersionCommand = class extends Command {
|
|
1342
1518
|
static paths = [[`--version`], [`-V`]];
|
|
1343
1519
|
async execute() {
|
|
@@ -1350,10 +1526,14 @@ var cli = new Cli({
|
|
|
1350
1526
|
binaryName: "ai-conventional-commit",
|
|
1351
1527
|
binaryVersion: pkgVersion
|
|
1352
1528
|
});
|
|
1529
|
+
cli.register(RootCommand);
|
|
1353
1530
|
cli.register(GenerateCommand);
|
|
1354
1531
|
cli.register(SplitCommand);
|
|
1355
1532
|
cli.register(RefineCommand);
|
|
1356
|
-
cli.register(
|
|
1533
|
+
cli.register(ModelsCommand);
|
|
1534
|
+
cli.register(ConfigShowCommand);
|
|
1535
|
+
cli.register(ConfigGetCommand);
|
|
1536
|
+
cli.register(ConfigSetCommand);
|
|
1357
1537
|
cli.register(VersionCommand);
|
|
1358
1538
|
cli.runExit(process.argv.slice(2), {
|
|
1359
1539
|
stdin: process.stdin,
|
package/package.json
CHANGED