aicodeswitch 2.0.6 → 2.0.8
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/CHANGELOG.md +4 -0
- package/bin/ui.js +8 -3
- package/dist/server/main.js +16 -18
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
### 2.0.8 (2026-02-02)
|
|
6
|
+
|
|
7
|
+
### 2.0.7 (2026-02-02)
|
|
8
|
+
|
|
5
9
|
### 2.0.6 (2026-02-01)
|
|
6
10
|
|
|
7
11
|
### 2.0.5 (2026-01-27)
|
package/bin/ui.js
CHANGED
|
@@ -7,19 +7,24 @@ const { getServerInfo } = require('./utils/get-server');
|
|
|
7
7
|
|
|
8
8
|
const openBrowser = (url) => {
|
|
9
9
|
let command;
|
|
10
|
+
let args;
|
|
10
11
|
|
|
11
12
|
if (os.platform() === 'darwin') {
|
|
12
13
|
command = 'open';
|
|
14
|
+
args = [url];
|
|
13
15
|
} else if (os.platform() === 'win32') {
|
|
14
|
-
command = '
|
|
16
|
+
command = 'cmd';
|
|
17
|
+
args = ['/c', 'start', '', url]; // 空字符串作为窗口标题
|
|
15
18
|
} else {
|
|
16
19
|
// Linux and others
|
|
17
20
|
command = 'xdg-open';
|
|
21
|
+
args = [url];
|
|
18
22
|
}
|
|
19
23
|
|
|
20
|
-
const child = spawn(command,
|
|
24
|
+
const child = spawn(command, args, {
|
|
21
25
|
detached: true,
|
|
22
|
-
stdio: 'ignore'
|
|
26
|
+
stdio: 'ignore',
|
|
27
|
+
shell: os.platform() === 'win32' // Windows 需要 shell
|
|
23
28
|
});
|
|
24
29
|
|
|
25
30
|
child.unref();
|
package/dist/server/main.js
CHANGED
|
@@ -27,13 +27,15 @@ const version_check_1 = require("./version-check");
|
|
|
27
27
|
const utils_1 = require("./utils");
|
|
28
28
|
const config_metadata_1 = require("./config-metadata");
|
|
29
29
|
const config_1 = require("./config");
|
|
30
|
-
const
|
|
30
|
+
const appDir = path_1.default.join(os_1.default.homedir(), '.aicodeswitch');
|
|
31
|
+
const dataDir = path_1.default.join(appDir, 'data');
|
|
32
|
+
const dotenvPath = path_1.default.resolve(appDir, 'aicodeswitch.conf');
|
|
33
|
+
const migrationHashFilePath = path_1.default.join(appDir, 'migration-hash');
|
|
31
34
|
if (fs_1.default.existsSync(dotenvPath)) {
|
|
32
35
|
dotenv_1.default.config({ path: dotenvPath });
|
|
33
36
|
}
|
|
34
37
|
const host = process.env.HOST || '127.0.0.1';
|
|
35
38
|
const port = process.env.PORT ? parseInt(process.env.PORT, 10) : 4567;
|
|
36
|
-
const dataDir = process.env.DATA_DIR ? path_1.default.resolve(process.cwd(), process.env.DATA_DIR) : path_1.default.join(os_1.default.homedir(), '.aicodeswitch/data');
|
|
37
39
|
let globalProxyConfig = null;
|
|
38
40
|
function updateProxyConfig(config) {
|
|
39
41
|
if (config.proxyEnabled && config.proxyUrl) {
|
|
@@ -116,16 +118,17 @@ const writeClaudeConfig = (dbManager) => __awaiter(void 0, void 0, void 0, funct
|
|
|
116
118
|
fs_1.default.writeFileSync(claudeSettingsPath, JSON.stringify(claudeSettings, null, 2));
|
|
117
119
|
// Claude Code .claude.json
|
|
118
120
|
const claudeJsonPath = path_1.default.join(homeDir, '.claude.json');
|
|
119
|
-
//
|
|
121
|
+
// 先读取原文件内容(如果存在)
|
|
122
|
+
let claudeJson = {};
|
|
123
|
+
if (fs_1.default.existsSync(claudeJsonPath)) {
|
|
124
|
+
claudeJson = JSON.parse(fs_1.default.readFileSync(claudeJsonPath, 'utf8'));
|
|
125
|
+
}
|
|
126
|
+
// 然后处理备份
|
|
120
127
|
if (!fs_1.default.existsSync(claudeJsonBakPath)) {
|
|
121
128
|
if (fs_1.default.existsSync(claudeJsonPath)) {
|
|
122
129
|
fs_1.default.renameSync(claudeJsonPath, claudeJsonBakPath);
|
|
123
130
|
}
|
|
124
131
|
}
|
|
125
|
-
let claudeJson = {};
|
|
126
|
-
if (fs_1.default.existsSync(claudeJsonPath)) {
|
|
127
|
-
claudeJson = JSON.parse(fs_1.default.readFileSync(claudeJsonPath, 'utf8'));
|
|
128
|
-
}
|
|
129
132
|
claudeJson.hasCompletedOnboarding = true;
|
|
130
133
|
fs_1.default.writeFileSync(claudeJsonPath, JSON.stringify(claudeJson, null, 2));
|
|
131
134
|
// 保存元数据
|
|
@@ -1288,8 +1291,6 @@ ${instruction}
|
|
|
1288
1291
|
const text = yield resp.text();
|
|
1289
1292
|
res.type('text/plain').send(text);
|
|
1290
1293
|
})));
|
|
1291
|
-
// Migration 相关端点
|
|
1292
|
-
const getMigrationHashPath = () => path_1.default.join(dataDir, '.migration-hash');
|
|
1293
1294
|
// 查找 migration.md 文件的路径
|
|
1294
1295
|
const findMigrationPath = () => {
|
|
1295
1296
|
// 可能的路径列表
|
|
@@ -1314,20 +1315,18 @@ ${instruction}
|
|
|
1314
1315
|
res.json({ shouldShow: false, content: '' });
|
|
1315
1316
|
return;
|
|
1316
1317
|
}
|
|
1317
|
-
const content = fs_1.default.readFileSync(migrationPath, 'utf-8');
|
|
1318
|
+
const content = fs_1.default.readFileSync(migrationPath, 'utf-8').trim();
|
|
1318
1319
|
// 计算当前内容的 hash
|
|
1319
1320
|
const currentHash = (0, crypto_1.createHash)('sha256').update(content).digest('hex');
|
|
1320
|
-
// 读取之前保存的 hash
|
|
1321
|
-
const hashPath = getMigrationHashPath();
|
|
1322
1321
|
// 如果 hash 文件不存在,说明是第一次安装
|
|
1323
|
-
if (!fs_1.default.existsSync(
|
|
1322
|
+
if (!fs_1.default.existsSync(migrationHashFilePath)) {
|
|
1324
1323
|
// 第一次安装,直接保存当前 hash,不显示弹窗
|
|
1325
|
-
fs_1.default.writeFileSync(
|
|
1324
|
+
fs_1.default.writeFileSync(migrationHashFilePath, currentHash, 'utf-8');
|
|
1326
1325
|
res.json({ shouldShow: false, content: '' });
|
|
1327
1326
|
return;
|
|
1328
1327
|
}
|
|
1329
1328
|
// 读取已保存的 hash
|
|
1330
|
-
const savedHash = fs_1.default.readFileSync(
|
|
1329
|
+
const savedHash = fs_1.default.readFileSync(migrationHashFilePath, 'utf-8').trim();
|
|
1331
1330
|
// 如果 hash 不同,需要显示弹窗
|
|
1332
1331
|
const shouldShow = savedHash !== currentHash;
|
|
1333
1332
|
res.json({ shouldShow, content: shouldShow ? content : '' });
|
|
@@ -1345,11 +1344,10 @@ ${instruction}
|
|
|
1345
1344
|
res.json({ success: false });
|
|
1346
1345
|
return;
|
|
1347
1346
|
}
|
|
1348
|
-
const content = fs_1.default.readFileSync(migrationPath, 'utf-8');
|
|
1347
|
+
const content = fs_1.default.readFileSync(migrationPath, 'utf-8').trim();
|
|
1349
1348
|
const hash = (0, crypto_1.createHash)('sha256').update(content).digest('hex');
|
|
1350
1349
|
// 保存 hash 到文件
|
|
1351
|
-
|
|
1352
|
-
fs_1.default.writeFileSync(hashPath, hash, 'utf-8');
|
|
1350
|
+
fs_1.default.writeFileSync(migrationHashFilePath, hash, 'utf-8');
|
|
1353
1351
|
res.json({ success: true });
|
|
1354
1352
|
}
|
|
1355
1353
|
catch (error) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aicodeswitch",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.8",
|
|
4
4
|
"description": "A tool to help you manage AI programming tools to access large language models locally. It allows your Claude Code, Codex and other tools to no longer be limited to official models.",
|
|
5
5
|
"author": "tangshuang",
|
|
6
6
|
"license": "GPL-3.0",
|