@lobehub/lobehub 2.0.0-next.266 → 2.0.0-next.268

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 (136) hide show
  1. package/.cursor/rules/microcopy-cn.mdc +75 -63
  2. package/.cursor/rules/microcopy-en.mdc +4 -8
  3. package/CHANGELOG.md +50 -0
  4. package/README.md +8 -8
  5. package/README.zh-CN.md +8 -8
  6. package/apps/desktop/src/main/locales/default/common.ts +2 -2
  7. package/changelog/v1.json +10 -0
  8. package/docs/development/database-schema.dbml +4 -0
  9. package/e2e/CLAUDE.md +43 -81
  10. package/e2e/cucumber.config.js +1 -0
  11. package/e2e/docs/local-setup.md +67 -219
  12. package/e2e/scripts/setup.ts +529 -0
  13. package/e2e/src/features/home/sidebarAgent.feature +62 -0
  14. package/e2e/src/features/home/sidebarGroup.feature +62 -0
  15. package/e2e/src/features/page/README.md +118 -0
  16. package/e2e/src/features/page/crud.feature +62 -0
  17. package/e2e/src/features/page/editor-content.feature +93 -0
  18. package/e2e/src/features/page/editor-meta.feature +60 -0
  19. package/e2e/src/steps/agent/conversation.steps.ts +4 -4
  20. package/e2e/src/steps/home/sidebarAgent.steps.ts +370 -0
  21. package/e2e/src/steps/home/sidebarGroup.steps.ts +168 -0
  22. package/e2e/src/steps/hooks.ts +4 -0
  23. package/e2e/src/steps/page/editor-content.steps.ts +344 -0
  24. package/e2e/src/steps/page/editor-meta.steps.ts +410 -0
  25. package/e2e/src/steps/page/page-crud.steps.ts +363 -0
  26. package/e2e/src/support/world.ts +12 -0
  27. package/locales/ar/file.json +2 -0
  28. package/locales/bg-BG/file.json +2 -0
  29. package/locales/de-DE/file.json +2 -0
  30. package/locales/en-US/auth.json +1 -1
  31. package/locales/en-US/file.json +2 -0
  32. package/locales/en-US/metadata.json +2 -2
  33. package/locales/es-ES/file.json +2 -0
  34. package/locales/fa-IR/file.json +2 -0
  35. package/locales/fr-FR/file.json +2 -0
  36. package/locales/it-IT/file.json +2 -0
  37. package/locales/ja-JP/file.json +2 -0
  38. package/locales/ko-KR/file.json +2 -0
  39. package/locales/nl-NL/file.json +2 -0
  40. package/locales/pl-PL/file.json +2 -0
  41. package/locales/pt-BR/file.json +2 -0
  42. package/locales/ru-RU/file.json +2 -0
  43. package/locales/tr-TR/file.json +2 -0
  44. package/locales/vi-VN/file.json +2 -0
  45. package/locales/zh-CN/file.json +2 -0
  46. package/locales/zh-TW/file.json +2 -0
  47. package/package.json +3 -3
  48. package/packages/builtin-agents/src/agents/agent-builder/index.ts +1 -1
  49. package/packages/builtin-agents/src/agents/group-agent-builder/index.ts +1 -1
  50. package/packages/builtin-agents/src/agents/page-agent/index.ts +1 -1
  51. package/packages/const/src/settings/group.ts +0 -10
  52. package/packages/database/migrations/0068_update_group_data.sql +4 -0
  53. package/packages/database/migrations/meta/0068_snapshot.json +9588 -0
  54. package/packages/database/migrations/meta/_journal.json +7 -0
  55. package/packages/database/src/models/__tests__/chatGroup.test.ts +5 -7
  56. package/packages/database/src/models/__tests__/knowledgeBase.test.ts +185 -0
  57. package/packages/database/src/models/knowledgeBase.ts +67 -3
  58. package/packages/database/src/repositories/agentGroup/index.test.ts +23 -29
  59. package/packages/database/src/repositories/agentGroup/index.ts +4 -9
  60. package/packages/database/src/repositories/knowledge/index.ts +3 -3
  61. package/packages/database/src/schemas/chatGroup.ts +4 -3
  62. package/packages/database/src/types/chatGroup.ts +0 -7
  63. package/packages/types/src/agentGroup/index.ts +30 -9
  64. package/packages/utils/src/multimodalContent.test.ts +302 -0
  65. package/packages/utils/src/server/__tests__/sse.test.ts +353 -0
  66. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/Editing.tsx +4 -11
  67. package/src/app/[variants]/(main)/home/_layout/Body/Agent/List/AgentGroupItem/index.tsx +3 -3
  68. package/src/app/[variants]/(main)/home/_layout/Body/Agent/ModalProvider.tsx +9 -32
  69. package/src/app/[variants]/(main)/home/_layout/hooks/useCreateMenuItems.tsx +3 -37
  70. package/src/app/[variants]/(main)/home/_layout/hooks/useSessionGroupMenuItems.tsx +7 -53
  71. package/src/app/[variants]/(main)/home/features/RecentPage/List.tsx +2 -1
  72. package/src/app/[variants]/(main)/resource/features/DndContextWrapper.tsx +1 -1
  73. package/src/app/[variants]/(main)/resource/library/_layout/Sidebar.tsx +2 -2
  74. package/src/app/[variants]/(main)/resource/library/features/LibraryMenu.tsx +2 -2
  75. package/src/app/[variants]/(mobile)/chat/settings/features/SettingButton.tsx +2 -12
  76. package/src/components/ChatGroupWizard/ChatGroupWizard.tsx +5 -27
  77. package/src/components/DragUpload/index.tsx +24 -27
  78. package/src/components/MemberSelectionModal/MemberSelectionModal.tsx +2 -11
  79. package/src/features/ChatInput/ActionBar/Params/Controls.tsx +42 -7
  80. package/src/features/CommandMenu/useCommandMenu.ts +4 -14
  81. package/src/features/ResourceManager/components/Editor/index.tsx +2 -3
  82. package/src/features/ResourceManager/components/Explorer/Header/index.tsx +13 -17
  83. package/src/features/ResourceManager/components/Explorer/ItemDropdown/useFileItemDropdown.tsx +1 -1
  84. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/TruncatedFileName.tsx +130 -0
  85. package/src/features/ResourceManager/components/Explorer/ListView/ListItem/index.tsx +36 -4
  86. package/src/features/ResourceManager/components/Explorer/ListView/Skeleton.tsx +4 -3
  87. package/src/features/ResourceManager/components/Explorer/ListView/index.tsx +58 -2
  88. package/src/features/ResourceManager/components/Explorer/MasonryView/index.tsx +58 -6
  89. package/src/features/ResourceManager/components/Explorer/MoveToFolderModal.tsx +2 -5
  90. package/src/features/ResourceManager/components/Explorer/ToolBar/BatchActionsDropdown.tsx +9 -5
  91. package/src/features/ResourceManager/components/Explorer/index.tsx +11 -56
  92. package/src/features/ResourceManager/components/Header/AddButton.tsx +5 -6
  93. package/src/features/ResourceManager/components/LibraryHierarchy/HierarchyNode.tsx +382 -0
  94. package/src/features/ResourceManager/components/LibraryHierarchy/index.tsx +396 -0
  95. package/src/features/ResourceManager/components/LibraryHierarchy/styles.ts +19 -0
  96. package/src/features/ResourceManager/components/LibraryHierarchy/treeState.ts +178 -0
  97. package/src/features/ResourceManager/components/LibraryHierarchy/types.ts +10 -0
  98. package/src/features/ResourceManager/index.tsx +3 -0
  99. package/src/layout/GlobalProvider/GroupWizardProvider.tsx +6 -29
  100. package/src/locales/default/auth.ts +1 -1
  101. package/src/locales/default/file.ts +2 -0
  102. package/src/locales/default/metadata.ts +2 -2
  103. package/src/server/modules/AgentRuntime/AgentRuntimeCoordinator.ts +30 -30
  104. package/src/server/modules/AgentRuntime/AgentStateManager.ts +23 -23
  105. package/src/server/modules/AgentRuntime/InMemoryAgentStateManager.ts +16 -16
  106. package/src/server/modules/AgentRuntime/InMemoryStreamEventManager.ts +13 -13
  107. package/src/server/modules/AgentRuntime/RuntimeExecutors.ts +2 -2
  108. package/src/server/modules/AgentRuntime/StreamEventManager.ts +18 -18
  109. package/src/server/modules/AgentRuntime/types.ts +21 -21
  110. package/src/server/routers/lambda/__tests__/agentGroup.test.ts +8 -8
  111. package/src/server/routers/lambda/agentGroup.ts +10 -12
  112. package/src/server/services/document/index.ts +1 -0
  113. package/src/store/agentGroup/slices/curd.test.ts +4 -4
  114. package/src/store/file/slices/fileManager/action.ts +12 -4
  115. package/src/store/home/slices/homeInput/action.ts +0 -3
  116. package/src/store/home/slices/sidebarUI/action.ts +9 -0
  117. package/src/store/session/slices/session/action.ts +5 -9
  118. package/src/app/[variants]/(mobile)/chat/settings/features/AgentTeamSettings/index.tsx +0 -95
  119. package/src/features/GroupChatSettings/AgentCard.tsx +0 -154
  120. package/src/features/GroupChatSettings/AgentTeamChatSettings.tsx +0 -179
  121. package/src/features/GroupChatSettings/AgentTeamMembersSettings.tsx +0 -244
  122. package/src/features/GroupChatSettings/AgentTeamMetaSettings.tsx +0 -94
  123. package/src/features/GroupChatSettings/AgentTeamSettings.tsx +0 -54
  124. package/src/features/GroupChatSettings/GroupCategory/index.tsx +0 -30
  125. package/src/features/GroupChatSettings/GroupCategory/useGroupCategory.tsx +0 -42
  126. package/src/features/GroupChatSettings/GroupChatSettingsProvider.tsx +0 -19
  127. package/src/features/GroupChatSettings/HostMemberCard.tsx +0 -113
  128. package/src/features/GroupChatSettings/StoreUpdater.tsx +0 -34
  129. package/src/features/GroupChatSettings/hooks/useGroupChatSettings.ts +0 -25
  130. package/src/features/GroupChatSettings/index.ts +0 -16
  131. package/src/features/GroupChatSettings/store/action.ts +0 -105
  132. package/src/features/GroupChatSettings/store/index.ts +0 -18
  133. package/src/features/GroupChatSettings/store/initialState.ts +0 -23
  134. package/src/features/GroupChatSettings/store/selectors.ts +0 -13
  135. package/src/features/ResourceManager/components/Tree/index.tsx +0 -883
  136. /package/src/features/ResourceManager/components/{Tree → LibraryHierarchy}/TreeSkeleton.tsx +0 -0
@@ -3,7 +3,7 @@ export default {
3
3
  'changelog.title': 'Changelog',
4
4
  'chat.description':
5
5
  '{{appName}} brings you the best UI experience for ChatGPT, Claude, Gemini, and OLLaMA.',
6
- 'chat.title': '{{appName}} · For Collaborative Agents',
6
+ 'chat.title': '{{appName}} · Where Agents Collaborate',
7
7
  'discover.assistants.description':
8
8
  'Content, Q&A, images, video, voice, workflows—browse and add Agents from the Community.',
9
9
  'discover.assistants.title': 'Agent Community',
@@ -30,5 +30,5 @@ export default {
30
30
  'plugins.title': 'Skill Community',
31
31
  'welcome.description':
32
32
  '{{appName}} brings you the best UI experience for ChatGPT, Claude, Gemini, and OLLaMA.',
33
- 'welcome.title': 'Welcome to {{appName}} · For Collaborative Agents',
33
+ 'welcome.title': 'Welcome to {{appName}} · Where Agents Collaborate',
34
34
  };
@@ -9,27 +9,27 @@ const log = debug('lobe-server:agent-runtime:coordinator');
9
9
 
10
10
  export interface AgentRuntimeCoordinatorOptions {
11
11
  /**
12
- * 自定义状态管理器实现
13
- * 默认根据 Redis 可用性自动选择实现
12
+ * Custom state manager implementation
13
+ * Defaults to automatic selection based on Redis availability
14
14
  */
15
15
  stateManager?: IAgentStateManager;
16
16
  /**
17
- * 自定义流式事件管理器实现
18
- * 默认根据 Redis 可用性自动选择实现
17
+ * Custom stream event manager implementation
18
+ * Defaults to automatic selection based on Redis availability
19
19
  */
20
20
  streamEventManager?: IStreamEventManager;
21
21
  }
22
22
 
23
23
  /**
24
24
  * Agent Runtime Coordinator
25
- * 协调 AgentStateManager StreamEventManager 的操作
26
- * 负责在状态变更时发送相应的事件
25
+ * Coordinates operations between AgentStateManager and StreamEventManager
26
+ * Responsible for sending corresponding events when state changes occur
27
27
  *
28
- * 默认行为:
29
- * - Redis 可用时使用 Redis 实现
30
- * - Redis 不可用时自动回退到内存实现(本地开发模式)
28
+ * Default behavior:
29
+ * - Uses Redis implementation when Redis is available
30
+ * - Automatically falls back to in-memory implementation when Redis is unavailable (local development mode)
31
31
  *
32
- * 支持依赖注入,可以传入自定义实现
32
+ * Supports dependency injection, allowing custom implementations to be passed in
33
33
  */
34
34
  export class AgentRuntimeCoordinator {
35
35
  private stateManager: IAgentStateManager;
@@ -41,7 +41,7 @@ export class AgentRuntimeCoordinator {
41
41
  }
42
42
 
43
43
  /**
44
- * 创建新的 Agent 操作并发送初始化事件
44
+ * Create a new Agent operation and send initialization event
45
45
  */
46
46
  async createAgentOperation(
47
47
  operationId: string,
@@ -52,14 +52,14 @@ export class AgentRuntimeCoordinator {
52
52
  },
53
53
  ): Promise<void> {
54
54
  try {
55
- // 创建操作元数据
55
+ // Create operation metadata
56
56
  await this.stateManager.createOperationMetadata(operationId, data);
57
57
 
58
- // 获取创建的元数据
58
+ // Get the created metadata
59
59
  const metadata = await this.stateManager.getOperationMetadata(operationId);
60
60
 
61
61
  if (metadata) {
62
- // 发送 agent runtime init 事件
62
+ // Send agent runtime init event
63
63
  await this.streamEventManager.publishAgentRuntimeInit(operationId, metadata);
64
64
  log('[%s] Agent operation created and initialized', operationId);
65
65
  }
@@ -70,16 +70,16 @@ export class AgentRuntimeCoordinator {
70
70
  }
71
71
 
72
72
  /**
73
- * 保存 Agent 状态并处理相应事件
73
+ * Save Agent state and handle corresponding events
74
74
  */
75
75
  async saveAgentState(operationId: string, state: AgentState): Promise<void> {
76
76
  try {
77
77
  const previousState = await this.stateManager.loadAgentState(operationId);
78
78
 
79
- // 保存状态
79
+ // Save state
80
80
  await this.stateManager.saveAgentState(operationId, state);
81
81
 
82
- // 如果状态变为 done,发送 agent runtime end 事件
82
+ // If status changes to done, send agent runtime end event
83
83
  if (state.status === 'done' && previousState?.status !== 'done') {
84
84
  await this.streamEventManager.publishAgentRuntimeEnd(operationId, state.stepCount, state);
85
85
  log('[%s] Agent runtime completed', operationId);
@@ -91,18 +91,18 @@ export class AgentRuntimeCoordinator {
91
91
  }
92
92
 
93
93
  /**
94
- * 保存步骤结果并处理相应事件
94
+ * Save step result and handle corresponding events
95
95
  */
96
96
  async saveStepResult(operationId: string, stepResult: StepResult): Promise<void> {
97
97
  try {
98
- // 获取之前的状态用于检测状态变化
98
+ // Get previous state for detecting state changes
99
99
  const previousState = await this.stateManager.loadAgentState(operationId);
100
100
 
101
- // 保存步骤结果
101
+ // Save step result
102
102
  await this.stateManager.saveStepResult(operationId, stepResult);
103
103
 
104
- // 如果状态变为 done,发送 agent_runtime_end 事件
105
- // 这确保 agent_runtime_end 在所有步骤事件之后发送
104
+ // If status changes to done, send agent_runtime_end event
105
+ // This ensures agent_runtime_end is sent after all step events
106
106
  if (stepResult.newState.status === 'done' && previousState?.status !== 'done') {
107
107
  await this.streamEventManager.publishAgentRuntimeEnd(
108
108
  operationId,
@@ -118,28 +118,28 @@ export class AgentRuntimeCoordinator {
118
118
  }
119
119
 
120
120
  /**
121
- * 获取 Agent 状态
121
+ * Get Agent state
122
122
  */
123
123
  async loadAgentState(operationId: string): Promise<AgentState | null> {
124
124
  return this.stateManager.loadAgentState(operationId);
125
125
  }
126
126
 
127
127
  /**
128
- * 获取操作元数据
128
+ * Get operation metadata
129
129
  */
130
130
  async getOperationMetadata(operationId: string): Promise<AgentOperationMetadata | null> {
131
131
  return this.stateManager.getOperationMetadata(operationId);
132
132
  }
133
133
 
134
134
  /**
135
- * 获取执行历史
135
+ * Get execution history
136
136
  */
137
137
  async getExecutionHistory(operationId: string, limit?: number): Promise<any[]> {
138
138
  return this.stateManager.getExecutionHistory(operationId, limit);
139
139
  }
140
140
 
141
141
  /**
142
- * 删除 Agent 操作
142
+ * Delete Agent operation
143
143
  */
144
144
  async deleteAgentOperation(operationId: string): Promise<void> {
145
145
  try {
@@ -155,14 +155,14 @@ export class AgentRuntimeCoordinator {
155
155
  }
156
156
 
157
157
  /**
158
- * 获取活跃操作
158
+ * Get active operations
159
159
  */
160
160
  async getActiveOperations(): Promise<string[]> {
161
161
  return this.stateManager.getActiveOperations();
162
162
  }
163
163
 
164
164
  /**
165
- * 获取统计信息
165
+ * Get statistics
166
166
  */
167
167
  async getStats(): Promise<{
168
168
  activeOperations: number;
@@ -174,14 +174,14 @@ export class AgentRuntimeCoordinator {
174
174
  }
175
175
 
176
176
  /**
177
- * 清理过期操作
177
+ * Clean up expired operations
178
178
  */
179
179
  async cleanupExpiredOperations(): Promise<number> {
180
180
  return this.stateManager.cleanupExpiredOperations();
181
181
  }
182
182
 
183
183
  /**
184
- * 关闭连接
184
+ * Close connections
185
185
  */
186
186
  async disconnect(): Promise<void> {
187
187
  await Promise.all([this.stateManager.disconnect(), this.streamEventManager.disconnect()]);
@@ -42,7 +42,7 @@ export class AgentStateManager {
42
42
  }
43
43
 
44
44
  /**
45
- * 保存 Agent 状态
45
+ * Save Agent state
46
46
  */
47
47
  async saveAgentState(operationId: string, state: AgentState): Promise<void> {
48
48
  const stateKey = `${this.STATE_PREFIX}:${operationId}`;
@@ -51,7 +51,7 @@ export class AgentStateManager {
51
51
  const serializedState = JSON.stringify(state);
52
52
  await this.redis.setex(stateKey, this.DEFAULT_TTL, serializedState);
53
53
 
54
- // 更新元数据
54
+ // Update metadata
55
55
  await this.updateOperationMetadata(operationId, {
56
56
  lastActiveAt: new Date().toISOString(),
57
57
  status: state.status,
@@ -59,7 +59,7 @@ export class AgentStateManager {
59
59
  totalSteps: state.stepCount,
60
60
  });
61
61
 
62
- // 状态变更事件通过 saveStepResult 中的 events 数组记录
62
+ // State change events are recorded through the events array in saveStepResult
63
63
 
64
64
  log('[%s] Saved state for step %d', operationId, state.stepCount);
65
65
  } catch (error) {
@@ -69,7 +69,7 @@ export class AgentStateManager {
69
69
  }
70
70
 
71
71
  /**
72
- * 加载 Agent 状态
72
+ * Load Agent state
73
73
  */
74
74
  async loadAgentState(operationId: string): Promise<AgentState | null> {
75
75
  const stateKey = `${this.STATE_PREFIX}:${operationId}`;
@@ -92,17 +92,17 @@ export class AgentStateManager {
92
92
  }
93
93
 
94
94
  /**
95
- * 保存步骤执行结果
95
+ * Save step execution result
96
96
  */
97
97
  async saveStepResult(operationId: string, stepResult: StepResult): Promise<void> {
98
98
  const pipeline = this.redis.multi();
99
99
 
100
100
  try {
101
- // 保存最新状态
101
+ // Save latest state
102
102
  const stateKey = `${this.STATE_PREFIX}:${operationId}`;
103
103
  pipeline.setex(stateKey, this.DEFAULT_TTL, JSON.stringify(stepResult.newState));
104
104
 
105
- // 保存步骤历史
105
+ // Save step history
106
106
  const stepsKey = `${this.STEPS_PREFIX}:${operationId}`;
107
107
  const stepData = {
108
108
  context: stepResult.nextContext,
@@ -114,19 +114,19 @@ export class AgentStateManager {
114
114
  };
115
115
 
116
116
  pipeline.lpush(stepsKey, JSON.stringify(stepData));
117
- pipeline.ltrim(stepsKey, 0, 199); // 保留最近 200
117
+ pipeline.ltrim(stepsKey, 0, 199); // Keep most recent 200 steps
118
118
  pipeline.expire(stepsKey, this.DEFAULT_TTL);
119
119
 
120
- // 保存步骤的事件序列到 agent_runtime_events
120
+ // Save step event sequence to agent_runtime_events
121
121
  if (stepResult.events && stepResult.events.length > 0) {
122
122
  const eventsKey = `${this.EVENTS_PREFIX}:${operationId}`;
123
123
 
124
124
  pipeline.lpush(eventsKey, JSON.stringify(stepResult.events));
125
- pipeline.ltrim(eventsKey, 0, 199); // 保留最近 200 步的事件
125
+ pipeline.ltrim(eventsKey, 0, 199); // Keep events from most recent 200 steps
126
126
  pipeline.expire(eventsKey, this.DEFAULT_TTL);
127
127
  }
128
128
 
129
- // 更新操作元数据
129
+ // Update operation metadata
130
130
  const metaKey = `${this.METADATA_PREFIX}:${operationId}`;
131
131
  const metadata: Partial<AgentOperationMetadata> = {
132
132
  lastActiveAt: new Date().toISOString(),
@@ -152,14 +152,14 @@ export class AgentStateManager {
152
152
  }
153
153
 
154
154
  /**
155
- * 获取执行历史
155
+ * Get execution history
156
156
  */
157
157
  async getExecutionHistory(operationId: string, limit: number = 50): Promise<any[]> {
158
158
  const stepsKey = `${this.STEPS_PREFIX}:${operationId}`;
159
159
 
160
160
  try {
161
161
  const history = await this.redis.lrange(stepsKey, 0, limit - 1);
162
- return history.map((item) => JSON.parse(item)).reverse(); // 最早的在前面
162
+ return history.map((item) => JSON.parse(item)).reverse(); // Earliest first
163
163
  } catch (error) {
164
164
  console.error('Failed to get execution history:', error);
165
165
  return [];
@@ -167,7 +167,7 @@ export class AgentStateManager {
167
167
  }
168
168
 
169
169
  /**
170
- * 获取操作元数据
170
+ * Get operation metadata
171
171
  */
172
172
  async getOperationMetadata(operationId: string): Promise<AgentOperationMetadata | null> {
173
173
  const metaKey = `${this.METADATA_PREFIX}:${operationId}`;
@@ -198,7 +198,7 @@ export class AgentStateManager {
198
198
  }
199
199
 
200
200
  /**
201
- * 创建新的操作元数据
201
+ * Create new operation metadata
202
202
  */
203
203
  async createOperationMetadata(
204
204
  operationId: string,
@@ -222,7 +222,7 @@ export class AgentStateManager {
222
222
  userId: data.userId,
223
223
  };
224
224
 
225
- // 序列化复杂对象
225
+ // Serialize complex objects
226
226
  const redisData: Record<string, string> = {
227
227
  createdAt: metadata.createdAt,
228
228
  lastActiveAt: metadata.lastActiveAt,
@@ -247,7 +247,7 @@ export class AgentStateManager {
247
247
  }
248
248
 
249
249
  /**
250
- * 更新操作元数据
250
+ * Update operation metadata
251
251
  */
252
252
  private async updateOperationMetadata(
253
253
  operationId: string,
@@ -278,7 +278,7 @@ export class AgentStateManager {
278
278
  }
279
279
 
280
280
  /**
281
- * 删除 Agent 操作的所有数据
281
+ * Delete all data for Agent operation
282
282
  */
283
283
  async deleteAgentOperation(operationId: string): Promise<void> {
284
284
  const keys = [
@@ -298,7 +298,7 @@ export class AgentStateManager {
298
298
  }
299
299
 
300
300
  /**
301
- * 获取所有活跃操作
301
+ * Get all active operations
302
302
  */
303
303
  async getActiveOperations(): Promise<string[]> {
304
304
  try {
@@ -312,7 +312,7 @@ export class AgentStateManager {
312
312
  }
313
313
 
314
314
  /**
315
- * 清理过期的操作数据
315
+ * Clean up expired operation data
316
316
  */
317
317
  async cleanupExpiredOperations(): Promise<number> {
318
318
  try {
@@ -327,7 +327,7 @@ export class AgentStateManager {
327
327
  const now = Date.now();
328
328
  const hoursSinceActive = (now - lastActiveTime) / (1000 * 60 * 60);
329
329
 
330
- // 清理超过 2 小时未活跃的操作
330
+ // Clean up operations inactive for more than 2 hours
331
331
  if (hoursSinceActive > 2) {
332
332
  await this.deleteAgentOperation(operationId);
333
333
  cleanedCount++;
@@ -344,7 +344,7 @@ export class AgentStateManager {
344
344
  }
345
345
 
346
346
  /**
347
- * 获取统计信息
347
+ * Get statistics
348
348
  */
349
349
  async getStats(): Promise<{
350
350
  activeOperations: number;
@@ -397,7 +397,7 @@ export class AgentStateManager {
397
397
  }
398
398
 
399
399
  /**
400
- * 关闭 Redis 连接
400
+ * Close Redis connection
401
401
  */
402
402
  async disconnect(): Promise<void> {
403
403
  await this.redis.quit();
@@ -8,7 +8,7 @@ const log = debug('lobe-server:agent-runtime:in-memory-state-manager');
8
8
 
9
9
  /**
10
10
  * In-Memory Agent State Manager
11
- * 内存实现,用于测试和本地开发环境
11
+ * In-memory implementation for testing and local development environments
12
12
  */
13
13
  export class InMemoryAgentStateManager implements IAgentStateManager {
14
14
  private states: Map<string, AgentState> = new Map();
@@ -17,10 +17,10 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
17
17
  private events: Map<string, any[][]> = new Map();
18
18
 
19
19
  async saveAgentState(operationId: string, state: AgentState): Promise<void> {
20
- // 深拷贝以避免引用问题
20
+ // Deep clone to avoid reference issues
21
21
  this.states.set(operationId, structuredClone(state));
22
22
 
23
- // 更新元数据
23
+ // Update metadata
24
24
  const existingMeta = this.metadata.get(operationId);
25
25
  if (existingMeta) {
26
26
  existingMeta.lastActiveAt = new Date().toISOString();
@@ -39,15 +39,15 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
39
39
  }
40
40
 
41
41
  log('[%s] Loaded state (step %d)', operationId, state.stepCount);
42
- // 返回深拷贝以避免外部修改影响内部状态
42
+ // Return deep clone to prevent external modifications from affecting internal state
43
43
  return structuredClone(state);
44
44
  }
45
45
 
46
46
  async saveStepResult(operationId: string, stepResult: StepResult): Promise<void> {
47
- // 保存最新状态
47
+ // Save latest state
48
48
  this.states.set(operationId, structuredClone(stepResult.newState));
49
49
 
50
- // 保存步骤历史
50
+ // Save step history
51
51
  let stepHistory = this.steps.get(operationId);
52
52
  if (!stepHistory) {
53
53
  stepHistory = [];
@@ -63,14 +63,14 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
63
63
  timestamp: Date.now(),
64
64
  };
65
65
 
66
- // 在开头插入(最新的在前面)
66
+ // Insert at beginning (newest first)
67
67
  stepHistory.unshift(stepData);
68
- // 保留最近 200
68
+ // Keep most recent 200 steps
69
69
  if (stepHistory.length > 200) {
70
70
  stepHistory.length = 200;
71
71
  }
72
72
 
73
- // 保存步骤的事件序列
73
+ // Save step event sequence
74
74
  if (stepResult.events && stepResult.events.length > 0) {
75
75
  let eventHistory = this.events.get(operationId);
76
76
  if (!eventHistory) {
@@ -83,7 +83,7 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
83
83
  }
84
84
  }
85
85
 
86
- // 更新操作元数据
86
+ // Update operation metadata
87
87
  const existingMeta = this.metadata.get(operationId);
88
88
  if (existingMeta) {
89
89
  existingMeta.lastActiveAt = new Date().toISOString();
@@ -106,7 +106,7 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
106
106
  return [];
107
107
  }
108
108
 
109
- // 返回反转后的数组(最早的在前面)
109
+ // Return reversed array (earliest first)
110
110
  return history.slice(0, limit).reverse();
111
111
  }
112
112
 
@@ -161,7 +161,7 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
161
161
  const now = Date.now();
162
162
  const hoursSinceActive = (now - lastActiveTime) / (1000 * 60 * 60);
163
163
 
164
- // 清理超过 1 小时未活跃的操作
164
+ // Clean up operations inactive for more than 1 hour
165
165
  if (hoursSinceActive > 1) {
166
166
  await this.deleteAgentOperation(operationId);
167
167
  cleanedCount++;
@@ -214,12 +214,12 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
214
214
  }
215
215
 
216
216
  async disconnect(): Promise<void> {
217
- // 内存实现无需断开连接
217
+ // In-memory implementation doesn't need to disconnect
218
218
  log('InMemoryAgentStateManager disconnected');
219
219
  }
220
220
 
221
221
  /**
222
- * 清空所有数据(用于测试)
222
+ * Clear all data (for testing)
223
223
  */
224
224
  clear(): void {
225
225
  this.states.clear();
@@ -230,7 +230,7 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
230
230
  }
231
231
 
232
232
  /**
233
- * 获取事件历史(用于测试验证)
233
+ * Get event history (for test verification)
234
234
  */
235
235
  getEventHistory(operationId: string): any[][] {
236
236
  return this.events.get(operationId) ?? [];
@@ -238,6 +238,6 @@ export class InMemoryAgentStateManager implements IAgentStateManager {
238
238
  }
239
239
 
240
240
  /**
241
- * 单例实例,用于测试和本地开发环境
241
+ * Singleton instance for testing and local development environments
242
242
  */
243
243
  export const inMemoryAgentStateManager = new InMemoryAgentStateManager();
@@ -9,7 +9,7 @@ type EventCallback = (events: StreamEvent[]) => void;
9
9
 
10
10
  /**
11
11
  * In-Memory Stream Event Manager
12
- * 内存实现,用于测试和本地开发环境
12
+ * In-memory implementation for testing and local development environments
13
13
  */
14
14
  export class InMemoryStreamEventManager implements IStreamEventManager {
15
15
  private streams: Map<string, StreamEvent[]> = new Map();
@@ -34,7 +34,7 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
34
34
  timestamp: Date.now(),
35
35
  };
36
36
 
37
- // 获取或创建 stream
37
+ // Get or create stream
38
38
  let stream = this.streams.get(operationId);
39
39
  if (!stream) {
40
40
  stream = [];
@@ -43,14 +43,14 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
43
43
 
44
44
  stream.push(eventData);
45
45
 
46
- // 限制流长度,防止内存溢出
46
+ // Limit stream length to prevent memory overflow
47
47
  if (stream.length > 1000) {
48
48
  stream.shift();
49
49
  }
50
50
 
51
51
  log('Published event %s for operation %s:%d', eventData.type, operationId, eventData.stepIndex);
52
52
 
53
- // 通知订阅者
53
+ // Notify subscribers
54
54
  const callbacks = this.subscribers.get(operationId);
55
55
  if (callbacks) {
56
56
  for (const callback of callbacks) {
@@ -111,7 +111,7 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
111
111
  return [];
112
112
  }
113
113
 
114
- // 返回最近的 count 条事件(倒序)
114
+ // Return most recent count events (in reverse order)
115
115
  return stream.slice(-count).reverse();
116
116
  }
117
117
 
@@ -126,12 +126,12 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
126
126
  }
127
127
 
128
128
  async disconnect(): Promise<void> {
129
- // 内存实现无需断开连接
129
+ // In-memory implementation doesn't need to disconnect
130
130
  log('InMemoryStreamEventManager disconnected');
131
131
  }
132
132
 
133
133
  /**
134
- * 订阅流式事件(用于测试)
134
+ * Subscribe to stream events (for testing)
135
135
  */
136
136
  subscribe(operationId: string, callback: EventCallback): () => void {
137
137
  let callbacks = this.subscribers.get(operationId);
@@ -141,7 +141,7 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
141
141
  }
142
142
  callbacks.push(callback);
143
143
 
144
- // 返回取消订阅函数
144
+ // Return unsubscribe function
145
145
  return () => {
146
146
  const cbs = this.subscribers.get(operationId);
147
147
  if (cbs) {
@@ -154,7 +154,7 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
154
154
  }
155
155
 
156
156
  /**
157
- * 清空所有数据(用于测试)
157
+ * Clear all data (for testing)
158
158
  */
159
159
  clear(): void {
160
160
  this.streams.clear();
@@ -164,14 +164,14 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
164
164
  }
165
165
 
166
166
  /**
167
- * 获取所有事件(用于测试验证)
167
+ * Get all events (for test verification)
168
168
  */
169
169
  getAllEvents(operationId: string): StreamEvent[] {
170
170
  return this.streams.get(operationId) ?? [];
171
171
  }
172
172
 
173
173
  /**
174
- * 等待特定类型的事件(用于测试)
174
+ * Wait for a specific event type (for testing)
175
175
  */
176
176
  waitForEvent(
177
177
  operationId: string,
@@ -196,7 +196,7 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
196
196
  }
197
197
  });
198
198
 
199
- // 检查已有事件
199
+ // Check existing events
200
200
  const existingEvents = this.streams.get(operationId) ?? [];
201
201
  for (const event of existingEvents) {
202
202
  if (event.type === eventType) {
@@ -211,6 +211,6 @@ export class InMemoryStreamEventManager implements IStreamEventManager {
211
211
  }
212
212
 
213
213
  /**
214
- * 单例实例,用于测试和本地开发环境
214
+ * Singleton instance for testing and local development environments
215
215
  */
216
216
  export const inMemoryStreamEventManager = new InMemoryStreamEventManager();
@@ -43,8 +43,8 @@ export const createRuntimeExecutors = (
43
43
  ctx: RuntimeExecutorContext,
44
44
  ): Partial<Record<AgentInstruction['type'], InstructionExecutor>> => ({
45
45
  /**
46
- * 创建流式 LLM 执行器
47
- * 集成 Agent Runtime 和流式事件发布
46
+ * Create streaming LLM executor
47
+ * Integrates Agent Runtime and stream event publishing
48
48
  */
49
49
  call_llm: async (instruction, state) => {
50
50
  const { payload } = instruction as Extract<AgentInstruction, { type: 'call_llm' }>;