coding-tool-x 3.5.2 → 3.5.3
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 +8 -0
- package/package.json +2 -2
- package/src/index.js +21 -10
- package/src/server/index.js +5 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,14 @@
|
|
|
4
4
|
|
|
5
5
|
该项目遵循 [Semantic Versioning](https://semver.org/)。
|
|
6
6
|
|
|
7
|
+
## [3.5.3] - 2026-03-23
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
- **Windows 全局安装后 UI 启动失败** - 发布依赖中显式加入 `rxjs`,并移除无效的 `file:` 本地运行时依赖,修复 `ctx start` / `ctx ui --daemon` 在 Windows 上因 `inquirer` 缺少运行时依赖而启动失败的问题
|
|
11
|
+
- **非交互启动链路解耦交互依赖** - CLI 与服务入口改为按需加载 `inquirer`,即使交互菜单依赖异常,后台启动命令仍可进入服务启动流程
|
|
12
|
+
- **Codex PowerShell 环境同步降级处理** - Windows 上 `pwsh` 超时或缺失时,Codex 环境变量同步改为告警降级,不再直接中断代理恢复与服务启动
|
|
13
|
+
- **残留端口清理体验修复** - `ctx stop` 现在会额外清理受管端口上的残留进程,并给出更明确的端口占用提示,减少二次启动时的误报
|
|
14
|
+
|
|
7
15
|
## [3.3.8] - 2026-03-12
|
|
8
16
|
|
|
9
17
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "coding-tool-x",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.3",
|
|
4
4
|
"description": "Vibe Coding 增强工作助手 - 智能会话管理、动态渠道切换、全局搜索、实时监控",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -58,7 +58,6 @@
|
|
|
58
58
|
"@iarna/toml": "^2.2.5",
|
|
59
59
|
"adm-zip": "^0.5.16",
|
|
60
60
|
"ajv": "^8.17.1",
|
|
61
|
-
"cc-tool-web": "file:src/web",
|
|
62
61
|
"chalk": "^4.1.2",
|
|
63
62
|
"express": "^4.21.2",
|
|
64
63
|
"http-proxy": "^1.18.1",
|
|
@@ -67,6 +66,7 @@
|
|
|
67
66
|
"open": "^8.4.2",
|
|
68
67
|
"ora": "^5.4.1",
|
|
69
68
|
"pm2": "^6.0.14",
|
|
69
|
+
"rxjs": "^7.8.2",
|
|
70
70
|
"semver": "^7.6.0",
|
|
71
71
|
"toml": "^3.0.0",
|
|
72
72
|
"ws": "^8.18.3"
|
package/src/index.js
CHANGED
|
@@ -6,30 +6,24 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
const { loadConfig } = require('./config/loader');
|
|
9
|
-
const { showMainMenu } = require('./ui/menu');
|
|
10
|
-
const { handleList } = require('./commands/list');
|
|
11
|
-
const { handleSearch } = require('./commands/search');
|
|
12
|
-
const { switchProject } = require('./commands/switch');
|
|
13
9
|
const { resetConfig } = require('./reset-config');
|
|
14
|
-
const { handleChannelManagement, handleAddChannel, handleChannelStatus } = require('./commands/channels');
|
|
15
|
-
const { handleToggleProxy } = require('./commands/toggle-proxy');
|
|
16
|
-
const { handlePortConfig } = require('./commands/port-config');
|
|
17
|
-
const { handleSwitchCliType } = require('./commands/cli-type');
|
|
18
10
|
const { handleStart, handleStop, handleRestart, handleStatus } = require('./commands/daemon');
|
|
19
11
|
const { handleProxyStart: proxyStart, handleProxyStop: proxyStop, handleProxyRestart, handleProxyStatus: proxyStatus } = require('./commands/proxy-control');
|
|
20
12
|
const { handleLogs } = require('./commands/logs');
|
|
21
13
|
const { handleStats, handleStatsExport } = require('./commands/stats');
|
|
22
14
|
const { handleDoctor } = require('./commands/doctor');
|
|
23
15
|
const { handleUpdate } = require('./commands/update');
|
|
24
|
-
const { workspaceMenu } = require('./commands/workspace');
|
|
25
16
|
const { ensureStorageDirMigrated } = require('./config/paths');
|
|
26
17
|
const PluginManager = require('./plugins/plugin-manager');
|
|
27
18
|
const eventBus = require('./plugins/event-bus');
|
|
28
19
|
const chalk = require('chalk');
|
|
29
|
-
const inquirer = require('inquirer');
|
|
30
20
|
const path = require('path');
|
|
31
21
|
const fs = require('fs');
|
|
32
22
|
|
|
23
|
+
function getInquirer() {
|
|
24
|
+
return require('inquirer');
|
|
25
|
+
}
|
|
26
|
+
|
|
33
27
|
// 读取版本号
|
|
34
28
|
function getVersion() {
|
|
35
29
|
const packagePath = path.join(__dirname, '../package.json');
|
|
@@ -338,6 +332,7 @@ async function main() {
|
|
|
338
332
|
|
|
339
333
|
// port 命令 - 配置端口
|
|
340
334
|
if (args[0] === 'port') {
|
|
335
|
+
const { handlePortConfig } = require('./commands/port-config');
|
|
341
336
|
await handlePortConfig();
|
|
342
337
|
return;
|
|
343
338
|
}
|
|
@@ -400,6 +395,7 @@ async function main() {
|
|
|
400
395
|
|
|
401
396
|
while (true) {
|
|
402
397
|
// 显示主菜单
|
|
398
|
+
const { showMainMenu } = require('./ui/menu');
|
|
403
399
|
const action = await showMainMenu(config);
|
|
404
400
|
|
|
405
401
|
// 发送命令开始事件
|
|
@@ -409,7 +405,9 @@ async function main() {
|
|
|
409
405
|
|
|
410
406
|
switch (action) {
|
|
411
407
|
case 'list':
|
|
408
|
+
const { handleList } = require('./commands/list');
|
|
412
409
|
await handleList(config, async () => {
|
|
410
|
+
const { switchProject } = require('./commands/switch');
|
|
413
411
|
const switched = await switchProject(config);
|
|
414
412
|
if (switched) {
|
|
415
413
|
// 重新加载配置以获取最新的项目设置
|
|
@@ -420,7 +418,9 @@ async function main() {
|
|
|
420
418
|
break;
|
|
421
419
|
|
|
422
420
|
case 'search':
|
|
421
|
+
const { handleSearch } = require('./commands/search');
|
|
423
422
|
await handleSearch(config, async () => {
|
|
423
|
+
const { switchProject } = require('./commands/switch');
|
|
424
424
|
const switched = await switchProject(config);
|
|
425
425
|
if (switched) {
|
|
426
426
|
config = loadConfig();
|
|
@@ -430,11 +430,14 @@ async function main() {
|
|
|
430
430
|
break;
|
|
431
431
|
|
|
432
432
|
case 'switch':
|
|
433
|
+
const { switchProject } = require('./commands/switch');
|
|
433
434
|
const switched = await switchProject(config);
|
|
434
435
|
if (switched) {
|
|
435
436
|
config = loadConfig();
|
|
436
437
|
// 切换成功后自动进入会话列表
|
|
438
|
+
const { handleList } = require('./commands/list');
|
|
437
439
|
await handleList(config, async () => {
|
|
440
|
+
const { switchProject } = require('./commands/switch');
|
|
438
441
|
const switched = await switchProject(config);
|
|
439
442
|
if (switched) {
|
|
440
443
|
config = loadConfig();
|
|
@@ -445,26 +448,32 @@ async function main() {
|
|
|
445
448
|
break;
|
|
446
449
|
|
|
447
450
|
case 'workspace':
|
|
451
|
+
const { workspaceMenu } = require('./commands/workspace');
|
|
448
452
|
await workspaceMenu();
|
|
449
453
|
break;
|
|
450
454
|
|
|
451
455
|
case 'switch-cli-type':
|
|
456
|
+
const { handleSwitchCliType } = require('./commands/cli-type');
|
|
452
457
|
await handleSwitchCliType();
|
|
453
458
|
config = loadConfig(); // 重新加载配置以获取新的类型
|
|
454
459
|
break;
|
|
455
460
|
|
|
456
461
|
case 'switch-channel':
|
|
462
|
+
const { handleChannelManagement } = require('./commands/channels');
|
|
457
463
|
await handleChannelManagement();
|
|
458
464
|
break;
|
|
459
465
|
case 'channel-status':
|
|
466
|
+
const { handleChannelStatus } = require('./commands/channels');
|
|
460
467
|
await handleChannelStatus();
|
|
461
468
|
break;
|
|
462
469
|
|
|
463
470
|
case 'toggle-proxy':
|
|
471
|
+
const { handleToggleProxy } = require('./commands/toggle-proxy');
|
|
464
472
|
await handleToggleProxy();
|
|
465
473
|
break;
|
|
466
474
|
|
|
467
475
|
case 'add-channel':
|
|
476
|
+
const { handleAddChannel } = require('./commands/channels');
|
|
468
477
|
await handleAddChannel();
|
|
469
478
|
break;
|
|
470
479
|
|
|
@@ -475,6 +484,7 @@ async function main() {
|
|
|
475
484
|
}
|
|
476
485
|
|
|
477
486
|
case 'port-config':
|
|
487
|
+
const { handlePortConfig } = require('./commands/port-config');
|
|
478
488
|
await handlePortConfig();
|
|
479
489
|
break;
|
|
480
490
|
|
|
@@ -484,6 +494,7 @@ async function main() {
|
|
|
484
494
|
|
|
485
495
|
case 'plugin-menu': {
|
|
486
496
|
const { handlePluginCommand } = require('./commands/plugin');
|
|
497
|
+
const inquirer = getInquirer();
|
|
487
498
|
|
|
488
499
|
// Show plugin management submenu
|
|
489
500
|
const pluginAction = await inquirer.prompt([{
|
package/src/server/index.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const express = require('express');
|
|
2
2
|
const path = require('path');
|
|
3
3
|
const chalk = require('chalk');
|
|
4
|
-
const inquirer = require('inquirer');
|
|
5
4
|
const { loadConfig } = require('../config/loader');
|
|
6
5
|
const { PATHS, ensureStorageDirMigrated } = require('../config/paths');
|
|
7
6
|
const { startWebSocketServer: attachWebSocketServer } = require('./websocket-server');
|
|
@@ -25,6 +24,10 @@ const { startOpenCodeProxyServer, collectProxyModelList } = require('./opencode-
|
|
|
25
24
|
const { createRemoteMutationGuard } = require('./services/network-access');
|
|
26
25
|
const { createApiRequestLogger } = require('./services/request-logger');
|
|
27
26
|
|
|
27
|
+
function getInquirer() {
|
|
28
|
+
return require('inquirer');
|
|
29
|
+
}
|
|
30
|
+
|
|
28
31
|
function isInteractivePortConflictMode(options = {}) {
|
|
29
32
|
if (options.interactive === false) {
|
|
30
33
|
return false;
|
|
@@ -73,6 +76,7 @@ async function startServer(port, host = '127.0.0.1', options = {}) {
|
|
|
73
76
|
shouldKill = true;
|
|
74
77
|
} else if (interactiveMode) {
|
|
75
78
|
// 询问用户是否关闭占用端口的进程
|
|
79
|
+
const inquirer = getInquirer();
|
|
76
80
|
const answer = await inquirer.prompt([
|
|
77
81
|
{
|
|
78
82
|
type: 'list',
|