@lobehub/lobehub 2.0.0-next.50 → 2.0.0-next.51

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 (118) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/apps/desktop/src/main/controllers/ShellCommandCtr.ts +242 -0
  3. package/apps/desktop/src/main/controllers/__tests__/ShellCommandCtr.test.ts +499 -0
  4. package/changelog/v1.json +9 -0
  5. package/locales/ar/chat.json +20 -0
  6. package/locales/ar/common.json +1 -0
  7. package/locales/ar/components.json +6 -0
  8. package/locales/ar/plugin.json +1 -0
  9. package/locales/bg-BG/chat.json +20 -0
  10. package/locales/bg-BG/common.json +1 -0
  11. package/locales/bg-BG/components.json +6 -0
  12. package/locales/bg-BG/plugin.json +1 -0
  13. package/locales/de-DE/chat.json +20 -0
  14. package/locales/de-DE/common.json +1 -0
  15. package/locales/de-DE/components.json +6 -0
  16. package/locales/de-DE/plugin.json +1 -0
  17. package/locales/en-US/chat.json +20 -0
  18. package/locales/en-US/common.json +1 -0
  19. package/locales/en-US/components.json +6 -0
  20. package/locales/en-US/plugin.json +1 -0
  21. package/locales/es-ES/chat.json +20 -0
  22. package/locales/es-ES/common.json +1 -0
  23. package/locales/es-ES/components.json +6 -0
  24. package/locales/es-ES/plugin.json +1 -0
  25. package/locales/fa-IR/chat.json +20 -0
  26. package/locales/fa-IR/common.json +1 -0
  27. package/locales/fa-IR/components.json +6 -0
  28. package/locales/fa-IR/plugin.json +1 -0
  29. package/locales/fr-FR/chat.json +20 -0
  30. package/locales/fr-FR/common.json +1 -0
  31. package/locales/fr-FR/components.json +6 -0
  32. package/locales/fr-FR/plugin.json +1 -0
  33. package/locales/it-IT/chat.json +20 -0
  34. package/locales/it-IT/common.json +1 -0
  35. package/locales/it-IT/components.json +6 -0
  36. package/locales/it-IT/plugin.json +1 -0
  37. package/locales/ja-JP/chat.json +20 -0
  38. package/locales/ja-JP/common.json +1 -0
  39. package/locales/ja-JP/components.json +6 -0
  40. package/locales/ja-JP/plugin.json +1 -0
  41. package/locales/ko-KR/chat.json +20 -0
  42. package/locales/ko-KR/common.json +1 -0
  43. package/locales/ko-KR/components.json +6 -0
  44. package/locales/ko-KR/plugin.json +1 -0
  45. package/locales/nl-NL/chat.json +20 -0
  46. package/locales/nl-NL/common.json +1 -0
  47. package/locales/nl-NL/components.json +6 -0
  48. package/locales/nl-NL/plugin.json +1 -0
  49. package/locales/pl-PL/chat.json +20 -0
  50. package/locales/pl-PL/common.json +1 -0
  51. package/locales/pl-PL/components.json +6 -0
  52. package/locales/pl-PL/plugin.json +1 -0
  53. package/locales/pt-BR/chat.json +20 -0
  54. package/locales/pt-BR/common.json +1 -0
  55. package/locales/pt-BR/components.json +6 -0
  56. package/locales/pt-BR/plugin.json +1 -0
  57. package/locales/ru-RU/chat.json +20 -0
  58. package/locales/ru-RU/common.json +1 -0
  59. package/locales/ru-RU/components.json +6 -0
  60. package/locales/ru-RU/plugin.json +1 -0
  61. package/locales/tr-TR/chat.json +20 -0
  62. package/locales/tr-TR/common.json +1 -0
  63. package/locales/tr-TR/components.json +6 -0
  64. package/locales/tr-TR/plugin.json +1 -0
  65. package/locales/vi-VN/chat.json +20 -0
  66. package/locales/vi-VN/common.json +1 -0
  67. package/locales/vi-VN/components.json +6 -0
  68. package/locales/vi-VN/plugin.json +1 -0
  69. package/locales/zh-CN/chat.json +20 -0
  70. package/locales/zh-CN/common.json +1 -0
  71. package/locales/zh-CN/components.json +6 -0
  72. package/locales/zh-CN/plugin.json +1 -0
  73. package/locales/zh-TW/chat.json +20 -0
  74. package/locales/zh-TW/common.json +1 -0
  75. package/locales/zh-TW/components.json +6 -0
  76. package/locales/zh-TW/plugin.json +1 -0
  77. package/package.json +1 -1
  78. package/packages/agent-runtime/src/core/InterventionChecker.ts +1 -1
  79. package/packages/agent-runtime/src/core/__tests__/InterventionChecker.test.ts +23 -23
  80. package/packages/agent-runtime/src/types/state.ts +7 -1
  81. package/packages/const/src/settings/tool.ts +1 -5
  82. package/packages/file-loaders/src/loaders/docx/index.ts +1 -1
  83. package/packages/model-bank/src/aiModels/wenxin.ts +1348 -291
  84. package/packages/model-runtime/src/providers/wenxin/index.ts +22 -1
  85. package/packages/model-runtime/src/utils/modelParse.ts +6 -0
  86. package/packages/types/src/tool/builtin.ts +9 -0
  87. package/packages/types/src/tool/intervention.ts +32 -2
  88. package/packages/types/src/user/settings/tool.ts +3 -27
  89. package/src/config/modelProviders/wenxin.ts +2 -3
  90. package/src/features/Conversation/MarkdownElements/remarkPlugins/__snapshots__/createRemarkSelfClosingTagPlugin.test.ts.snap +133 -0
  91. package/src/features/Conversation/MarkdownElements/remarkPlugins/createRemarkSelfClosingTagPlugin.test.ts +48 -0
  92. package/src/features/Conversation/MarkdownElements/remarkPlugins/createRemarkSelfClosingTagPlugin.ts +2 -1
  93. package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/Fallback.tsx +98 -0
  94. package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/ModeSelector.tsx +5 -6
  95. package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/index.tsx +40 -36
  96. package/src/features/Conversation/Messages/Group/Tool/Render/index.tsx +25 -18
  97. package/src/features/LocalFile/LocalFile.tsx +55 -5
  98. package/src/locales/default/components.ts +6 -0
  99. package/src/locales/default/plugin.ts +1 -0
  100. package/src/services/electron/localFileService.ts +4 -0
  101. package/src/store/chat/agents/GeneralChatAgent.ts +26 -1
  102. package/src/store/chat/agents/__tests__/GeneralChatAgent.test.ts +173 -0
  103. package/src/store/chat/slices/aiChat/actions/conversationControl.ts +8 -40
  104. package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +91 -34
  105. package/src/store/user/selectors.ts +1 -0
  106. package/src/store/user/slices/settings/action.ts +12 -0
  107. package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +0 -7
  108. package/src/store/user/slices/settings/selectors/index.ts +1 -0
  109. package/src/store/user/slices/settings/selectors/settings.test.ts +0 -37
  110. package/src/store/user/slices/settings/selectors/settings.ts +0 -5
  111. package/src/store/user/slices/settings/selectors/toolIntervention.ts +17 -0
  112. package/src/tools/interventions.ts +8 -0
  113. package/src/tools/local-system/Intervention/RunCommand/index.tsx +56 -0
  114. package/src/tools/local-system/Intervention/index.tsx +17 -0
  115. package/src/tools/local-system/Render/RunCommand/index.tsx +100 -21
  116. package/src/tools/local-system/Render/index.tsx +2 -0
  117. package/src/tools/local-system/index.ts +180 -0
  118. package/src/tools/local-system/systemRole.ts +61 -7
package/CHANGELOG.md CHANGED
@@ -2,6 +2,31 @@
2
2
 
3
3
  # Changelog
4
4
 
5
+ ## [Version 2.0.0-next.51](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.50...v2.0.0-next.51)
6
+
7
+ <sup>Released on **2025-11-13**</sup>
8
+
9
+ #### 💄 Styles
10
+
11
+ - **misc**: Update ERNIE-5.0-Thinking-Preview model.
12
+
13
+ <br/>
14
+
15
+ <details>
16
+ <summary><kbd>Improvements and Fixes</kbd></summary>
17
+
18
+ #### Styles
19
+
20
+ - **misc**: Update ERNIE-5.0-Thinking-Preview model, closes [#10196](https://github.com/lobehub/lobe-chat/issues/10196) ([89f3eed](https://github.com/lobehub/lobe-chat/commit/89f3eed))
21
+
22
+ </details>
23
+
24
+ <div align="right">
25
+
26
+ [![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
27
+
28
+ </div>
29
+
5
30
  ## [Version 2.0.0-next.50](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.49...v2.0.0-next.50)
6
31
 
7
32
  <sup>Released on **2025-11-13**</sup>
@@ -0,0 +1,242 @@
1
+ import {
2
+ GetCommandOutputParams,
3
+ GetCommandOutputResult,
4
+ KillCommandParams,
5
+ KillCommandResult,
6
+ RunCommandParams,
7
+ RunCommandResult,
8
+ } from '@lobechat/electron-client-ipc';
9
+ import { ChildProcess, spawn } from 'node:child_process';
10
+ import { randomUUID } from 'node:crypto';
11
+
12
+ import { createLogger } from '@/utils/logger';
13
+
14
+ import { ControllerModule, ipcClientEvent } from './index';
15
+
16
+ const logger = createLogger('controllers:ShellCommandCtr');
17
+
18
+ interface ShellProcess {
19
+ lastReadStderr: number;
20
+ lastReadStdout: number;
21
+ process: ChildProcess;
22
+ stderr: string[];
23
+ stdout: string[];
24
+ }
25
+
26
+ export default class ShellCommandCtr extends ControllerModule {
27
+ // Shell process management
28
+ private shellProcesses = new Map<string, ShellProcess>();
29
+
30
+ @ipcClientEvent('runCommand')
31
+ async handleRunCommand({
32
+ command,
33
+ description,
34
+ run_in_background,
35
+ timeout = 120_000,
36
+ }: RunCommandParams): Promise<RunCommandResult> {
37
+ const logPrefix = `[runCommand: ${description || command.slice(0, 50)}]`;
38
+ logger.debug(`${logPrefix} Starting command execution`, {
39
+ background: run_in_background,
40
+ timeout,
41
+ });
42
+
43
+ // Validate timeout
44
+ const effectiveTimeout = Math.min(Math.max(timeout, 1000), 600_000);
45
+
46
+ // Cross-platform shell selection
47
+ const shellConfig =
48
+ process.platform === 'win32'
49
+ ? { args: ['/c', command], cmd: 'cmd.exe' }
50
+ : { args: ['-c', command], cmd: '/bin/sh' };
51
+
52
+ try {
53
+ if (run_in_background) {
54
+ // Background execution
55
+ const shellId = randomUUID();
56
+ const childProcess = spawn(shellConfig.cmd, shellConfig.args, {
57
+ env: process.env,
58
+ shell: false,
59
+ });
60
+
61
+ const shellProcess: ShellProcess = {
62
+ lastReadStderr: 0,
63
+ lastReadStdout: 0,
64
+ process: childProcess,
65
+ stderr: [],
66
+ stdout: [],
67
+ };
68
+
69
+ // Capture output
70
+ childProcess.stdout?.on('data', (data) => {
71
+ shellProcess.stdout.push(data.toString());
72
+ });
73
+
74
+ childProcess.stderr?.on('data', (data) => {
75
+ shellProcess.stderr.push(data.toString());
76
+ });
77
+
78
+ childProcess.on('exit', (code) => {
79
+ logger.debug(`${logPrefix} Background process exited`, { code, shellId });
80
+ });
81
+
82
+ this.shellProcesses.set(shellId, shellProcess);
83
+
84
+ logger.info(`${logPrefix} Started background execution`, { shellId });
85
+ return {
86
+ shell_id: shellId,
87
+ success: true,
88
+ };
89
+ } else {
90
+ // Synchronous execution with timeout
91
+ return new Promise((resolve) => {
92
+ const childProcess = spawn(shellConfig.cmd, shellConfig.args, {
93
+ env: process.env,
94
+ shell: false,
95
+ });
96
+
97
+ let stdout = '';
98
+ let stderr = '';
99
+ let killed = false;
100
+
101
+ const timeoutHandle = setTimeout(() => {
102
+ killed = true;
103
+ childProcess.kill();
104
+ resolve({
105
+ error: `Command timed out after ${effectiveTimeout}ms`,
106
+ stderr,
107
+ stdout,
108
+ success: false,
109
+ });
110
+ }, effectiveTimeout);
111
+
112
+ childProcess.stdout?.on('data', (data) => {
113
+ stdout += data.toString();
114
+ });
115
+
116
+ childProcess.stderr?.on('data', (data) => {
117
+ stderr += data.toString();
118
+ });
119
+
120
+ childProcess.on('exit', (code) => {
121
+ if (!killed) {
122
+ clearTimeout(timeoutHandle);
123
+ const success = code === 0;
124
+ logger.info(`${logPrefix} Command completed`, { code, success });
125
+ resolve({
126
+ exit_code: code || 0,
127
+ output: stdout + stderr,
128
+ stderr,
129
+ stdout,
130
+ success,
131
+ });
132
+ }
133
+ });
134
+
135
+ childProcess.on('error', (error) => {
136
+ clearTimeout(timeoutHandle);
137
+ logger.error(`${logPrefix} Command failed:`, error);
138
+ resolve({
139
+ error: error.message,
140
+ stderr,
141
+ stdout,
142
+ success: false,
143
+ });
144
+ });
145
+ });
146
+ }
147
+ } catch (error) {
148
+ logger.error(`${logPrefix} Failed to execute command:`, error);
149
+ return {
150
+ error: (error as Error).message,
151
+ success: false,
152
+ };
153
+ }
154
+ }
155
+
156
+ @ipcClientEvent('getCommandOutput')
157
+ async handleGetCommandOutput({
158
+ filter,
159
+ shell_id,
160
+ }: GetCommandOutputParams): Promise<GetCommandOutputResult> {
161
+ const logPrefix = `[getCommandOutput: ${shell_id}]`;
162
+ logger.debug(`${logPrefix} Retrieving output`);
163
+
164
+ const shellProcess = this.shellProcesses.get(shell_id);
165
+ if (!shellProcess) {
166
+ logger.error(`${logPrefix} Shell process not found`);
167
+ return {
168
+ error: `Shell ID ${shell_id} not found`,
169
+ output: '',
170
+ running: false,
171
+ stderr: '',
172
+ stdout: '',
173
+ success: false,
174
+ };
175
+ }
176
+
177
+ const { lastReadStderr, lastReadStdout, process: childProcess, stderr, stdout } = shellProcess;
178
+
179
+ // Get new output since last read
180
+ const newStdout = stdout.slice(lastReadStdout).join('');
181
+ const newStderr = stderr.slice(lastReadStderr).join('');
182
+ let output = newStdout + newStderr;
183
+
184
+ // Apply filter if provided
185
+ if (filter) {
186
+ try {
187
+ const regex = new RegExp(filter, 'gm');
188
+ const lines = output.split('\n');
189
+ output = lines.filter((line) => regex.test(line)).join('\n');
190
+ } catch (error) {
191
+ logger.error(`${logPrefix} Invalid filter regex:`, error);
192
+ }
193
+ }
194
+
195
+ // Update last read positions separately
196
+ shellProcess.lastReadStdout = stdout.length;
197
+ shellProcess.lastReadStderr = stderr.length;
198
+
199
+ const running = childProcess.exitCode === null;
200
+
201
+ logger.debug(`${logPrefix} Output retrieved`, {
202
+ outputLength: output.length,
203
+ running,
204
+ });
205
+
206
+ return {
207
+ output,
208
+ running,
209
+ stderr: newStderr,
210
+ stdout: newStdout,
211
+ success: true,
212
+ };
213
+ }
214
+
215
+ @ipcClientEvent('killCommand')
216
+ async handleKillCommand({ shell_id }: KillCommandParams): Promise<KillCommandResult> {
217
+ const logPrefix = `[killCommand: ${shell_id}]`;
218
+ logger.debug(`${logPrefix} Attempting to kill shell`);
219
+
220
+ const shellProcess = this.shellProcesses.get(shell_id);
221
+ if (!shellProcess) {
222
+ logger.error(`${logPrefix} Shell process not found`);
223
+ return {
224
+ error: `Shell ID ${shell_id} not found`,
225
+ success: false,
226
+ };
227
+ }
228
+
229
+ try {
230
+ shellProcess.process.kill();
231
+ this.shellProcesses.delete(shell_id);
232
+ logger.info(`${logPrefix} Shell killed successfully`);
233
+ return { success: true };
234
+ } catch (error) {
235
+ logger.error(`${logPrefix} Failed to kill shell:`, error);
236
+ return {
237
+ error: (error as Error).message,
238
+ success: false,
239
+ };
240
+ }
241
+ }
242
+ }