git-repo-comitter 0.4.7 → 0.5.1
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 +41 -42
- package/dist/index.cjs +9 -6
- package/package.json +3 -5
- package/dist/index.cjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,60 +1,71 @@
|
|
|
1
1
|
# git-repo-comitter
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/git-repo-comitter)
|
|
4
|
+
[](https://unlicense.org)
|
|
5
|
+
|
|
6
|
+
基于大语言模型的 Git 提交信息生成工具。自动读取 Git 差异,调用 OpenAI 兼容 API 生成 [Conventional Commits](https://www.conventionalcommits.org/) 格式的提交信息并执行提交。
|
|
4
7
|
|
|
5
8
|
## 特性
|
|
6
9
|
|
|
7
|
-
- 自动检测暂存/未暂存的变更,合并为完整 diff 提交给 LLM
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
- 环境变量 `.env` 和用户配置文件双重覆盖
|
|
11
|
-
- 无暂存变更时自动 `git add -A`
|
|
12
|
-
- 内置 Conventional Commits 中文 prompt
|
|
10
|
+
- **自动差异收集** — 自动检测暂存/未暂存的变更,合并为完整 diff 提交给 LLM
|
|
11
|
+
- **一站式配置** — 交互式初始化向导,配置持久化到 `~/.grc/config.json`
|
|
12
|
+
- **中文提交信息** — 内置 Conventional Commits 中文 prompt,生成中文描述
|
|
13
13
|
|
|
14
|
-
##
|
|
14
|
+
## 使用示例
|
|
15
|
+
```text
|
|
16
|
+
D:\path\to\repo> grc
|
|
17
|
+
暂存所有变更...
|
|
18
|
+
正在生成提交信息...
|
|
15
19
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
```
|
|
20
|
+
提交信息:
|
|
21
|
+
docs(readme): 更新 README 文档结构和配置优先级说明
|
|
19
22
|
|
|
20
|
-
|
|
23
|
+
- 移除“模型无关”特性描述
|
|
24
|
+
- 简化配置优先级为两层:用户配置和系统环境变量
|
|
25
|
+
- 调整环境变量表格格式,默认端点改为 localhost
|
|
26
|
+
- 将“快速开始”章节提前,移除“技术栈”和“许可”章节
|
|
21
27
|
|
|
22
|
-
|
|
23
|
-
pnpm build && node dist/index.cjs
|
|
24
|
-
```
|
|
28
|
+
提交成功!
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
D:\path\to\repo>
|
|
31
|
+
```
|
|
27
32
|
|
|
28
|
-
|
|
33
|
+
## 快速开始
|
|
29
34
|
|
|
30
35
|
```bash
|
|
31
36
|
# 交互式配置
|
|
32
|
-
npx
|
|
37
|
+
npx grc init
|
|
33
38
|
|
|
34
39
|
# 生成提交信息并提交
|
|
35
|
-
npx
|
|
40
|
+
npx grc
|
|
36
41
|
```
|
|
37
42
|
|
|
38
|
-
|
|
43
|
+
## 安装
|
|
39
44
|
|
|
40
45
|
```bash
|
|
41
|
-
grc
|
|
42
|
-
grc
|
|
46
|
+
npx grc --version
|
|
43
47
|
```
|
|
44
48
|
|
|
49
|
+
本地开发:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pnpm build && node dist/index.cjs
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## 使用
|
|
56
|
+
|
|
45
57
|
### 配置优先级
|
|
46
58
|
|
|
47
59
|
1. 用户配置文件 `~/.grc/config.json`
|
|
48
|
-
2.
|
|
49
|
-
3. 环境变量
|
|
60
|
+
2. 系统环境变量
|
|
50
61
|
|
|
51
62
|
### 环境变量
|
|
52
63
|
|
|
53
|
-
| 变量
|
|
54
|
-
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
64
|
+
| 变量 | 说明 | 默认值 |
|
|
65
|
+
|----------------|----------|----------------------------|
|
|
66
|
+
| `LLM_ENDPOINT` | API 端点 | `https://localhost/api/v1` |
|
|
67
|
+
| `LLM_MODEL` | 模型名称 | `deepseek-v4-flash` |
|
|
68
|
+
| `LLM_API_KEY` | API 密钥 | |
|
|
58
69
|
|
|
59
70
|
### 交互式初始化
|
|
60
71
|
|
|
@@ -66,16 +77,4 @@ grc init
|
|
|
66
77
|
|
|
67
78
|
## 提交信息风格
|
|
68
79
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
## 技术栈
|
|
72
|
-
|
|
73
|
-
- TypeScript + Vite(构建 CLI 产物为 CommonJS)
|
|
74
|
-
- OpenAI SDK
|
|
75
|
-
- YAML(用户配置解析)
|
|
76
|
-
- dotenv(环境变量加载)
|
|
77
|
-
- Husky + lint-staged + ESLint + Prettier
|
|
78
|
-
|
|
79
|
-
## 许可
|
|
80
|
-
|
|
81
|
-
Unlicense — 公有领域贡献。
|
|
80
|
+
遵循 Conventional Commits 规范,中文描述。支持 `feat`、`fix`、`refactor`、`docs` 等类型,scope 可选,正文支持分条陈述。
|
package/dist/index.cjs
CHANGED
|
@@ -3,7 +3,10 @@ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=
|
|
|
3
3
|
`+e),t.trim()&&n.push(`=== Unstaged Changes ===
|
|
4
4
|
`+t),n.join(`
|
|
5
5
|
|
|
6
|
-
`)}function w(){return S(`diff --cached --name-only`).trim().length>0}function T(e){let t=(typeof e==`string`?JSON.parse(e):e).choices?.[0]?.message?.content;return typeof t==`string`?t.trim():Array.isArray(t)?t.filter(e=>e.type===`text`).map(e=>e.text).join(``).trim():``}var E
|
|
6
|
+
`)}function w(){return S(`diff --cached --name-only`).trim().length>0}function T(e){let t=(typeof e==`string`?JSON.parse(e):e).choices?.[0]?.message?.content;return typeof t==`string`?t.trim():Array.isArray(t)?t.filter(e=>e.type===`text`).map(e=>e.text).join(``).trim():``}var E=[`feat`,`fix`,`docs`,`style`,`refactor`,`perf`,`test`,`build`,`ci`,`chore`,`revert`];function D(e){let t=e.indexOf(`
|
|
7
|
+
|
|
8
|
+
`),n=t===-1?e.trim():e.slice(0,t).trim(),r=t===-1?``:e.slice(t+2).trim(),i=n.match(/^(?<type>[a-zA-Z]+)(?:\((?<scope>[^)]*)\))?(?<breaking>!)?:\s*(?<description>.+)$/);if(!i)return{valid:!1,reason:`标题不符合 Conventional Commits 格式:type(optional scope): description`};let{type:a,description:o}=i.groups;if(!E.includes(a))return{valid:!1,reason:`type 字段的值 "${a}" 不在允许的列表中 (${E.join(`, `)})`};if(n.length>72)return{valid:!1,reason:`标题行超过 72 字符限制 (当前 ${n.length} 字符)`};if(r){if(t===-1)return{valid:!1,reason:`正文前需空一行`};let e=r.split(`
|
|
9
|
+
`).filter(e=>e.length>72);if(e.length>0)return{valid:!1,reason:`正文行超出 72 字符限制: ${e.join(`, `)}`}}return{valid:!0}}var O=`你是一位擅长编写 Git 提交信息的专家。根据提供的 Git diff,生成简洁且描述准确的提交信息。
|
|
7
10
|
|
|
8
11
|
格式规范:
|
|
9
12
|
- 遵循 Conventional Commits:<type>(<scope>): <description>
|
|
@@ -33,9 +36,9 @@ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=
|
|
|
33
36
|
- 迁移 session 和 permission 模块至新接口
|
|
34
37
|
- 移除已废弃的 getCacheKey 方法
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
`)
|
|
38
|
-
`);let
|
|
39
|
+
只回复提交信息本身,不要添加任何解释。`,k=3;async function A(e,t){if(!t.apiKey)throw Error(`LLM_API_KEY 未设置,请在 .env 或环境变量中配置。`);let n=new p.default({apiKey:t.apiKey,baseURL:t.endpoint}),r=[{role:`system`,content:O},{role:`user`,content:`以下是 Git diff 内容:\n\n${e}`}];for(let e=1;e<=k;e++){let i=await n.chat.completions.create({model:t.llm.model,temperature:t.llm.temperature,max_tokens:t.llm.maxOutputTokens,messages:r}),a=T(i);if(!a)throw Error(`LLM 返回了空的提交信息。响应内容:${JSON.stringify(i)}`);let o=await D(a);if(o.valid)return a;if(e<k)console.log(` 提交信息格式校验未通过(第 ${e} 次): ${o.reason}`),console.log(` 正在重新生成...
|
|
40
|
+
`),r.push({role:`assistant`,content:a},{role:`user`,content:`生成的提交信息格式不符合规范:${o.reason}。请严格按照 Conventional Commits 格式重新生成。`});else throw Error(`LLM 提交信息格式校验失败(已重试 ${k} 次): ${o.reason}\n最后一次生成的提交信息:\n${a}`)}throw Error(`意外的错误:重试循环结束后仍未能生成有效提交信息`)}function j(){let e=y();return e.apiKey||(console.error("错误:LLM_API_KEY 未设置,请运行 `grc init` 进行配置。"),process.exit(1)),e}function M(){w()?console.log(`检出已有暂存变更,直接提交...`):(console.log(`暂存所有变更...`),b())}function N(){let e=C();return e.trim()||(console.log(`没有可提交的变更。`),process.exit(0)),e}async function P(){let e=j();M();let t=N();console.log(`正在生成提交信息...
|
|
41
|
+
`);let n=await A(t,e);x(n),console.log(`提交信息:\n ${n}\n`),console.log(`提交成功!`)}function F(e){let t=(0,m.createInterface)({input:process.stdin,output:process.stdout});return t.question(e).finally(()=>t.close())}async function I(){console.log(`LLM 配置初始化
|
|
42
|
+
`);let e=_(),t=(await F(`大模型链接(API 地址)[${e.endpoint||`https://api.openai.com/v1`}]: `)).trim()||e.endpoint||`https://api.openai.com/v1`,n=(await F(`模型名称 [${e.llm?.model||`deepseek-v4-flash`}]: `)).trim()||e.llm?.model||`deepseek-v4-flash`,r=(await F(`API Key [${e.apiKey?`***`:`(必填)`}]: `)).trim()||e.apiKey;r||(console.error(`
|
|
39
43
|
错误:API Key 不能为空。`),process.exit(1)),v({apiKey:r,endpoint:t,llm:{model:n,temperature:.7,maxInputTokens:262144,maxOutputTokens:16384}}),console.log(`
|
|
40
|
-
配置已保存到 ~/.grc/config.json`)}function
|
|
41
|
-
//# sourceMappingURL=index.cjs.map
|
|
44
|
+
配置已保存到 ~/.grc/config.json`)}function L(){let e=(0,u.resolve)(__dirname,`..`,`package.json`);return JSON.parse((0,l.readFileSync)(e,`utf-8`)).version}var R=new c.Command;R.name(`grc`).version(L(),`-v, --version`,`显示当前版本`).description(`一款使用 LLM 生成 Git 提交信息并执行提交的命令行工具`).helpOption(`-h, --help`,`显示帮助信息`),R.command(`init`).description(`交互式 LLM 配置初始化`).action(()=>{I().catch(e=>{console.error(`错误:`,e.message),process.exit(1)})});function z(){if(process.argv.slice(2).length===0){P().catch(e=>{console.error(`错误:`,e.message),process.exit(1)});return}R.parse(process.argv)}z();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "git-repo-comitter",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"description": "A CLI tool that uses LLM to generate Git commit messages and execute commits",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
@@ -12,10 +12,9 @@
|
|
|
12
12
|
"dist"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
-
"
|
|
16
|
-
"build": "tsc && vite build",
|
|
17
|
-
"preview": "vite preview",
|
|
15
|
+
"build": "tsc --noEmit && vite build",
|
|
18
16
|
"lint": "eslint src/",
|
|
17
|
+
"check": "tsc --noEmit",
|
|
19
18
|
"format": "prettier --write \"src/**/*.ts\"",
|
|
20
19
|
"prepare": "husky"
|
|
21
20
|
},
|
|
@@ -63,7 +62,6 @@
|
|
|
63
62
|
},
|
|
64
63
|
"dependencies": {
|
|
65
64
|
"commander": "^15.0.0",
|
|
66
|
-
"dotenv": "^17.4.2",
|
|
67
65
|
"openai": "^6.46.0",
|
|
68
66
|
"yaml": "^2.9.0"
|
|
69
67
|
}
|
package/dist/index.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/config/types.ts","../src/config/loader.ts","../src/git/commit.ts","../src/git/diff.ts","../src/utils/llm.ts","../src/llm/client.ts","../src/commands/commit.ts","../src/utils/cli.ts","../src/commands/init.ts","../src/cli.ts","../src/index.ts"],"sourcesContent":["export interface LLMConfig {\n model: string;\n temperature: number;\n maxInputTokens: number;\n maxOutputTokens: number;\n}\n\nexport interface AppConfig {\n llm: LLMConfig;\n apiKey: string;\n endpoint: string;\n}\n\nexport const DEFAULT_CONFIG: AppConfig = {\n llm: {\n model: \"deepseek-v4-flash\",\n temperature: 0.7,\n maxInputTokens: 262144,\n maxOutputTokens: 16384,\n },\n apiKey: \"\",\n endpoint: \"https://api.openai.com/v1\",\n};\n","import { existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { homedir } from \"os\";\nimport { resolve } from \"path\";\n\nimport { type AppConfig, DEFAULT_CONFIG } from \"./types\";\n\nconst USER_CONFIG_PATH = resolve(homedir(), \".grc\", \"config.json\");\n\nexport function loadUserConfig(): Partial<AppConfig> {\n try {\n if (!existsSync(USER_CONFIG_PATH)) return {};\n const raw = readFileSync(USER_CONFIG_PATH, \"utf-8\");\n const parsed = JSON.parse(raw);\n return {\n ...parsed,\n llm: parsed.llm ? { ...parsed.llm } : undefined,\n };\n } catch {\n return {};\n }\n}\n\nexport function saveUserConfig(config: Partial<AppConfig>): void {\n const dir = resolve(homedir(), \".grc\");\n if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n writeFileSync(USER_CONFIG_PATH, JSON.stringify(config, null, 2), \"utf-8\");\n}\n\nexport function loadConfig(): AppConfig {\n const userConfig = loadUserConfig();\n\n const envModel = process.env.LLM_MODEL;\n const envApiKey = process.env.LLM_API_KEY;\n const envEndpoint = process.env.LLM_ENDPOINT;\n\n return {\n ...DEFAULT_CONFIG,\n ...userConfig,\n llm: {\n ...DEFAULT_CONFIG.llm,\n ...(userConfig.llm || {}),\n ...(envModel ? { model: envModel } : {}),\n },\n apiKey: envApiKey || userConfig.apiKey || \"\",\n endpoint: envEndpoint || userConfig.endpoint || DEFAULT_CONFIG.endpoint,\n };\n}\n","import { execSync } from \"child_process\";\n\nexport function gitAddAll(): void {\n execSync(\"git add .\", { cwd: process.cwd(), encoding: \"utf-8\" });\n}\n\nexport function gitCommit(message: string): void {\n const escapedMessage = message.replace(/\"/g, '\\\\\"');\n execSync(`git commit -m \"${escapedMessage}\"`, {\n cwd: process.cwd(),\n encoding: \"utf-8\",\n });\n}\n","import { execSync } from \"child_process\";\n\nfunction execGit(args: string): string {\n try {\n return execSync(`git ${args}`, {\n cwd: process.cwd(),\n encoding: \"utf-8\",\n });\n } catch {\n return \"\";\n }\n}\n\nexport function getAllDiff(): string {\n const staged = execGit(\"diff --cached\");\n const unstaged = execGit(\"diff\");\n\n const parts: string[] = [];\n if (staged.trim()) {\n parts.push(\"=== Staged Changes ===\\n\" + staged);\n }\n if (unstaged.trim()) {\n parts.push(\"=== Unstaged Changes ===\\n\" + unstaged);\n }\n return parts.join(\"\\n\\n\");\n}\n\nexport function hasStagedChanges(): boolean {\n const result = execGit(\"diff --cached --name-only\");\n return result.trim().length > 0;\n}\n","export interface MessageContentPart {\n type: string;\n text: string;\n}\n\nexport interface ChatCompletionMessage {\n content: string | MessageContentPart[] | null;\n}\n\nexport interface ChatCompletionChoice {\n message: ChatCompletionMessage;\n}\n\nexport interface ChatCompletionResponse {\n choices: ChatCompletionChoice[];\n}\n\nexport function extractContent(\n response: ChatCompletionResponse | string,\n): string {\n const data = typeof response === \"string\" ? JSON.parse(response) : response;\n const content = data.choices?.[0]?.message?.content;\n if (typeof content === \"string\") return content.trim();\n if (Array.isArray(content)) {\n return content\n .filter((c) => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\")\n .trim();\n }\n return \"\";\n}\n","import OpenAI from \"openai\";\n\nimport type { AppConfig } from \"../config/types\";\nimport { extractContent } from \"../utils/llm\";\n\nconst SYSTEM_PROMPT = `你是一位擅长编写 Git 提交信息的专家。根据提供的 Git diff,生成简洁且描述准确的提交信息。\n\n格式规范:\n- 遵循 Conventional Commits:<type>(<scope>): <description>\n- type 可选值:feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert\n- 标题行控制在 72 字符以内\n- 正文使用无序列表分条陈述,每条以 \"- \" 开头\n- 如变更较简单,可省略正文,仅保留标题行\n- 标题和正文之间用空行隔开\n- 提交的信息必须符合 Conventional Commits 格式\n- 描述语言使用中文,避免使用英文。\n\n示例:\n1. 仅标题行:\n fix(auth): 修复登录重定向丢失 query 参数的问题\n\n2. 标题 + 正文:\n feat(api): 新增用户批量导入接口\n\n - 支持 CSV 和 JSON 两种文件格式\n - 单次最多处理 1000 条记录\n - 导入失败时返回逐条错误详情\n\n3. 多处关联变更:\n refactor(storage): 统一缓存键的生成逻辑\n\n - 抽取 keyBuilder 工具函数替代各处硬编码\n - 迁移 session 和 permission 模块至新接口\n - 移除已废弃的 getCacheKey 方法\n\n只回复提交信息本身,不要添加任何解释。`;\n\nexport async function generateCommitMessage(\n diff: string,\n config: AppConfig,\n): Promise<string> {\n if (!config.apiKey) {\n throw new Error(\"LLM_API_KEY 未设置,请在 .env 或环境变量中配置。\");\n }\n\n const client = new OpenAI({\n apiKey: config.apiKey,\n baseURL: config.endpoint,\n });\n\n const response = await client.chat.completions.create({\n model: config.llm.model,\n temperature: config.llm.temperature,\n max_tokens: config.llm.maxOutputTokens,\n messages: [\n { role: \"system\", content: SYSTEM_PROMPT },\n {\n role: \"user\",\n content: `以下是 Git diff 内容:\\n\\n${diff}`,\n },\n ],\n });\n\n const message = extractContent(response);\n if (!message) {\n throw new Error(\n `LLM 返回了空的提交信息。响应内容:${JSON.stringify(response)}`,\n );\n }\n return message;\n}\n","import { loadConfig } from \"../config/loader\";\nimport type { AppConfig } from \"../config/types\";\nimport { gitAddAll, gitCommit } from \"../git/commit\";\nimport { getAllDiff, hasStagedChanges } from \"../git/diff\";\nimport { generateCommitMessage } from \"../llm/client\";\n\nfunction ensureConfig(): AppConfig {\n const config = loadConfig();\n if (!config.apiKey) {\n console.error(\"错误:LLM_API_KEY 未设置,请运行 `grc init` 进行配置。\");\n process.exit(1);\n }\n return config;\n}\n\nfunction stageOrProceed(): void {\n if (hasStagedChanges()) {\n console.log(\"检出已有暂存变更,直接提交...\");\n } else {\n console.log(\"暂存所有变更...\");\n gitAddAll();\n }\n}\n\nfunction getChanges(): string {\n const diff = getAllDiff();\n if (!diff.trim()) {\n console.log(\"没有可提交的变更。\");\n process.exit(0);\n }\n return diff;\n}\n\nexport async function runCommit(): Promise<void> {\n const config = ensureConfig();\n stageOrProceed();\n const diff = getChanges();\n console.log(\"正在生成提交信息...\\n\");\n const message = await generateCommitMessage(diff, config);\n gitCommit(message);\n console.log(`提交信息:\\n ${message}\\n`);\n console.log(\"提交成功!\");\n}\n","import { createInterface } from \"readline/promises\";\n\nexport function question(query: string): Promise<string> {\n const rl = createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n return rl.question(query).finally(() => rl.close());\n}\n","import { loadUserConfig, saveUserConfig } from \"../config/loader\";\nimport { question } from \"../utils/cli\";\n\nexport async function runInit(): Promise<void> {\n console.log(\"LLM 配置初始化\\n\");\n\n const existing = loadUserConfig();\n\n const endpoint =\n (\n await question(\n `大模型链接(API 地址)[${existing.endpoint || \"https://api.openai.com/v1\"}]: `,\n )\n ).trim() ||\n existing.endpoint ||\n \"https://api.openai.com/v1\";\n\n const model =\n (\n await question(\n `模型名称 [${existing.llm?.model || \"deepseek-v4-flash\"}]: `,\n )\n ).trim() ||\n existing.llm?.model ||\n \"deepseek-v4-flash\";\n\n const apiKey =\n (\n await question(`API Key [${existing.apiKey ? \"***\" : \"(必填)\"}]: `)\n ).trim() || existing.apiKey;\n\n if (!apiKey) {\n console.error(\"\\n错误:API Key 不能为空。\");\n process.exit(1);\n }\n\n saveUserConfig({\n apiKey,\n endpoint,\n llm: {\n model,\n temperature: 0.7,\n maxInputTokens: 262144,\n maxOutputTokens: 16384,\n },\n });\n console.log(\"\\n配置已保存到 ~/.grc/config.json\");\n}\n","import { Command } from \"commander\";\nimport { readFileSync } from \"fs\";\nimport { resolve } from \"path\";\n\nimport { runCommit } from \"./commands/commit\";\nimport { runInit } from \"./commands/init\";\n\nexport function getVersion(): string {\n const pkgPath = resolve(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n return pkg.version;\n}\nconst program = new Command();\n\nprogram\n .name(\"grc\")\n .version(getVersion(), \"-v, --version\", \"显示当前版本\")\n .description(\"一款使用 LLM 生成 Git 提交信息并执行提交的命令行工具\")\n .helpOption(\"-h, --help\", \"显示帮助信息\");\n\nprogram\n .command(\"init\")\n .description(\"交互式 LLM 配置初始化\")\n .action(() => {\n runInit().catch((err: Error) => {\n console.error(\"错误:\", err.message);\n process.exit(1);\n });\n });\n\nexport function runCli(): void {\n const args = process.argv.slice(2);\n\n if (args.length === 0) {\n runCommit().catch((err: Error) => {\n console.error(\"错误:\", err.message);\n process.exit(1);\n });\n return;\n }\n\n program.parse(process.argv);\n}\n","import { runCli } from \"./cli\";\n\nrunCli();\n"],"mappings":";soBAaA,IAAa,EAA4B,CACvC,IAAK,CACH,MAAO,oBACP,YAAa,GACb,eAAgB,OAChB,gBAAiB,KACnB,EACA,OAAQ,GACR,SAAU,2BACZ,EChBM,GAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,CAAmC,EAAG,OAAQ,aAAa,EAEjE,SAAgB,GAAqC,CACnD,GAAI,CACF,GAAI,EAAA,EAAA,EAAA,WAAA,CAAY,CAAgB,EAAG,MAAO,CAAC,EAC3C,IAAM,GAAA,EAAA,EAAA,aAAA,CAAmB,EAAkB,OAAO,EAC5C,EAAS,KAAK,MAAM,CAAG,EAC7B,MAAO,CACL,GAAG,EACH,IAAK,EAAO,IAAM,CAAE,GAAG,EAAO,GAAI,EAAI,IAAA,EACxC,CACF,MAAQ,CACN,MAAO,CAAC,CACV,CACF,CAEA,SAAgB,EAAe,EAAkC,CAC/D,IAAM,GAAA,EAAA,EAAA,QAAA,EAAA,EAAA,EAAA,QAAA,CAAsB,EAAG,MAAM,GACjC,EAAA,EAAA,WAAA,CAAY,CAAG,IAAG,EAAA,EAAA,UAAA,CAAU,EAAK,CAAE,UAAW,EAAK,CAAC,GACxD,EAAA,EAAA,cAAA,CAAc,EAAkB,KAAK,UAAU,EAAQ,KAAM,CAAC,EAAG,OAAO,CAC1E,CAEA,SAAgB,GAAwB,CACtC,IAAM,EAAa,EAAe,EAE5B,EAAW,QAAQ,IAAI,UACvB,EAAY,QAAQ,IAAI,YACxB,EAAc,QAAQ,IAAI,aAEhC,MAAO,CACL,GAAG,EACH,GAAG,EACH,IAAK,CACH,GAAG,EAAe,IAClB,GAAI,EAAW,KAAO,CAAC,EACvB,GAAI,EAAW,CAAE,MAAO,CAAS,EAAI,CAAC,CACxC,EACA,OAAQ,GAAa,EAAW,QAAU,GAC1C,SAAU,GAAe,EAAW,UAAY,EAAe,QACjE,CACF,CC5CA,SAAgB,GAAkB,EAChC,EAAA,EAAA,SAAA,CAAS,YAAa,CAAE,IAAK,QAAQ,IAAI,EAAG,SAAU,OAAQ,CAAC,CACjE,CAEA,SAAgB,EAAU,EAAuB,EAE/C,EAAA,EAAA,SAAA,CAAS,kBADc,EAAQ,QAAQ,KAAM,KAClB,EAAe,GAAI,CAC5C,IAAK,QAAQ,IAAI,EACjB,SAAU,OACZ,CAAC,CACH,CCVA,SAAS,EAAQ,EAAsB,CACrC,GAAI,CACF,OAAA,EAAA,EAAA,SAAA,CAAgB,OAAO,IAAQ,CAC7B,IAAK,QAAQ,IAAI,EACjB,SAAU,OACZ,CAAC,CACH,MAAQ,CACN,MAAO,EACT,CACF,CAEA,SAAgB,GAAqB,CACnC,IAAM,EAAS,EAAQ,eAAe,EAChC,EAAW,EAAQ,MAAM,EAEzB,EAAkB,CAAC,EAOzB,OANI,EAAO,KAAK,GACd,EAAM,KAAK;EAA6B,CAAM,EAE5C,EAAS,KAAK,GAChB,EAAM,KAAK;EAA+B,CAAQ,EAE7C,EAAM,KAAK;;CAAM,CAC1B,CAEA,SAAgB,GAA4B,CAE1C,OADe,EAAQ,2BAChB,CAAA,CAAO,KAAK,CAAC,CAAC,OAAS,CAChC,CCbA,SAAgB,EACd,EACQ,CAER,IAAM,GADO,OAAO,GAAa,SAAW,KAAK,MAAM,CAAQ,EAAI,EAAA,CAC9C,UAAU,EAAE,EAAE,SAAS,QAS5C,OARI,OAAO,GAAY,SAAiB,EAAQ,KAAK,EACjD,MAAM,QAAQ,CAAO,EAChB,EACJ,OAAQ,GAAM,EAAE,OAAS,MAAM,CAAC,CAChC,IAAK,GAAM,EAAE,IAAI,CAAC,CAClB,KAAK,EAAE,CAAC,CACR,KAAK,EAEH,EACT,CC1BA,IAAM,EAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBAgCtB,eAAsB,EACpB,EACA,EACiB,CACjB,GAAI,CAAC,EAAO,OACV,MAAU,MAAM,mCAAmC,EAQrD,IAAM,EAAW,MAAM,IALJ,EAAA,QAAO,CACxB,OAAQ,EAAO,OACf,QAAS,EAAO,QAClB,CAEuB,CAAA,CAAO,KAAK,YAAY,OAAO,CACpD,MAAO,EAAO,IAAI,MAClB,YAAa,EAAO,IAAI,YACxB,WAAY,EAAO,IAAI,gBACvB,SAAU,CACR,CAAE,KAAM,SAAU,QAAS,CAAc,EACzC,CACE,KAAM,OACN,QAAS,uBAAuB,GAClC,CACF,CACF,CAAC,EAEK,EAAU,EAAe,CAAQ,EACvC,GAAI,CAAC,EACH,MAAU,MACR,sBAAsB,KAAK,UAAU,CAAQ,GAC/C,EAEF,OAAO,CACT,CChEA,SAAS,GAA0B,CACjC,IAAM,EAAS,EAAW,EAK1B,OAJK,EAAO,SACV,QAAQ,MAAM,yCAAyC,EACvD,QAAQ,KAAK,CAAC,GAET,CACT,CAEA,SAAS,GAAuB,CAC1B,EAAiB,EACnB,QAAQ,IAAI,kBAAkB,GAE9B,QAAQ,IAAI,WAAW,EACvB,EAAU,EAEd,CAEA,SAAS,GAAqB,CAC5B,IAAM,EAAO,EAAW,EAKxB,OAJK,EAAK,KAAK,IACb,QAAQ,IAAI,WAAW,EACvB,QAAQ,KAAK,CAAC,GAET,CACT,CAEA,eAAsB,GAA2B,CAC/C,IAAM,EAAS,EAAa,EAC5B,EAAe,EACf,IAAM,EAAO,EAAW,EACxB,QAAQ,IAAI;CAAe,EAC3B,IAAM,EAAU,MAAM,EAAsB,EAAM,CAAM,EACxD,EAAU,CAAO,EACjB,QAAQ,IAAI,YAAY,EAAQ,GAAG,EACnC,QAAQ,IAAI,OAAO,CACrB,CCxCA,SAAgB,EAAS,EAAgC,CACvD,IAAM,GAAA,EAAA,EAAA,gBAAA,CAAqB,CACzB,MAAO,QAAQ,MACf,OAAQ,QAAQ,MAClB,CAAC,EACD,OAAO,EAAG,SAAS,CAAK,CAAC,CAAC,YAAc,EAAG,MAAM,CAAC,CACpD,CCLA,eAAsB,GAAyB,CAC7C,QAAQ,IAAI;CAAa,EAEzB,IAAM,EAAW,EAAe,EAE1B,GAEF,MAAM,EACJ,iBAAiB,EAAS,UAAY,4BAA4B,IACpE,EAAA,CACA,KAAK,GACP,EAAS,UACT,4BAEI,GAEF,MAAM,EACJ,SAAS,EAAS,KAAK,OAAS,oBAAoB,IACtD,EAAA,CACA,KAAK,GACP,EAAS,KAAK,OACd,oBAEI,GAEF,MAAM,EAAS,YAAY,EAAS,OAAS,MAAQ,OAAO,IAAI,EAAA,CAChE,KAAK,GAAK,EAAS,OAElB,IACH,QAAQ,MAAM;iBAAoB,EAClC,QAAQ,KAAK,CAAC,GAGhB,EAAe,CACb,SACA,WACA,IAAK,CACH,QACA,YAAa,GACb,eAAgB,OAChB,gBAAiB,KACnB,CACF,CAAC,EACD,QAAQ,IAAI;0BAA6B,CAC3C,CCxCA,SAAgB,GAAqB,CACnC,IAAM,GAAA,EAAA,EAAA,QAAA,CAAkB,UAAW,KAAM,cAAc,EAEvD,OADY,KAAK,OAAA,EAAA,EAAA,aAAA,CAAmB,EAAS,OAAO,CAC7C,CAAA,CAAI,OACb,CACA,IAAM,EAAU,IAAI,EAAA,QAEpB,EACG,KAAK,KAAK,CAAC,CACX,QAAQ,EAAW,EAAG,gBAAiB,QAAQ,CAAC,CAChD,YAAY,iCAAiC,CAAC,CAC9C,WAAW,aAAc,QAAQ,EAEpC,EACG,QAAQ,MAAM,CAAC,CACf,YAAY,eAAe,CAAC,CAC5B,WAAa,CACZ,EAAQ,CAAC,CAAC,MAAO,GAAe,CAC9B,QAAQ,MAAM,MAAO,EAAI,OAAO,EAChC,QAAQ,KAAK,CAAC,CAChB,CAAC,CACH,CAAC,EAEH,SAAgB,GAAe,CAG7B,GAFa,QAAQ,KAAK,MAAM,CAE5B,CAAA,CAAK,SAAW,EAAG,CACrB,EAAU,CAAC,CAAC,MAAO,GAAe,CAChC,QAAQ,MAAM,MAAO,EAAI,OAAO,EAChC,QAAQ,KAAK,CAAC,CAChB,CAAC,EACD,MACF,CAEA,EAAQ,MAAM,QAAQ,IAAI,CAC5B,CCxCA,EAAO"}
|