gityo 1.0.11 → 1.0.12
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 +44 -5
- package/dist/index.js +65 -29
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -46,13 +46,14 @@ If you already staged files before running `gityo`, only those are used for the
|
|
|
46
46
|
gityo
|
|
47
47
|
gityo --generate
|
|
48
48
|
gityo --model fast --generate
|
|
49
|
-
gityo --
|
|
49
|
+
gityo --style concise --generate
|
|
50
|
+
gityo --input "fix login redirect bug"
|
|
50
51
|
gityo --yolo
|
|
51
52
|
```
|
|
52
53
|
|
|
53
54
|
## AI setup
|
|
54
55
|
|
|
55
|
-
A configured model is required — gityo won't run without one, and the API key must be resolvable from your environment even when you pass `--
|
|
56
|
+
A configured model is required — gityo won't run without one, and the API key must be resolvable from your environment even when you pass `--input`. Models live in a `models` map in your config file. Each key is a name you can pick with `--model`; the `default` key is used when you don't pass `--model`:
|
|
56
57
|
|
|
57
58
|
```json
|
|
58
59
|
{
|
|
@@ -68,7 +69,8 @@ A configured model is required — gityo won't run without one, and the API key
|
|
|
68
69
|
"apiKeyEnv": "OPENAI_API_KEY",
|
|
69
70
|
"model": "gpt-5-mini"
|
|
70
71
|
}
|
|
71
|
-
}
|
|
72
|
+
},
|
|
73
|
+
"style": "concise"
|
|
72
74
|
}
|
|
73
75
|
```
|
|
74
76
|
|
|
@@ -101,6 +103,7 @@ Then use:
|
|
|
101
103
|
```bash
|
|
102
104
|
gityo --generate
|
|
103
105
|
gityo --model fast --generate
|
|
106
|
+
gityo --style concise --generate
|
|
104
107
|
```
|
|
105
108
|
|
|
106
109
|
Providers are the official Vercel AI SDK packages: `@ai-sdk/openai`, `@ai-sdk/openai-compatible`, `@ai-sdk/anthropic`, `@ai-sdk/google`, `@ai-sdk/xai`, `@ai-sdk/azure`, `@ai-sdk/amazon-bedrock`, `@ai-sdk/groq`, `@ai-sdk/mistral`, `@ai-sdk/deepseek`, `@ai-sdk/togetherai`, `@ai-sdk/fireworks`, `@ai-sdk/perplexity`, `@ai-sdk/cohere`, `@ai-sdk/cerebras`, `@ai-sdk/luma`, `@ai-sdk/fal`, `@ai-sdk/deepinfra`, `@ai-sdk/google-vertex`, `@openrouter/ai-sdk-provider`, plus `ai-sdk-ollama`, `ollama-ai-provider-v2`, `workers-ai-provider`, `zhipu-ai-provider`, `sambanova-ai-provider`, `vercel-minimax-ai-provider`, `@aihubmix/ai-sdk-provider`, `ai-gateway-provider`, `@friendliai/ai-provider`, `@helicone/ai-sdk-provider`, and `ai-sdk-provider-opencode-sdk`.
|
|
@@ -116,7 +119,7 @@ gityo config
|
|
|
116
119
|
Config is edited by hand in a JSON file. Project config goes in:
|
|
117
120
|
|
|
118
121
|
```text
|
|
119
|
-
.gityo.
|
|
122
|
+
.gityo.json
|
|
120
123
|
```
|
|
121
124
|
|
|
122
125
|
Global config goes in:
|
|
@@ -151,6 +154,13 @@ Example:
|
|
|
151
154
|
"model": "gpt-5-nano"
|
|
152
155
|
}
|
|
153
156
|
},
|
|
157
|
+
"style": "concise",
|
|
158
|
+
"styles": {
|
|
159
|
+
"team": "Use conventional commits. Keep the subject under 72 characters.",
|
|
160
|
+
"release": {
|
|
161
|
+
"path": ".gityo/release-style.md"
|
|
162
|
+
}
|
|
163
|
+
},
|
|
154
164
|
"autoAcceptMessage": false,
|
|
155
165
|
"postCommand": "push",
|
|
156
166
|
"autoRunPostCommand": false,
|
|
@@ -160,6 +170,35 @@ Example:
|
|
|
160
170
|
}
|
|
161
171
|
```
|
|
162
172
|
|
|
173
|
+
### Commit message styles
|
|
174
|
+
|
|
175
|
+
Styles control the base commit-message convention sent to the model. Built-in
|
|
176
|
+
styles are `default`, `concise`, `explanatory`, `plain`, and `gitmoji`.
|
|
177
|
+
|
|
178
|
+
- `default` uses conventional commits and adds a body only for substantial,
|
|
179
|
+
multi-part changes that benefit from more context.
|
|
180
|
+
- `concise` uses conventional commits and adds a body only when it is essential.
|
|
181
|
+
- `explanatory` uses conventional commits and encourages a useful explanatory
|
|
182
|
+
body.
|
|
183
|
+
- `plain` produces a short, non-conventional imperative subject line.
|
|
184
|
+
- `gitmoji` prefixes a conventional subject with a relevant gitmoji.
|
|
185
|
+
|
|
186
|
+
Choose a default with `style`, or select one for a command with `--style`:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
gityo --style team --generate
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Custom `styles` extend the built-ins. A custom style with the same name replaces
|
|
193
|
+
the built-in style. A style can be inline text or an object with a `path` to a
|
|
194
|
+
prompt file. File paths are passed to Node's `path.resolve()`, so relative paths
|
|
195
|
+
resolve from the directory where you run `gityo`.
|
|
196
|
+
|
|
197
|
+
Style selection priority is `--style`, then config `style`, then `default`.
|
|
198
|
+
|
|
199
|
+
`instructions` uses the same format. Set it to a string or `{ "path": "..." }`
|
|
200
|
+
to load additional instructions from a file.
|
|
201
|
+
|
|
163
202
|
### Large changes
|
|
164
203
|
|
|
165
204
|
When the diff is small, it is sent to the model as-is. When it is too large for one request, gityo minimizes it first:
|
|
@@ -186,5 +225,5 @@ Keep the subject line under 72 characters.
|
|
|
186
225
|
Priority is simple:
|
|
187
226
|
|
|
188
227
|
- `.gityo.md` for repo-specific instructions
|
|
189
|
-
- `.gityo.
|
|
228
|
+
- `.gityo.json` for project config
|
|
190
229
|
- `~/.config/gityo.json` for your defaults
|
package/dist/index.js
CHANGED
|
@@ -1710,7 +1710,7 @@ function useColor() {
|
|
|
1710
1710
|
if (process$1.env.FORCE_COLOR || process$1.env.CLICOLOR_FORCE !== void 0) return true;
|
|
1711
1711
|
}
|
|
1712
1712
|
new Command();
|
|
1713
|
-
var version$4 = "1.0.
|
|
1713
|
+
var version$4 = "1.0.12";
|
|
1714
1714
|
Object.freeze({ status: "aborted" });
|
|
1715
1715
|
function $constructor$3(name$16, initializer$6, params) {
|
|
1716
1716
|
function init$1(inst, def) {
|
|
@@ -175933,29 +175933,34 @@ const modelSchema = object$4({
|
|
|
175933
175933
|
apiUrl: url$3().optional(),
|
|
175934
175934
|
options: record$3(string$6(), unknown$3()).optional()
|
|
175935
175935
|
});
|
|
175936
|
+
const instructionSchema = union$4([string$6().min(1), object$4({ path: string$6().min(1) })]);
|
|
175936
175937
|
const configSchema = object$4({
|
|
175937
175938
|
$schema: url$3(),
|
|
175938
175939
|
models: record$3(string$6().min(1), modelSchema),
|
|
175939
|
-
|
|
175940
|
-
|
|
175940
|
+
instructions: instructionSchema,
|
|
175941
|
+
style: string$6().min(1),
|
|
175942
|
+
styles: record$3(string$6().min(1), instructionSchema),
|
|
175941
175943
|
maxDiffTokens: number$5().int().min(1e3),
|
|
175942
175944
|
perFileCap: number$5().int().min(50),
|
|
175943
|
-
|
|
175944
|
-
autoRunPostCommand: boolean$5()
|
|
175945
|
+
autoAcceptMessage: boolean$5(),
|
|
175946
|
+
autoRunPostCommand: boolean$5(),
|
|
175947
|
+
postCommand: _enum$4(["push", "push-and-pull"]).nullable()
|
|
175945
175948
|
}).partial();
|
|
175946
175949
|
function resolveConfig(input) {
|
|
175947
175950
|
const parsed = configSchema.parse(input);
|
|
175948
175951
|
return {
|
|
175949
175952
|
models: parsed.models,
|
|
175953
|
+
style: parsed.style,
|
|
175954
|
+
styles: parsed.styles,
|
|
175950
175955
|
instructions: parsed.instructions,
|
|
175951
|
-
autoAcceptCommitMessage: parsed.autoAcceptMessage ?? false,
|
|
175952
175956
|
maxDiffTokens: parsed.maxDiffTokens,
|
|
175953
175957
|
perFileCap: parsed.perFileCap,
|
|
175954
|
-
|
|
175955
|
-
autoRunPostCommand: parsed.autoRunPostCommand ?? false
|
|
175958
|
+
autoAcceptCommitMessage: parsed.autoAcceptMessage ?? false,
|
|
175959
|
+
autoRunPostCommand: parsed.autoRunPostCommand ?? false,
|
|
175960
|
+
postCommand: parsed.postCommand === void 0 ? "push" : parsed.postCommand
|
|
175956
175961
|
};
|
|
175957
175962
|
}
|
|
175958
|
-
const PROJECT_CONFIG_FILE_NAME = ".gityo.
|
|
175963
|
+
const PROJECT_CONFIG_FILE_NAME = ".gityo.json";
|
|
175959
175964
|
const GLOBAL_CONFIG_FILE_PATH = path.join(os.homedir(), ".config", "gityo.json");
|
|
175960
175965
|
async function loadConfig(cwd = process.cwd()) {
|
|
175961
175966
|
const [globalConfig$3, projectConfig, projectInstructions] = await Promise.all([
|
|
@@ -181257,7 +181262,6 @@ function hardSplit(text$1, maxTokens) {
|
|
|
181257
181262
|
if (current.length > 0) chunks.push(current);
|
|
181258
181263
|
return chunks;
|
|
181259
181264
|
}
|
|
181260
|
-
var system_prompt_default = "You are a strict Git commit message generator. ONLY output the commit message, nothing else.\n\nREQUIRED FORMAT:\n- First line: <type>(<scope>): <subject> (max 50 characters)\n- Types: feat, fix, docs, style, refactor, perf, test, chore, ci\n- Subject: imperative mood, lowercase, no period\n- If body needed: blank line + detailed explanation (wrapped at 72 chars)\n\nSTRICT RULES:\n1. MUST use conventional commits format: type(scope): subject\n2. Subject line MUST be under 50 characters\n3. Subject MUST be in imperative mood (e.g., \"add\", \"fix\", \"update\")\n4. Subject MUST be lowercase\n5. Subject MUST NOT end with a period\n6. MUST provide clear context about WHAT changed and WHY\n7. MUST be specific about affected functions, components, or modules\n8. MUST NOT use vague terms like \"Update\", \"Fix stuff\", \"Changes\"\n9. If including a body, MUST have exactly one blank line between subject and body\n10. Body lines MUST wrap at 72 characters\n\nOUTPUT INSTRUCTION:\nReturn ONLY the commit message. No explanations, no extra text, no markdown formatting.\n\nEXAMPLE:\nfeat(llm): add support for streaming responses\n\nImplement streaming response handling for commit message\ngeneration to improve user experience with large diffs.\nAdds new stream event handlers and updates the API contract.\n\nAnalyze the diff and generate a message following ALL rules above.";
|
|
181261
181265
|
const summarizePrompt = `You summarize parts of a large git diff for a commit message generator.
|
|
181262
181266
|
Describe WHAT changed, in which files or modules, and any observable intent.
|
|
181263
181267
|
Be factual and terse. Do NOT write a commit message. Maximum 120 words.`;
|
|
@@ -181268,8 +181272,8 @@ async function ask(languageModel, system, messages) {
|
|
|
181268
181272
|
messages
|
|
181269
181273
|
})).text.trim();
|
|
181270
181274
|
}
|
|
181271
|
-
async function generateCommitMessage(languageModel, instructions, diff) {
|
|
181272
|
-
return ask(languageModel,
|
|
181275
|
+
async function generateCommitMessage(languageModel, style, instructions, diff) {
|
|
181276
|
+
return ask(languageModel, style, [{
|
|
181273
181277
|
role: "user",
|
|
181274
181278
|
content: `Changes:\n${diff}`
|
|
181275
181279
|
}, {
|
|
@@ -181286,8 +181290,8 @@ async function summarizeChanges(languageModel, toc, chunk$1) {
|
|
|
181286
181290
|
content: "Summarize these changes."
|
|
181287
181291
|
}]);
|
|
181288
181292
|
}
|
|
181289
|
-
async function generateCommitMessageFromSummaries(
|
|
181290
|
-
return ask(
|
|
181293
|
+
async function generateCommitMessageFromSummaries(llm, style, instructions, toc, summaries) {
|
|
181294
|
+
return ask(llm, style, [{
|
|
181291
181295
|
role: "user",
|
|
181292
181296
|
content: `All changed files:\n${toc}\n\nSummaries of all changes:\n${summaries.map((summary, index$2) => `Part ${index$2 + 1}:\n${summary}`).join("\n\n")}`
|
|
181293
181297
|
}, {
|
|
@@ -181315,6 +181319,28 @@ function resolveLanguageModel(modelConfig) {
|
|
|
181315
181319
|
...modelConfig.options
|
|
181316
181320
|
}).languageModel(modelConfig.model);
|
|
181317
181321
|
}
|
|
181322
|
+
const BUILTIN_STYLES = {
|
|
181323
|
+
default: "You are a strict Git commit message generator. ONLY output the commit message, nothing else.\n\nREQUIRED FORMAT:\n\n- First line: <type>(<scope>): <subject> (max 50 characters)\n- Types: feat, fix, docs, style, refactor, perf, test, chore, ci\n- Subject: imperative mood, lowercase, no period\n- Optional body: blank line + concise explanation (wrapped at 72 chars)\n\nSTRICT RULES:\n\n- MUST use conventional commits format: type(scope): subject\n- Subject line MUST be under 50 characters\n- Subject MUST be in imperative mood (e.g., \"add\", \"fix\", \"update\")\n- Subject MUST be lowercase\n- Subject MUST NOT end with a period\n- MUST provide clear context about WHAT changed\n- MUST be specific about affected functions, components, or modules\n- MUST NOT use vague terms like \"Update\", \"Fix stuff\", \"Changes\"\n- Do NOT include a body for a small or focused change\n- Include a body only when the diff contains several substantial related changes and explaining them adds useful context\n- When a body is warranted, explain WHY when the rationale or impact is not obvious; do not force or invent a reason\n- If including a body, MUST have exactly one blank line between subject and body\n- Body lines MUST wrap at 72 characters\n\nOUTPUT INSTRUCTION:\nReturn ONLY the commit message. No explanations, no extra text, no markdown formatting.\n\nEXAMPLE:\nfeat(llm): add streaming responses\n\nAnalyze the diff and generate a message following ALL rules above.\n",
|
|
181324
|
+
concise: "You are a strict Git commit message generator. ONLY output the commit message, nothing else.\n\nREQUIRED FORMAT:\n- First line: <type>(<scope>): <subject> (max 50 characters)\n- Types: feat, fix, docs, style, refactor, perf, test, chore, ci\n- Subject: imperative mood, lowercase, no period\n- Exceptional body: blank line + minimal explanation (wrapped at 72 chars)\n\nSTRICT RULES:\n- MUST use conventional commits format: type(scope): subject\n- Subject line MUST be under 50 characters\n- Subject MUST be in imperative mood (e.g., \"add\", \"fix\", \"update\")\n- Subject MUST be lowercase\n- Subject MUST NOT end with a period\n- MUST provide clear context about the most important change\n- MUST be specific about affected functions, components, or modules\n- MUST NOT use vague terms like \"Update\", \"Fix stuff\", \"Changes\"\n- MUST prefer a subject line with no body\n- Include a body only when absolutely necessary to communicate critical context that cannot be expressed in the subject\n- If including a body, keep it as short as possible and explain WHY only when that rationale or impact is essential and supported by the diff\n- If including a body, MUST have exactly one blank line between subject and body\n- Body lines MUST wrap at 72 characters\n\nOUTPUT INSTRUCTION:\nReturn ONLY the commit message. No explanations, no extra text, no markdown formatting.\n\nEXAMPLE:\nfix(config): preserve provider settings\n\nAnalyze the diff and generate a message following ALL rules above.\n",
|
|
181325
|
+
explanatory: "You are a strict Git commit message generator. ONLY output the commit message, nothing else.\n\nREQUIRED FORMAT:\n- First line: <type>(<scope>): <subject> (max 72 characters)\n- Types: feat, fix, docs, style, refactor, perf, test, chore, ci\n- Subject: imperative mood, lowercase, no period\n- Encouraged body: blank line + concise explanation (wrapped at 72 chars)\n\nSTRICT RULES:\n- MUST use conventional commits format: type(scope): subject\n- Subject line MUST be under 72 characters\n- Subject MUST be in imperative mood (e.g., \"add\", \"fix\", \"update\")\n- Subject MUST be lowercase\n- Subject MUST NOT end with a period\n- MUST provide clear context about WHAT changed\n- MUST be specific about affected functions, components, or modules\n- MUST NOT use vague terms like \"Update\", \"Fix stuff\", \"Changes\"\n- Include a body whenever it adds meaningful context beyond the subject\n- Use the body to explain WHY the change was made or its impact when supported by the diff; do not force or invent a reason\n- Omit the body only when it would merely repeat the subject\n- If including a body, MUST have exactly one blank line between subject and body\n- Body lines MUST wrap at 72 characters\n\nOUTPUT INSTRUCTION:\nReturn ONLY the commit message. No explanations, no extra text, no markdown formatting.\n\nEXAMPLE:\nfix(config): preserve custom provider settings\n\nReload stored provider options before applying command-line overrides to\nprevent unrelated settings from being discarded.\n\nAnalyze the diff and generate a message following ALL rules above.\n",
|
|
181326
|
+
plain: "You are a strict Git commit message generator. ONLY output the commit message, nothing else.\n\nREQUIRED FORMAT:\n- Only line: <subject> (max 72 characters)\n- Subject: imperative mood, lowercase, no punctuation\n- No prefix, scope, emoji, or body\n\nSTRICT RULES:\n- MUST output exactly one plain subject line\n- Complete line MUST be under 72 characters\n- Subject MUST start with an imperative verb (e.g., \"add\", \"fix\", \"update\")\n- Subject MUST be lowercase\n- Subject MUST NOT end with punctuation\n- MUST provide clear context about the most important change\n- MUST be specific about affected functions, components, or modules\n- MUST NOT use vague terms like \"Update\", \"Fix stuff\", \"Changes\"\n- MUST NOT use conventional commit types, scopes, prefixes, or emoji\n- MUST NOT include a body\n\nOUTPUT INSTRUCTION:\nReturn ONLY the commit message. No explanations, no extra text, no markdown formatting.\n\nEXAMPLE:\npreserve custom provider settings\n\nAnalyze the diff and generate a message following ALL rules above.\n",
|
|
181327
|
+
gitmoji: "You are a strict Git commit message generator. ONLY output the commit message, nothing else.\n\nREQUIRED FORMAT:\n- Only line: <gitmoji> <type>(<scope>): <subject> (max 72 characters)\n- Types: feat, fix, docs, style, refactor, perf, test, chore, ci\n- Subject: imperative mood, lowercase, no period\n- No body\n\nSTRICT RULES:\n- MUST use gitmoji conventional commits format: <gitmoji> type(scope): subject\n- MUST choose exactly one gitmoji that best represents the change\n- Use relevant gitmoji such as ✨ for features, 🐛 for fixes, 📝 for documentation, ♻️ for refactoring, ✅ for tests, or 🔧 for configuration\n- Complete line MUST be under 72 characters\n- Subject MUST be in imperative mood (e.g., \"add\", \"fix\", \"update\")\n- Subject MUST be lowercase\n- Subject MUST NOT end with a period\n- MUST provide clear context about the most important change\n- MUST be specific about affected functions, components, or modules\n- MUST NOT use vague terms like \"Update\", \"Fix stuff\", \"Changes\"\n- MUST NOT include a body\n\nOUTPUT INSTRUCTION:\nReturn ONLY the commit message. No explanations, no extra text, no markdown formatting.\n\nEXAMPLE:\n✨ feat(cli): add interactive style selection\n\nAnalyze the diff and generate a message following ALL rules above.\n"
|
|
181328
|
+
};
|
|
181329
|
+
function getStyleKeys(styles$2) {
|
|
181330
|
+
return Object.keys({
|
|
181331
|
+
...BUILTIN_STYLES,
|
|
181332
|
+
...styles$2
|
|
181333
|
+
});
|
|
181334
|
+
}
|
|
181335
|
+
async function resolveStyle(styleKey, styles$2) {
|
|
181336
|
+
const style = styles$2?.[styleKey] ?? BUILTIN_STYLES[styleKey];
|
|
181337
|
+
if (!style) return;
|
|
181338
|
+
return resolveInstructionContent(style);
|
|
181339
|
+
}
|
|
181340
|
+
async function resolveInstructionContent(instruction) {
|
|
181341
|
+
if (typeof instruction === "string") return instruction;
|
|
181342
|
+
return readFile(path.resolve(instruction.path), "utf8");
|
|
181343
|
+
}
|
|
181318
181344
|
const isUpKey = (key$1, keybindings = []) => key$1.name === "up" || keybindings.includes("vim") && key$1.name === "k" || keybindings.includes("emacs") && key$1.ctrl && key$1.name === "p";
|
|
181319
181345
|
const isDownKey = (key$1, keybindings = []) => key$1.name === "down" || keybindings.includes("vim") && key$1.name === "j" || keybindings.includes("emacs") && key$1.ctrl && key$1.name === "n";
|
|
181320
181346
|
const isSpaceKey = (key$1) => key$1.name === "space";
|
|
@@ -198117,7 +198143,11 @@ async function runWithLoading(label, task) {
|
|
|
198117
198143
|
let index$2 = 0;
|
|
198118
198144
|
const interval = setInterval(() => {
|
|
198119
198145
|
readline.cursorTo(process.stdout, 0);
|
|
198120
|
-
process.stdout.write(
|
|
198146
|
+
process.stdout.write([
|
|
198147
|
+
source_default.cyan(frames[index$2]) + " ",
|
|
198148
|
+
source_default.cyan(label),
|
|
198149
|
+
source_default.reset.dim("...")
|
|
198150
|
+
].join(""));
|
|
198121
198151
|
index$2 = (index$2 + 1) % frames.length;
|
|
198122
198152
|
}, 80);
|
|
198123
198153
|
try {
|
|
@@ -198143,10 +198173,17 @@ async function mainController(options = {}) {
|
|
|
198143
198173
|
throw new Error(hint);
|
|
198144
198174
|
}
|
|
198145
198175
|
const languageModel = resolveLanguageModel(modelConfig);
|
|
198176
|
+
const styleKey = options.style ?? config$4.style ?? "default";
|
|
198177
|
+
const style = await resolveStyle(styleKey, config$4.styles);
|
|
198178
|
+
if (!style) {
|
|
198179
|
+
const availableStyles = getStyleKeys(config$4.styles).join(", ");
|
|
198180
|
+
throw new Error(`Style '${styleKey}' is not configured. Available styles: ${availableStyles}.`);
|
|
198181
|
+
}
|
|
198182
|
+
const instructions = config$4.instructions ? await resolveInstructionContent(config$4.instructions) : null;
|
|
198146
198183
|
const forceLLMGenerate = options.generate || options.yolo;
|
|
198147
198184
|
const forceExecPostCommand = options.post || options.yolo;
|
|
198148
|
-
let finalCommitMessage = options.
|
|
198149
|
-
if (typeof options.
|
|
198185
|
+
let finalCommitMessage = options.input?.trim() ?? "";
|
|
198186
|
+
if (typeof options.input === "string" && finalCommitMessage.length === 0) throw new Error("Provided commit message input cannot be empty.");
|
|
198150
198187
|
const files = await getChangedFiles(git);
|
|
198151
198188
|
if (files.length === 0) return console.log("No changed files found.");
|
|
198152
198189
|
const { diff, hasStaged } = await getCommitDiff(git);
|
|
@@ -198168,11 +198205,12 @@ async function mainController(options = {}) {
|
|
|
198168
198205
|
finalCommitMessage = (await runWithLoading("Generating commit message", () => generateMessage({
|
|
198169
198206
|
git,
|
|
198170
198207
|
languageModel,
|
|
198171
|
-
|
|
198208
|
+
style,
|
|
198209
|
+
instructions,
|
|
198172
198210
|
diff,
|
|
198173
198211
|
files,
|
|
198174
|
-
|
|
198175
|
-
|
|
198212
|
+
perFileCap: config$4.perFileCap ?? DEFAULT_PER_FILE_CAP,
|
|
198213
|
+
maxDiffTokens: config$4.maxDiffTokens ?? DEFAULT_MAX_DIFF_TOKENS
|
|
198176
198214
|
}))).trim();
|
|
198177
198215
|
if (finalCommitMessage.length === 0) throw new Error("The selected model returned an empty commit message.");
|
|
198178
198216
|
console.log(source_default.cyan.dim(finalCommitMessage));
|
|
@@ -198194,15 +198232,13 @@ async function mainController(options = {}) {
|
|
|
198194
198232
|
if (config$4.postCommand === "push-and-pull") await liveGit.pull();
|
|
198195
198233
|
}
|
|
198196
198234
|
async function generateMessage(options) {
|
|
198197
|
-
const { git, languageModel, instructions, diff } = options;
|
|
198198
|
-
if (estimateTokens(diff) <= options.maxDiffTokens) return generateCommitMessage(languageModel, instructions, diff);
|
|
198199
|
-
console.log(source_default.yellow("• Large diff detected, minimizing"));
|
|
198235
|
+
const { git, languageModel, style, instructions, diff } = options;
|
|
198236
|
+
if (estimateTokens(diff) <= options.maxDiffTokens) return generateCommitMessage(languageModel, style, instructions, diff);
|
|
198200
198237
|
const { toc, body } = await minimizeDiff(git, {
|
|
198201
198238
|
perFileCap: options.perFileCap,
|
|
198202
198239
|
allFiles: options.files
|
|
198203
198240
|
});
|
|
198204
|
-
if (estimateTokens(toc) + estimateTokens(body) <= options.maxDiffTokens) return generateCommitMessage(languageModel, instructions, `${toc}\n\n${body}`);
|
|
198205
|
-
console.log(source_default.yellow("• Diff still too large, summarizing in parts"));
|
|
198241
|
+
if (estimateTokens(toc) + estimateTokens(body) <= options.maxDiffTokens) return generateCommitMessage(languageModel, style, instructions, `${toc}\n\n${body}`);
|
|
198206
198242
|
let effectiveToc = toc;
|
|
198207
198243
|
let chunkBudget = options.maxDiffTokens - estimateTokens(effectiveToc) - PROMPT_RESERVE_TOKENS;
|
|
198208
198244
|
if (chunkBudget < MIN_CHUNK_BUDGET_TOKENS) {
|
|
@@ -198219,7 +198255,7 @@ async function generateMessage(options) {
|
|
|
198219
198255
|
}
|
|
198220
198256
|
}
|
|
198221
198257
|
await Promise.all(Array.from({ length: Math.min(MAP_CONCURRENCY, chunks.length) }, worker));
|
|
198222
|
-
return generateCommitMessageFromSummaries(languageModel, instructions, effectiveToc, summaries);
|
|
198258
|
+
return generateCommitMessageFromSummaries(languageModel, style, instructions, effectiveToc, summaries);
|
|
198223
198259
|
}
|
|
198224
198260
|
var AppUserCanceledError = class extends Error {};
|
|
198225
198261
|
function handleError(fn$1) {
|
|
@@ -198231,9 +198267,9 @@ function handleError(fn$1) {
|
|
|
198231
198267
|
}
|
|
198232
198268
|
});
|
|
198233
198269
|
}
|
|
198234
|
-
const app = new Command().name("gityo").
|
|
198235
|
-
if (options.generate && options.
|
|
198236
|
-
console.error("Cannot use --generate and --
|
|
198270
|
+
const app = new Command().name("gityo").description("Stage changes, generate or enter a commit message, create a commit, and run a post-commit git command.").option("-i, --input <input>", "Use the provided input as the commit message.").option("-s, --style <style>", "Commit message style key to use (defaults to \"default\").").option("-m, --model <model>", "Model key from config to use (defaults to \"default\").").option("-g, --generate", "Generate a commit message and commit without asking.").option("-p, --post", "Run the post-commit git command without asking.").option("-y, --yolo", "Skip all questions, and generate message, commit, run post command. [Will fail if no model available]").version(`v${version$4}`, "-v, --version", "Show the current version.").action((options) => {
|
|
198271
|
+
if (options.generate && options.input) {
|
|
198272
|
+
console.error("Cannot use --generate and --input together.");
|
|
198237
198273
|
process.exit(1);
|
|
198238
198274
|
}
|
|
198239
198275
|
handleError(() => mainController(options));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gityo",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.12",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "git+https://github.com/NazmusSayad/gityo.git"
|
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
"sideEffects": false,
|
|
9
9
|
"type": "module",
|
|
10
10
|
"scripts": {
|
|
11
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"typecheck:watch": "tsc --noEmit --watch",
|
|
13
|
+
"lint": "eslint .",
|
|
14
|
+
"lint:fix": "eslint . --fix",
|
|
14
15
|
"build": "tsdown --config ./tsdown.config.ts",
|
|
15
|
-
"dev": "
|
|
16
|
-
"
|
|
16
|
+
"dev": "tsdown --config ./tsdown.config.ts --watch",
|
|
17
|
+
"start": "node --watch ./dist/index.js",
|
|
17
18
|
"json": "tsx ./src/json.ts"
|
|
18
19
|
},
|
|
19
20
|
"bin": {
|