@myassis/gateway 1.0.73 → 1.0.75

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/dist/api/index.js CHANGED
@@ -131,7 +131,7 @@ function skillHubRequest(path, options) {
131
131
  exports.authApi = {
132
132
  login: (data) => authRequest('/login', { method: 'POST', body: data, skipAuth: true }),
133
133
  register: (data) => authRequest('/register', { method: 'POST', body: data, skipAuth: true }),
134
- logout: (token) => authRequest('/logout', { method: 'POST', body: {}, token }),
134
+ logout: (refreshToken, token) => authRequest('/logout', { method: 'POST', body: { refreshToken }, token }),
135
135
  refresh: (refreshToken) => authRequest('/refresh', { method: 'POST', body: { refreshToken }, skipAuth: true }),
136
136
  me: (token) => authRequest('/me', { token }),
137
137
  updateProfile: (data, token) => authRequest('/profile', { method: 'PUT', body: data, token }),
@@ -142,7 +142,6 @@ exports.authApi = {
142
142
  exports.skillsApi = {
143
143
  list: (token) => dataRequest('/skills?brief=true', { token }),
144
144
  get: (skillId, token) => dataRequest(`/skills/${skillId}`, { token }),
145
- install: (data, token) => dataRequest('/skills', { method: 'POST', body: data, token }),
146
145
  create: (data, token) => dataRequest('/skills', { method: 'POST', body: data, token }),
147
146
  update: (skillId, data, token) => dataRequest(`/skills/${skillId}`, { method: 'PUT', body: data, token }),
148
147
  uninstall: (skillId, token) => dataRequest(`/skills/${skillId}`, { method: 'DELETE', token }),
@@ -5,11 +5,13 @@ exports.requireAuth = void 0;
5
5
  * 认证中间件
6
6
  * 从请求头 Authorization: Bearer <token> 解码 JWT,提取 userId
7
7
  * 同时保留原始 token 供路由转发给 Server
8
+ *
9
+ * 注:Gateway 不自行验证 JWT 签名,而是比对 authStore 中由 Server 下发并本地持久化的 token。
10
+ * 因此无需也不应持有 JWT_SECRET,避免密钥在末端多处散落。
8
11
  */
9
- const authStore_js_1 = require("../stores/authStore.js");
12
+ const authStore_js_1 = require("@/stores/authStore.js");
10
13
  const shared_1 = require("@myassis/shared");
11
14
  const logger = (0, shared_1.getLogger)('middleware/auth');
12
- const JWT_SECRET = process.env.JWT_SECRET || 'your-secret-key-change-in-production';
13
15
  /**
14
16
  * 从请求头提取 Bearer token
15
17
  */
@@ -1,14 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const express_1 = require("express");
4
- const auth_js_1 = require("../middleware/auth.js");
5
- const index_js_1 = require("../api/index.js");
6
- const index_js_2 = require("../services/session/index.js");
7
- const AgentManager_js_1 = require("../services/agent/AgentManager.js");
8
- const AgentStore_js_1 = require("../services/agent/AgentStore.js");
4
+ const auth_js_1 = require("@/middleware/auth.js");
5
+ const index_js_1 = require("@/api/index.js");
6
+ const index_js_2 = require("@/services/session/index.js");
7
+ const AgentManager_js_1 = require("@/services/agent/AgentManager.js");
8
+ const AgentStore_js_1 = require("@/services/agent/AgentStore.js");
9
9
  const shared_1 = require("@myassis/shared");
10
10
  const logger = (0, shared_1.getLogger)('AgentRoutes');
11
- const SessionStore_js_1 = require("../services/session/SessionStore.js");
11
+ const SessionStore_js_1 = require("@/services/session/SessionStore.js");
12
12
  const router = (0, express_1.Router)();
13
13
  // 所有路由需要认证
14
14
  router.use(auth_js_1.requireAuth, (req, _res, next) => {
@@ -135,23 +135,25 @@ router.post('/refresh', async (req, res) => {
135
135
  });
136
136
  }
137
137
  });
138
- // Logout - 清除本地存储
138
+ // Logout - 通知 Server 失效 refreshToken,并清除当前用户的本地存储
139
139
  router.post('/logout', auth_js_1.requireAuth, async (req, res) => {
140
+ const token = req.token;
141
+ // 优先用客户端上报的 refreshToken,缺失时回退到 Gateway 本地持久化的那一个
142
+ const refreshToken = req.body?.refreshToken || index_js_2.authStore.getRefreshToken(req.userId) || undefined;
140
143
  try {
141
- const { refreshToken } = req.body;
142
- // 用 AsyncLocalStorage 将 token 注入 server 请求上下文
143
- await (0, index_js_3.runWithToken)(req.token, async () => {
144
- if (refreshToken) {
145
- index_js_1.authApi.logout(req.token).catch(() => { });
146
- }
147
- });
148
- index_js_2.authStore.clear();
149
- res.json({ success: true });
144
+ if (refreshToken) {
145
+ // 用 AsyncLocalStorage 将 token 注入 server 请求上下文;
146
+ // 必须 await,否则请求可能在上下文退出后才发出
147
+ await (0, index_js_3.runWithToken)(token, () => index_js_1.authApi.logout(refreshToken, token));
148
+ }
150
149
  }
151
150
  catch (error) {
152
- index_js_2.authStore.clear();
153
- res.json({ success: true });
151
+ // 登出为 best-effort:服务端失败不能阻断本地清理
152
+ logger.warn('Logout: failed to revoke refreshToken on server:', error?.message);
154
153
  }
154
+ // 只移除当前用户:authMap 为多用户共享,clear() 会把其他人一起踢下线
155
+ index_js_2.authStore.removeByToken(token);
156
+ res.json({ success: true });
155
157
  });
156
158
  // Check authentication - 验证 token 有效性并获取用户信息
157
159
  router.get('/isAuth', auth_js_1.requireAuth, async (req, res) => {
@@ -186,7 +188,7 @@ router.post('/account/delete', auth_js_1.requireAuth, async (req, res) => {
186
188
  // 转发删除账号请求到 Server(带上 token)
187
189
  const response = await index_js_1.authApi.deleteAccount({ password }, req.token);
188
190
  if (response.success) {
189
- index_js_2.authStore.clear();
191
+ index_js_2.authStore.removeByToken(req.token);
190
192
  }
191
193
  res.json(response);
192
194
  }
@@ -96,7 +96,7 @@ router.delete('/account', auth_js_1.requireAuth, async (req, res) => {
96
96
  try {
97
97
  const result = await index_js_3.authApi.deleteAccount({ password: req.params.password }, req.token);
98
98
  if (result.success) {
99
- index_js_2.authStore.clear();
99
+ index_js_2.authStore.removeByToken(req.token);
100
100
  }
101
101
  res.json(result);
102
102
  }
@@ -6,9 +6,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.deleteFile = void 0;
7
7
  const express_1 = require("express");
8
8
  const multer_1 = __importDefault(require("multer"));
9
- const index_js_1 = require("../config/index.js");
10
- const auth_js_1 = require("../middleware/auth.js");
11
- const index_js_2 = require("../api/index.js");
9
+ const index_js_1 = require("@/config/index.js");
10
+ const auth_js_1 = require("@/middleware/auth.js");
11
+ const index_js_2 = require("@/api/index.js");
12
12
  const shared_1 = require("@myassis/shared");
13
13
  const logger = (0, shared_1.getLogger)('UploadRoutes');
14
14
  const router = (0, express_1.Router)();
@@ -11,7 +11,7 @@ const WebSocketService_js_1 = require("./WebSocketService.js");
11
11
  const index_js_1 = require("./session/index.js");
12
12
  const shared_1 = require("@myassis/shared");
13
13
  const dataService_js_1 = require("./dataService.js");
14
- const authStore_js_1 = require("../stores/authStore.js");
14
+ const authStore_js_1 = require("@/stores/authStore.js");
15
15
  const logger = (0, shared_1.getLogger)('TaskSchedulerService');
16
16
  const EXPIRED_THRESHOLD = 60 * 60 * 1000; // 1小时
17
17
  const CHECK_INTERVAL = 60 * 1000; // 1分钟
@@ -10,7 +10,7 @@
10
10
  */
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.taskService = void 0;
13
- const index_js_1 = require("../stores/index.js");
13
+ const index_js_1 = require("@/stores/index.js");
14
14
  const index_js_2 = require("../api/index.js");
15
15
  const LocalTaskService_js_1 = require("./LocalTaskService.js");
16
16
  const shared_1 = require("@myassis/shared");
@@ -7,9 +7,9 @@ exports.initAgentManager = exports.agentManagerMap = exports.AgentManager = void
7
7
  const uuid_1 = require("uuid");
8
8
  const Agent_js_1 = require("./Agent.js");
9
9
  const SessionManager_js_1 = require("../session/SessionManager.js");
10
- const authStore_js_1 = require("../../stores/authStore.js");
10
+ const authStore_js_1 = require("@/stores/authStore.js");
11
11
  const shared_1 = require("@myassis/shared");
12
- const index_js_1 = __importDefault(require("../../config/index.js"));
12
+ const index_js_1 = __importDefault(require("@/config/index.js"));
13
13
  const logger = (0, shared_1.getLogger)('AgentManager');
14
14
  /**
15
15
  * AgentManager - Business logic layer
@@ -53,14 +53,18 @@ exports.authService = {
53
53
  return response;
54
54
  },
55
55
  // 登出
56
- logout: async (token) => {
57
- try {
58
- await index_js_1.authApi.logout(token);
59
- }
60
- catch (e) {
61
- // 忽略错误
56
+ logout: async (token, refreshToken) => {
57
+ const userId = index_js_2.authStore.getUserId(token);
58
+ const revokeToken = refreshToken || (userId ? index_js_2.authStore.getRefreshToken(userId) : null);
59
+ if (revokeToken) {
60
+ try {
61
+ await index_js_1.authApi.logout(revokeToken, token);
62
+ }
63
+ catch (e) {
64
+ // 登出为 best-effort,服务端失败不阻断本地清理
65
+ }
62
66
  }
63
- index_js_2.authStore.clear();
67
+ index_js_2.authStore.removeByToken(token);
64
68
  return { success: true };
65
69
  },
66
70
  // 获取当前用户
@@ -92,30 +96,9 @@ exports.authService = {
92
96
  exports.skillsService = {
93
97
  list: async (token) => await index_js_1.skillsApi.list(token),
94
98
  get: (skillId, token) => index_js_1.skillsApi.get(skillId, token),
95
- install: async (skillHubId, token) => {
96
- // 1. 从技能库获取技能详情
97
- const hubResult = await index_js_1.skillHubApi.get(skillHubId, token);
98
- if (!hubResult.success || !hubResult.data) {
99
- return { success: false, error: '获取技能详情失败' };
100
- }
101
- const hub = hubResult.data;
102
- // 2. 创建用户技能记录
103
- const skillData = {
104
- name: hub.name,
105
- description: hub.description || '',
106
- content: hub.content || '',
107
- icon: hub.icon,
108
- templateId: skillHubId,
109
- isActive: true,
110
- apiKeyRequired: hub.apiKeyRequired || false,
111
- };
112
- const response = await index_js_1.skillsApi.create(skillData, token);
113
- if (response.success) {
114
- // 3. 增加安装计数
115
- await index_js_1.skillHubApi.install(skillHubId, token);
116
- }
117
- return response;
118
- },
99
+ // 安装技能:字段由服务端从 skill_hubs 回填,此处不再拼装 body,
100
+ // 防止漏传 scriptsUrl / version 等字段导致入库为空
101
+ install: async (skillHubId, token) => await index_js_1.skillHubApi.install(skillHubId, token),
119
102
  update: (skillId, data, token) => index_js_1.skillsApi.update(skillId, data, token),
120
103
  uninstall: async (skillId, token) => await index_js_1.skillsApi.uninstall(skillId, token),
121
104
  setApiKey: (skillId, apiKey, token) => {
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getGlobalModelSelector = exports.parseAruments = exports.LLMClient = void 0;
7
- const index_js_1 = require("../../stores/index.js");
7
+ const index_js_1 = require("@/stores/index.js");
8
8
  const shared_1 = require("@myassis/shared");
9
9
  const promises_1 = __importDefault(require("fs/promises"));
10
10
  const logger = (0, shared_1.getLogger)('LLMClient');
@@ -28,9 +28,9 @@ const shared_1 = require("@myassis/shared");
28
28
  const logger = (0, shared_1.getLogger)('MemoryManager');
29
29
  const models_js_1 = require("../models.js");
30
30
  const dataService_js_1 = require("../dataService.js");
31
- const index_js_1 = require("../../stores/index.js");
31
+ const index_js_1 = require("@/stores/index.js");
32
32
  const LLMClient_js_1 = require("../llm/LLMClient.js");
33
- const index_js_2 = require("../../config/index.js");
33
+ const index_js_2 = require("@/config/index.js");
34
34
  const DEFAULT_CONFIG = {
35
35
  summaryThreshold: 10,
36
36
  enabled: true,
@@ -27,15 +27,15 @@ exports.Session = exports.handleApprovalResponse = exports.registerApprovalWaite
27
27
  const uuid_1 = require("uuid");
28
28
  const shared_1 = require("@myassis/shared");
29
29
  const SessionStore_js_1 = require("./SessionStore.js");
30
- const AgentStore_js_1 = require("../../services/agent/AgentStore.js");
31
- const authStore_js_1 = require("../../stores/authStore.js");
32
- const models_js_1 = require("../../services/models.js");
33
- const index_js_1 = require("../../services/tools/index.js");
30
+ const AgentStore_js_1 = require("@/services/agent/AgentStore.js");
31
+ const authStore_js_1 = require("@/stores/authStore.js");
32
+ const models_js_1 = require("@/services/models.js");
33
+ const index_js_1 = require("@/services/tools/index.js");
34
34
  const systemPrompt_js_1 = require("../systemPrompt.js");
35
35
  const LLMClient_js_1 = require("../llm/LLMClient.js");
36
- const dataService_js_1 = require("../../services/dataService.js");
36
+ const dataService_js_1 = require("@/services/dataService.js");
37
37
  const MemoryManager_js_1 = require("../memory/MemoryManager.js");
38
- const index_js_2 = require("../../config/index.js");
38
+ const index_js_2 = require("@/config/index.js");
39
39
  const SessionManager_js_1 = require("./SessionManager.js");
40
40
  const logger = (0, shared_1.getLogger)('Session');
41
41
  const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms));
@@ -5,7 +5,7 @@ const uuid_1 = require("uuid");
5
5
  const shared_1 = require("@myassis/shared");
6
6
  const logger = (0, shared_1.getLogger)('SessionManager');
7
7
  const SessionStore_js_1 = require("./SessionStore.js");
8
- const authStore_js_1 = require("../../stores/authStore.js");
8
+ const authStore_js_1 = require("@/stores/authStore.js");
9
9
  const Session_js_1 = require("./Session.js");
10
10
  /**
11
11
  * SessionManager - Business logic layer
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.getSystemPromptAsync = exports.LANGUAGES = exports.CHAT_STYLE_TEMPLATES = void 0;
7
- const index_js_1 = require("../stores/index.js");
7
+ const index_js_1 = require("@/stores/index.js");
8
8
  const os_1 = __importDefault(require("os"));
9
9
  const dataService_js_1 = require("./dataService.js");
10
10
  const shared_1 = require("@myassis/shared");
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.modelTool = void 0;
4
4
  const dataService_js_1 = require("../dataService.js");
5
- const index_js_1 = require("../../stores/index.js");
5
+ const index_js_1 = require("@/stores/index.js");
6
6
  exports.modelTool = {
7
7
  name: 'model',
8
8
  description: '模型管理工具',
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.skillTool = void 0;
4
4
  const dataService_js_1 = require("../dataService.js");
5
- const index_js_1 = require("../../stores/index.js");
5
+ const index_js_1 = require("@/stores/index.js");
6
6
  const shared_1 = require("@myassis/shared");
7
7
  const logger = (0, shared_1.getLogger)('skill');
8
8
  exports.skillTool = {
@@ -168,12 +168,39 @@ exports.authStore = {
168
168
  }
169
169
  },
170
170
  /**
171
- * 清除认证数据(内存 + 本地)
171
+ * 清除全部认证数据(内存 + 本地)
172
+ * 注:authMap 为多用户共享,单用户登出请用 remove/removeByToken。
172
173
  */
173
174
  clear() {
174
175
  clearAuth();
175
176
  logger.debug('Auth cleared');
176
177
  },
178
+ /**
179
+ * 移除单个用户的认证数据,不影响其他已登录用户
180
+ * @returns 是否确实移除了记录
181
+ */
182
+ remove(userId) {
183
+ if (!authMap) {
184
+ this.load();
185
+ }
186
+ const removed = authMap.delete(userId);
187
+ if (removed) {
188
+ saveAuthToFile(authMap);
189
+ logger.debug('Auth removed for user:', userId);
190
+ }
191
+ return removed;
192
+ },
193
+ /**
194
+ * 按 accessToken 定位并移除单个用户的认证数据
195
+ * @returns 是否确实移除了记录
196
+ */
197
+ removeByToken(token) {
198
+ const userId = this.getUserId(token);
199
+ if (!userId) {
200
+ return false;
201
+ }
202
+ return this.remove(userId);
203
+ },
177
204
  /**
178
205
  * 更新用户信息
179
206
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myassis/gateway",
3
- "version": "1.0.73",
3
+ "version": "1.0.75",
4
4
  "description": "我的助手 Gateway Service - 本地 AI 网关服务,支持认证、WebSocket 实时通信和任务调度",
5
5
  "main": "dist/index.js",
6
6
  "bin": {