@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.
- package/CHANGELOG.md +25 -0
- package/apps/desktop/src/main/controllers/ShellCommandCtr.ts +242 -0
- package/apps/desktop/src/main/controllers/__tests__/ShellCommandCtr.test.ts +499 -0
- package/changelog/v1.json +9 -0
- package/locales/ar/chat.json +20 -0
- package/locales/ar/common.json +1 -0
- package/locales/ar/components.json +6 -0
- package/locales/ar/plugin.json +1 -0
- package/locales/bg-BG/chat.json +20 -0
- package/locales/bg-BG/common.json +1 -0
- package/locales/bg-BG/components.json +6 -0
- package/locales/bg-BG/plugin.json +1 -0
- package/locales/de-DE/chat.json +20 -0
- package/locales/de-DE/common.json +1 -0
- package/locales/de-DE/components.json +6 -0
- package/locales/de-DE/plugin.json +1 -0
- package/locales/en-US/chat.json +20 -0
- package/locales/en-US/common.json +1 -0
- package/locales/en-US/components.json +6 -0
- package/locales/en-US/plugin.json +1 -0
- package/locales/es-ES/chat.json +20 -0
- package/locales/es-ES/common.json +1 -0
- package/locales/es-ES/components.json +6 -0
- package/locales/es-ES/plugin.json +1 -0
- package/locales/fa-IR/chat.json +20 -0
- package/locales/fa-IR/common.json +1 -0
- package/locales/fa-IR/components.json +6 -0
- package/locales/fa-IR/plugin.json +1 -0
- package/locales/fr-FR/chat.json +20 -0
- package/locales/fr-FR/common.json +1 -0
- package/locales/fr-FR/components.json +6 -0
- package/locales/fr-FR/plugin.json +1 -0
- package/locales/it-IT/chat.json +20 -0
- package/locales/it-IT/common.json +1 -0
- package/locales/it-IT/components.json +6 -0
- package/locales/it-IT/plugin.json +1 -0
- package/locales/ja-JP/chat.json +20 -0
- package/locales/ja-JP/common.json +1 -0
- package/locales/ja-JP/components.json +6 -0
- package/locales/ja-JP/plugin.json +1 -0
- package/locales/ko-KR/chat.json +20 -0
- package/locales/ko-KR/common.json +1 -0
- package/locales/ko-KR/components.json +6 -0
- package/locales/ko-KR/plugin.json +1 -0
- package/locales/nl-NL/chat.json +20 -0
- package/locales/nl-NL/common.json +1 -0
- package/locales/nl-NL/components.json +6 -0
- package/locales/nl-NL/plugin.json +1 -0
- package/locales/pl-PL/chat.json +20 -0
- package/locales/pl-PL/common.json +1 -0
- package/locales/pl-PL/components.json +6 -0
- package/locales/pl-PL/plugin.json +1 -0
- package/locales/pt-BR/chat.json +20 -0
- package/locales/pt-BR/common.json +1 -0
- package/locales/pt-BR/components.json +6 -0
- package/locales/pt-BR/plugin.json +1 -0
- package/locales/ru-RU/chat.json +20 -0
- package/locales/ru-RU/common.json +1 -0
- package/locales/ru-RU/components.json +6 -0
- package/locales/ru-RU/plugin.json +1 -0
- package/locales/tr-TR/chat.json +20 -0
- package/locales/tr-TR/common.json +1 -0
- package/locales/tr-TR/components.json +6 -0
- package/locales/tr-TR/plugin.json +1 -0
- package/locales/vi-VN/chat.json +20 -0
- package/locales/vi-VN/common.json +1 -0
- package/locales/vi-VN/components.json +6 -0
- package/locales/vi-VN/plugin.json +1 -0
- package/locales/zh-CN/chat.json +20 -0
- package/locales/zh-CN/common.json +1 -0
- package/locales/zh-CN/components.json +6 -0
- package/locales/zh-CN/plugin.json +1 -0
- package/locales/zh-TW/chat.json +20 -0
- package/locales/zh-TW/common.json +1 -0
- package/locales/zh-TW/components.json +6 -0
- package/locales/zh-TW/plugin.json +1 -0
- package/package.json +1 -1
- package/packages/agent-runtime/src/core/InterventionChecker.ts +1 -1
- package/packages/agent-runtime/src/core/__tests__/InterventionChecker.test.ts +23 -23
- package/packages/agent-runtime/src/types/state.ts +7 -1
- package/packages/const/src/settings/tool.ts +1 -5
- package/packages/file-loaders/src/loaders/docx/index.ts +1 -1
- package/packages/model-bank/src/aiModels/wenxin.ts +1348 -291
- package/packages/model-runtime/src/providers/wenxin/index.ts +22 -1
- package/packages/model-runtime/src/utils/modelParse.ts +6 -0
- package/packages/types/src/tool/builtin.ts +9 -0
- package/packages/types/src/tool/intervention.ts +32 -2
- package/packages/types/src/user/settings/tool.ts +3 -27
- package/src/config/modelProviders/wenxin.ts +2 -3
- package/src/features/Conversation/MarkdownElements/remarkPlugins/__snapshots__/createRemarkSelfClosingTagPlugin.test.ts.snap +133 -0
- package/src/features/Conversation/MarkdownElements/remarkPlugins/createRemarkSelfClosingTagPlugin.test.ts +48 -0
- package/src/features/Conversation/MarkdownElements/remarkPlugins/createRemarkSelfClosingTagPlugin.ts +2 -1
- package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/Fallback.tsx +98 -0
- package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/ModeSelector.tsx +5 -6
- package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/index.tsx +40 -36
- package/src/features/Conversation/Messages/Group/Tool/Render/index.tsx +25 -18
- package/src/features/LocalFile/LocalFile.tsx +55 -5
- package/src/locales/default/components.ts +6 -0
- package/src/locales/default/plugin.ts +1 -0
- package/src/services/electron/localFileService.ts +4 -0
- package/src/store/chat/agents/GeneralChatAgent.ts +26 -1
- package/src/store/chat/agents/__tests__/GeneralChatAgent.test.ts +173 -0
- package/src/store/chat/slices/aiChat/actions/conversationControl.ts +8 -40
- package/src/store/chat/slices/aiChat/actions/streamingExecutor.ts +91 -34
- package/src/store/user/selectors.ts +1 -0
- package/src/store/user/slices/settings/action.ts +12 -0
- package/src/store/user/slices/settings/selectors/__snapshots__/settings.test.ts.snap +0 -7
- package/src/store/user/slices/settings/selectors/index.ts +1 -0
- package/src/store/user/slices/settings/selectors/settings.test.ts +0 -37
- package/src/store/user/slices/settings/selectors/settings.ts +0 -5
- package/src/store/user/slices/settings/selectors/toolIntervention.ts +17 -0
- package/src/tools/interventions.ts +8 -0
- package/src/tools/local-system/Intervention/RunCommand/index.tsx +56 -0
- package/src/tools/local-system/Intervention/index.tsx +17 -0
- package/src/tools/local-system/Render/RunCommand/index.tsx +100 -21
- package/src/tools/local-system/Render/index.tsx +2 -0
- package/src/tools/local-system/index.ts +180 -0
- 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
|
+
[](#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
|
+
}
|