vibecodingmachine-core 1.0.2 → 2025.11.2-7.1302
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/.babelrc +13 -13
- package/README.md +28 -28
- package/__tests__/applescript-manager-claude-fix.test.js +286 -286
- package/__tests__/requirement-2-auto-start-looping.test.js +69 -69
- package/__tests__/requirement-3-auto-start-looping.test.js +69 -69
- package/__tests__/requirement-4-auto-start-looping.test.js +69 -69
- package/__tests__/requirement-6-auto-start-looping.test.js +73 -73
- package/__tests__/requirement-7-status-tracking.test.js +332 -332
- package/jest.config.js +18 -18
- package/jest.setup.js +12 -12
- package/package.json +48 -48
- package/src/auth/access-denied.html +119 -119
- package/src/auth/shared-auth-storage.js +230 -230
- package/src/autonomous-mode/feature-implementer.cjs +70 -70
- package/src/autonomous-mode/feature-implementer.js +425 -425
- package/src/chat-management/chat-manager.cjs +71 -71
- package/src/chat-management/chat-manager.js +342 -342
- package/src/ide-integration/__tests__/applescript-manager-thread-closure.test.js +227 -227
- package/src/ide-integration/aider-cli-manager.cjs +850 -850
- package/src/ide-integration/applescript-manager.cjs +1088 -1088
- package/src/ide-integration/applescript-manager.js +2802 -2802
- package/src/ide-integration/applescript-utils.js +306 -306
- package/src/ide-integration/cdp-manager.cjs +221 -221
- package/src/ide-integration/cdp-manager.js +321 -321
- package/src/ide-integration/claude-code-cli-manager.cjs +301 -301
- package/src/ide-integration/cline-cli-manager.cjs +2252 -2252
- package/src/ide-integration/continue-cli-manager.js +431 -431
- package/src/ide-integration/provider-manager.cjs +354 -354
- package/src/ide-integration/quota-detector.cjs +34 -34
- package/src/ide-integration/quota-detector.js +349 -349
- package/src/ide-integration/windows-automation-manager.js +262 -262
- package/src/index.cjs +47 -43
- package/src/index.js +17 -17
- package/src/llm/direct-llm-manager.cjs +609 -609
- package/src/ui/ButtonComponents.js +247 -247
- package/src/ui/ChatInterface.js +499 -499
- package/src/ui/StateManager.js +259 -259
- package/src/utils/audit-logger.cjs +116 -116
- package/src/utils/config-helpers.cjs +94 -94
- package/src/utils/config-helpers.js +94 -94
- package/src/utils/electron-update-checker.js +113 -85
- package/src/utils/gcloud-auth.cjs +394 -394
- package/src/utils/logger.cjs +193 -193
- package/src/utils/logger.js +191 -191
- package/src/utils/repo-helpers.cjs +120 -120
- package/src/utils/repo-helpers.js +120 -120
- package/src/utils/requirement-helpers.js +432 -432
- package/src/utils/update-checker.js +227 -167
- package/src/utils/version-checker.js +169 -0
|
@@ -1,116 +1,116 @@
|
|
|
1
|
-
// Shared audit logger for both Electron app and CLI
|
|
2
|
-
const fs = require('fs');
|
|
3
|
-
const path = require('path');
|
|
4
|
-
|
|
5
|
-
function getDateStr(d = new Date()) {
|
|
6
|
-
const y = d.getFullYear();
|
|
7
|
-
const m = String(d.getMonth() + 1).padStart(2, '0');
|
|
8
|
-
const day = String(d.getDate()).padStart(2, '0');
|
|
9
|
-
return `${y}-${m}-${day}`;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
function getAuditLogDir() {
|
|
13
|
-
return path.join(process.cwd(), 'logs', 'audit');
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function ensureAuditLogDir() {
|
|
17
|
-
const dir = getAuditLogDir();
|
|
18
|
-
try {
|
|
19
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
20
|
-
} catch (_) {}
|
|
21
|
-
return dir;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function appendAuditLog(entry) {
|
|
25
|
-
try {
|
|
26
|
-
const dir = ensureAuditLogDir();
|
|
27
|
-
const when = entry && entry.timestamp ? new Date(entry.timestamp) : new Date();
|
|
28
|
-
const dateStr = getDateStr(when);
|
|
29
|
-
const filePath = path.join(dir, `${dateStr}.jsonl`);
|
|
30
|
-
const line = JSON.stringify(entry) + '\n';
|
|
31
|
-
fs.appendFileSync(filePath, line);
|
|
32
|
-
return { success: true };
|
|
33
|
-
} catch (e) {
|
|
34
|
-
return { success: false, error: e.message };
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function listAuditLogDates() {
|
|
39
|
-
try {
|
|
40
|
-
const dir = getAuditLogDir();
|
|
41
|
-
if (!fs.existsSync(dir)) return [];
|
|
42
|
-
return fs.readdirSync(dir)
|
|
43
|
-
.filter(f => f.endsWith('.jsonl'))
|
|
44
|
-
.map(f => f.replace(/\.jsonl$/, ''))
|
|
45
|
-
.sort();
|
|
46
|
-
} catch (e) {
|
|
47
|
-
return [];
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function readAuditLog(dateStr) {
|
|
52
|
-
try {
|
|
53
|
-
const dir = getAuditLogDir();
|
|
54
|
-
const filePath = path.join(dir, `${dateStr}.jsonl`);
|
|
55
|
-
if (!fs.existsSync(filePath)) return [];
|
|
56
|
-
const data = fs.readFileSync(filePath, 'utf8');
|
|
57
|
-
return data.split('\n').filter(Boolean).map(line => {
|
|
58
|
-
try {
|
|
59
|
-
return JSON.parse(line);
|
|
60
|
-
} catch {
|
|
61
|
-
return null;
|
|
62
|
-
}
|
|
63
|
-
}).filter(Boolean);
|
|
64
|
-
} catch (e) {
|
|
65
|
-
return [];
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function logAutoModeStart(ide, maxChats) {
|
|
70
|
-
const entry = {
|
|
71
|
-
timestamp: new Date().toISOString(),
|
|
72
|
-
type: 'auto-mode-start',
|
|
73
|
-
ide,
|
|
74
|
-
maxChats,
|
|
75
|
-
message: `Auto Mode started with ${ide}, max chats: ${maxChats === 0 ? 'unlimited' : maxChats}`
|
|
76
|
-
};
|
|
77
|
-
appendAuditLog(entry);
|
|
78
|
-
return entry;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function logAutoModeStop(reason = 'manual') {
|
|
82
|
-
const entry = {
|
|
83
|
-
timestamp: new Date().toISOString(),
|
|
84
|
-
type: 'auto-mode-stop',
|
|
85
|
-
reason,
|
|
86
|
-
message: `Auto Mode stopped (${reason})`
|
|
87
|
-
};
|
|
88
|
-
appendAuditLog(entry);
|
|
89
|
-
return entry;
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function logIDEMessage(ide, message, truncate = 100) {
|
|
93
|
-
const displayMessage = message.length > truncate
|
|
94
|
-
? message.substring(0, truncate) + '...'
|
|
95
|
-
: message;
|
|
96
|
-
|
|
97
|
-
const entry = {
|
|
98
|
-
timestamp: new Date().toISOString(),
|
|
99
|
-
type: 'ide-message',
|
|
100
|
-
ide,
|
|
101
|
-
message: displayMessage,
|
|
102
|
-
fullMessage: message
|
|
103
|
-
};
|
|
104
|
-
appendAuditLog(entry);
|
|
105
|
-
return entry;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
module.exports = {
|
|
109
|
-
appendAuditLog,
|
|
110
|
-
listAuditLogDates,
|
|
111
|
-
readAuditLog,
|
|
112
|
-
logAutoModeStart,
|
|
113
|
-
logAutoModeStop,
|
|
114
|
-
logIDEMessage,
|
|
115
|
-
getDateStr
|
|
116
|
-
};
|
|
1
|
+
// Shared audit logger for both Electron app and CLI
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
function getDateStr(d = new Date()) {
|
|
6
|
+
const y = d.getFullYear();
|
|
7
|
+
const m = String(d.getMonth() + 1).padStart(2, '0');
|
|
8
|
+
const day = String(d.getDate()).padStart(2, '0');
|
|
9
|
+
return `${y}-${m}-${day}`;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getAuditLogDir() {
|
|
13
|
+
return path.join(process.cwd(), 'logs', 'audit');
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function ensureAuditLogDir() {
|
|
17
|
+
const dir = getAuditLogDir();
|
|
18
|
+
try {
|
|
19
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
20
|
+
} catch (_) {}
|
|
21
|
+
return dir;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function appendAuditLog(entry) {
|
|
25
|
+
try {
|
|
26
|
+
const dir = ensureAuditLogDir();
|
|
27
|
+
const when = entry && entry.timestamp ? new Date(entry.timestamp) : new Date();
|
|
28
|
+
const dateStr = getDateStr(when);
|
|
29
|
+
const filePath = path.join(dir, `${dateStr}.jsonl`);
|
|
30
|
+
const line = JSON.stringify(entry) + '\n';
|
|
31
|
+
fs.appendFileSync(filePath, line);
|
|
32
|
+
return { success: true };
|
|
33
|
+
} catch (e) {
|
|
34
|
+
return { success: false, error: e.message };
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function listAuditLogDates() {
|
|
39
|
+
try {
|
|
40
|
+
const dir = getAuditLogDir();
|
|
41
|
+
if (!fs.existsSync(dir)) return [];
|
|
42
|
+
return fs.readdirSync(dir)
|
|
43
|
+
.filter(f => f.endsWith('.jsonl'))
|
|
44
|
+
.map(f => f.replace(/\.jsonl$/, ''))
|
|
45
|
+
.sort();
|
|
46
|
+
} catch (e) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function readAuditLog(dateStr) {
|
|
52
|
+
try {
|
|
53
|
+
const dir = getAuditLogDir();
|
|
54
|
+
const filePath = path.join(dir, `${dateStr}.jsonl`);
|
|
55
|
+
if (!fs.existsSync(filePath)) return [];
|
|
56
|
+
const data = fs.readFileSync(filePath, 'utf8');
|
|
57
|
+
return data.split('\n').filter(Boolean).map(line => {
|
|
58
|
+
try {
|
|
59
|
+
return JSON.parse(line);
|
|
60
|
+
} catch {
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
}).filter(Boolean);
|
|
64
|
+
} catch (e) {
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function logAutoModeStart(ide, maxChats) {
|
|
70
|
+
const entry = {
|
|
71
|
+
timestamp: new Date().toISOString(),
|
|
72
|
+
type: 'auto-mode-start',
|
|
73
|
+
ide,
|
|
74
|
+
maxChats,
|
|
75
|
+
message: `Auto Mode started with ${ide}, max chats: ${maxChats === 0 ? 'unlimited' : maxChats}`
|
|
76
|
+
};
|
|
77
|
+
appendAuditLog(entry);
|
|
78
|
+
return entry;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function logAutoModeStop(reason = 'manual') {
|
|
82
|
+
const entry = {
|
|
83
|
+
timestamp: new Date().toISOString(),
|
|
84
|
+
type: 'auto-mode-stop',
|
|
85
|
+
reason,
|
|
86
|
+
message: `Auto Mode stopped (${reason})`
|
|
87
|
+
};
|
|
88
|
+
appendAuditLog(entry);
|
|
89
|
+
return entry;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function logIDEMessage(ide, message, truncate = 100) {
|
|
93
|
+
const displayMessage = message.length > truncate
|
|
94
|
+
? message.substring(0, truncate) + '...'
|
|
95
|
+
: message;
|
|
96
|
+
|
|
97
|
+
const entry = {
|
|
98
|
+
timestamp: new Date().toISOString(),
|
|
99
|
+
type: 'ide-message',
|
|
100
|
+
ide,
|
|
101
|
+
message: displayMessage,
|
|
102
|
+
fullMessage: message
|
|
103
|
+
};
|
|
104
|
+
appendAuditLog(entry);
|
|
105
|
+
return entry;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
module.exports = {
|
|
109
|
+
appendAuditLog,
|
|
110
|
+
listAuditLogDates,
|
|
111
|
+
readAuditLog,
|
|
112
|
+
logAutoModeStart,
|
|
113
|
+
logAutoModeStop,
|
|
114
|
+
logIDEMessage,
|
|
115
|
+
getDateStr
|
|
116
|
+
};
|
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Get the config directory path
|
|
7
|
-
* Uses the same location as Electron's app.getPath('userData')
|
|
8
|
-
* @returns {string} The config directory path
|
|
9
|
-
*/
|
|
10
|
-
function getConfigDir() {
|
|
11
|
-
const platform = process.platform;
|
|
12
|
-
const home = os.homedir();
|
|
13
|
-
|
|
14
|
-
let configDir;
|
|
15
|
-
if (platform === 'darwin') {
|
|
16
|
-
// macOS: ~/Library/Application Support/vibecodingmachine
|
|
17
|
-
configDir = path.join(home, 'Library', 'Application Support', 'vibecodingmachine');
|
|
18
|
-
} else if (platform === 'win32') {
|
|
19
|
-
// Windows: %APPDATA%\vibecodingmachine
|
|
20
|
-
configDir = path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'vibecodingmachine');
|
|
21
|
-
} else {
|
|
22
|
-
// Linux: ~/.config/vibecodingmachine
|
|
23
|
-
configDir = path.join(home, '.config', 'vibecodingmachine');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return configDir;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Get the config file path
|
|
31
|
-
* @returns {string} The config file path
|
|
32
|
-
*/
|
|
33
|
-
function getConfigPath() {
|
|
34
|
-
return path.join(getConfigDir(), 'vibecodingmachine-config.json');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Load the config from disk
|
|
39
|
-
* @returns {Promise<Object>} The config object
|
|
40
|
-
*/
|
|
41
|
-
async function loadConfig() {
|
|
42
|
-
try {
|
|
43
|
-
const configPath = getConfigPath();
|
|
44
|
-
if (await fs.pathExists(configPath)) {
|
|
45
|
-
return await fs.readJson(configPath);
|
|
46
|
-
}
|
|
47
|
-
} catch (error) {
|
|
48
|
-
// Ignore errors, return empty config
|
|
49
|
-
}
|
|
50
|
-
return {};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Save the config to disk
|
|
55
|
-
* @param {Object} config - The config object to save
|
|
56
|
-
* @returns {Promise<void>}
|
|
57
|
-
*/
|
|
58
|
-
async function saveConfig(config) {
|
|
59
|
-
const configPath = getConfigPath();
|
|
60
|
-
await fs.ensureDir(path.dirname(configPath));
|
|
61
|
-
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get a config value
|
|
66
|
-
* @param {string} key - The config key
|
|
67
|
-
* @param {*} defaultValue - The default value if key doesn't exist
|
|
68
|
-
* @returns {Promise<*>} The config value
|
|
69
|
-
*/
|
|
70
|
-
async function getConfigValue(key, defaultValue = null) {
|
|
71
|
-
const config = await loadConfig();
|
|
72
|
-
return config[key] !== undefined ? config[key] : defaultValue;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Set a config value
|
|
77
|
-
* @param {string} key - The config key
|
|
78
|
-
* @param {*} value - The value to set
|
|
79
|
-
* @returns {Promise<void>}
|
|
80
|
-
*/
|
|
81
|
-
async function setConfigValue(key, value) {
|
|
82
|
-
const config = await loadConfig();
|
|
83
|
-
config[key] = value;
|
|
84
|
-
await saveConfig(config);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
module.exports = {
|
|
88
|
-
getConfigDir,
|
|
89
|
-
getConfigPath,
|
|
90
|
-
loadConfig,
|
|
91
|
-
saveConfig,
|
|
92
|
-
getConfigValue,
|
|
93
|
-
setConfigValue
|
|
94
|
-
};
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the config directory path
|
|
7
|
+
* Uses the same location as Electron's app.getPath('userData')
|
|
8
|
+
* @returns {string} The config directory path
|
|
9
|
+
*/
|
|
10
|
+
function getConfigDir() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const home = os.homedir();
|
|
13
|
+
|
|
14
|
+
let configDir;
|
|
15
|
+
if (platform === 'darwin') {
|
|
16
|
+
// macOS: ~/Library/Application Support/vibecodingmachine
|
|
17
|
+
configDir = path.join(home, 'Library', 'Application Support', 'vibecodingmachine');
|
|
18
|
+
} else if (platform === 'win32') {
|
|
19
|
+
// Windows: %APPDATA%\vibecodingmachine
|
|
20
|
+
configDir = path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'vibecodingmachine');
|
|
21
|
+
} else {
|
|
22
|
+
// Linux: ~/.config/vibecodingmachine
|
|
23
|
+
configDir = path.join(home, '.config', 'vibecodingmachine');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return configDir;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the config file path
|
|
31
|
+
* @returns {string} The config file path
|
|
32
|
+
*/
|
|
33
|
+
function getConfigPath() {
|
|
34
|
+
return path.join(getConfigDir(), 'vibecodingmachine-config.json');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Load the config from disk
|
|
39
|
+
* @returns {Promise<Object>} The config object
|
|
40
|
+
*/
|
|
41
|
+
async function loadConfig() {
|
|
42
|
+
try {
|
|
43
|
+
const configPath = getConfigPath();
|
|
44
|
+
if (await fs.pathExists(configPath)) {
|
|
45
|
+
return await fs.readJson(configPath);
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
// Ignore errors, return empty config
|
|
49
|
+
}
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Save the config to disk
|
|
55
|
+
* @param {Object} config - The config object to save
|
|
56
|
+
* @returns {Promise<void>}
|
|
57
|
+
*/
|
|
58
|
+
async function saveConfig(config) {
|
|
59
|
+
const configPath = getConfigPath();
|
|
60
|
+
await fs.ensureDir(path.dirname(configPath));
|
|
61
|
+
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get a config value
|
|
66
|
+
* @param {string} key - The config key
|
|
67
|
+
* @param {*} defaultValue - The default value if key doesn't exist
|
|
68
|
+
* @returns {Promise<*>} The config value
|
|
69
|
+
*/
|
|
70
|
+
async function getConfigValue(key, defaultValue = null) {
|
|
71
|
+
const config = await loadConfig();
|
|
72
|
+
return config[key] !== undefined ? config[key] : defaultValue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Set a config value
|
|
77
|
+
* @param {string} key - The config key
|
|
78
|
+
* @param {*} value - The value to set
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
async function setConfigValue(key, value) {
|
|
82
|
+
const config = await loadConfig();
|
|
83
|
+
config[key] = value;
|
|
84
|
+
await saveConfig(config);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
getConfigDir,
|
|
89
|
+
getConfigPath,
|
|
90
|
+
loadConfig,
|
|
91
|
+
saveConfig,
|
|
92
|
+
getConfigValue,
|
|
93
|
+
setConfigValue
|
|
94
|
+
};
|
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const fs = require('fs-extra');
|
|
3
|
-
const os = require('os');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Get the config directory path
|
|
7
|
-
* Uses the same location as Electron's app.getPath('userData')
|
|
8
|
-
* @returns {string} The config directory path
|
|
9
|
-
*/
|
|
10
|
-
function getConfigDir() {
|
|
11
|
-
const platform = process.platform;
|
|
12
|
-
const home = os.homedir();
|
|
13
|
-
|
|
14
|
-
let configDir;
|
|
15
|
-
if (platform === 'darwin') {
|
|
16
|
-
// macOS: ~/Library/Application Support/vibecodingmachine
|
|
17
|
-
configDir = path.join(home, 'Library', 'Application Support', 'vibecodingmachine');
|
|
18
|
-
} else if (platform === 'win32') {
|
|
19
|
-
// Windows: %APPDATA%\vibecodingmachine
|
|
20
|
-
configDir = path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'vibecodingmachine');
|
|
21
|
-
} else {
|
|
22
|
-
// Linux: ~/.config/vibecodingmachine
|
|
23
|
-
configDir = path.join(home, '.config', 'vibecodingmachine');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
return configDir;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
/**
|
|
30
|
-
* Get the config file path
|
|
31
|
-
* @returns {string} The config file path
|
|
32
|
-
*/
|
|
33
|
-
function getConfigPath() {
|
|
34
|
-
return path.join(getConfigDir(), 'vibecodingmachine-config.json');
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Load the config from disk
|
|
39
|
-
* @returns {Promise<Object>} The config object
|
|
40
|
-
*/
|
|
41
|
-
async function loadConfig() {
|
|
42
|
-
try {
|
|
43
|
-
const configPath = getConfigPath();
|
|
44
|
-
if (await fs.pathExists(configPath)) {
|
|
45
|
-
return await fs.readJson(configPath);
|
|
46
|
-
}
|
|
47
|
-
} catch (error) {
|
|
48
|
-
// Ignore errors, return empty config
|
|
49
|
-
}
|
|
50
|
-
return {};
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
* Save the config to disk
|
|
55
|
-
* @param {Object} config - The config object to save
|
|
56
|
-
* @returns {Promise<void>}
|
|
57
|
-
*/
|
|
58
|
-
async function saveConfig(config) {
|
|
59
|
-
const configPath = getConfigPath();
|
|
60
|
-
await fs.ensureDir(path.dirname(configPath));
|
|
61
|
-
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get a config value
|
|
66
|
-
* @param {string} key - The config key
|
|
67
|
-
* @param {*} defaultValue - The default value if key doesn't exist
|
|
68
|
-
* @returns {Promise<*>} The config value
|
|
69
|
-
*/
|
|
70
|
-
async function getConfigValue(key, defaultValue = null) {
|
|
71
|
-
const config = await loadConfig();
|
|
72
|
-
return config[key] !== undefined ? config[key] : defaultValue;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Set a config value
|
|
77
|
-
* @param {string} key - The config key
|
|
78
|
-
* @param {*} value - The value to set
|
|
79
|
-
* @returns {Promise<void>}
|
|
80
|
-
*/
|
|
81
|
-
async function setConfigValue(key, value) {
|
|
82
|
-
const config = await loadConfig();
|
|
83
|
-
config[key] = value;
|
|
84
|
-
await saveConfig(config);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
module.exports = {
|
|
88
|
-
getConfigDir,
|
|
89
|
-
getConfigPath,
|
|
90
|
-
loadConfig,
|
|
91
|
-
saveConfig,
|
|
92
|
-
getConfigValue,
|
|
93
|
-
setConfigValue
|
|
94
|
-
};
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const os = require('os');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Get the config directory path
|
|
7
|
+
* Uses the same location as Electron's app.getPath('userData')
|
|
8
|
+
* @returns {string} The config directory path
|
|
9
|
+
*/
|
|
10
|
+
function getConfigDir() {
|
|
11
|
+
const platform = process.platform;
|
|
12
|
+
const home = os.homedir();
|
|
13
|
+
|
|
14
|
+
let configDir;
|
|
15
|
+
if (platform === 'darwin') {
|
|
16
|
+
// macOS: ~/Library/Application Support/vibecodingmachine
|
|
17
|
+
configDir = path.join(home, 'Library', 'Application Support', 'vibecodingmachine');
|
|
18
|
+
} else if (platform === 'win32') {
|
|
19
|
+
// Windows: %APPDATA%\vibecodingmachine
|
|
20
|
+
configDir = path.join(process.env.APPDATA || path.join(home, 'AppData', 'Roaming'), 'vibecodingmachine');
|
|
21
|
+
} else {
|
|
22
|
+
// Linux: ~/.config/vibecodingmachine
|
|
23
|
+
configDir = path.join(home, '.config', 'vibecodingmachine');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return configDir;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the config file path
|
|
31
|
+
* @returns {string} The config file path
|
|
32
|
+
*/
|
|
33
|
+
function getConfigPath() {
|
|
34
|
+
return path.join(getConfigDir(), 'vibecodingmachine-config.json');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Load the config from disk
|
|
39
|
+
* @returns {Promise<Object>} The config object
|
|
40
|
+
*/
|
|
41
|
+
async function loadConfig() {
|
|
42
|
+
try {
|
|
43
|
+
const configPath = getConfigPath();
|
|
44
|
+
if (await fs.pathExists(configPath)) {
|
|
45
|
+
return await fs.readJson(configPath);
|
|
46
|
+
}
|
|
47
|
+
} catch (error) {
|
|
48
|
+
// Ignore errors, return empty config
|
|
49
|
+
}
|
|
50
|
+
return {};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Save the config to disk
|
|
55
|
+
* @param {Object} config - The config object to save
|
|
56
|
+
* @returns {Promise<void>}
|
|
57
|
+
*/
|
|
58
|
+
async function saveConfig(config) {
|
|
59
|
+
const configPath = getConfigPath();
|
|
60
|
+
await fs.ensureDir(path.dirname(configPath));
|
|
61
|
+
await fs.writeJson(configPath, config, { spaces: 2 });
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get a config value
|
|
66
|
+
* @param {string} key - The config key
|
|
67
|
+
* @param {*} defaultValue - The default value if key doesn't exist
|
|
68
|
+
* @returns {Promise<*>} The config value
|
|
69
|
+
*/
|
|
70
|
+
async function getConfigValue(key, defaultValue = null) {
|
|
71
|
+
const config = await loadConfig();
|
|
72
|
+
return config[key] !== undefined ? config[key] : defaultValue;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Set a config value
|
|
77
|
+
* @param {string} key - The config key
|
|
78
|
+
* @param {*} value - The value to set
|
|
79
|
+
* @returns {Promise<void>}
|
|
80
|
+
*/
|
|
81
|
+
async function setConfigValue(key, value) {
|
|
82
|
+
const config = await loadConfig();
|
|
83
|
+
config[key] = value;
|
|
84
|
+
await saveConfig(config);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
module.exports = {
|
|
88
|
+
getConfigDir,
|
|
89
|
+
getConfigPath,
|
|
90
|
+
loadConfig,
|
|
91
|
+
saveConfig,
|
|
92
|
+
getConfigValue,
|
|
93
|
+
setConfigValue
|
|
94
|
+
};
|