aicodeswitch 1.4.0 → 1.5.0

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/CLAUDE.md CHANGED
@@ -190,3 +190,4 @@ aicos version # Show current version information
190
190
  * 使用yarn作为包管理器,请使用yarn安装依赖。
191
191
  * 前端依赖库安装在devDependencies中,请使用yarn install --dev安装。
192
192
  * 所有对话请使用中文。生成代码中的文案及相关注释根据代码原本的语言生成。
193
+ * 在服务端,直接使用 __dirname 来获取当前目录,不要使用 process.cwd()
package/README.md CHANGED
@@ -7,6 +7,8 @@ AI Code Switch 是帮助你在本地管理 AI 编程工具接入大模型的工
7
7
 
8
8
  **而且它尽可能简单的帮你解决这件事。**
9
9
 
10
+ 视频演示:[https://www.bilibili.com/video/BV1uEznBuEJd/](https://www.bilibili.com/video/BV1uEznBuEJd/?from=github)
11
+
10
12
  ## 安装
11
13
 
12
14
  ```
@@ -34,8 +34,7 @@ exports.compareVersions = compareVersions;
34
34
  // 获取当前版本
35
35
  const getCurrentVersion = () => {
36
36
  try {
37
- // 在构建环境中,__dirname 可能不可用
38
- const packageJsonPath = path_1.default.resolve(process.cwd(), 'package.json');
37
+ const packageJsonPath = path_1.default.resolve(__dirname, '../../package.json');
39
38
  const packageJson = JSON.parse(fs_1.default.readFileSync(packageJsonPath, 'utf-8'));
40
39
  return packageJson.version;
41
40
  }
@@ -102,6 +102,8 @@ AI Code Switch 是帮助你在本地管理 AI 编程工具接入大模型的工
102
102
 
103
103
  **而且它尽可能简单的帮你解决这件事。**
104
104
 
105
+ 视频演示:[https://www.bilibili.com/video/BV1uEznBuEJd/](https://www.bilibili.com/video/BV1uEznBuEJd/?from=github)
106
+
105
107
  ## 安装
106
108
 
107
109
  \`\`\`
@@ -4,7 +4,7 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>AI Code Switch</title>
7
- <script type="module" crossorigin src="./assets/index-s2lL7OMJ.js"></script>
7
+ <script type="module" crossorigin src="./assets/index-DJ5R6Vso.js"></script>
8
8
  <link rel="stylesheet" crossorigin href="./assets/index-dcQX0zYo.css">
9
9
  </head>
10
10
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aicodeswitch",
3
- "version": "1.4.0",
3
+ "version": "1.5.0",
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",
@@ -36,7 +36,7 @@
36
36
  "scripts": {
37
37
  "dev": "concurrently \"npm run dev:server\" \"npm run dev:ui\"",
38
38
  "dev:ui": "vite",
39
- "dev:server": "tsx watch --env-file=.env --tsconfig=tsconfig.server.json server/main.ts",
39
+ "dev:server": "tsx watch --env-file=.env --tsconfig=tsconfig.server.json src/server/main.ts",
40
40
  "build": "npm run build:ui && npm run build:server",
41
41
  "build:ui": "vite build",
42
42
  "build:server": "tsc -p tsconfig.server.json",
@@ -0,0 +1,79 @@
1
+ import { Request, Response, NextFunction } from 'express';
2
+ import jwt from 'jsonwebtoken';
3
+ import crypto from 'crypto';
4
+
5
+ const AUTH_CODE = process.env.AUTH || '';
6
+ const JWT_SECRET = process.env.JWT_SECRET || (AUTH_CODE ? crypto.createHash('sha256').update(AUTH_CODE).digest('hex') : '');
7
+ const TOKEN_EXPIRY = '7d'; // 7天有效期
8
+
9
+ interface JWTPayload {
10
+ authenticated: boolean;
11
+ }
12
+
13
+ /**
14
+ * 检查是否启用鉴权
15
+ */
16
+ export function isAuthEnabled(): boolean {
17
+ return AUTH_CODE.trim().length > 0;
18
+ }
19
+
20
+ /**
21
+ * 验证鉴权码
22
+ */
23
+ export function verifyAuthCode(authCode: string): boolean {
24
+ if (!isAuthEnabled()) {
25
+ return true; // 未启用鉴权,直接通过
26
+ }
27
+ return authCode === AUTH_CODE;
28
+ }
29
+
30
+ /**
31
+ * 生成 JWT Token
32
+ */
33
+ export function generateToken(): string {
34
+ const payload: JWTPayload = {
35
+ authenticated: true,
36
+ };
37
+ return jwt.sign(payload, JWT_SECRET, { expiresIn: TOKEN_EXPIRY });
38
+ }
39
+
40
+ /**
41
+ * 验证 JWT Token
42
+ */
43
+ export function verifyToken(token: string): boolean {
44
+ try {
45
+ jwt.verify(token, JWT_SECRET) as JWTPayload;
46
+ return true;
47
+ } catch (error) {
48
+ return false;
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Express 中间件: 验证 JWT Token
54
+ *
55
+ * 如果未启用鉴权,直接放行
56
+ * 如果启用鉴权但 token 无效,返回 401
57
+ */
58
+ export function authMiddleware(req: Request, res: Response, next: NextFunction): void {
59
+ // 如果未启用鉴权,直接放行
60
+ if (!isAuthEnabled()) {
61
+ next();
62
+ return;
63
+ }
64
+
65
+ // 从 Authorization header 中提取 token
66
+ const authHeader = req.headers.authorization;
67
+ if (!authHeader || !authHeader.startsWith('Bearer ')) {
68
+ res.status(401).json({ error: 'Unauthorized: Missing or invalid token' });
69
+ return;
70
+ }
71
+
72
+ const token = authHeader.substring(7); // 移除 "Bearer " 前缀
73
+
74
+ if (verifyToken(token)) {
75
+ next();
76
+ } else {
77
+ res.status(401).json({ error: 'Unauthorized: Invalid or expired token' });
78
+ }
79
+ }