@myassis/gateway 1.0.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.
Files changed (65) hide show
  1. package/README.md +194 -0
  2. package/dist/.env +6 -0
  3. package/dist/api/index.js +182 -0
  4. package/dist/config/index.js +41 -0
  5. package/dist/index.js +183 -0
  6. package/dist/middleware/auth.js +53 -0
  7. package/dist/middleware/errorHandler.js +20 -0
  8. package/dist/routes/agent.js +513 -0
  9. package/dist/routes/auth.js +172 -0
  10. package/dist/routes/chat.js +45 -0
  11. package/dist/routes/config.js +21 -0
  12. package/dist/routes/models.js +123 -0
  13. package/dist/routes/service.js +240 -0
  14. package/dist/routes/settings.js +101 -0
  15. package/dist/routes/skillHub.js +126 -0
  16. package/dist/routes/skills.js +159 -0
  17. package/dist/routes/tasks.js +149 -0
  18. package/dist/routes/upload.js +129 -0
  19. package/dist/routes/version.js +66 -0
  20. package/dist/services/HMSPushService.js +24 -0
  21. package/dist/services/LocalTaskService.js +223 -0
  22. package/dist/services/NotificationService.js +242 -0
  23. package/dist/services/ServiceManager.js +348 -0
  24. package/dist/services/TaskSchedulerService.js +195 -0
  25. package/dist/services/TaskService.js +240 -0
  26. package/dist/services/WebSocketService.js +236 -0
  27. package/dist/services/agent/Agent.js +120 -0
  28. package/dist/services/agent/AgentManager.js +265 -0
  29. package/dist/services/agent/AgentStore.js +73 -0
  30. package/dist/services/dataService.js +293 -0
  31. package/dist/services/index.js +15 -0
  32. package/dist/services/llm/LLMClient.js +724 -0
  33. package/dist/services/memory/MemoryManager.js +117 -0
  34. package/dist/services/model/ModelCapabilities.js +141 -0
  35. package/dist/services/model/index.js +4 -0
  36. package/dist/services/models.js +16 -0
  37. package/dist/services/session/MigrationManager.js +176 -0
  38. package/dist/services/session/Session.js +733 -0
  39. package/dist/services/session/SessionManager.js +255 -0
  40. package/dist/services/session/SessionStore.js +186 -0
  41. package/dist/services/session/index.js +3 -0
  42. package/dist/services/skills.js +34 -0
  43. package/dist/services/systemPrompt.js +150 -0
  44. package/dist/services/task/PushTokenStore.js +124 -0
  45. package/dist/services/task/TaskStore.js +143 -0
  46. package/dist/services/tools/calculator.js +27 -0
  47. package/dist/services/tools/edit.js +318 -0
  48. package/dist/services/tools/exec.js +119 -0
  49. package/dist/services/tools/fetch.js +155 -0
  50. package/dist/services/tools/file.js +315 -0
  51. package/dist/services/tools/index.js +48 -0
  52. package/dist/services/tools/keyboard.js +145 -0
  53. package/dist/services/tools/model.js +86 -0
  54. package/dist/services/tools/mouse.js +55 -0
  55. package/dist/services/tools/screenshot.js +19 -0
  56. package/dist/services/tools/search.js +53 -0
  57. package/dist/services/tools/skill.js +108 -0
  58. package/dist/services/tools/task.js +110 -0
  59. package/dist/services/tools/types.js +1 -0
  60. package/dist/services/tools/webFetch.js +34 -0
  61. package/dist/stores/authStore.js +178 -0
  62. package/dist/stores/index.js +6 -0
  63. package/dist/stores/memoryStore.js +191 -0
  64. package/dist/stores/persistStore.js +317 -0
  65. package/package.json +94 -0
@@ -0,0 +1,240 @@
1
+ /**
2
+ * Gateway 统一任务服务
3
+ *
4
+ * 根据 platformApply 路由任务到本地存储或服务器 API
5
+ *
6
+ * 路由规则:
7
+ * - platformApply === currentPlatform → 本地 SQLite 存储(localTaskService)
8
+ * - platformApply !== currentPlatform → 服务器 API(tasksApi)
9
+ */
10
+ import { tasksApi } from '../api';
11
+ import { localTaskService } from './LocalTaskService';
12
+ import { getLogger } from '@pocketclaw/shared';
13
+ import { getPlatform } from '@pocketclaw/shared/dist/utils/system.js';
14
+ // 当前网关平台标识
15
+ const CURRENT_PLATFORM = process.env.GATEWAY_PLATFORM || getPlatform();
16
+ const logger = getLogger('TaskService');
17
+ /**
18
+ * 判断任务是否应该存储在本地
19
+ */
20
+ function isLocalTask(platformApply) {
21
+ // 默认保存到本地 SQLite
22
+ if (!platformApply)
23
+ return true;
24
+ if (platformApply === CURRENT_PLATFORM)
25
+ return true;
26
+ return false;
27
+ }
28
+ class TaskService {
29
+ /**
30
+ * 创建任务(自动路由)
31
+ */
32
+ async createTask(data) {
33
+ const isLocal = isLocalTask(data.platformApply);
34
+ logger.info('[TaskService] 创建任务', {
35
+ title: data.title,
36
+ platformApply: data.platformApply,
37
+ currentPlatform: CURRENT_PLATFORM,
38
+ route: isLocal ? 'local' : 'server',
39
+ });
40
+ if (isLocal) {
41
+ const task = localTaskService.createTask({
42
+ userId: data.userId,
43
+ title: data.title,
44
+ description: data.description,
45
+ taskType: data.taskType,
46
+ recurrenceRule: data.recurrenceRule,
47
+ intervalValue: data.intervalValue,
48
+ intervalUnit: data.intervalUnit,
49
+ scheduledAt: data.scheduledAt,
50
+ startTime: data.startTime,
51
+ endTime: data.endTime,
52
+ platformApply: data.platformApply,
53
+ pushToken: data.pushToken,
54
+ });
55
+ return { id: task.id, isLocal: true };
56
+ }
57
+ else {
58
+ const result = await tasksApi.create({
59
+ user_id: data.userId,
60
+ title: data.title,
61
+ description: data.description,
62
+ task_type: data.taskType,
63
+ recurrence_rule: data.recurrenceRule,
64
+ interval_value: data.intervalValue,
65
+ interval_unit: data.intervalUnit,
66
+ scheduled_at: typeof data.scheduledAt === 'object'
67
+ ? new Date(data.scheduledAt).toISOString()
68
+ : data.scheduledAt,
69
+ start_time: data.startTime
70
+ ? (typeof data.startTime === 'object' ? new Date(data.startTime).toISOString() : data.startTime)
71
+ : undefined,
72
+ end_time: data.endTime
73
+ ? (typeof data.endTime === 'object' ? new Date(data.endTime).toISOString() : data.endTime)
74
+ : undefined,
75
+ platform_apply: data.platformApply,
76
+ });
77
+ return { id: String(result.id || result), isLocal: false };
78
+ }
79
+ }
80
+ /**
81
+ * 获取任务(自动路由 - 先本地后服务器)
82
+ */
83
+ async getTask(taskId) {
84
+ const localTask = localTaskService.getTask(taskId);
85
+ if (localTask)
86
+ return localTask;
87
+ try {
88
+ const result = await tasksApi.get(taskId);
89
+ return this.transformServerTask(result);
90
+ }
91
+ catch (error) {
92
+ logger.warn('[TaskService] 获取服务器任务失败', { taskId, error });
93
+ return null;
94
+ }
95
+ }
96
+ /**
97
+ * 获取任务列表(合并本地和服务器)
98
+ */
99
+ async listTasks(params) {
100
+ const localResult = localTaskService.listTasks(params);
101
+ let serverTasks = [];
102
+ try {
103
+ const serverResult = await tasksApi.list({
104
+ status: params?.status,
105
+ page: params?.page ? String(params.page) : undefined,
106
+ pageSize: params?.pageSize ? String(params.pageSize) : undefined,
107
+ });
108
+ if (Array.isArray(serverResult)) {
109
+ serverTasks = serverResult.map(t => this.transformServerTask(t)).filter(Boolean);
110
+ }
111
+ else if (serverResult?.data && Array.isArray(serverResult.data)) {
112
+ serverTasks = serverResult.data.map(t => this.transformServerTask(t)).filter(Boolean);
113
+ }
114
+ }
115
+ catch (error) {
116
+ logger.warn('[TaskService] 获取服务器任务列表失败', { error });
117
+ }
118
+ const localIds = new Set(localResult.tasks.map(t => t.id));
119
+ const mergedTasks = [
120
+ ...localResult.tasks,
121
+ ...serverTasks.filter(t => !localIds.has(t.id)),
122
+ ];
123
+ mergedTasks.sort((a, b) => b.scheduledAt - a.scheduledAt);
124
+ return { tasks: mergedTasks, total: mergedTasks.length };
125
+ }
126
+ /**
127
+ * 更新任务(自动路由)
128
+ */
129
+ async updateTask(taskId, data) {
130
+ const localTask = localTaskService.getTask(taskId);
131
+ if (localTask) {
132
+ const result = localTaskService.updateTask(taskId, data);
133
+ return result !== null;
134
+ }
135
+ else {
136
+ try {
137
+ await tasksApi.update(taskId, {
138
+ title: data.title,
139
+ description: data.description,
140
+ task_type: data.taskType,
141
+ recurrence_rule: data.recurrenceRule,
142
+ interval_value: data.intervalValue,
143
+ interval_unit: data.intervalUnit,
144
+ scheduled_at: data.scheduledAt
145
+ ? (typeof data.scheduledAt === 'object' ? new Date(data.scheduledAt).toISOString() : data.scheduledAt)
146
+ : undefined,
147
+ start_time: data.startTime
148
+ ? (typeof data.startTime === 'object' ? new Date(data.startTime).toISOString() : data.startTime)
149
+ : undefined,
150
+ end_time: data.endTime
151
+ ? (typeof data.endTime === 'object' ? new Date(data.endTime).toISOString() : data.endTime)
152
+ : undefined,
153
+ status: data.status,
154
+ });
155
+ return true;
156
+ }
157
+ catch (error) {
158
+ logger.error('[TaskService] 更新服务器任务失败', { taskId, error });
159
+ return false;
160
+ }
161
+ }
162
+ }
163
+ /**
164
+ * 删除任务(自动路由)
165
+ */
166
+ async deleteTask(taskId) {
167
+ const localTask = localTaskService.getTask(taskId);
168
+ if (localTask) {
169
+ return localTaskService.deleteTask(taskId);
170
+ }
171
+ else {
172
+ try {
173
+ await tasksApi.delete(taskId);
174
+ return true;
175
+ }
176
+ catch (error) {
177
+ logger.error('[TaskService] 删除服务器任务失败', { taskId, error });
178
+ return false;
179
+ }
180
+ }
181
+ }
182
+ /**
183
+ * 更新任务状态
184
+ */
185
+ async updateTaskStatus(taskId, status) {
186
+ const localTask = localTaskService.getTask(taskId);
187
+ if (localTask) {
188
+ await localTaskService.updateTaskStatus(taskId, status);
189
+ return true;
190
+ }
191
+ else {
192
+ try {
193
+ await tasksApi.updateStatus(taskId, { status });
194
+ return true;
195
+ }
196
+ catch (error) {
197
+ logger.error('[TaskService] 更新服务器任务状态失败', { taskId, status, error });
198
+ return false;
199
+ }
200
+ }
201
+ }
202
+ /**
203
+ * 完成任务
204
+ */
205
+ async completeTask(taskId) {
206
+ return this.updateTaskStatus(taskId, 'completed');
207
+ }
208
+ /**
209
+ * 取消任务
210
+ */
211
+ async cancelTask(taskId) {
212
+ return this.updateTaskStatus(taskId, 'cancelled');
213
+ }
214
+ /**
215
+ * 转换服务器任务格式
216
+ */
217
+ transformServerTask(serverTask) {
218
+ if (!serverTask)
219
+ return null;
220
+ return {
221
+ id: String(serverTask.id || serverTask.task_id),
222
+ userId: String(serverTask.user_id || serverTask.userId),
223
+ title: serverTask.title || '',
224
+ description: serverTask.description,
225
+ taskType: serverTask.task_type || serverTask.taskType || 'one_time',
226
+ recurrenceRule: serverTask.recurrence_rule || serverTask.recurrenceRule,
227
+ intervalValue: serverTask.interval_value || serverTask.intervalValue,
228
+ intervalUnit: serverTask.interval_unit || serverTask.intervalUnit,
229
+ scheduledAt: new Date(serverTask.scheduled_at || serverTask.scheduledAt).getTime(),
230
+ startTime: serverTask.start_time ? new Date(serverTask.start_time).getTime() : undefined,
231
+ endTime: serverTask.end_time ? new Date(serverTask.end_time).getTime() : undefined,
232
+ status: serverTask.status || 'pending',
233
+ platformApply: serverTask.platform_apply || serverTask.platformApply,
234
+ pushToken: serverTask.push_token || serverTask.pushToken,
235
+ createdAt: new Date(serverTask.created_at || serverTask.createdAt).getTime(),
236
+ updatedAt: new Date(serverTask.updated_at || serverTask.updatedAt).getTime(),
237
+ };
238
+ }
239
+ }
240
+ export const taskService = new TaskService();
@@ -0,0 +1,236 @@
1
+ /**
2
+ * WebSocket 服务
3
+ * 负责实时消息推送,使用 ws 库实现
4
+ */
5
+ import { WebSocketServer, WebSocket } from 'ws';
6
+ import { authStore } from '../stores/index.js';
7
+ import { getLogger } from '@pocketclaw/shared';
8
+ const logger = getLogger('WebSocketService');
9
+ class WebSocketService {
10
+ wss = null;
11
+ clients = new Map();
12
+ heartbeatInterval = null;
13
+ /**
14
+ * 初始化 WebSocket 服务器,挂载到 HTTP Server 上
15
+ */
16
+ initialize(server) {
17
+ this.wss = new WebSocketServer({ server, path: '/ws' });
18
+ // 防止 WebSocketServer error 事件未监听导致进程崩溃(如 EADDRINUSE)
19
+ this.wss.on('error', (err) => {
20
+ logger.error('WebSocketServer error:', err);
21
+ });
22
+ this.wss.on('connection', (ws, req) => {
23
+ const clientKey = this.getClientKey(req);
24
+ if (!clientKey) {
25
+ logger.warn('连接无标识,断开');
26
+ ws.close(4001, 'Unauthorized');
27
+ return;
28
+ }
29
+ const userId = clientKey;
30
+ logger.info(`用户 ${userId} 已连接`);
31
+ const client = {
32
+ ws,
33
+ userId,
34
+ connectedAt: Date.now(),
35
+ isAlive: true,
36
+ };
37
+ // 如果同一用户已有连接,关闭旧连接
38
+ const existingClient = this.clients.get(userId);
39
+ if (existingClient && existingClient.ws.readyState === WebSocket.OPEN) {
40
+ existingClient.ws.close(4002, 'Replaced by new connection');
41
+ }
42
+ this.clients.set(userId, client);
43
+ // 心跳检测
44
+ ws.on('pong', () => {
45
+ if (this.clients.has(userId)) {
46
+ this.clients.get(userId).isAlive = true;
47
+ }
48
+ });
49
+ // 接收消息
50
+ ws.on('message', (data) => {
51
+ try {
52
+ const message = JSON.parse(data.toString());
53
+ this.handleMessage(userId, message);
54
+ }
55
+ catch {
56
+ logger.warn(`用户 ${userId} 发送了无效消息`);
57
+ }
58
+ });
59
+ // 断开连接
60
+ ws.on('close', () => {
61
+ logger.info(`用户 ${userId} 已断开`);
62
+ this.clients.delete(userId);
63
+ });
64
+ ws.on('error', (error) => {
65
+ logger.error(`用户 ${userId} 连接错误:`, error);
66
+ this.clients.delete(userId);
67
+ });
68
+ // 发送连接成功消息
69
+ this.sendToUser(userId, {
70
+ type: 'connected',
71
+ payload: {
72
+ userId,
73
+ timestamp: Date.now(),
74
+ },
75
+ });
76
+ });
77
+ // 启动心跳检测
78
+ this.heartbeatInterval = setInterval(() => {
79
+ this.wss.clients.forEach((ws) => {
80
+ const client = Array.from(this.clients.values()).find(c => c.ws === ws);
81
+ if (!client)
82
+ return;
83
+ if (!client.isAlive) {
84
+ logger.info(`用户 ${client.userId} 心跳超时,断开`);
85
+ this.clients.delete(client.userId);
86
+ return ws.terminate();
87
+ }
88
+ client.isAlive = false;
89
+ ws.ping();
90
+ });
91
+ }, 30000);
92
+ logger.info('WebSocket 服务已启动,路径: /ws');
93
+ }
94
+ /**
95
+ * 从请求中提取用户标识
96
+ * Desktop 不存储 token,Gateway 直接信任连接并使用已登录用户的 ID
97
+ */
98
+ getClientKey(req) {
99
+ // 直接使用 authStore 中的用户 ID(Gateway 登录后的用户)
100
+ const userId = authStore.getUserId();
101
+ if (userId) {
102
+ return String(userId);
103
+ }
104
+ return null;
105
+ }
106
+ /**
107
+ * 处理客户端发来的消息
108
+ */
109
+ handleMessage(userId, message) {
110
+ switch (message.type) {
111
+ case 'ping':
112
+ this.sendToUser(userId, { type: 'pong', payload: { timestamp: Date.now() } });
113
+ break;
114
+ case 'subscribe':
115
+ logger.debug(`用户 ${userId} 订阅: ${message.payload?.channel || 'all'}`);
116
+ break;
117
+ default:
118
+ logger.debug(`收到用户 ${userId} 的消息: ${message.type}`);
119
+ }
120
+ }
121
+ /**
122
+ * 向指定用户发送消息
123
+ */
124
+ sendToUser(userId, message) {
125
+ const client = this.clients.get(String(userId));
126
+ if (!client || client.ws.readyState !== WebSocket.OPEN) {
127
+ return false;
128
+ }
129
+ try {
130
+ client.ws.send(JSON.stringify(message));
131
+ return true;
132
+ }
133
+ catch (error) {
134
+ logger.error(`发送消息给用户 ${userId} 失败:`, error);
135
+ return false;
136
+ }
137
+ }
138
+ /**
139
+ * 检查用户是否在线
140
+ */
141
+ isUserOnline(userId) {
142
+ const client = this.clients.get(String(userId));
143
+ return !!client && client.ws.readyState === WebSocket.OPEN;
144
+ }
145
+ /**
146
+ * 发送任务通知
147
+ */
148
+ sendTaskNotification(task) {
149
+ return this.sendToUser(String(task.userId), {
150
+ type: 'task_notification',
151
+ payload: {
152
+ id: task.id,
153
+ title: task.title,
154
+ description: task.description,
155
+ status: task.status,
156
+ scheduledAt: task.scheduledAt,
157
+ },
158
+ });
159
+ }
160
+ /**
161
+ * 发送任务触发通知给 Desktop(要求 Desktop 在当前会话执行任务)
162
+ * 返回 true 表示发送成功(Desktop 在线),false 表示 Desktop 不在线
163
+ */
164
+ sendTaskTrigger(task) {
165
+ return this.sendToUser(String(task.userId), {
166
+ type: 'task_trigger',
167
+ payload: {
168
+ id: task.id,
169
+ title: task.title,
170
+ description: task.description,
171
+ taskType: task.taskType,
172
+ scheduledAt: task.scheduledAt,
173
+ },
174
+ });
175
+ }
176
+ /**
177
+ * 发送更新提示给用户
178
+ * 无 nssm 时通过此方法推送到 Desktop,显示手动更新对话框
179
+ */
180
+ sendUpdateRequired(userId, message) {
181
+ return this.sendToUser(userId, {
182
+ type: 'update_required',
183
+ payload: {
184
+ message,
185
+ timestamp: Date.now(),
186
+ },
187
+ });
188
+ }
189
+ /**
190
+ * 广播消息给所有在线用户
191
+ */
192
+ broadcast(message) {
193
+ const data = JSON.stringify(message);
194
+ this.clients.forEach((client) => {
195
+ if (client.ws.readyState === WebSocket.OPEN) {
196
+ try {
197
+ client.ws.send(data);
198
+ }
199
+ catch (error) {
200
+ logger.error(`广播消息给用户 ${client.userId} 失败:`, error);
201
+ }
202
+ }
203
+ });
204
+ }
205
+ /**
206
+ * 获取在线用户数
207
+ */
208
+ getOnlineCount() {
209
+ return this.clients.size;
210
+ }
211
+ /**
212
+ * 获取在线用户列表
213
+ */
214
+ getOnlineUsers() {
215
+ return Array.from(this.clients.keys());
216
+ }
217
+ /**
218
+ * 关闭 WebSocket 服务器
219
+ */
220
+ shutdown() {
221
+ if (this.heartbeatInterval) {
222
+ clearInterval(this.heartbeatInterval);
223
+ this.heartbeatInterval = null;
224
+ }
225
+ this.clients.forEach((client) => {
226
+ client.ws.close(1001, 'Server shutting down');
227
+ });
228
+ this.clients.clear();
229
+ if (this.wss) {
230
+ this.wss.close();
231
+ this.wss = null;
232
+ }
233
+ logger.info('WebSocket 服务已关闭');
234
+ }
235
+ }
236
+ export const webSocketService = new WebSocketService();
@@ -0,0 +1,120 @@
1
+ import { v4 as uuidv4 } from 'uuid';
2
+ import { sessionManager } from '../session/SessionManager';
3
+ /**
4
+ * Agent - Business logic entity
5
+ * Represents an AI agent with independent system prompt and multiple sessions
6
+ */
7
+ export class Agent {
8
+ id;
9
+ userId;
10
+ name;
11
+ description;
12
+ systemPrompt;
13
+ avatar;
14
+ config;
15
+ createdAt;
16
+ updatedAt;
17
+ isCurrent; // 是否是当前正在查看的 Agent
18
+ store;
19
+ constructor(data, store, agentManager) {
20
+ this.id = data.id;
21
+ this.userId = data.userId;
22
+ this.name = data.name;
23
+ this.description = data.description;
24
+ this.systemPrompt = data.systemPrompt;
25
+ this.avatar = data.avatar;
26
+ this.config = data.config;
27
+ this.createdAt = data.createdAt;
28
+ this.updatedAt = data.updatedAt;
29
+ this.isCurrent = data.isCurrent || false;
30
+ this.store = store;
31
+ }
32
+ /**
33
+ * Get all sessions under this agent
34
+ */
35
+ getSessions() {
36
+ const allSessions = sessionManager.getUserSessions();
37
+ return allSessions.filter(s => s.agentId === this.id);
38
+ }
39
+ /**
40
+ * Create new session under this agent
41
+ */
42
+ createSession(config = {}) {
43
+ const session = sessionManager.createSession({
44
+ id: config.id || uuidv4(),
45
+ title: config.title || '新会话',
46
+ selectModelId: config.selectModelId,
47
+ agentId: this.id, // Associate with this agent
48
+ });
49
+ return session;
50
+ }
51
+ /**
52
+ * Update session under this agent
53
+ */
54
+ updateSession(sessionId, data) {
55
+ const session = this.getSession(sessionId);
56
+ if (!session)
57
+ return null;
58
+ return sessionManager.updateSession(sessionId, data);
59
+ }
60
+ /**
61
+ * Delete session under this agent
62
+ */
63
+ deleteSession(sessionId) {
64
+ const session = this.getSession(sessionId);
65
+ if (!session)
66
+ return false;
67
+ return sessionManager.deleteSession(sessionId);
68
+ }
69
+ /**
70
+ * Get session under this agent
71
+ */
72
+ getSession(sessionId) {
73
+ const session = sessionManager.getSession(sessionId);
74
+ if (session && session.agentId === this.id) {
75
+ return session;
76
+ }
77
+ return null;
78
+ }
79
+ /**
80
+ * Update agent info
81
+ */
82
+ update(updates) {
83
+ if (updates.name !== undefined)
84
+ this.name = updates.name;
85
+ if (updates.description !== undefined)
86
+ this.description = updates.description;
87
+ if (updates.systemPrompt !== undefined)
88
+ this.systemPrompt = updates.systemPrompt;
89
+ if (updates.avatar !== undefined)
90
+ this.avatar = updates.avatar;
91
+ if (updates.config !== undefined)
92
+ this.config = updates.config;
93
+ this.updatedAt = Date.now();
94
+ this.save();
95
+ }
96
+ /**
97
+ * Save to database
98
+ */
99
+ save() {
100
+ const data = {
101
+ id: this.id,
102
+ userId: this.userId,
103
+ name: this.name,
104
+ description: this.description,
105
+ systemPrompt: this.systemPrompt,
106
+ avatar: this.avatar,
107
+ config: this.config,
108
+ createdAt: this.createdAt,
109
+ updatedAt: this.updatedAt,
110
+ isCurrent: this.isCurrent,
111
+ };
112
+ this.store.update(data);
113
+ }
114
+ /**
115
+ * Delete agent (will cascade delete all sessions)
116
+ */
117
+ delete() {
118
+ this.store.delete(this.id);
119
+ }
120
+ }