@myassis/gateway 1.0.0 → 1.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.
Files changed (50) hide show
  1. package/dist/api/index.js +69 -59
  2. package/dist/config/index.js +2 -2
  3. package/dist/index.js +85 -11
  4. package/dist/middleware/auth.js +9 -25
  5. package/dist/middleware/errorHandler.js +1 -1
  6. package/dist/routes/agent.js +30 -19
  7. package/dist/routes/auth.js +35 -26
  8. package/dist/routes/chat.js +1 -1
  9. package/dist/routes/models.js +11 -14
  10. package/dist/routes/service.js +3 -6
  11. package/dist/routes/settings.js +11 -9
  12. package/dist/routes/skillHub.js +10 -6
  13. package/dist/routes/skills.js +13 -10
  14. package/dist/routes/tasks.js +6 -3
  15. package/dist/routes/upload.js +5 -2
  16. package/dist/routes/version.js +4 -4
  17. package/dist/services/LocalTaskService.js +1 -1
  18. package/dist/services/NotificationService.js +1 -1
  19. package/dist/services/ServiceManager.js +12 -12
  20. package/dist/services/TaskSchedulerService.js +18 -9
  21. package/dist/services/TaskService.js +23 -20
  22. package/dist/services/WebSocketService.js +16 -6
  23. package/dist/services/agent/Agent.js +7 -7
  24. package/dist/services/agent/AgentManager.js +25 -17
  25. package/dist/services/agent/AgentStore.js +1 -1
  26. package/dist/services/dataService.js +60 -70
  27. package/dist/services/index.js +1 -1
  28. package/dist/services/llm/LLMClient.js +11 -9
  29. package/dist/services/memory/MemoryManager.js +177 -14
  30. package/dist/services/session/MigrationManager.js +1 -1
  31. package/dist/services/session/Session.js +70 -46
  32. package/dist/services/session/SessionManager.js +12 -5
  33. package/dist/services/session/SessionStore.js +1 -27
  34. package/dist/services/session/index.js +1 -1
  35. package/dist/services/systemPrompt.js +8 -4
  36. package/dist/services/task/PushTokenStore.js +1 -19
  37. package/dist/services/task/TaskStore.js +1 -20
  38. package/dist/services/tools/edit.js +122 -148
  39. package/dist/services/tools/exec.js +1 -1
  40. package/dist/services/tools/fetch.js +1 -1
  41. package/dist/services/tools/file.js +4 -9
  42. package/dist/services/tools/index.js +4 -3
  43. package/dist/services/tools/model.js +8 -6
  44. package/dist/services/tools/sessionsSpawn.js +54 -0
  45. package/dist/services/tools/skill.js +13 -12
  46. package/dist/services/tools/task.js +2 -4
  47. package/dist/stores/authStore.js +52 -66
  48. package/dist/stores/persistStore.js +37 -3
  49. package/package.json +8 -4
  50. package/scripts/postbuild.js +39 -0
@@ -1,19 +1,12 @@
1
1
  import { Router } from 'express';
2
2
  import { authApi } from '../api/index.js';
3
3
  import { authStore } from '../stores/index.js';
4
- import { optionalAuth, requireAuth } from '../middleware/auth.js';
5
- import { getLogger } from '@pocketclaw/shared';
6
- import { getPlatform } from '@pocketclaw/shared/dist/utils/system.js';
4
+ import { requireAuth } from '../middleware/auth.js';
5
+ import { runWithToken } from '../api/index.js';
6
+ import { getLogger } from '@myassis/shared';
7
+ import { getPlatform } from '@myassis/shared/dist/utils/system.js';
7
8
  const logger = getLogger('auth');
8
9
  const router = Router();
9
- // Check auth status - 解码请求中的 token 返回认证状态
10
- router.get('/isAuth', optionalAuth, async (req, res) => {
11
- const userId = req.userId;
12
- res.json({
13
- authenticated: !!userId,
14
- user: userId ? { id: userId } : null,
15
- });
16
- });
17
10
  // Get publish token - 获取发布技能库所需的 token
18
11
  router.get('/publish-token', requireAuth, async (req, res) => {
19
12
  res.json({
@@ -40,7 +33,7 @@ router.post('/register', async (req, res) => {
40
33
  if (response.success && response.data) {
41
34
  const expiresIn = response.data.expiresIn || 86400;
42
35
  authStore.save({
43
- token: response.data.accessToken,
36
+ accessToken: response.data.accessToken,
44
37
  refreshToken: response.data.refreshToken,
45
38
  expiresIn,
46
39
  expiresAt: Date.now() + expiresIn * 1000,
@@ -79,17 +72,10 @@ router.post('/login', async (req, res) => {
79
72
  platform: getPlatform(),
80
73
  });
81
74
  if (response.success && response.data) {
82
- const expiresIn = response.data.expiresIn || 86400;
83
- authStore.save({
84
- token: response.data.accessToken,
85
- refreshToken: response.data.refreshToken,
86
- expiresIn,
87
- expiresAt: Date.now() + expiresIn * 1000,
88
- user: response.data.user,
89
- });
75
+ authStore.save(response.data);
90
76
  res.json({
91
77
  success: true,
92
- user: response.data.user,
78
+ data: response.data,
93
79
  });
94
80
  }
95
81
  else {
@@ -132,12 +118,13 @@ router.post('/refresh', async (req, res) => {
132
118
  // Logout - 清除本地存储
133
119
  router.post('/logout', requireAuth, async (req, res) => {
134
120
  try {
135
- // refreshToken 在请求 body 中
136
121
  const { refreshToken } = req.body;
137
- // 尝试转发登出请求到 Server(忽略错误)
138
- if (refreshToken) {
139
- authApi.logout().catch(() => { });
140
- }
122
+ // AsyncLocalStorage 将 token 注入 server 请求上下文
123
+ await runWithToken(req.token, async () => {
124
+ if (refreshToken) {
125
+ authApi.logout(req.token).catch(() => { });
126
+ }
127
+ });
141
128
  authStore.clear();
142
129
  res.json({ success: true });
143
130
  }
@@ -146,6 +133,28 @@ router.post('/logout', requireAuth, async (req, res) => {
146
133
  res.json({ success: true });
147
134
  }
148
135
  });
136
+ // Check authentication - 验证 token 有效性并获取用户信息
137
+ router.get('/isAuth', requireAuth, async (req, res) => {
138
+ try {
139
+ // 用 AsyncLocalStorage 将 token 注入 server 请求上下文
140
+ const userResponse = await runWithToken(req.token, async () => {
141
+ return await authApi.me(req.token);
142
+ });
143
+ res.json({
144
+ authenticated: true,
145
+ user: userResponse.data,
146
+ });
147
+ }
148
+ catch (error) {
149
+ logger.error('Auth check error:', error);
150
+ // token 无效时返回认证失败
151
+ res.status(401).json({
152
+ authenticated: false,
153
+ user: null,
154
+ error: error.message || 'Invalid token',
155
+ });
156
+ }
157
+ });
149
158
  // Delete account - 删除账号
150
159
  router.post('/account/delete', requireAuth, async (req, res) => {
151
160
  try {
@@ -1,5 +1,5 @@
1
1
  import { Router } from 'express';
2
- import { getLogger } from '@pocketclaw/shared';
2
+ import { getLogger } from '@myassis/shared';
3
3
  const logger = getLogger('ChatRoutes');
4
4
  const router = Router();
5
5
  // Chat completion proxy - forwards to cloud API
@@ -1,17 +1,21 @@
1
1
  import express from 'express';
2
- import { getLogger, detectModelCapabilities } from '@pocketclaw/shared';
2
+ import { getLogger, detectModelCapabilities } from '@myassis/shared';
3
3
  import { modelsService } from '../services/index.js';
4
4
  import { persistStore } from '../stores/persistStore.js';
5
5
  import { requireAuth } from '../middleware/auth.js';
6
+ import { runWithToken } from '../api/index.js';
6
7
  const logger = getLogger('models');
7
8
  const router = express.Router();
9
+ router.use(requireAuth, (req, _res, next) => {
10
+ void runWithToken(req.token, async () => { next(); });
11
+ });
8
12
  /**
9
13
  * 获取所有模型配置
10
14
  * GET /api/v1/models
11
15
  */
12
16
  router.get('/', async (req, res) => {
13
17
  try {
14
- const result = await modelsService.list();
18
+ const result = await modelsService.list(req.token);
15
19
  res.json(result);
16
20
  }
17
21
  catch (error) {
@@ -25,7 +29,7 @@ router.get('/', async (req, res) => {
25
29
  */
26
30
  router.get('/:id', async (req, res) => {
27
31
  try {
28
- const result = await modelsService.get(req.params.id);
32
+ const result = await modelsService.get(req.params.id, req.token);
29
33
  res.json(result);
30
34
  }
31
35
  catch (error) {
@@ -42,18 +46,14 @@ router.post('/', requireAuth, async (req, res) => {
42
46
  const userId = req.userId;
43
47
  const modelData = req.body;
44
48
  const apiKey = modelData.apiKey;
45
- // 自动检测模型能力,设置 supportsToolCall
46
49
  const modelCapabilities = detectModelCapabilities(modelData.modelId || '');
47
50
  const dataToSave = {
48
51
  ...modelData,
49
- // 数据库 is_primary, is_active, supports_tool_call 都是 INTEGER 类型,转换为 0/1
50
52
  isPrimary: modelData.isPrimary ? 1 : 0,
51
53
  isActive: modelData.isActive ? 1 : 0,
52
54
  supportsToolCall: modelCapabilities.supportsToolCall ? 1 : 0,
53
55
  };
54
- // 调用服务端,不包含 apiKey
55
- const result = await modelsService.create(dataToSave);
56
- // 如果提供了 API Key,持久化存储
56
+ const result = await runWithToken(req.token, () => modelsService.create(dataToSave, req.token));
57
57
  if (apiKey && result.success && result.data?.id) {
58
58
  persistStore.setModelApiKey(result.data.id, apiKey);
59
59
  }
@@ -73,18 +73,15 @@ router.put('/:id', requireAuth, async (req, res) => {
73
73
  const userId = req.userId;
74
74
  const modelData = req.body;
75
75
  const apiKey = modelData.apiKey;
76
- // API Key 单独存储到本地,不传给服务端
77
76
  if (apiKey) {
78
77
  persistStore.setModelApiKey(req.params.id, apiKey);
79
78
  }
80
- // 自动检测模型能力,设置 supportsToolCall
81
79
  const modelCapabilities = detectModelCapabilities(modelData.modelId || '');
82
80
  const dataToSave = {
83
81
  ...modelData,
84
82
  supportsToolCall: modelCapabilities.supportsToolCall ? 1 : 0,
85
83
  };
86
- // 调用服务端,不包含 apiKey
87
- const result = await modelsService.update(req.params.id, dataToSave);
84
+ const result = await runWithToken(req.token, () => modelsService.update(req.params.id, dataToSave, req.token));
88
85
  res.json(result);
89
86
  }
90
87
  catch (error) {
@@ -98,7 +95,7 @@ router.put('/:id', requireAuth, async (req, res) => {
98
95
  */
99
96
  router.delete('/:id', async (req, res) => {
100
97
  try {
101
- const result = await modelsService.delete(req.params.id);
98
+ const result = await modelsService.delete(req.params.id, req.token);
102
99
  res.json(result);
103
100
  }
104
101
  catch (error) {
@@ -112,7 +109,7 @@ router.delete('/:id', async (req, res) => {
112
109
  */
113
110
  router.post('/:id/primary', async (req, res) => {
114
111
  try {
115
- const result = await modelsService.setPrimary(req.params.id);
112
+ const result = await modelsService.setPrimary(req.params.id, req.token);
116
113
  res.json(result);
117
114
  }
118
115
  catch (error) {
@@ -1,12 +1,9 @@
1
1
  import { Router } from 'express';
2
- import { getLogger } from '@pocketclaw/shared';
2
+ import { getLogger } from '@myassis/shared';
3
3
  import path from 'path';
4
4
  import { getServiceInfo, installService, uninstallService, startService, stopService, restartService, checkForUpdates, updateService, } from '../services/ServiceManager.js';
5
5
  import { webSocketService } from '../services/WebSocketService.js';
6
- import { requireAuth } from '../middleware/auth.js';
7
6
  const router = Router();
8
- // 所有 service 路由需要认证
9
- router.use(requireAuth);
10
7
  const logger = getLogger('service');
11
8
  /**
12
9
  * 获取服务状态
@@ -185,8 +182,8 @@ router.get('/latest-exe-url', async (_req, res) => {
185
182
  return;
186
183
  }
187
184
  // TODO: 从 GitHub Releases 或自有 CDN 获取下载地址
188
- // 示例: https://github.com/pocketclaw/gateway/releases/download/v${check.latestVersion}/gateway.exe
189
- const downloadUrl = `https://pocket-claw-1251246038.cos.ap-chengdu.myqcloud.com/pocket-claw-1251246038/installs/v${check.latestVersion}/gateway-installer_${check.latestVersion}.exe`;
185
+ // 示例: https://github.com/myassis/gateway/releases/download/v${check.latestVersion}/gateway.exe
186
+ const downloadUrl = `https://my-assis-1251246038.cos.ap-chengdu.myqcloud.com/my-assis-1251246038/installs/v${check.latestVersion}/gateway-installer_${check.latestVersion}.exe`;
190
187
  res.json({
191
188
  success: true,
192
189
  hasUpdate: true,
@@ -1,17 +1,19 @@
1
1
  import express from 'express';
2
- import { getLogger } from '@pocketclaw/shared';
2
+ import { getLogger } from '@myassis/shared';
3
3
  import { settingsService } from '../services/index.js';
4
4
  import { authStore, persistStore } from '../stores/index.js';
5
- import { authApi } from '../api/index.js';
5
+ import { authApi, runWithToken } from '../api/index.js';
6
+ import { requireAuth } from '../middleware/auth.js';
6
7
  const logger = getLogger('settings');
7
8
  const router = express.Router();
9
+ router.use(requireAuth);
8
10
  /**
9
11
  * 获取用户设置
10
12
  * GET /api/v1/settings
11
13
  */
12
14
  router.get('/', async (req, res) => {
13
15
  try {
14
- const result = await settingsService.get();
16
+ const result = await settingsService.get(req.token);
15
17
  res.json(result);
16
18
  }
17
19
  catch (error) {
@@ -23,9 +25,9 @@ router.get('/', async (req, res) => {
23
25
  * 更新用户设置
24
26
  * PUT /api/v1/settings
25
27
  */
26
- router.put('/', async (req, res) => {
28
+ router.put('/', requireAuth, async (req, res) => {
27
29
  try {
28
- const result = await settingsService.update(req.body);
30
+ const result = await runWithToken(req.token, () => settingsService.update(req.body, req.token));
29
31
  res.json(result);
30
32
  }
31
33
  catch (error) {
@@ -37,14 +39,14 @@ router.put('/', async (req, res) => {
37
39
  * 修改密码
38
40
  * PUT /api/v1/settings/password
39
41
  */
40
- router.put('/password', async (req, res) => {
42
+ router.put('/password', requireAuth, async (req, res) => {
41
43
  try {
42
44
  const { oldPassword, newPassword } = req.body;
43
45
  if (!oldPassword || !newPassword) {
44
46
  res.status(400).json({ success: false, error: 'Missing required fields' });
45
47
  return;
46
48
  }
47
- const result = await authApi.changePassword({ oldPassword, newPassword });
49
+ const result = await authApi.changePassword({ oldPassword, newPassword }, req.token);
48
50
  res.json(result);
49
51
  }
50
52
  catch (error) {
@@ -85,9 +87,9 @@ router.put('/local', async (req, res) => {
85
87
  * 删除账号
86
88
  * DELETE /api/v1/settings/account
87
89
  */
88
- router.delete('/account', async (req, res) => {
90
+ router.delete('/account', requireAuth, async (req, res) => {
89
91
  try {
90
- const result = await authApi.deleteAccount({ password: req.params.password });
92
+ const result = await authApi.deleteAccount({ password: req.params.password }, req.token);
91
93
  if (result.success) {
92
94
  authStore.clear();
93
95
  }
@@ -5,9 +5,13 @@
5
5
  import express from 'express';
6
6
  import { skillHubService } from '../services/index.js';
7
7
  import { requireAuth } from '../middleware/auth.js';
8
- import { getLogger } from '@pocketclaw/shared';
8
+ import { runWithToken } from '../api/index.js';
9
+ import { getLogger } from '@myassis/shared';
9
10
  const logger = getLogger('skillHub');
10
11
  const router = express.Router();
12
+ router.use(requireAuth, (req, _res, next) => {
13
+ void runWithToken(req.token, async () => { next(); });
14
+ });
11
15
  /**
12
16
  * 获取技能库列表
13
17
  * GET /api/v1/skill-hub?page=1&pageSize=20&keyword=xxx&category=xxx
@@ -42,7 +46,7 @@ router.get('/:id', async (req, res) => {
42
46
  if (!hubId) {
43
47
  return res.status(400).json({ success: false, error: '无效的技能库ID' });
44
48
  }
45
- const result = await skillHubService.get(hubId);
49
+ const result = await skillHubService.get(hubId, req.token);
46
50
  res.json(result);
47
51
  }
48
52
  catch (error) {
@@ -60,7 +64,7 @@ router.get('/:id/used', async (req, res) => {
60
64
  if (!hubId) {
61
65
  return res.status(400).json({ success: false, error: '无效的技能库ID' });
62
66
  }
63
- const result = await skillHubService.checkUsed(hubId);
67
+ const result = await skillHubService.checkUsed(hubId, req.token);
64
68
  res.json(result);
65
69
  }
66
70
  catch (error) {
@@ -78,7 +82,7 @@ router.get('/:id/user-rating', async (req, res) => {
78
82
  if (!hubId) {
79
83
  return res.status(400).json({ success: false, error: '无效的技能库ID' });
80
84
  }
81
- const result = await skillHubService.userRating(hubId);
85
+ const result = await skillHubService.userRating(hubId, req.token);
82
86
  res.json(result);
83
87
  }
84
88
  catch (error) {
@@ -92,7 +96,7 @@ router.get('/:id/user-rating', async (req, res) => {
92
96
  */
93
97
  router.get('/categories/list', async (req, res) => {
94
98
  try {
95
- const result = await skillHubService.categories();
99
+ const result = await skillHubService.categories(req.token);
96
100
  res.json(result);
97
101
  }
98
102
  catch (error) {
@@ -115,7 +119,7 @@ router.post('/:id/rate', requireAuth, async (req, res) => {
115
119
  if (rating === undefined || rating < 1 || rating > 5) {
116
120
  return res.status(400).json({ success: false, error: '评分必须是1-5的数字' });
117
121
  }
118
- const result = await skillHubService.rate(hubId, rating);
122
+ const result = await runWithToken(req.token, () => skillHubService.rate(hubId, rating, req.token));
119
123
  res.json(result);
120
124
  }
121
125
  catch (error) {
@@ -5,18 +5,21 @@
5
5
  import express from 'express';
6
6
  import { skillsService } from '../services/index.js';
7
7
  import { persistStore } from '../stores/persistStore.js';
8
- import { getLogger } from '@pocketclaw/shared';
8
+ import { getLogger } from '@myassis/shared';
9
9
  import { requireAuth } from '../middleware/auth.js';
10
+ import { runWithToken } from '../api/index.js';
10
11
  const logger = getLogger('skills');
11
12
  const router = express.Router();
12
- router.use(requireAuth);
13
+ router.use(requireAuth, (req, _res, next) => {
14
+ void runWithToken(req.token, async () => { next(); });
15
+ });
13
16
  /**
14
17
  * 获取用户已安装的技能列表
15
18
  * GET /api/v1/skills
16
19
  */
17
20
  router.get('/', async (req, res) => {
18
21
  try {
19
- const result = await skillsService.list();
22
+ const result = await skillsService.list(req.token);
20
23
  res.json(result);
21
24
  }
22
25
  catch (error) {
@@ -34,7 +37,7 @@ router.post('/parse', async (req, res) => {
34
37
  if (!content) {
35
38
  return res.status(400).json({ success: false, error: '缺少 content 参数' });
36
39
  }
37
- const result = await skillsService.parse(content);
40
+ const result = await skillsService.parse(content, req.token);
38
41
  res.json(result);
39
42
  }
40
43
  catch (error) {
@@ -49,7 +52,7 @@ router.post('/parse', async (req, res) => {
49
52
  router.get('/:id', async (req, res) => {
50
53
  try {
51
54
  const skillId = req.params.id;
52
- const result = await skillsService.get(skillId);
55
+ const result = await skillsService.get(skillId, req.token);
53
56
  res.json(result);
54
57
  }
55
58
  catch (error) {
@@ -69,7 +72,7 @@ router.post('/', async (req, res) => {
69
72
  if (skillHubId) {
70
73
  // 从技能库安装
71
74
  const hubId = String(skillHubId);
72
- const result = await skillsService.install(hubId);
75
+ const result = await skillsService.install(hubId, req.token);
73
76
  res.json(result);
74
77
  }
75
78
  else {
@@ -77,7 +80,7 @@ router.post('/', async (req, res) => {
77
80
  if (!req.body.name) {
78
81
  return res.status(400).json({ success: false, error: '自定义技能必须提供 name' });
79
82
  }
80
- const result = await skillsService.create(req.body);
83
+ const result = await skillsService.create(req.body, req.token);
81
84
  res.json(result);
82
85
  }
83
86
  }
@@ -93,7 +96,7 @@ router.post('/', async (req, res) => {
93
96
  router.put('/:id', async (req, res) => {
94
97
  try {
95
98
  const skillId = req.params.id;
96
- const result = await skillsService.update(skillId, req.body);
99
+ const result = await skillsService.update(skillId, req.body, req.token);
97
100
  res.json(result);
98
101
  }
99
102
  catch (error) {
@@ -108,7 +111,7 @@ router.put('/:id', async (req, res) => {
108
111
  router.delete('/:id', async (req, res) => {
109
112
  try {
110
113
  const skillId = req.params.id;
111
- const result = await skillsService.uninstall(skillId);
114
+ const result = await skillsService.uninstall(skillId, req.token);
112
115
  res.json(result);
113
116
  }
114
117
  catch (error) {
@@ -148,7 +151,7 @@ router.post('/:id/rating', async (req, res) => {
148
151
  if (!score || score < 1 || score > 5) {
149
152
  return res.status(400).json({ success: false, error: '评分必须在 1-5 之间' });
150
153
  }
151
- const result = await skillsService.rate(skillId, score);
154
+ const result = await skillsService.rate(skillId, score, req.token);
152
155
  res.json(result);
153
156
  }
154
157
  catch (error) {
@@ -4,11 +4,14 @@
4
4
  */
5
5
  import express from 'express';
6
6
  import { tasksService } from '../services/index.js';
7
- import { getLogger } from '@pocketclaw/shared';
7
+ import { getLogger } from '@myassis/shared';
8
8
  import { requireAuth } from '../middleware/auth.js';
9
+ import { runWithToken } from '../api/index.js';
9
10
  const logger = getLogger('tasks');
10
11
  const router = express.Router();
11
- router.use(requireAuth);
12
+ router.use(requireAuth, (req, _res, next) => {
13
+ void runWithToken(req.token, async () => { next(); });
14
+ });
12
15
  /**
13
16
  * 获取任务列表
14
17
  * GET /api/v1/tasks
@@ -17,7 +20,7 @@ router.get('/', async (req, res) => {
17
20
  try {
18
21
  const { status, page, pageSize } = req.query;
19
22
  const userId = req.userId;
20
- const result = await tasksService.list({ status, page, pageSize }, userId);
23
+ const result = await tasksService.list(userId, { status, page, pageSize });
21
24
  res.json(result);
22
25
  }
23
26
  catch (error) {
@@ -2,10 +2,13 @@ import { Router } from 'express';
2
2
  import multer from 'multer';
3
3
  import { appConfig } from '@/config/index.js';
4
4
  import { requireAuth } from '@/middleware/auth.js';
5
- import { getLogger } from '@pocketclaw/shared';
5
+ import { runWithToken } from '@/api/index.js';
6
+ import { getLogger } from '@myassis/shared';
6
7
  const logger = getLogger('UploadRoutes');
7
8
  const router = Router();
8
- router.use(requireAuth);
9
+ router.use(requireAuth, (req, _res, next) => {
10
+ void runWithToken(req.token, async () => { next(); });
11
+ });
9
12
  // 配置 multer 用于解析 multipart/form-data
10
13
  const upload = multer({
11
14
  storage: multer.memoryStorage(),
@@ -1,11 +1,11 @@
1
1
  import express from 'express';
2
2
  import axios from 'axios';
3
3
  import { appConfig } from '../config/index.js';
4
- import { optionalAuth } from '../middleware/auth.js';
4
+ import { requireAuth } from '../middleware/auth.js';
5
5
  import { readFileSync } from 'fs';
6
6
  import { resolve, dirname } from 'path';
7
7
  import { fileURLToPath } from 'url';
8
- import { getLogger } from '@pocketclaw/shared';
8
+ import { getLogger } from '@myassis/shared';
9
9
  const logger = getLogger('VersionRoutes');
10
10
  const router = express.Router();
11
11
  // ESM 兼容的 __dirname
@@ -42,9 +42,9 @@ router.get('/local', async (req, res) => {
42
42
  /**
43
43
  * 转发到服务端接口
44
44
  */
45
- router.get('/latest', optionalAuth, async (req, res) => {
45
+ router.get('/latest', requireAuth, async (req, res) => {
46
46
  try {
47
- const serverBaseUrl = appConfig.serverBaseUrl || 'https://api.pocketclaw.ai';
47
+ const serverBaseUrl = appConfig.serverBaseUrl || 'http://localhost:9091';
48
48
  const response = await axios.get(`${serverBaseUrl}/api/v1/version/latest`, {
49
49
  timeout: 10000,
50
50
  headers: {
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import { v4 as uuidv4 } from 'uuid';
8
8
  import { TaskStore } from './task/TaskStore';
9
- import { getLogger, sharedTaskService, formatUTCForLog } from '@pocketclaw/shared';
9
+ import { getLogger, sharedTaskService, formatUTCForLog } from '@myassis/shared';
10
10
  const logger = getLogger('LocalTaskService');
11
11
  class LocalTaskService {
12
12
  store;
@@ -6,7 +6,7 @@
6
6
  import { PushTokenStore } from './task/PushTokenStore';
7
7
  import { webSocketService } from './WebSocketService';
8
8
  import { hmsPushService } from './HMSPushService';
9
- import { getLogger } from '@pocketclaw/shared';
9
+ import { getLogger } from '@myassis/shared';
10
10
  const logger = getLogger('NotificationService');
11
11
  const log = logger;
12
12
  // 全局 PushTokenStore 实例
@@ -5,8 +5,8 @@ import fs from 'fs';
5
5
  import axios from 'axios';
6
6
  import { fileURLToPath } from 'url';
7
7
  const execAsync = promisify(exec);
8
- export const SERVICE_NAME = 'myclaw-gateway';
9
- export const SERVICE_DISPLAY_NAME = 'MyClaw Desktop Gateway Service';
8
+ export const SERVICE_NAME = 'myassis-gateway';
9
+ export const SERVICE_DISPLAY_NAME = '我的助手 Desktop Gateway Service';
10
10
  // ─── 平台无关工具 ────────────────────────────────────────────
11
11
  function getServiceScript() {
12
12
  // pkg 环境
@@ -94,7 +94,7 @@ async function restartServiceWindows() {
94
94
  success: false,
95
95
  message: '检测到您尚未安装 nssm,无法自动重启服务。请手动执行以下步骤更新 Gateway:\n' +
96
96
  '1. 在桌面上停止 Gateway 服务(系统托盘 → 右键 → 退出)\n' +
97
- '2. 运行 `npm install -g @myclaw/gateway@latest`\n' +
97
+ '2. 运行 `npm install -g @myassis/gateway@latest`\n' +
98
98
  '3. 重新启动 Gateway 服务\n\n' +
99
99
  '如需自动重启功能,请从 https://nssm.cc/download 下载 nssm 并放置到 Gateway 同目录下',
100
100
  };
@@ -160,11 +160,11 @@ Environment=NODE_ENV=production
160
160
  [Install]
161
161
  WantedBy=multi-user.target
162
162
  `;
163
- await fs.promises.writeFile('/tmp/myclaw-gateway.service', unitContent, 'utf8');
164
- await execAsync('cp /tmp/myclaw-gateway.service /etc/systemd/system/myclaw-gateway.service', { timeout: 10000 });
163
+ await fs.promises.writeFile('/tmp/myassis-gateway.service', unitContent, 'utf8');
164
+ await execAsync('cp /tmp/myassis-gateway.service /etc/systemd/system/myassis-gateway.service', { timeout: 10000 });
165
165
  await execAsync('systemctl daemon-reload', { timeout: 10000 });
166
- await execAsync('systemctl enable myclaw-gateway', { timeout: 10000 });
167
- await execAsync('systemctl start myclaw-gateway', { timeout: 10000 });
166
+ await execAsync('systemctl enable myassis-gateway', { timeout: 10000 });
167
+ await execAsync('systemctl start myassis-gateway', { timeout: 10000 });
168
168
  return { success: true, message: '服务安装并启动成功' };
169
169
  }
170
170
  catch (err) {
@@ -173,9 +173,9 @@ WantedBy=multi-user.target
173
173
  }
174
174
  async function uninstallLinux() {
175
175
  try {
176
- await execAsync('systemctl stop myclaw-gateway', { timeout: 10000 });
177
- await execAsync('systemctl disable myclaw-gateway', { timeout: 10000 });
178
- await execAsync('rm -f /etc/systemd/system/myclaw-gateway.service', { timeout: 10000 });
176
+ await execAsync('systemctl stop myassis-gateway', { timeout: 10000 });
177
+ await execAsync('systemctl disable myassis-gateway', { timeout: 10000 });
178
+ await execAsync('rm -f /etc/systemd/system/myassis-gateway.service', { timeout: 10000 });
179
179
  await execAsync('systemctl daemon-reload', { timeout: 10000 });
180
180
  return { success: true, message: '服务卸载成功' };
181
181
  }
@@ -304,7 +304,7 @@ function compareVersions(a, b) {
304
304
  export async function checkForUpdates() {
305
305
  try {
306
306
  const currentVersion = getPackageVersion();
307
- const response = await axios.get('https://registry.npmjs.org/@myclaw/gateway/latest', { timeout: 10000 });
307
+ const response = await axios.get('https://registry.npmjs.org/@myassis/gateway/latest', { timeout: 10000 });
308
308
  const latestVersion = response.data.version;
309
309
  if (!latestVersion) {
310
310
  return { hasUpdate: false, currentVersion, latestVersion: currentVersion, error: '无法获取最新版本' };
@@ -326,7 +326,7 @@ export async function updateService() {
326
326
  return { success: true, message: `已是最新版本 ${check.currentVersion}` };
327
327
  }
328
328
  console.log(`发现新版本 ${check.latestVersion},正在更新...`);
329
- const { stdout, stderr } = await execAsync('npm install -g @myclaw/gateway@latest', { timeout: 120000 });
329
+ const { stdout, stderr } = await execAsync('npm install -g @myassis/gateway@latest', { timeout: 120000 });
330
330
  if (stdout)
331
331
  console.log(stdout);
332
332
  if (stderr)
@@ -5,9 +5,10 @@
5
5
  */
6
6
  import { taskStore } from './task/TaskStore';
7
7
  import { webSocketService } from './WebSocketService';
8
- import { sessionManager } from './session';
9
- import { getLogger, getUTCTimeKey, formatUTCForLog, holidayService } from '@pocketclaw/shared';
8
+ import { getSessionManager } from './session';
9
+ import { getLogger, getUTCTimeKey, formatUTCForLog, holidayService } from '@myassis/shared';
10
10
  import { tasksService } from './dataService';
11
+ import { authStore } from '@/stores';
11
12
  const logger = getLogger('TaskSchedulerService');
12
13
  const EXPIRED_THRESHOLD = 60 * 60 * 1000; // 1小时
13
14
  const CHECK_INTERVAL = 60 * 1000; // 1分钟
@@ -65,13 +66,17 @@ class TaskSchedulerService {
65
66
  try {
66
67
  const now = Date.now();
67
68
  const nowBeforeHour = now - EXPIRED_THRESHOLD;
68
- const response = await tasksService.list();
69
- if (!response.success) {
69
+ const authMap = authStore.getAll();
70
+ if (!authMap) {
71
+ return;
72
+ }
73
+ const response = await Promise.all(Array.from(authMap.values()).map(x => tasksService.list(x.user.id)));
74
+ if (response.some(x => !x.success)) {
70
75
  logger.error('获取任务失败');
71
76
  return;
72
77
  }
73
78
  // 获取过期待执行任务
74
- const tasks = response.data.filter(x => x.scheduledAt < nowBeforeHour && x.status !== 'completed' && x.status !== 'expired' && x.status !== 'error');
79
+ const tasks = response.flatMap(x => x.data).filter(x => x.scheduledAt < nowBeforeHour && x.status !== 'completed' && x.status !== 'expired' && x.status !== 'error');
75
80
  if (tasks.length > 0) {
76
81
  for (let task of tasks) {
77
82
  await tasksService.updateStatus(task.id, 'expired');
@@ -90,13 +95,17 @@ class TaskSchedulerService {
90
95
  const now = Date.now();
91
96
  const nowBeforeHour = now - EXPIRED_THRESHOLD;
92
97
  const timeKey = getUTCTimeKey(new Date());
93
- const response = await tasksService.list();
94
- if (!response.success) {
98
+ const authMap = authStore.getAll();
99
+ if (!authMap) {
100
+ return;
101
+ }
102
+ const response = await Promise.all(Array.from(authMap.values()).map(x => tasksService.list(x.user.id)));
103
+ if (response.some(x => !x.success)) {
95
104
  logger.error('获取任务失败');
96
105
  return;
97
106
  }
98
107
  // 获取待执行任务
99
- const tasks = response.data.filter(x => x.scheduledAt >= nowBeforeHour && x.scheduledAt <= now && x.status === 'pending');
108
+ const tasks = response.flatMap(x => x.data).filter(x => x.scheduledAt >= nowBeforeHour && x.scheduledAt <= now && x.status === 'pending');
100
109
  if (tasks.length > 0) {
101
110
  logger.info(`Found ${tasks.length} tasks to execute at ${timeKey}`);
102
111
  for (const task of tasks) {
@@ -152,7 +161,7 @@ class TaskSchedulerService {
152
161
  */
153
162
  async executeTaskLocally(task) {
154
163
  try {
155
- const currentSession = sessionManager.getCurrentSession();
164
+ const currentSession = getSessionManager(task.userId).getCurrentSession();
156
165
  if (!currentSession) {
157
166
  logger.warn(`No current session found, cannot execute task: ${task.title}`);
158
167
  return;