aicodeswitch 2.0.1 → 2.0.2

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 CHANGED
@@ -2,6 +2,8 @@
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.2 (2026-01-27)
6
+
5
7
  ### 2.0.1 (2026-01-27)
6
8
 
7
9
  ### 1.10.2 (2026-01-26)
package/bin/start.js CHANGED
@@ -6,6 +6,7 @@ const chalk = require('chalk');
6
6
  const boxen = require('boxen');
7
7
  const ora = require('ora');
8
8
  const { isServerRunning, getServerInfo } = require('./utils/get-server');
9
+ const { findPidByPort } = require('./utils/port-utils');
9
10
 
10
11
  const PID_FILE = path.join(os.homedir(), '.aicodeswitch', 'server.pid');
11
12
  const LOG_FILE = path.join(os.homedir(), '.aicodeswitch', 'server.log');
@@ -23,13 +24,14 @@ const start = async (options = {}) => {
23
24
  console.log('\n');
24
25
 
25
26
  // 已经运行
26
- if (isServerRunning()) {
27
- const { host, port } = getServerInfo();
27
+ const { host, port } = getServerInfo();
28
+ if (isServerRunning() || await findPidByPort(port)) {
28
29
  if (!silent) {
29
30
  if (!silent) {
30
31
  console.log(boxen(
31
32
  chalk.yellow.bold('⚠ Server is already running!\n\n') +
32
- chalk.white(`URL: `) + chalk.cyan.bold(`http://${host}:${port}`),
33
+ chalk.white(`URL: `) + chalk.cyan.bold(`http://${host}:${port}\n\n`) +
34
+ chalk.white('Use ') + chalk.cyan('aicos restart') + chalk.white(' to restart the server.\n'),
33
35
  {
34
36
  padding: 1,
35
37
  margin: 1,
package/bin/stop.js CHANGED
@@ -14,126 +14,92 @@ const stop = async (options = {}) => {
14
14
 
15
15
  console.log('\n');
16
16
 
17
- const { host, port } = getServerInfo();
17
+ const spinner = ora({ text: chalk.cyan('Stopping server...'), color: 'cyan' }).start();
18
18
 
19
- if (!fs.existsSync(PID_FILE)) {
20
- if (!silent) {
21
- // PID 文件不存在,尝试通过端口检测进程
22
- console.log(boxen(
23
- chalk.yellow('⚠ PID file not found, checking port...'),
24
- {
25
- padding: 1,
26
- margin: 1,
27
- borderStyle: 'round',
28
- borderColor: 'yellow'
29
- }
30
- ));
31
- }
32
-
33
- const spinner = ora({
34
- text: chalk.cyan(`Checking port ${port}...`),
35
- color: 'cyan'
36
- }).start();
37
-
38
- const pid = await findPidByPort(port);
39
-
40
- if (pid) {
41
- spinner.text = chalk.cyan(`Found process on port ${port}, stopping...`);
19
+ // 第一步:如果 PID 文件存在,优先通过 PID 文件停止服务器
20
+ if (fs.existsSync(PID_FILE)) {
21
+ try {
22
+ const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8'), 10);
42
23
 
43
24
  const processInfo = await getProcessInfo(pid);
44
25
  if (!silent) {
45
26
  console.log('\n' + chalk.gray(`Process found: ${chalk.white(pid)} (${chalk.gray(processInfo)})`));
46
27
  }
47
28
 
48
- const killed = await killProcess(pid);
49
-
50
- if (killed) {
51
- spinner.succeed(chalk.green(`Process ${pid} terminated successfully`));
52
- showStoppedMessage();
53
- } else {
54
- spinner.fail(chalk.red('Failed to terminate process'));
55
- }
56
- } else {
57
- spinner.info(chalk.yellow(`No process found on port ${port}`));
58
- if (!silent) {
59
- console.log(boxen(
60
- chalk.yellow.bold('⚠ Server is not running'),
61
- {
62
- padding: 1,
63
- margin: 1,
64
- borderStyle: 'round',
65
- borderColor: 'yellow'
66
- }
67
- ));
68
- }
69
- }
70
- if (!silent) {
71
- console.log('\n');
72
- }
73
-
74
- if (callback) {
75
- console.log(boxen(chalk.yellow.bold('⚠ Server is not running')));
76
- callback();
77
- }
78
- return;
79
- }
80
-
81
- const spinner = ora({
82
- text: chalk.cyan('Stopping server...'),
83
- color: 'cyan'
84
- }).start();
85
-
86
- try {
87
- const pid = parseInt(fs.readFileSync(PID_FILE, 'utf-8'), 10);
88
-
89
- // 尝试终止进程
90
- try {
29
+ // 尝试终止进程
91
30
  process.kill(pid, 'SIGTERM');
92
31
 
93
32
  // 等待进程停止
94
33
  let attempts = 0;
95
34
  const maxAttempts = 10;
96
35
 
97
- const checkStopped = setInterval(() => {
98
- attempts++;
99
- try {
100
- process.kill(pid, 0);
101
- if (attempts >= maxAttempts) {
36
+ await new Promise((resolve) => {
37
+ const checkStopped = setInterval(() => {
38
+ attempts++;
39
+ try {
40
+ process.kill(pid, 0);
41
+ if (attempts >= maxAttempts) {
42
+ clearInterval(checkStopped);
43
+ // 强制终止
44
+ process.kill(pid, 'SIGKILL');
45
+ spinner.warn(chalk.yellow(`PID ${pid} forcefully killed!`));
46
+ fs.unlinkSync(PID_FILE);
47
+ resolve();
48
+ }
49
+ } catch (err) {
50
+ spinner.succeed(chalk.green(`PID ${pid} killed!`));
51
+ // 进程已停止
102
52
  clearInterval(checkStopped);
103
- // 强制终止
104
- process.kill(pid, 'SIGKILL');
105
- spinner.warn(chalk.yellow('Server forcefully stopped'));
106
53
  fs.unlinkSync(PID_FILE);
107
- if (!silent) {
108
- showStoppedMessage();
109
- }
110
- callback && callback();
54
+ resolve();
111
55
  }
112
- } catch (err) {
113
- // 进程已停止
114
- clearInterval(checkStopped);
115
- spinner.succeed(chalk.green('Server stopped successfully'));
116
- fs.unlinkSync(PID_FILE);
117
- if (!silent) {
118
- showStoppedMessage();
119
- }
120
- callback && callback();
121
- }
122
- }, 200);
123
-
124
- } catch (err) {
56
+ }, 200);
57
+ });
58
+ }
59
+ catch (err) {
125
60
  // 进程不存在
126
- spinner.warn(chalk.yellow('Process not found'));
61
+ if (err.code === 'ESRCH') {
62
+ spinner.warn(chalk.yellow(`PID ${pid} not found!`));
63
+ }
64
+ else {
65
+ spinner.fail(chalk.red(`\nError: ${err.message}\n`));
66
+ }
127
67
  fs.unlinkSync(PID_FILE);
68
+ }
69
+ }
70
+
71
+ // 第二步:如果 PID 文件不存在,通过端口检测进程并停止
72
+ const { port } = getServerInfo();
73
+ spinner.text = chalk.yellow(`⚠ Checking port... (port: ${port})`);
74
+ const pid = await findPidByPort(port);
75
+ if (pid) {
76
+ spinner.text = chalk.cyan(`Found process on port ${port}, stopping...`);
77
+
78
+ const processInfo = await getProcessInfo(pid);
79
+ if (!silent) {
80
+ console.log('\n' + chalk.gray(`Process found: ${chalk.white(pid)} (${chalk.gray(processInfo)})`));
81
+ }
82
+
83
+ const killed = await killProcess(pid);
84
+ if (killed) {
85
+ spinner.succeed(chalk.green(`Process ${pid} terminated successfully`));
128
86
  if (!silent) {
129
87
  showStoppedMessage();
130
88
  }
131
- callback && callback();
132
89
  }
133
- } catch (err) {
134
- spinner.fail(chalk.red('Failed to stop server'));
135
- console.log(chalk.red(`\nError: ${err.message}\n`));
90
+ else {
91
+ spinner.fail(chalk.red('Failed to terminate process'));
92
+ }
136
93
  }
94
+ else {
95
+ spinner.info(chalk.yellow(`No process found on port ${port}`));
96
+ if (!silent) {
97
+ showStoppedMessage();
98
+ }
99
+ }
100
+
101
+ // 第三步:(callback)
102
+ callback && callback();
137
103
  };
138
104
 
139
105
  const showStoppedMessage = () => {
@@ -539,8 +539,9 @@ const registerRoutes = (dbManager, proxyServer) => {
539
539
  const start = () => __awaiter(void 0, void 0, void 0, function* () {
540
540
  fs_1.default.mkdirSync(dataDir, { recursive: true });
541
541
  const dbManager = new database_1.DatabaseManager(dataDir);
542
- const proxyServer = new proxy_server_1.ProxyServer(dbManager, app);
542
+ // 必须先初始化数据库,否则会报错
543
543
  yield dbManager.initialize();
544
+ const proxyServer = new proxy_server_1.ProxyServer(dbManager, app);
544
545
  // Initialize proxy server and register proxy routes last
545
546
  proxyServer.initialize();
546
547
  // Register admin routes first
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aicodeswitch",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
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",