@lobehub/lobehub 2.0.0-next.52 → 2.0.0-next.54
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 +58 -0
- package/README.md +8 -8
- package/README.zh-CN.md +8 -8
- package/apps/desktop/package.json +1 -1
- package/changelog/v1.json +21 -0
- package/package.json +2 -2
- package/packages/const/src/models.ts +2 -0
- package/packages/electron-server-ipc/src/ipcClient.ts +31 -31
- package/packages/electron-server-ipc/src/ipcServer.ts +15 -15
- package/packages/model-bank/src/aiModels/aihubmix.ts +106 -2
- package/packages/model-bank/src/aiModels/openai.ts +107 -3
- package/packages/model-bank/src/aiModels/qwen.ts +76 -7
- package/packages/model-bank/src/types/aiModel.ts +1 -0
- package/packages/types/src/agent/chatConfig.ts +9 -0
- package/src/app/[variants]/(main)/chat/components/WorkspaceLayout.tsx +32 -23
- package/src/features/ChatInput/ActionBar/Model/ControlsForm.tsx +12 -0
- package/src/features/ChatInput/ActionBar/Model/GPT51ReasoningEffortSlider.tsx +58 -0
- package/src/features/ChatItem/components/MessageContent.tsx +3 -1
- package/src/features/Conversation/Messages/Assistant/index.tsx +7 -1
- package/src/features/Conversation/Messages/Group/Tool/Render/Intervention/ApprovalActions.tsx +34 -13
- package/src/features/Conversation/Messages/User/index.tsx +11 -1
- package/src/libs/mcp/__tests__/__snapshots__/index.test.ts.snap +0 -6
- package/src/locales/default/chat.ts +2 -0
- package/src/locales/default/tool.ts +8 -0
- package/src/services/chat/index.ts +7 -0
- package/src/store/chat/slices/aiChat/actions/conversationControl.ts +42 -0
- package/src/store/chat/slices/builtinTool/actions/localSystem.ts +1 -1
- package/src/tools/interventions.ts +3 -5
- package/src/tools/local-system/Intervention/MoveLocalFiles/MoveFileItem.tsx +56 -0
- package/src/tools/local-system/Intervention/MoveLocalFiles/index.tsx +26 -0
- package/src/tools/local-system/Intervention/RunCommand/index.tsx +3 -5
- package/src/tools/local-system/Intervention/index.ts +11 -0
- package/src/tools/local-system/Render/MoveLocalFiles/MoveFileItem.tsx +56 -0
- package/src/tools/local-system/Render/MoveLocalFiles/index.tsx +26 -0
- package/src/tools/local-system/Render/ReadLocalFile/ReadFileView.tsx +2 -1
- package/src/tools/local-system/Render/index.ts +21 -0
- package/src/tools/local-system/index.ts +1 -0
- package/src/tools/renders.ts +6 -24
- package/src/tools/web-browsing/Render/index.ts +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,64 @@
|
|
|
2
2
|
|
|
3
3
|
# Changelog
|
|
4
4
|
|
|
5
|
+
## [Version 2.0.0-next.54](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.53...v2.0.0-next.54)
|
|
6
|
+
|
|
7
|
+
<sup>Released on **2025-11-14**</sup>
|
|
8
|
+
|
|
9
|
+
#### 💄 Styles
|
|
10
|
+
|
|
11
|
+
- **misc**: Refactor and support move locale file intervention.
|
|
12
|
+
|
|
13
|
+
<br/>
|
|
14
|
+
|
|
15
|
+
<details>
|
|
16
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
17
|
+
|
|
18
|
+
#### Styles
|
|
19
|
+
|
|
20
|
+
- **misc**: Refactor and support move locale file intervention, closes [#10213](https://github.com/lobehub/lobe-chat/issues/10213) ([63cac81](https://github.com/lobehub/lobe-chat/commit/63cac81))
|
|
21
|
+
|
|
22
|
+
</details>
|
|
23
|
+
|
|
24
|
+
<div align="right">
|
|
25
|
+
|
|
26
|
+
[](#readme-top)
|
|
27
|
+
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
## [Version 2.0.0-next.53](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.52...v2.0.0-next.53)
|
|
31
|
+
|
|
32
|
+
<sup>Released on **2025-11-14**</sup>
|
|
33
|
+
|
|
34
|
+
#### ✨ Features
|
|
35
|
+
|
|
36
|
+
- **misc**: Add GPT-5.1 models.
|
|
37
|
+
|
|
38
|
+
#### 💄 Styles
|
|
39
|
+
|
|
40
|
+
- **misc**: Fix approving render and improve Conversation style.
|
|
41
|
+
|
|
42
|
+
<br/>
|
|
43
|
+
|
|
44
|
+
<details>
|
|
45
|
+
<summary><kbd>Improvements and Fixes</kbd></summary>
|
|
46
|
+
|
|
47
|
+
#### What's improved
|
|
48
|
+
|
|
49
|
+
- **misc**: Add GPT-5.1 models, closes [#10206](https://github.com/lobehub/lobe-chat/issues/10206) ([afd3a47](https://github.com/lobehub/lobe-chat/commit/afd3a47))
|
|
50
|
+
|
|
51
|
+
#### Styles
|
|
52
|
+
|
|
53
|
+
- **misc**: Fix approving render and improve Conversation style, closes [#10210](https://github.com/lobehub/lobe-chat/issues/10210) ([841b7f1](https://github.com/lobehub/lobe-chat/commit/841b7f1))
|
|
54
|
+
|
|
55
|
+
</details>
|
|
56
|
+
|
|
57
|
+
<div align="right">
|
|
58
|
+
|
|
59
|
+
[](#readme-top)
|
|
60
|
+
|
|
61
|
+
</div>
|
|
62
|
+
|
|
5
63
|
## [Version 2.0.0-next.52](https://github.com/lobehub/lobe-chat/compare/v2.0.0-next.51...v2.0.0-next.52)
|
|
6
64
|
|
|
7
65
|
<sup>Released on **2025-11-13**</sup>
|
package/README.md
CHANGED
|
@@ -345,14 +345,14 @@ In addition, these plugins are not limited to news aggregation, but can also ext
|
|
|
345
345
|
|
|
346
346
|
<!-- PLUGIN LIST -->
|
|
347
347
|
|
|
348
|
-
| Recent Submits
|
|
349
|
-
|
|
|
350
|
-
| [
|
|
351
|
-
| [
|
|
352
|
-
| [
|
|
353
|
-
| [
|
|
354
|
-
|
|
355
|
-
> 📊 Total plugins: [<kbd>**
|
|
348
|
+
| Recent Submits | Description |
|
|
349
|
+
| -------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
|
350
|
+
| [SEO](https://lobechat.com/discover/plugin/SEO)<br/><sup>By **orrenprunckun** on **2025-11-14**</sup> | Enter any URL and keyword and get an On-Page SEO analysis & insights!<br/>`seo` |
|
|
351
|
+
| [Shopping tools](https://lobechat.com/discover/plugin/ShoppingTools)<br/><sup>By **shoppingtools** on **2025-10-27**</sup> | Search for products on eBay & AliExpress, find eBay events & coupons. Get prompt examples.<br/>`shopping` `e-bay` `ali-express` `coupons` |
|
|
352
|
+
| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-09-27**</sup> | Analyze stocks and get comprehensive real-time investment data and analytics.<br/>`stock` |
|
|
353
|
+
| [Web](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | Smart web search that reads and analyzes pages to deliver comprehensive answers from Google results.<br/>`web` `search` |
|
|
354
|
+
|
|
355
|
+
> 📊 Total plugins: [<kbd>**42**</kbd>](https://lobechat.com/discover/plugins)
|
|
356
356
|
|
|
357
357
|
<!-- PLUGIN LIST -->
|
|
358
358
|
|
package/README.zh-CN.md
CHANGED
|
@@ -338,14 +338,14 @@ LobeChat 的插件生态系统是其核心功能的重要扩展,它极大地
|
|
|
338
338
|
|
|
339
339
|
<!-- PLUGIN LIST -->
|
|
340
340
|
|
|
341
|
-
| 最近新增
|
|
342
|
-
|
|
|
343
|
-
| [
|
|
344
|
-
| [
|
|
345
|
-
| [
|
|
346
|
-
| [
|
|
347
|
-
|
|
348
|
-
> 📊 Total plugins: [<kbd>**
|
|
341
|
+
| 最近新增 | 描述 |
|
|
342
|
+
| --------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
343
|
+
| [SEO](https://lobechat.com/discover/plugin/SEO)<br/><sup>By **orrenprunckun** on **2025-11-14**</sup> | 输入任何 URL 和关键词,获取页面 SEO 分析和见解!<br/>`seo` |
|
|
344
|
+
| [购物工具](https://lobechat.com/discover/plugin/ShoppingTools)<br/><sup>By **shoppingtools** on **2025-10-27**</sup> | 在 eBay 和 AliExpress 上搜索产品,查找 eBay 活动和优惠券。获取快速示例。<br/>`购物` `e-bay` `ali-express` `优惠券` |
|
|
345
|
+
| [PortfolioMeta](https://lobechat.com/discover/plugin/StockData)<br/><sup>By **portfoliometa** on **2025-09-27**</sup> | 分析股票并获取全面的实时投资数据和分析。<br/>`股票` |
|
|
346
|
+
| [网页](https://lobechat.com/discover/plugin/web)<br/><sup>By **Proghit** on **2025-01-24**</sup> | 智能网页搜索,读取和分析页面,以提供来自 Google 结果的全面答案。<br/>`网页` `搜索` |
|
|
347
|
+
|
|
348
|
+
> 📊 Total plugins: [<kbd>**42**</kbd>](https://lobechat.com/discover/plugins)
|
|
349
349
|
|
|
350
350
|
<!-- PLUGIN LIST -->
|
|
351
351
|
|
package/changelog/v1.json
CHANGED
|
@@ -1,4 +1,25 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"children": {
|
|
4
|
+
"improvements": [
|
|
5
|
+
"Refactor and support move locale file intervention."
|
|
6
|
+
]
|
|
7
|
+
},
|
|
8
|
+
"date": "2025-11-14",
|
|
9
|
+
"version": "2.0.0-next.54"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"children": {
|
|
13
|
+
"features": [
|
|
14
|
+
"Add GPT-5.1 models."
|
|
15
|
+
],
|
|
16
|
+
"improvements": [
|
|
17
|
+
"Fix approving render and improve Conversation style."
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
"date": "2025-11-14",
|
|
21
|
+
"version": "2.0.0-next.53"
|
|
22
|
+
},
|
|
2
23
|
{
|
|
3
24
|
"children": {
|
|
4
25
|
"fixes": [
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lobehub/lobehub",
|
|
3
|
-
"version": "2.0.0-next.
|
|
3
|
+
"version": "2.0.0-next.54",
|
|
4
4
|
"description": "LobeHub - an open-source,comprehensive AI Agent framework that supports speech synthesis, multimodal, and extensible Function Call plugin system. Supports one-click free deployment of your private ChatGPT/LLM web application.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"framework",
|
|
@@ -174,7 +174,7 @@
|
|
|
174
174
|
"@lobehub/market-sdk": "^0.23.0",
|
|
175
175
|
"@lobehub/tts": "^2.0.1",
|
|
176
176
|
"@lobehub/ui": "^2.13.8",
|
|
177
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
177
|
+
"@modelcontextprotocol/sdk": "^1.22.0",
|
|
178
178
|
"@neondatabase/serverless": "^1.0.2",
|
|
179
179
|
"@next/third-parties": "^16.0.1",
|
|
180
180
|
"@opentelemetry/exporter-jaeger": "^2.2.0",
|
|
@@ -28,19 +28,19 @@ export class ElectronIpcClient {
|
|
|
28
28
|
this.initialize();
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
//
|
|
31
|
+
// Initialize client
|
|
32
32
|
private initialize() {
|
|
33
33
|
try {
|
|
34
34
|
const tempDir = os.tmpdir();
|
|
35
35
|
|
|
36
|
-
// Windows
|
|
36
|
+
// Force use of named pipe on Windows platform
|
|
37
37
|
if (process.platform === 'win32') {
|
|
38
38
|
this.socketPath = WINDOW_PIPE_FILE(this.appId);
|
|
39
39
|
log('Using named pipe for Windows: %s', this.socketPath);
|
|
40
40
|
return;
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
//
|
|
43
|
+
// Try to read sock info file on other platforms
|
|
44
44
|
const socketInfoPath = path.join(tempDir, SOCK_INFO_FILE(this.appId));
|
|
45
45
|
|
|
46
46
|
log('Looking for socket info at: %s', socketInfoPath);
|
|
@@ -49,7 +49,7 @@ export class ElectronIpcClient {
|
|
|
49
49
|
this.socketPath = socketInfo.socketPath;
|
|
50
50
|
log('Found socket path: %s', this.socketPath);
|
|
51
51
|
} else {
|
|
52
|
-
//
|
|
52
|
+
// If socket information is not found, use default sock file path
|
|
53
53
|
this.socketPath = path.join(tempDir, SOCK_FILE(this.appId));
|
|
54
54
|
log('Socket info not found, using default sock path: %s', this.socketPath);
|
|
55
55
|
}
|
|
@@ -59,7 +59,7 @@ export class ElectronIpcClient {
|
|
|
59
59
|
}
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
-
//
|
|
62
|
+
// Connect to Electron IPC server
|
|
63
63
|
private connect(): Promise<void> {
|
|
64
64
|
if (this.connected || !this.socketPath) {
|
|
65
65
|
log('Connection skipped: Connected=%s, SocketPath=%s', this.connected, !!this.socketPath);
|
|
@@ -80,18 +80,18 @@ export class ElectronIpcClient {
|
|
|
80
80
|
const dataStr = data.toString();
|
|
81
81
|
log('Received data: %s', dataStr.length > 100 ? `${dataStr.slice(0, 100)}...` : dataStr);
|
|
82
82
|
|
|
83
|
-
//
|
|
83
|
+
// Add new data to buffer
|
|
84
84
|
this.dataBuffer += dataStr;
|
|
85
85
|
|
|
86
|
-
//
|
|
86
|
+
// Split messages by newline
|
|
87
87
|
const messages = this.dataBuffer.split('\n');
|
|
88
88
|
|
|
89
|
-
//
|
|
89
|
+
// The last element may be an incomplete message, keep it in buffer
|
|
90
90
|
this.dataBuffer = messages.pop() || '';
|
|
91
91
|
log('Buffer remainder: %d bytes', this.dataBuffer.length);
|
|
92
92
|
|
|
93
93
|
for (const message of messages) {
|
|
94
|
-
if (!message.trim()) continue; //
|
|
94
|
+
if (!message.trim()) continue; // Skip empty messages
|
|
95
95
|
|
|
96
96
|
try {
|
|
97
97
|
const response = JSON.parse(message);
|
|
@@ -138,20 +138,20 @@ export class ElectronIpcClient {
|
|
|
138
138
|
});
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
//
|
|
141
|
+
// Handle disconnection
|
|
142
142
|
private handleDisconnect() {
|
|
143
143
|
log('Handling disconnect, connection attempts: %d', this.connectionAttempts);
|
|
144
|
-
//
|
|
144
|
+
// Clear reconnection timer
|
|
145
145
|
if (this.reconnectTimeout) {
|
|
146
146
|
clearTimeout(this.reconnectTimeout);
|
|
147
147
|
this.reconnectTimeout = null;
|
|
148
148
|
log('Cleared reconnect timeout');
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
-
//
|
|
151
|
+
// Clear data buffer
|
|
152
152
|
this.dataBuffer = '';
|
|
153
153
|
|
|
154
|
-
//
|
|
154
|
+
// Reject all pending requests
|
|
155
155
|
const pendingCount = this.requestQueue.size;
|
|
156
156
|
log('Rejecting %d pending requests', pendingCount);
|
|
157
157
|
for (const [id, { reject }] of this.requestQueue) {
|
|
@@ -160,7 +160,7 @@ export class ElectronIpcClient {
|
|
|
160
160
|
}
|
|
161
161
|
this.requestQueue.clear();
|
|
162
162
|
|
|
163
|
-
//
|
|
163
|
+
// Attempt to reconnect
|
|
164
164
|
if (this.connectionAttempts < this.maxConnectionAttempts) {
|
|
165
165
|
this.connectionAttempts++;
|
|
166
166
|
const delay = Math.min(1000 * Math.pow(2, this.connectionAttempts - 1), 30_000);
|
|
@@ -177,14 +177,14 @@ export class ElectronIpcClient {
|
|
|
177
177
|
}
|
|
178
178
|
}
|
|
179
179
|
|
|
180
|
-
//
|
|
180
|
+
// Send request to Electron IPC server
|
|
181
181
|
public async sendRequest<T>(method: ServerDispatchEventKey, params: any = {}): Promise<T> {
|
|
182
182
|
if (!this.socketPath) {
|
|
183
183
|
console.error('Cannot send request: Electron IPC connection not available');
|
|
184
184
|
throw new Error('Electron IPC connection not available');
|
|
185
185
|
}
|
|
186
186
|
|
|
187
|
-
//
|
|
187
|
+
// Connect first if not connected
|
|
188
188
|
if (!this.connected) {
|
|
189
189
|
log('Not connected, connecting before sending request');
|
|
190
190
|
await this.connect();
|
|
@@ -208,7 +208,7 @@ export class ElectronIpcClient {
|
|
|
208
208
|
const cleanupAndReject = (error: any) => {
|
|
209
209
|
clearTimeout(requestTimeoutId);
|
|
210
210
|
this.requestQueue.delete(id);
|
|
211
|
-
//
|
|
211
|
+
// Keep console.error log for timeout errors
|
|
212
212
|
if (
|
|
213
213
|
error &&
|
|
214
214
|
error.message &&
|
|
@@ -226,29 +226,29 @@ export class ElectronIpcClient {
|
|
|
226
226
|
requestTimeoutId = setTimeout(() => {
|
|
227
227
|
const pendingRequest = this.requestQueue.get(id);
|
|
228
228
|
if (pendingRequest) {
|
|
229
|
-
//
|
|
230
|
-
//
|
|
229
|
+
// Request is still in queue, indicating timeout
|
|
230
|
+
// Call its dedicated reject handler (cleanupAndReject)
|
|
231
231
|
const errorMsg = `Request timed out, method: ${method}`;
|
|
232
|
-
// console.error
|
|
232
|
+
// console.error is handled in cleanupAndReject
|
|
233
233
|
pendingRequest.reject(new Error(errorMsg));
|
|
234
234
|
}
|
|
235
|
-
//
|
|
235
|
+
// If pendingRequest does not exist, the request has been processed and its timeout has been cleared
|
|
236
236
|
}, 5000);
|
|
237
237
|
|
|
238
238
|
try {
|
|
239
|
-
//
|
|
239
|
+
// Send request
|
|
240
240
|
const requestJson = JSON.stringify(request) + '\n';
|
|
241
241
|
log('Writing request to socket, size: %d bytes', requestJson.length);
|
|
242
242
|
this.socket!.write(requestJson, (err) => {
|
|
243
243
|
if (err) {
|
|
244
|
-
//
|
|
245
|
-
//
|
|
244
|
+
// Write failed, request should be treated as failed
|
|
245
|
+
// Call its reject handler (cleanupAndReject)
|
|
246
246
|
const pending = this.requestQueue.get(id);
|
|
247
247
|
if (pending) {
|
|
248
|
-
pending.reject(err); //
|
|
248
|
+
pending.reject(err); // This will call cleanupAndReject
|
|
249
249
|
} else {
|
|
250
|
-
//
|
|
251
|
-
//
|
|
250
|
+
// This should not happen in theory, as write failures are usually quick
|
|
251
|
+
// But for safety, ensure the original promise is rejected
|
|
252
252
|
cleanupAndReject(err);
|
|
253
253
|
}
|
|
254
254
|
console.error('Failed to write request to socket: %o', err);
|
|
@@ -258,15 +258,15 @@ export class ElectronIpcClient {
|
|
|
258
258
|
});
|
|
259
259
|
} catch (err) {
|
|
260
260
|
console.error('Error sending request (during setup/write phase): %o', err);
|
|
261
|
-
//
|
|
262
|
-
//
|
|
263
|
-
// (clearTimeout(undefined)
|
|
261
|
+
// Error occurring here means the request didn't even have a chance to enter the queue or set timeout
|
|
262
|
+
// Call cleanupAndReject directly to ensure consistency, although requestTimeoutId may be undefined at this point
|
|
263
|
+
// (clearTimeout(undefined) is safe)
|
|
264
264
|
cleanupAndReject(err);
|
|
265
265
|
}
|
|
266
266
|
});
|
|
267
267
|
}
|
|
268
268
|
|
|
269
|
-
//
|
|
269
|
+
// Close connection
|
|
270
270
|
public close() {
|
|
271
271
|
log('Closing client connection');
|
|
272
272
|
if (this.reconnectTimeout) {
|
|
@@ -19,25 +19,25 @@ export class ElectronIPCServer {
|
|
|
19
19
|
constructor(appId: string, eventHandler: ElectronIPCEventHandler) {
|
|
20
20
|
this.appId = appId;
|
|
21
21
|
const isWindows = process.platform === 'win32';
|
|
22
|
-
//
|
|
22
|
+
// Create unique socket path to avoid conflicts
|
|
23
23
|
this.socketPath = isWindows
|
|
24
24
|
? WINDOW_PIPE_FILE(appId)
|
|
25
25
|
: path.join(os.tmpdir(), SOCK_FILE(appId));
|
|
26
26
|
|
|
27
|
-
//
|
|
27
|
+
// For Unix sockets, ensure the file does not exist
|
|
28
28
|
if (!isWindows && fs.existsSync(this.socketPath)) {
|
|
29
29
|
log('Removing existing socket file at: %s', this.socketPath);
|
|
30
30
|
fs.unlinkSync(this.socketPath);
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
//
|
|
33
|
+
// Create server
|
|
34
34
|
log('Creating IPC server');
|
|
35
35
|
this.server = net.createServer(this.handleConnection.bind(this));
|
|
36
36
|
|
|
37
37
|
this.eventHandler = eventHandler;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
//
|
|
40
|
+
// Start server
|
|
41
41
|
public start(): Promise<void> {
|
|
42
42
|
log('Starting IPC server');
|
|
43
43
|
return new Promise((resolve, reject) => {
|
|
@@ -49,7 +49,7 @@ export class ElectronIPCServer {
|
|
|
49
49
|
this.server.listen(this.socketPath, () => {
|
|
50
50
|
log('Electron IPC server listening on %s', this.socketPath);
|
|
51
51
|
|
|
52
|
-
//
|
|
52
|
+
// Write socket path to temporary file for Next.js server to read
|
|
53
53
|
const tempDir = os.tmpdir();
|
|
54
54
|
const socketInfoPath = path.join(tempDir, SOCK_INFO_FILE(this.appId));
|
|
55
55
|
log('Writing socket info to: %s', socketInfoPath);
|
|
@@ -60,7 +60,7 @@ export class ElectronIPCServer {
|
|
|
60
60
|
});
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
//
|
|
63
|
+
// Handle client connection
|
|
64
64
|
private handleConnection(socket: net.Socket): void {
|
|
65
65
|
let dataBuffer = '';
|
|
66
66
|
log('New client connection established');
|
|
@@ -70,12 +70,12 @@ export class ElectronIPCServer {
|
|
|
70
70
|
log('Received data chunk, size: %d bytes', chunk.length);
|
|
71
71
|
dataBuffer += chunk;
|
|
72
72
|
|
|
73
|
-
//
|
|
73
|
+
// Split messages by \n\n
|
|
74
74
|
const messages = dataBuffer.split('\n');
|
|
75
|
-
//
|
|
75
|
+
// Keep the last potentially incomplete message
|
|
76
76
|
dataBuffer = messages.pop() || '';
|
|
77
77
|
|
|
78
|
-
//
|
|
78
|
+
// Process each complete message
|
|
79
79
|
for (const message of messages) {
|
|
80
80
|
if (!message.trim()) continue;
|
|
81
81
|
|
|
@@ -101,12 +101,12 @@ export class ElectronIPCServer {
|
|
|
101
101
|
});
|
|
102
102
|
}
|
|
103
103
|
|
|
104
|
-
//
|
|
104
|
+
// Handle client request
|
|
105
105
|
private handleRequest = async (socket: net.Socket, request: any) => {
|
|
106
106
|
const { id, method, params } = request;
|
|
107
107
|
log('Handling request: %s (ID: %s)', method, id);
|
|
108
108
|
|
|
109
|
-
//
|
|
109
|
+
// Execute corresponding operation based on request method
|
|
110
110
|
const eventHandler = this.eventHandler[method as ServerDispatchEventKey];
|
|
111
111
|
if (!eventHandler) {
|
|
112
112
|
console.error('No handler found for method: %s', method);
|
|
@@ -126,28 +126,28 @@ export class ElectronIPCServer {
|
|
|
126
126
|
}
|
|
127
127
|
};
|
|
128
128
|
|
|
129
|
-
//
|
|
129
|
+
// Send result
|
|
130
130
|
private sendResult(socket: net.Socket, id: string, result: any): void {
|
|
131
131
|
const response = JSON.stringify({ id, result }) + '\n\n';
|
|
132
132
|
log('Sending success response for ID: %s, size: %d bytes', id, response.length);
|
|
133
133
|
socket.write(response);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
//
|
|
136
|
+
// Send error
|
|
137
137
|
private sendError(socket: net.Socket, id: string, error: string): void {
|
|
138
138
|
const response = JSON.stringify({ error, id }) + '\n\n';
|
|
139
139
|
log('Sending error response for ID: %s: %s', id, error);
|
|
140
140
|
socket.write(response);
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
//
|
|
143
|
+
// Close server
|
|
144
144
|
public close(): Promise<void> {
|
|
145
145
|
log('Closing IPC server');
|
|
146
146
|
return new Promise((resolve) => {
|
|
147
147
|
this.server.close(() => {
|
|
148
148
|
log('Electron IPC server closed');
|
|
149
149
|
|
|
150
|
-
//
|
|
150
|
+
// Delete socket file (Unix platforms)
|
|
151
151
|
if (process.platform !== 'win32' && fs.existsSync(this.socketPath)) {
|
|
152
152
|
log('Removing socket file: %s', this.socketPath);
|
|
153
153
|
fs.unlinkSync(this.socketPath);
|
|
@@ -1,6 +1,112 @@
|
|
|
1
1
|
import { AIChatModelCard } from '../types/aiModel';
|
|
2
2
|
|
|
3
3
|
const aihubmixModels: AIChatModelCard[] = [
|
|
4
|
+
{
|
|
5
|
+
abilities: {
|
|
6
|
+
functionCall: true,
|
|
7
|
+
imageOutput: true,
|
|
8
|
+
reasoning: true,
|
|
9
|
+
search: true,
|
|
10
|
+
vision: true,
|
|
11
|
+
},
|
|
12
|
+
contextWindowTokens: 400_000,
|
|
13
|
+
description:
|
|
14
|
+
'GPT-5.1 — 针对编码和 agent 任务优化的旗舰模型,支持可配置的推理强度与更长上下文。',
|
|
15
|
+
displayName: 'GPT-5.1',
|
|
16
|
+
enabled: true,
|
|
17
|
+
id: 'gpt-5.1',
|
|
18
|
+
maxOutput: 128_000,
|
|
19
|
+
pricing: {
|
|
20
|
+
units: [
|
|
21
|
+
{ name: 'textInput', rate: 1.25, strategy: 'fixed', unit: 'millionTokens' },
|
|
22
|
+
{ name: 'textInput_cacheRead', rate: 0.125, strategy: 'fixed', unit: 'millionTokens' },
|
|
23
|
+
{ name: 'textOutput', rate: 10, strategy: 'fixed', unit: 'millionTokens' },
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
releasedAt: '2025-11-13',
|
|
27
|
+
settings: {
|
|
28
|
+
extendParams: ['gpt5_1ReasoningEffort', 'textVerbosity'],
|
|
29
|
+
searchImpl: 'params',
|
|
30
|
+
},
|
|
31
|
+
type: 'chat',
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
abilities: {
|
|
35
|
+
functionCall: true,
|
|
36
|
+
vision: true,
|
|
37
|
+
},
|
|
38
|
+
contextWindowTokens: 128_000,
|
|
39
|
+
description: 'GPT-5.1 Chat:用于 ChatGPT 的 GPT-5.1 变体,适合聊天场景。',
|
|
40
|
+
displayName: 'GPT-5.1 Chat',
|
|
41
|
+
enabled: true,
|
|
42
|
+
id: 'gpt-5.1-chat-latest',
|
|
43
|
+
maxOutput: 16_384,
|
|
44
|
+
pricing: {
|
|
45
|
+
units: [
|
|
46
|
+
{ name: 'textInput', rate: 1.25, strategy: 'fixed', unit: 'millionTokens' },
|
|
47
|
+
{ name: 'textInput_cacheRead', rate: 0.125, strategy: 'fixed', unit: 'millionTokens' },
|
|
48
|
+
{ name: 'textOutput', rate: 10, strategy: 'fixed', unit: 'millionTokens' },
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
releasedAt: '2025-11-13',
|
|
52
|
+
type: 'chat',
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
abilities: {
|
|
56
|
+
functionCall: true,
|
|
57
|
+
imageOutput: true,
|
|
58
|
+
reasoning: true,
|
|
59
|
+
search: true,
|
|
60
|
+
vision: true,
|
|
61
|
+
},
|
|
62
|
+
contextWindowTokens: 400_000,
|
|
63
|
+
description:
|
|
64
|
+
'GPT-5.1 Codex:针对 agentic 编码任务优化的 GPT-5.1 版本,可在 Responses API 中用于更复杂的代码/代理工作流。',
|
|
65
|
+
displayName: 'GPT-5.1 Codex',
|
|
66
|
+
id: 'gpt-5.1-codex',
|
|
67
|
+
maxOutput: 128_000,
|
|
68
|
+
pricing: {
|
|
69
|
+
units: [
|
|
70
|
+
{ name: 'textInput', rate: 1.25, strategy: 'fixed', unit: 'millionTokens' },
|
|
71
|
+
{ name: 'textInput_cacheRead', rate: 0.125, strategy: 'fixed', unit: 'millionTokens' },
|
|
72
|
+
{ name: 'textOutput', rate: 10, strategy: 'fixed', unit: 'millionTokens' },
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
releasedAt: '2025-11-13',
|
|
76
|
+
settings: {
|
|
77
|
+
extendParams: ['gpt5_1ReasoningEffort'],
|
|
78
|
+
searchImpl: 'params',
|
|
79
|
+
},
|
|
80
|
+
type: 'chat',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
abilities: {
|
|
84
|
+
functionCall: true,
|
|
85
|
+
imageOutput: true,
|
|
86
|
+
reasoning: true,
|
|
87
|
+
search: true,
|
|
88
|
+
vision: true,
|
|
89
|
+
},
|
|
90
|
+
contextWindowTokens: 400_000,
|
|
91
|
+
description:
|
|
92
|
+
'GPT-5.1 Codex mini:体积更小、成本更低的 Codex 变体,针对 agentic 编码任务进行了优化。',
|
|
93
|
+
displayName: 'GPT-5.1 Codex mini',
|
|
94
|
+
id: 'gpt-5.1-codex-mini',
|
|
95
|
+
maxOutput: 128_000,
|
|
96
|
+
pricing: {
|
|
97
|
+
units: [
|
|
98
|
+
{ name: 'textInput', rate: 0.25, strategy: 'fixed', unit: 'millionTokens' },
|
|
99
|
+
{ name: 'textInput_cacheRead', rate: 0.025, strategy: 'fixed', unit: 'millionTokens' },
|
|
100
|
+
{ name: 'textOutput', rate: 2, strategy: 'fixed', unit: 'millionTokens' },
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
releasedAt: '2025-11-13',
|
|
104
|
+
settings: {
|
|
105
|
+
extendParams: ['gpt5_1ReasoningEffort'],
|
|
106
|
+
searchImpl: 'params',
|
|
107
|
+
},
|
|
108
|
+
type: 'chat',
|
|
109
|
+
},
|
|
4
110
|
{
|
|
5
111
|
abilities: {
|
|
6
112
|
functionCall: true,
|
|
@@ -64,7 +170,6 @@ const aihubmixModels: AIChatModelCard[] = [
|
|
|
64
170
|
description:
|
|
65
171
|
'跨领域编码和代理任务的最佳模型。GPT-5 在准确性、速度、推理、上下文识别、结构化思维和问题解决方面实现了飞跃。',
|
|
66
172
|
displayName: 'GPT-5',
|
|
67
|
-
enabled: true,
|
|
68
173
|
id: 'gpt-5',
|
|
69
174
|
maxOutput: 128_000,
|
|
70
175
|
pricing: {
|
|
@@ -144,7 +249,6 @@ const aihubmixModels: AIChatModelCard[] = [
|
|
|
144
249
|
description:
|
|
145
250
|
'ChatGPT 中使用的 GPT-5 模型。结合了强大的语言理解与生成能力,适合对话式交互应用。',
|
|
146
251
|
displayName: 'GPT-5 Chat',
|
|
147
|
-
enabled: true,
|
|
148
252
|
id: 'gpt-5-chat-latest',
|
|
149
253
|
maxOutput: 128_000,
|
|
150
254
|
pricing: {
|