gent-cli 24.0.0 → 25.0.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/QUICKSTART.md +6 -5
- package/README.md +7 -6
- package/package.json +3 -3
- package/src/commands/ai.js +15 -30
- package/src/commands/ask.js +4 -1
- package/src/commands/canonical.js +73 -14
- package/src/commands/changelog.js +2 -0
- package/src/commands/chat.js +80 -0
- package/src/commands/commit.js +1 -0
- package/src/commands/config.js +1 -16
- package/src/commands/docs.js +2 -0
- package/src/commands/doctor.js +12 -12
- package/src/commands/explain.js +3 -3
- package/src/commands/merge.js +25 -3
- package/src/commands/resolve.js +30 -6
- package/src/commands/review.js +4 -3
- package/src/commands/setup.js +2 -52
- package/src/commands/summary.js +5 -1
- package/src/index.js +20 -11
- package/src/utils/ai-service.js +86 -163
- package/src/utils/user-config.js +3 -33
package/src/utils/user-config.js
CHANGED
|
@@ -5,7 +5,6 @@
|
|
|
5
5
|
*
|
|
6
6
|
* PURPOSE:
|
|
7
7
|
* Persist CLI-wide settings that should NOT live in a project's .gent/ dir:
|
|
8
|
-
* - AI key, AI model
|
|
9
8
|
* - API base URL (so users can point at a local backend without code edits)
|
|
10
9
|
* - Default identity (name/email) used when project .gent/config.json lacks one
|
|
11
10
|
*
|
|
@@ -13,13 +12,9 @@
|
|
|
13
12
|
* env var > ~/.gent/config.json > built-in default
|
|
14
13
|
*
|
|
15
14
|
* STORAGE:
|
|
16
|
-
* Plain JSON at ~/.gent/config.json.
|
|
17
|
-
* (AES via crypto-js, same scheme as auth-storage) so it isn't readable at a
|
|
18
|
-
* glance — not a real secret store, but better than plaintext on disk.
|
|
15
|
+
* Plain JSON at ~/.gent/config.json.
|
|
19
16
|
*
|
|
20
17
|
* KEYS (dot-notation):
|
|
21
|
-
* ai.api_key Anthropic API key
|
|
22
|
-
* ai.model Model id (e.g. claude-opus-4-7, claude-haiku-4-5)
|
|
23
18
|
* api.base_url Backend base URL (e.g. http://localhost:8000)
|
|
24
19
|
* web.base_url Web app (frontend) base URL (e.g. https://gent-nu2e.onrender.com)
|
|
25
20
|
* Used by `gent web` / `gent share`. This is a SEPARATE
|
|
@@ -34,17 +29,12 @@
|
|
|
34
29
|
const fs = require('fs').promises;
|
|
35
30
|
const path = require('path');
|
|
36
31
|
const os = require('os');
|
|
37
|
-
const CryptoJS = require('crypto-js');
|
|
38
32
|
const { GENT_DIR } = require('./constants');
|
|
39
33
|
|
|
40
34
|
const CONFIG_FILE_NAME = 'cli-config.json';
|
|
41
|
-
const SECRET_KEYS = new Set(
|
|
42
|
-
const OBFUSCATION_KEY = 'gent-cli-config-v1';
|
|
43
|
-
const OBFUSCATION_PREFIX = 'enc:v1:';
|
|
35
|
+
const SECRET_KEYS = new Set();
|
|
44
36
|
|
|
45
37
|
const ALLOWED_KEYS = new Set([
|
|
46
|
-
'ai.api_key',
|
|
47
|
-
'ai.model',
|
|
48
38
|
'api.base_url',
|
|
49
39
|
'web.base_url',
|
|
50
40
|
'user.name',
|
|
@@ -52,7 +42,6 @@ const ALLOWED_KEYS = new Set([
|
|
|
52
42
|
]);
|
|
53
43
|
|
|
54
44
|
const DEFAULTS = {
|
|
55
|
-
'ai.model': 'claude-opus-4-7',
|
|
56
45
|
'api.base_url': 'https://gent-api.onrender.com',
|
|
57
46
|
// The frontend has no production deployment yet; the server's own
|
|
58
47
|
// FRONTEND_URL setting defaults to the same value. Override with
|
|
@@ -61,8 +50,6 @@ const DEFAULTS = {
|
|
|
61
50
|
};
|
|
62
51
|
|
|
63
52
|
const ENV_OVERRIDES = {
|
|
64
|
-
'ai.api_key': 'ANTHROPIC_API_KEY',
|
|
65
|
-
'ai.model': 'GENT_AI_MODEL',
|
|
66
53
|
'api.base_url': 'GENT_API_URL',
|
|
67
54
|
'web.base_url': 'GENT_WEB_URL',
|
|
68
55
|
};
|
|
@@ -71,21 +58,6 @@ function getConfigPath() {
|
|
|
71
58
|
return path.join(os.homedir(), GENT_DIR, CONFIG_FILE_NAME);
|
|
72
59
|
}
|
|
73
60
|
|
|
74
|
-
function obfuscate(plaintext) {
|
|
75
|
-
if (typeof plaintext !== 'string' || plaintext.length === 0) return plaintext;
|
|
76
|
-
return OBFUSCATION_PREFIX + CryptoJS.AES.encrypt(plaintext, OBFUSCATION_KEY).toString();
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function deobfuscate(value) {
|
|
80
|
-
if (typeof value !== 'string' || !value.startsWith(OBFUSCATION_PREFIX)) return value;
|
|
81
|
-
try {
|
|
82
|
-
const bytes = CryptoJS.AES.decrypt(value.slice(OBFUSCATION_PREFIX.length), OBFUSCATION_KEY);
|
|
83
|
-
return bytes.toString(CryptoJS.enc.Utf8);
|
|
84
|
-
} catch {
|
|
85
|
-
return null;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
61
|
function setDeep(obj, dottedKey, value) {
|
|
90
62
|
const parts = dottedKey.split('.');
|
|
91
63
|
let cur = obj;
|
|
@@ -149,7 +121,6 @@ async function get(key) {
|
|
|
149
121
|
const data = await readRaw();
|
|
150
122
|
const raw = getDeep(data, key);
|
|
151
123
|
if (raw === undefined || raw === null) return undefined;
|
|
152
|
-
if (SECRET_KEYS.has(key)) return deobfuscate(raw);
|
|
153
124
|
return raw;
|
|
154
125
|
}
|
|
155
126
|
|
|
@@ -179,8 +150,7 @@ async function set(key, value) {
|
|
|
179
150
|
}
|
|
180
151
|
if (typeof value !== 'string') value = String(value);
|
|
181
152
|
const data = await readRaw();
|
|
182
|
-
|
|
183
|
-
setDeep(data, key, toStore);
|
|
153
|
+
setDeep(data, key, value);
|
|
184
154
|
await writeRaw(data);
|
|
185
155
|
}
|
|
186
156
|
|