@kud/ai-conventional-commit-cli 3.0.3 → 3.1.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.
@@ -0,0 +1,128 @@
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 || process.env.OPENCODE_FREE_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
+ maxFileLines: parseInt(process.env.AICC_MAX_FILE_LINES || "1000", 10),
13
+ skipFilePatterns: [
14
+ "**/package-lock.json",
15
+ "**/yarn.lock",
16
+ "**/pnpm-lock.yaml",
17
+ "**/bun.lockb",
18
+ "**/composer.lock",
19
+ "**/Gemfile.lock",
20
+ "**/Cargo.lock",
21
+ "**/poetry.lock",
22
+ "**/*.d.ts",
23
+ "**/dist/**",
24
+ "**/build/**",
25
+ "**/.next/**",
26
+ "**/out/**",
27
+ "**/coverage/**",
28
+ "**/*.min.js",
29
+ "**/*.min.css",
30
+ "**/*.map",
31
+ "**/.vite/**",
32
+ "**/.nuxt/**",
33
+ "**/.svelte-kit/**",
34
+ "**/.parcel-cache/**",
35
+ "**/.turbo/**",
36
+ "**/.cache/**"
37
+ ],
38
+ cacheDir: ".git/.aicc-cache",
39
+ plugins: [],
40
+ verbose: process.env.AICC_VERBOSE === "true",
41
+ yes: process.env.AICC_YES === "true"
42
+ };
43
+ function getGlobalConfigPath() {
44
+ const base = process.env.XDG_CONFIG_HOME || join(homedir(), ".config");
45
+ return resolve(base, "ai-conventional-commit-cli", "aicc.json");
46
+ }
47
+ function saveGlobalConfig(partial) {
48
+ const filePath = getGlobalConfigPath();
49
+ const dir = dirname(filePath);
50
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
51
+ let existing = {};
52
+ if (existsSync(filePath)) {
53
+ try {
54
+ existing = JSON.parse(readFileSync(filePath, "utf8")) || {};
55
+ } catch (e) {
56
+ if (process.env.AICC_VERBOSE === "true") {
57
+ console.error("[ai-cc] Failed to parse existing global config, overwriting.");
58
+ }
59
+ }
60
+ }
61
+ const merged = { ...existing, ...partial };
62
+ writeFileSync(filePath, JSON.stringify(merged, null, 2) + "\n", "utf8");
63
+ return filePath;
64
+ }
65
+ async function loadConfig(cwd = process.cwd()) {
66
+ return (await loadConfigDetailed(cwd)).config;
67
+ }
68
+ async function loadConfigDetailed(cwd = process.cwd()) {
69
+ let globalCfg = {};
70
+ const globalPath = getGlobalConfigPath();
71
+ if (existsSync(globalPath)) {
72
+ try {
73
+ globalCfg = JSON.parse(readFileSync(globalPath, "utf8")) || {};
74
+ } catch (e) {
75
+ if (process.env.AICC_VERBOSE === "true") {
76
+ console.error("[ai-cc] Failed to parse global config, ignoring.");
77
+ }
78
+ }
79
+ }
80
+ const explorer = cosmiconfig("aicc");
81
+ const result = await explorer.search(cwd);
82
+ const projectCfg = result?.config || {};
83
+ const envCfg = {};
84
+ if (process.env.AICC_MODEL) envCfg.model = process.env.AICC_MODEL;
85
+ if (process.env.AICC_PRIVACY) envCfg.privacy = process.env.AICC_PRIVACY;
86
+ if (process.env.AICC_STYLE) envCfg.style = process.env.AICC_STYLE;
87
+ if (process.env.AICC_STYLE_SAMPLES)
88
+ envCfg.styleSamples = parseInt(process.env.AICC_STYLE_SAMPLES, 10);
89
+ if (process.env.AICC_MAX_TOKENS) envCfg.maxTokens = parseInt(process.env.AICC_MAX_TOKENS, 10);
90
+ if (process.env.AICC_MAX_FILE_LINES)
91
+ envCfg.maxFileLines = parseInt(process.env.AICC_MAX_FILE_LINES, 10);
92
+ if (process.env.AICC_VERBOSE) envCfg.verbose = process.env.AICC_VERBOSE === "true";
93
+ if (process.env.AICC_YES) envCfg.yes = process.env.AICC_YES === "true";
94
+ const merged = {
95
+ ...DEFAULTS,
96
+ ...globalCfg,
97
+ ...projectCfg,
98
+ ...envCfg
99
+ };
100
+ merged.plugins = (merged.plugins || []).filter((p) => {
101
+ const abs = resolve(cwd, p);
102
+ return existsSync(abs);
103
+ });
104
+ if (!merged.skipFilePatterns) {
105
+ merged.skipFilePatterns = DEFAULTS.skipFilePatterns;
106
+ }
107
+ const sources = Object.keys(merged).reduce((acc, key) => {
108
+ const k = key;
109
+ let src = "default";
110
+ if (k in globalCfg) src = "global";
111
+ if (k in projectCfg) src = "project";
112
+ if (k in envCfg) src = "env";
113
+ acc[k] = src;
114
+ return acc;
115
+ }, {});
116
+ const withMeta = Object.assign(merged, { _sources: sources });
117
+ return {
118
+ config: withMeta,
119
+ raw: { defaults: DEFAULTS, global: globalCfg, project: projectCfg, env: envCfg }
120
+ };
121
+ }
122
+
123
+ export {
124
+ getGlobalConfigPath,
125
+ saveGlobalConfig,
126
+ loadConfig,
127
+ loadConfigDetailed
128
+ };