@adversity/coding-tool-x 3.0.6 → 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.
- package/CHANGELOG.md +38 -18
- package/README.md +8 -8
- package/dist/web/assets/ConfigTemplates-Bidwfdf2.css +1 -0
- package/dist/web/assets/ConfigTemplates-ZrK_s7ma.js +1 -0
- package/dist/web/assets/Home-B8YfhZ3c.js +1 -0
- package/dist/web/assets/Home-Di2qsylF.css +1 -0
- package/dist/web/assets/PluginManager-BD7QUZbU.js +1 -0
- package/dist/web/assets/PluginManager-ROyoZ-6m.css +1 -0
- package/dist/web/assets/ProjectList-C1fQb9OW.css +1 -0
- package/dist/web/assets/ProjectList-DRb1DuHV.js +1 -0
- package/dist/web/assets/SessionList-BGJWyneI.css +1 -0
- package/dist/web/assets/SessionList-lZ0LKzfT.js +1 -0
- package/dist/web/assets/SkillManager-C1xG5B4Q.js +1 -0
- package/dist/web/assets/SkillManager-D7pd-d_P.css +1 -0
- package/dist/web/assets/Terminal-DGNJeVtc.css +1 -0
- package/dist/web/assets/Terminal-DksBo_lM.js +1 -0
- package/dist/web/assets/WorkspaceManager-Burx7XOo.js +1 -0
- package/dist/web/assets/WorkspaceManager-CrwgQgmP.css +1 -0
- package/dist/web/assets/icons-kcfLIMBB.js +1 -0
- package/dist/web/assets/index-Ufv5rCa5.css +1 -0
- package/dist/web/assets/index-lAkrRC3h.js +2 -0
- package/dist/web/assets/markdown-BfC0goYb.css +10 -0
- package/dist/web/assets/markdown-C9MYpaSi.js +1 -0
- package/dist/web/assets/naive-ui-CSrLusZZ.js +1 -0
- package/dist/web/assets/{vendors-D2HHw_aW.js → vendors-CO3Upi1d.js} +2 -2
- package/dist/web/assets/vue-vendor-DqyWIXEb.js +45 -0
- package/dist/web/assets/xterm-6GBZ9nXN.css +32 -0
- package/dist/web/assets/xterm-BJzAjXCH.js +13 -0
- package/dist/web/index.html +8 -6
- package/package.json +4 -2
- package/src/commands/channels.js +48 -1
- package/src/commands/cli-type.js +4 -2
- package/src/commands/daemon.js +92 -13
- package/src/commands/doctor.js +10 -9
- package/src/commands/list.js +1 -1
- package/src/commands/logs.js +6 -4
- package/src/commands/port-config.js +24 -4
- package/src/commands/proxy-control.js +12 -6
- package/src/commands/search.js +1 -1
- package/src/commands/security.js +3 -2
- package/src/commands/stats.js +226 -52
- package/src/commands/switch.js +1 -1
- package/src/commands/toggle-proxy.js +31 -6
- package/src/commands/ui.js +8 -1
- package/src/commands/update.js +97 -0
- package/src/commands/workspace.js +1 -1
- package/src/config/default.js +39 -2
- package/src/config/loader.js +74 -8
- package/src/config/paths.js +105 -33
- package/src/index.js +67 -4
- package/src/plugins/constants.js +3 -2
- package/src/plugins/plugin-api.js +1 -1
- package/src/reset-config.js +4 -2
- package/src/server/api/agents.js +57 -14
- package/src/server/api/channels.js +112 -33
- package/src/server/api/codex-channels.js +111 -18
- package/src/server/api/codex-proxy.js +14 -8
- package/src/server/api/commands.js +71 -18
- package/src/server/api/config-export.js +0 -6
- package/src/server/api/config-registry.js +11 -3
- package/src/server/api/config.js +376 -5
- package/src/server/api/convert.js +133 -0
- package/src/server/api/dashboard.js +22 -6
- package/src/server/api/gemini-channels.js +107 -18
- package/src/server/api/gemini-proxy.js +14 -8
- package/src/server/api/gemini-sessions.js +1 -1
- package/src/server/api/health-check.js +4 -3
- package/src/server/api/mcp.js +3 -3
- package/src/server/api/opencode-channels.js +419 -0
- package/src/server/api/opencode-projects.js +99 -0
- package/src/server/api/opencode-proxy.js +198 -0
- package/src/server/api/opencode-sessions.js +403 -0
- package/src/server/api/opencode-statistics.js +57 -0
- package/src/server/api/plugins.js +66 -19
- package/src/server/api/prompts.js +2 -2
- package/src/server/api/proxy.js +7 -4
- package/src/server/api/sessions.js +3 -0
- package/src/server/api/skills.js +69 -18
- package/src/server/api/workspaces.js +78 -6
- package/src/server/codex-proxy-server.js +32 -19
- package/src/server/dev-server.js +1 -1
- package/src/server/gemini-proxy-server.js +17 -3
- package/src/server/index.js +164 -48
- package/src/server/opencode-proxy-server.js +4375 -0
- package/src/server/proxy-server.js +30 -19
- package/src/server/services/agents-service.js +61 -24
- package/src/server/services/channel-scheduler.js +9 -5
- package/src/server/services/channels.js +70 -12
- package/src/server/services/codex-channels.js +61 -23
- package/src/server/services/codex-settings-manager.js +271 -49
- package/src/server/services/codex-statistics-service.js +2 -2
- package/src/server/services/commands-service.js +84 -25
- package/src/server/services/config-export-service.js +7 -45
- package/src/server/services/config-registry-service.js +63 -17
- package/src/server/services/config-sync-manager.js +160 -7
- package/src/server/services/config-templates-service.js +204 -51
- package/src/server/services/env-checker.js +26 -12
- package/src/server/services/env-manager.js +126 -18
- package/src/server/services/favorites.js +5 -3
- package/src/server/services/gemini-channels.js +37 -15
- package/src/server/services/gemini-statistics-service.js +2 -2
- package/src/server/services/mcp-service.js +350 -9
- package/src/server/services/model-detector.js +707 -221
- package/src/server/services/network-access.js +80 -0
- package/src/server/services/opencode-channels.js +206 -0
- package/src/server/services/opencode-gateway-converter.js +639 -0
- package/src/server/services/opencode-sessions.js +663 -0
- package/src/server/services/opencode-settings-manager.js +342 -0
- package/src/server/services/opencode-statistics-service.js +255 -0
- package/src/server/services/plugins-service.js +479 -22
- package/src/server/services/prompts-service.js +53 -11
- package/src/server/services/proxy-runtime.js +1 -1
- package/src/server/services/repo-scanner-base.js +1 -1
- package/src/server/services/security-config.js +1 -1
- package/src/server/services/session-cache.js +1 -1
- package/src/server/services/skill-service.js +300 -46
- package/src/server/services/speed-test.js +464 -186
- package/src/server/services/statistics-service.js +2 -2
- package/src/server/services/terminal-commands.js +10 -3
- package/src/server/services/terminal-config.js +1 -1
- package/src/server/services/ui-config.js +1 -1
- package/src/server/services/workspace-service.js +57 -100
- package/src/server/websocket-server.js +132 -3
- package/src/ui/menu.js +49 -40
- package/src/utils/port-helper.js +22 -8
- package/src/utils/session.js +5 -4
- package/dist/web/assets/icons-BxudHPiX.js +0 -1
- package/dist/web/assets/index-D2VfwJBa.js +0 -14
- package/dist/web/assets/index-oXBzu0bd.css +0 -41
- package/dist/web/assets/naive-ui-DT-Uur8K.js +0 -1
- package/dist/web/assets/vue-vendor-6JaYHOiI.js +0 -44
- package/src/server/api/permissions.js +0 -385
- package/src/server/services/permission-templates-service.js +0 -308
package/src/config/loader.js
CHANGED
|
@@ -3,9 +3,18 @@ const fs = require('fs');
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
5
|
const DEFAULT_CONFIG = require('./default');
|
|
6
|
+
const { PATHS, ensureStorageDirMigrated } = require('./paths');
|
|
6
7
|
const eventBus = require('../plugins/event-bus');
|
|
7
8
|
|
|
8
|
-
const
|
|
9
|
+
const LEGACY_CONFIG_FILES = [
|
|
10
|
+
path.join(__dirname, '../../config.json'),
|
|
11
|
+
path.join(os.homedir(), '.claude', 'config.json')
|
|
12
|
+
];
|
|
13
|
+
|
|
14
|
+
function getConfigFilePath() {
|
|
15
|
+
ensureStorageDirMigrated();
|
|
16
|
+
return PATHS.configFile;
|
|
17
|
+
}
|
|
9
18
|
|
|
10
19
|
/**
|
|
11
20
|
* 展开 ~ 为用户主目录
|
|
@@ -31,19 +40,66 @@ function mergePricing(defaultPricing, overrides = {}) {
|
|
|
31
40
|
return merged;
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
function mergeDefaultModels(defaultModels, overrides = {}) {
|
|
44
|
+
const merged = {};
|
|
45
|
+
Object.keys(defaultModels).forEach((key) => {
|
|
46
|
+
// If user config has this tool type, use it; otherwise use default
|
|
47
|
+
merged[key] = (overrides && overrides[key]) ? overrides[key] : defaultModels[key];
|
|
48
|
+
});
|
|
49
|
+
return merged;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function mergeModelDiscovery(defaultModelDiscovery, overrides = {}) {
|
|
53
|
+
return {
|
|
54
|
+
...defaultModelDiscovery,
|
|
55
|
+
...(overrides || {})
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function readJsonFile(filePath) {
|
|
60
|
+
const content = fs.readFileSync(filePath, 'utf8');
|
|
61
|
+
return JSON.parse(content);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function migrateLegacyConfigIfNeeded(configFilePath) {
|
|
65
|
+
if (fs.existsSync(configFilePath)) return;
|
|
66
|
+
|
|
67
|
+
for (const legacyPath of LEGACY_CONFIG_FILES) {
|
|
68
|
+
try {
|
|
69
|
+
if (!legacyPath || legacyPath === configFilePath) continue;
|
|
70
|
+
if (!fs.existsSync(legacyPath)) continue;
|
|
71
|
+
const legacyConfig = readJsonFile(legacyPath);
|
|
72
|
+
const dir = path.dirname(configFilePath);
|
|
73
|
+
if (!fs.existsSync(dir)) {
|
|
74
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
75
|
+
}
|
|
76
|
+
fs.writeFileSync(configFilePath, JSON.stringify(legacyConfig, null, 2), 'utf8');
|
|
77
|
+
console.log(`[Config] 已迁移历史配置: ${legacyPath} -> ${configFilePath}`);
|
|
78
|
+
return;
|
|
79
|
+
} catch (error) {
|
|
80
|
+
console.warn(`[Config] 迁移历史配置失败: ${legacyPath}`, error.message);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
34
85
|
/**
|
|
35
86
|
* 加载配置
|
|
36
87
|
*/
|
|
37
88
|
function loadConfig() {
|
|
89
|
+
const configFilePath = getConfigFilePath();
|
|
90
|
+
migrateLegacyConfigIfNeeded(configFilePath);
|
|
91
|
+
|
|
38
92
|
try {
|
|
39
|
-
if (fs.existsSync(
|
|
40
|
-
const userConfig =
|
|
93
|
+
if (fs.existsSync(configFilePath)) {
|
|
94
|
+
const userConfig = readJsonFile(configFilePath);
|
|
41
95
|
const config = { ...DEFAULT_CONFIG, ...userConfig };
|
|
42
|
-
config.projectsDir = expandHome(config.projectsDir);
|
|
96
|
+
config.projectsDir = expandHome(config.projectsDir || DEFAULT_CONFIG.projectsDir);
|
|
43
97
|
|
|
44
98
|
// 合并 ports 配置
|
|
45
99
|
config.ports = { ...DEFAULT_CONFIG.ports, ...userConfig.ports };
|
|
46
100
|
config.pricing = mergePricing(DEFAULT_CONFIG.pricing, userConfig.pricing);
|
|
101
|
+
config.defaultModels = mergeDefaultModels(DEFAULT_CONFIG.defaultModels, userConfig.defaultModels);
|
|
102
|
+
config.modelDiscovery = mergeModelDiscovery(DEFAULT_CONFIG.modelDiscovery, userConfig.modelDiscovery);
|
|
47
103
|
|
|
48
104
|
// 确保有 currentProject,使用 defaultProject 作为 currentProject
|
|
49
105
|
if (!config.currentProject && config.defaultProject) {
|
|
@@ -54,9 +110,13 @@ function loadConfig() {
|
|
|
54
110
|
return config;
|
|
55
111
|
}
|
|
56
112
|
} catch (error) {
|
|
57
|
-
console.error(
|
|
113
|
+
console.error(`加载配置文件失败,使用默认配置: ${configFilePath}`);
|
|
58
114
|
}
|
|
59
|
-
const defaultConfig = {
|
|
115
|
+
const defaultConfig = {
|
|
116
|
+
...DEFAULT_CONFIG,
|
|
117
|
+
projectsDir: expandHome(DEFAULT_CONFIG.projectsDir),
|
|
118
|
+
currentProject: DEFAULT_CONFIG.defaultProject
|
|
119
|
+
};
|
|
60
120
|
eventBus.emitSync('config:loaded', { config: defaultConfig });
|
|
61
121
|
return defaultConfig;
|
|
62
122
|
}
|
|
@@ -65,11 +125,16 @@ function loadConfig() {
|
|
|
65
125
|
* 保存配置
|
|
66
126
|
*/
|
|
67
127
|
function saveConfig(config) {
|
|
128
|
+
const configFilePath = getConfigFilePath();
|
|
68
129
|
try {
|
|
69
|
-
|
|
130
|
+
const dir = path.dirname(configFilePath);
|
|
131
|
+
if (!fs.existsSync(dir)) {
|
|
132
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
133
|
+
}
|
|
134
|
+
fs.writeFileSync(configFilePath, JSON.stringify(config, null, 2), 'utf8');
|
|
70
135
|
eventBus.emitSync('config:saved', { config });
|
|
71
136
|
} catch (error) {
|
|
72
|
-
console.error(
|
|
137
|
+
console.error(`保存配置失败 (${configFilePath}):`, error.message);
|
|
73
138
|
}
|
|
74
139
|
}
|
|
75
140
|
|
|
@@ -77,4 +142,5 @@ module.exports = {
|
|
|
77
142
|
loadConfig,
|
|
78
143
|
saveConfig,
|
|
79
144
|
expandHome,
|
|
145
|
+
getConfigFilePath
|
|
80
146
|
};
|
package/src/config/paths.js
CHANGED
|
@@ -1,90 +1,149 @@
|
|
|
1
1
|
// CTX 工具路径配置
|
|
2
|
-
// 所有路径统一使用 ~/.
|
|
2
|
+
// 所有路径统一使用 ~/.cc-tool 目录
|
|
3
|
+
const fs = require('fs');
|
|
3
4
|
const path = require('path');
|
|
4
5
|
const os = require('os');
|
|
5
6
|
|
|
6
7
|
// 基础目录
|
|
7
|
-
const
|
|
8
|
+
const CC_TOOL_BASE_DIR = path.join(os.homedir(), '.cc-tool');
|
|
9
|
+
// 兼容旧变量名,避免外部调用方断裂
|
|
10
|
+
const CTX_BASE_DIR = CC_TOOL_BASE_DIR;
|
|
11
|
+
|
|
12
|
+
// 旧目录(升级时自动合并到 ~/.cc-tool)
|
|
13
|
+
const LEGACY_BASE_DIRS = [
|
|
14
|
+
path.join(os.homedir(), '.claude', 'ctx'),
|
|
15
|
+
path.join(os.homedir(), '.claude', 'cc-tool')
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
let migrationChecked = false;
|
|
19
|
+
|
|
20
|
+
function mergeDirectory(sourceDir, targetDir) {
|
|
21
|
+
if (!fs.existsSync(sourceDir)) return;
|
|
22
|
+
|
|
23
|
+
const sourceStat = fs.statSync(sourceDir);
|
|
24
|
+
if (sourceStat.isDirectory()) {
|
|
25
|
+
if (!fs.existsSync(targetDir)) {
|
|
26
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const entries = fs.readdirSync(sourceDir);
|
|
30
|
+
entries.forEach((entry) => {
|
|
31
|
+
mergeDirectory(path.join(sourceDir, entry), path.join(targetDir, entry));
|
|
32
|
+
});
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (!fs.existsSync(targetDir)) {
|
|
37
|
+
fs.copyFileSync(sourceDir, targetDir);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function ensureStorageDirMigrated() {
|
|
42
|
+
if (migrationChecked) {
|
|
43
|
+
return CC_TOOL_BASE_DIR;
|
|
44
|
+
}
|
|
45
|
+
migrationChecked = true;
|
|
46
|
+
|
|
47
|
+
if (!fs.existsSync(CC_TOOL_BASE_DIR)) {
|
|
48
|
+
fs.mkdirSync(CC_TOOL_BASE_DIR, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
LEGACY_BASE_DIRS.forEach((legacyDir) => {
|
|
52
|
+
if (!fs.existsSync(legacyDir)) return;
|
|
53
|
+
try {
|
|
54
|
+
mergeDirectory(legacyDir, CC_TOOL_BASE_DIR);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.warn(`[paths] 迁移目录失败: ${legacyDir} -> ${CC_TOOL_BASE_DIR}`, error.message);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
return CC_TOOL_BASE_DIR;
|
|
61
|
+
}
|
|
8
62
|
|
|
9
63
|
// 路径配置
|
|
10
64
|
const PATHS = {
|
|
11
65
|
// 基础目录
|
|
12
|
-
base:
|
|
66
|
+
base: CC_TOOL_BASE_DIR,
|
|
13
67
|
|
|
14
68
|
// 项目目录(存储项目配置和会话)
|
|
15
|
-
projects: path.join(
|
|
69
|
+
projects: path.join(CC_TOOL_BASE_DIR, 'projects'),
|
|
16
70
|
|
|
17
71
|
// 配置文件目录
|
|
18
|
-
config: path.join(
|
|
19
|
-
configFile: path.join(
|
|
72
|
+
config: path.join(CC_TOOL_BASE_DIR, 'config'),
|
|
73
|
+
configFile: path.join(CC_TOOL_BASE_DIR, 'config.json'),
|
|
20
74
|
|
|
21
75
|
// 日志目录
|
|
22
|
-
logs: path.join(
|
|
76
|
+
logs: path.join(CC_TOOL_BASE_DIR, 'logs'),
|
|
23
77
|
|
|
24
78
|
// 别名存储
|
|
25
|
-
aliases: path.join(
|
|
79
|
+
aliases: path.join(CC_TOOL_BASE_DIR, 'aliases.json'),
|
|
26
80
|
|
|
27
81
|
// 收藏夹存储
|
|
28
|
-
favorites: path.join(
|
|
82
|
+
favorites: path.join(CC_TOOL_BASE_DIR, 'favorites.json'),
|
|
29
83
|
|
|
30
84
|
// 渠道配置
|
|
31
85
|
channels: {
|
|
32
|
-
claude: path.join(
|
|
33
|
-
codex: path.join(
|
|
34
|
-
gemini: path.join(
|
|
86
|
+
claude: path.join(CC_TOOL_BASE_DIR, 'channels.json'),
|
|
87
|
+
codex: path.join(CC_TOOL_BASE_DIR, 'codex-channels.json'),
|
|
88
|
+
gemini: path.join(CC_TOOL_BASE_DIR, 'gemini-channels.json'),
|
|
89
|
+
opencode: path.join(CC_TOOL_BASE_DIR, 'opencode-channels.json')
|
|
35
90
|
},
|
|
36
91
|
|
|
37
92
|
// 激活渠道标记
|
|
38
93
|
activeChannel: {
|
|
39
|
-
claude: path.join(
|
|
40
|
-
codex: path.join(
|
|
41
|
-
gemini: path.join(
|
|
94
|
+
claude: path.join(CC_TOOL_BASE_DIR, 'active-channel.json'),
|
|
95
|
+
codex: path.join(CC_TOOL_BASE_DIR, 'codex-active-channel.json'),
|
|
96
|
+
gemini: path.join(CC_TOOL_BASE_DIR, 'gemini-active-channel.json'),
|
|
97
|
+
opencode: path.join(CC_TOOL_BASE_DIR, 'opencode-active-channel.json')
|
|
42
98
|
},
|
|
43
99
|
|
|
44
100
|
// 统计数据
|
|
45
101
|
statistics: {
|
|
46
|
-
claude: path.join(
|
|
47
|
-
codex: path.join(
|
|
48
|
-
gemini: path.join(
|
|
102
|
+
claude: path.join(CC_TOOL_BASE_DIR, 'statistics.json'),
|
|
103
|
+
codex: path.join(CC_TOOL_BASE_DIR, 'codex-statistics.json'),
|
|
104
|
+
gemini: path.join(CC_TOOL_BASE_DIR, 'gemini-statistics.json'),
|
|
105
|
+
opencode: path.join(CC_TOOL_BASE_DIR, 'opencode-statistics.json'),
|
|
49
106
|
dailyStats: {
|
|
50
|
-
claude: path.join(
|
|
51
|
-
codex: path.join(
|
|
52
|
-
gemini: path.join(
|
|
107
|
+
claude: path.join(CC_TOOL_BASE_DIR, 'daily-stats'),
|
|
108
|
+
codex: path.join(CC_TOOL_BASE_DIR, 'codex-daily-stats'),
|
|
109
|
+
gemini: path.join(CC_TOOL_BASE_DIR, 'gemini-daily-stats'),
|
|
110
|
+
opencode: path.join(CC_TOOL_BASE_DIR, 'opencode-daily-stats')
|
|
53
111
|
}
|
|
54
112
|
},
|
|
55
113
|
|
|
56
114
|
// 会话缓存
|
|
57
|
-
sessionCache: path.join(
|
|
115
|
+
sessionCache: path.join(CC_TOOL_BASE_DIR, 'session-cache.json'),
|
|
58
116
|
|
|
59
117
|
// 项目顺序
|
|
60
|
-
projectOrder: path.join(
|
|
118
|
+
projectOrder: path.join(CC_TOOL_BASE_DIR, 'project-order.json'),
|
|
61
119
|
|
|
62
120
|
// 环境备份
|
|
63
|
-
envBackups: path.join(
|
|
121
|
+
envBackups: path.join(CC_TOOL_BASE_DIR, 'env-backups'),
|
|
64
122
|
|
|
65
123
|
// UI 配置
|
|
66
|
-
uiConfig: path.join(
|
|
124
|
+
uiConfig: path.join(CC_TOOL_BASE_DIR, 'ui-config.json'),
|
|
67
125
|
|
|
68
126
|
// 飞书通知脚本
|
|
69
|
-
notifyHook: path.join(
|
|
127
|
+
notifyHook: path.join(CC_TOOL_BASE_DIR, 'notify-hook.js'),
|
|
70
128
|
|
|
71
129
|
// Skills 安装目录(注意:这个仍使用 Claude 原生路径)
|
|
72
130
|
skills: path.join(os.homedir(), '.claude', 'skills'),
|
|
73
131
|
|
|
74
132
|
// MCP 配置(注意:这个仍使用 Claude 原生路径)
|
|
75
|
-
mcpConfig: path.join(
|
|
133
|
+
mcpConfig: path.join(CC_TOOL_BASE_DIR, 'mcp-config.json'),
|
|
76
134
|
|
|
77
135
|
// Terminal 配置
|
|
78
|
-
terminalConfig: path.join(
|
|
136
|
+
terminalConfig: path.join(CC_TOOL_BASE_DIR, 'terminal-config.json'),
|
|
79
137
|
|
|
80
138
|
// Prompts
|
|
81
|
-
prompts: path.join(
|
|
139
|
+
prompts: path.join(CC_TOOL_BASE_DIR, 'prompts.json'),
|
|
82
140
|
|
|
83
141
|
// 代理运行时状态
|
|
84
142
|
proxyRuntime: {
|
|
85
|
-
claude: path.join(
|
|
86
|
-
codex: path.join(
|
|
87
|
-
gemini: path.join(
|
|
143
|
+
claude: path.join(CC_TOOL_BASE_DIR, 'proxy-runtime.json'),
|
|
144
|
+
codex: path.join(CC_TOOL_BASE_DIR, 'codex-proxy-runtime.json'),
|
|
145
|
+
gemini: path.join(CC_TOOL_BASE_DIR, 'gemini-proxy-runtime.json'),
|
|
146
|
+
opencode: path.join(CC_TOOL_BASE_DIR, 'opencode-proxy-runtime.json')
|
|
88
147
|
}
|
|
89
148
|
};
|
|
90
149
|
|
|
@@ -111,11 +170,24 @@ const NATIVE_PATHS = {
|
|
|
111
170
|
env: path.join(os.homedir(), '.gemini', '.env'),
|
|
112
171
|
envBackup: path.join(os.homedir(), '.gemini', '.env.cc-tool-backup'),
|
|
113
172
|
tmp: path.join(os.homedir(), '.gemini', 'tmp')
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
// OpenCode 原生配置
|
|
176
|
+
opencode: {
|
|
177
|
+
data: path.join(os.homedir(), '.local', 'share', 'opencode'),
|
|
178
|
+
config: path.join(os.homedir(), '.config', 'opencode'),
|
|
179
|
+
sessions: path.join(os.homedir(), '.local', 'share', 'opencode', 'storage', 'session'),
|
|
180
|
+
projects: path.join(os.homedir(), '.local', 'share', 'opencode', 'storage', 'project'),
|
|
181
|
+
messages: path.join(os.homedir(), '.local', 'share', 'opencode', 'storage', 'message'),
|
|
182
|
+
log: path.join(os.homedir(), '.local', 'share', 'opencode', 'log')
|
|
114
183
|
}
|
|
115
184
|
};
|
|
116
185
|
|
|
117
186
|
module.exports = {
|
|
118
187
|
PATHS,
|
|
119
188
|
NATIVE_PATHS,
|
|
120
|
-
CTX_BASE_DIR
|
|
189
|
+
CTX_BASE_DIR,
|
|
190
|
+
CC_TOOL_BASE_DIR,
|
|
191
|
+
LEGACY_BASE_DIRS,
|
|
192
|
+
ensureStorageDirMigrated
|
|
121
193
|
};
|
package/src/index.js
CHANGED
|
@@ -20,7 +20,9 @@ const { handleProxyStart: proxyStart, handleProxyStop: proxyStop, handleProxyRes
|
|
|
20
20
|
const { handleLogs } = require('./commands/logs');
|
|
21
21
|
const { handleStats, handleStatsExport } = require('./commands/stats');
|
|
22
22
|
const { handleDoctor } = require('./commands/doctor');
|
|
23
|
+
const { handleUpdate } = require('./commands/update');
|
|
23
24
|
const { workspaceMenu } = require('./commands/workspace');
|
|
25
|
+
const { ensureStorageDirMigrated } = require('./config/paths');
|
|
24
26
|
const PluginManager = require('./plugins/plugin-manager');
|
|
25
27
|
const eventBus = require('./plugins/event-bus');
|
|
26
28
|
const chalk = require('chalk');
|
|
@@ -48,8 +50,10 @@ function showHelp() {
|
|
|
48
50
|
console.log(' ctx status 查看服务状态\n');
|
|
49
51
|
|
|
50
52
|
console.log(chalk.yellow('📱 UI 管理:'));
|
|
51
|
-
console.log(' ctx ui 前台启动 Web UI
|
|
53
|
+
console.log(' ctx ui 前台启动 Web UI(仅本地访问)');
|
|
54
|
+
console.log(' ctx ui --host 前台启动 Web UI(允许 LAN 访问)');
|
|
52
55
|
console.log(' ctx ui start 后台启动 Web UI');
|
|
56
|
+
console.log(' ctx ui start --host 后台启动 Web UI(允许 LAN 访问)');
|
|
53
57
|
console.log(' ctx ui stop 停止 Web UI');
|
|
54
58
|
console.log(' ctx ui restart 重启 Web UI\n');
|
|
55
59
|
|
|
@@ -59,7 +63,8 @@ function showHelp() {
|
|
|
59
63
|
console.log(' ctx claude status 查看 Claude 代理状态');
|
|
60
64
|
console.log(' ctx codex start 启动 Codex 代理');
|
|
61
65
|
console.log(' ctx gemini start 启动 Gemini 代理');
|
|
62
|
-
console.log(
|
|
66
|
+
console.log(' ctx opencode start 启动 OpenCode 代理');
|
|
67
|
+
console.log(chalk.gray(' (codex/gemini/opencode 命令与 claude 类似)\n'));
|
|
63
68
|
|
|
64
69
|
console.log(chalk.yellow('📋 日志管理:'));
|
|
65
70
|
console.log(' ctx logs 查看所有日志');
|
|
@@ -76,7 +81,9 @@ function showHelp() {
|
|
|
76
81
|
console.log(' ctx stats export 导出统计数据\n');
|
|
77
82
|
|
|
78
83
|
console.log(chalk.yellow('🛠️ 其他命令:'));
|
|
84
|
+
console.log(' ctx update 检查并更新到最新版本');
|
|
79
85
|
console.log(' ctx doctor 系统诊断');
|
|
86
|
+
console.log(' ctx port 配置端口');
|
|
80
87
|
console.log(' ctx reset 重置配置');
|
|
81
88
|
console.log(' ctx security reset 关闭访问密码');
|
|
82
89
|
console.log(' ctx --version, -v 显示版本');
|
|
@@ -130,6 +137,8 @@ process.on('SIGINT', async () => {
|
|
|
130
137
|
* 主函数
|
|
131
138
|
*/
|
|
132
139
|
async function main() {
|
|
140
|
+
ensureStorageDirMigrated();
|
|
141
|
+
|
|
133
142
|
// 处理命令行参数
|
|
134
143
|
const args = process.argv.slice(2);
|
|
135
144
|
|
|
@@ -145,6 +154,47 @@ async function main() {
|
|
|
145
154
|
return;
|
|
146
155
|
}
|
|
147
156
|
|
|
157
|
+
// daemon 命令兼容(保持与 README 中旧命令一致)
|
|
158
|
+
if (args[0] === 'daemon') {
|
|
159
|
+
const subCommand = args[1] || 'status';
|
|
160
|
+
|
|
161
|
+
if (subCommand === 'start') {
|
|
162
|
+
await handleStart();
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
if (subCommand === 'stop') {
|
|
166
|
+
await handleStop();
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (subCommand === 'restart') {
|
|
170
|
+
await handleRestart();
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
if (subCommand === 'status') {
|
|
174
|
+
await handleStatus();
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
if (subCommand === 'logs') {
|
|
178
|
+
const options = {};
|
|
179
|
+
for (let i = 2; i < args.length; i++) {
|
|
180
|
+
if (args[i] === '--lines' && args[i + 1]) {
|
|
181
|
+
options.lines = parseInt(args[i + 1], 10);
|
|
182
|
+
i++;
|
|
183
|
+
} else if (args[i] === '--follow' || args[i] === '-f') {
|
|
184
|
+
options.follow = true;
|
|
185
|
+
} else if (args[i] === '--clear') {
|
|
186
|
+
options.clear = true;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
await handleLogs('ui', options);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
console.log(chalk.red(`\n❌ 未知 daemon 子命令: ${subCommand}\n`));
|
|
194
|
+
console.log(chalk.gray('支持的命令: start, stop, restart, status, logs\n'));
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
|
|
148
198
|
// reset 命令 - 恢复默认配置
|
|
149
199
|
if (args[0] === 'reset') {
|
|
150
200
|
await resetConfig();
|
|
@@ -205,8 +255,8 @@ async function main() {
|
|
|
205
255
|
return;
|
|
206
256
|
}
|
|
207
257
|
|
|
208
|
-
// claude/codex/gemini 代理管理命令
|
|
209
|
-
const channels = ['claude', 'codex', 'gemini'];
|
|
258
|
+
// claude/codex/gemini/opencode 代理管理命令
|
|
259
|
+
const channels = ['claude', 'codex', 'gemini', 'opencode'];
|
|
210
260
|
if (channels.includes(args[0])) {
|
|
211
261
|
const channel = args[0];
|
|
212
262
|
const action = args[1] || 'status';
|
|
@@ -279,6 +329,19 @@ async function main() {
|
|
|
279
329
|
return;
|
|
280
330
|
}
|
|
281
331
|
|
|
332
|
+
// update 命令 - 检查并更新到最新版本
|
|
333
|
+
if (args[0] === 'update') {
|
|
334
|
+
const checkOnly = args.includes('--check');
|
|
335
|
+
await handleUpdate({ checkOnly });
|
|
336
|
+
return;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// port 命令 - 配置端口
|
|
340
|
+
if (args[0] === 'port') {
|
|
341
|
+
await handlePortConfig();
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
282
345
|
// 代理命令
|
|
283
346
|
if (args[0] === 'proxy') {
|
|
284
347
|
const { handleProxyStart, handleProxyStop, handleProxyStatus } = require('./commands/proxy');
|
package/src/plugins/constants.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
|
-
const
|
|
2
|
+
const { PATHS, ensureStorageDirMigrated } = require('../config/paths');
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
ensureStorageDirMigrated();
|
|
5
|
+
const PLUGINS_DIR = path.join(PATHS.base, 'plugins');
|
|
5
6
|
const REGISTRY_FILE = path.join(PLUGINS_DIR, 'registry.json');
|
|
6
7
|
const CONFIG_DIR = path.join(PLUGINS_DIR, 'config');
|
|
7
8
|
const INSTALLED_DIR = path.join(PLUGINS_DIR, 'installed');
|
|
@@ -15,7 +15,7 @@ const packageJson = require('../../package.json');
|
|
|
15
15
|
function createPluginContext(pluginName, pluginConfig, pluginDir) {
|
|
16
16
|
const commandRegistry = new Map();
|
|
17
17
|
|
|
18
|
-
// Storage API - persists plugin data to ~/.
|
|
18
|
+
// Storage API - persists plugin data to ~/.cc-tool/plugins/config/<plugin-name>.json
|
|
19
19
|
const storage = createStorageAPI(pluginName);
|
|
20
20
|
|
|
21
21
|
// Logger API - prefixed logging
|
package/src/reset-config.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const os = require('os');
|
|
4
|
+
const { PATHS, ensureStorageDirMigrated } = require('./config/paths');
|
|
4
5
|
|
|
5
6
|
// 恢复配置到默认状态
|
|
6
7
|
async function resetConfig() {
|
|
7
8
|
console.log('\n开始恢复默认配置...\n');
|
|
9
|
+
ensureStorageDirMigrated();
|
|
8
10
|
|
|
9
11
|
try {
|
|
10
12
|
// 1. 尝试停止代理服务器(如果正在运行)
|
|
@@ -42,10 +44,10 @@ async function resetConfig() {
|
|
|
42
44
|
console.log('检测到代理配置,尝试恢复到正常渠道...');
|
|
43
45
|
|
|
44
46
|
// 读取激活的渠道
|
|
45
|
-
const activeChannelPath =
|
|
47
|
+
const activeChannelPath = PATHS.activeChannel.claude;
|
|
46
48
|
if (fs.existsSync(activeChannelPath)) {
|
|
47
49
|
const activeChannelData = JSON.parse(fs.readFileSync(activeChannelPath, 'utf8'));
|
|
48
|
-
const channelsPath =
|
|
50
|
+
const channelsPath = PATHS.channels.claude;
|
|
49
51
|
|
|
50
52
|
if (fs.existsSync(channelsPath)) {
|
|
51
53
|
const channelsData = JSON.parse(fs.readFileSync(channelsPath, 'utf8'));
|