Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
983c52b0e4 | ||
|
|
56bd3a46d7 | ||
|
|
2f495775ea | ||
|
|
e161fe059f | ||
|
|
96b6f0b63d |
@@ -1,4 +1,7 @@
|
|||||||
registry=https://registry.npmmirror.com
|
registry=https://registry.npmmirror.com
|
||||||
|
@metona-team:registry=https://git.metona.cn/api/packages/MetonaTeam/npm/
|
||||||
|
//git.metona.cn/api/packages/MetonaTeam/npm/:_auth=dGh6eHg6Mjc5MjQ2MDE5MGJkcW4=
|
||||||
|
//git.metona.cn/api/packages/MetonaTeam/npm/:always-auth=true
|
||||||
|
|
||||||
# 允许包的 postinstall 脚本(electron 需要下载二进制文件)
|
# 允许包的 postinstall 脚本(electron 需要下载二进制文件)
|
||||||
ignore-scripts=false
|
ignore-scripts=false
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Agnes AI Provider Adapter
|
* Agnes AI Provider Adapter
|
||||||
*
|
*
|
||||||
* OpenAI 兼容 API。支持 Tool Calling、Thinking 模式、多模态(图片)。
|
* OpenAI 兼容 API。支持 Tool Calling、Thinking 模式、多模态(图片 — URL + Base64)。
|
||||||
*
|
*
|
||||||
* 独立继承 BaseAdapter,通过 shared/openai-format 和 shared/sse-stream 复用
|
* 独立继承 BaseAdapter,通过 shared/openai-format 和 shared/sse-stream 复用
|
||||||
* OpenAI 兼容格式构建和 SSE 流式解析逻辑。不与其他 Provider Adapter 耦合。
|
* OpenAI 兼容格式构建和 SSE 流式解析逻辑。不与其他 Provider Adapter 耦合。
|
||||||
@@ -37,7 +37,7 @@ export class AgnesAdapter extends BaseAdapter {
|
|||||||
maxOutputTokens: 65_536,
|
maxOutputTokens: 65_536,
|
||||||
supportsToolCalling: true,
|
supportsToolCalling: true,
|
||||||
supportsThinking: true,
|
supportsThinking: true,
|
||||||
description: 'Agnes AI 快速版,1M 上下文,支持多模态图片与思考模式',
|
description: 'Agnes AI 快速版,1M 上下文,支持多模态图片(URL + Base64)与思考模式',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -136,6 +136,7 @@ export class AgnesAdapter extends BaseAdapter {
|
|||||||
*
|
*
|
||||||
* Agnes AI 特有参数:
|
* Agnes AI 特有参数:
|
||||||
* - 多模态图片:user 消息的 images[] → OpenAI content 数组 [{type:"text"}, {type:"image_url"}]
|
* - 多模态图片:user 消息的 images[] → OpenAI content 数组 [{type:"text"}, {type:"image_url"}]
|
||||||
|
* 支持 HTTPS URL 或 base64 Data URI(与 MiMo 一致)
|
||||||
* - chat_template_kwargs: { enable_thinking: true } — 启用思考模式(非 thinking 字段)
|
* - chat_template_kwargs: { enable_thinking: true } — 启用思考模式(非 thinking 字段)
|
||||||
* - 默认 max_tokens: 65536(1M 上下文,65.5K 最大输出)
|
* - 默认 max_tokens: 65536(1M 上下文,65.5K 最大输出)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* MiMo (Xiaomi) Provider Adapter
|
* MiMo (Xiaomi) Provider Adapter
|
||||||
*
|
*
|
||||||
* 基于 OpenAI 兼容 API。支持 Tool Calling、Thinking 模式、流式输出。
|
* 基于 OpenAI 兼容 API。支持 Tool Calling、Thinking 模式、流式输出。
|
||||||
* 模型: mimo-v2.5-pro(131072 max_tokens)/ mimo-v2.5(32768 max_tokens)
|
* 模型: mimo-v2.5-pro(1M 上下文 / 131072 max_tokens)/ mimo-v2.5(1M 上下文 / 32768 max_tokens)
|
||||||
*
|
*
|
||||||
* 独立继承 BaseAdapter,通过 shared/openai-format 和 shared/sse-stream 复用
|
* 独立继承 BaseAdapter,通过 shared/openai-format 和 shared/sse-stream 复用
|
||||||
* OpenAI 兼容格式构建和 SSE 流式解析逻辑。不与其他 Provider Adapter 耦合。
|
* OpenAI 兼容格式构建和 SSE 流式解析逻辑。不与其他 Provider Adapter 耦合。
|
||||||
@@ -31,13 +31,12 @@ export class MimoAdapter extends BaseAdapter {
|
|||||||
readonly supportsThinking = true;
|
readonly supportsThinking = true;
|
||||||
|
|
||||||
// MiMo 模型元信息
|
// MiMo 模型元信息
|
||||||
// mimo-v2.5-pro: 131072 max_completion_tokens;mimo-v2.5: 32768
|
// mimo-v2.5-pro: 1M 上下文(与 DeepSeek 一致)/ 131072 max_tokens;mimo-v2.5: 1M 上下文 / 32768 max_tokens
|
||||||
// 官方未公布上下文窗口大小,保守设为 131072(与 pro 的 max_output 一致)
|
|
||||||
private static readonly MODEL_INFO: Record<string, MetonaModelInfo> = {
|
private static readonly MODEL_INFO: Record<string, MetonaModelInfo> = {
|
||||||
'mimo-v2.5-pro': {
|
'mimo-v2.5-pro': {
|
||||||
id: 'mimo-v2.5-pro',
|
id: 'mimo-v2.5-pro',
|
||||||
name: 'MiMo V2.5 Pro',
|
name: 'MiMo V2.5 Pro',
|
||||||
contextWindow: 131_072,
|
contextWindow: 1_000_000,
|
||||||
maxOutputTokens: 131_072,
|
maxOutputTokens: 131_072,
|
||||||
supportsToolCalling: true,
|
supportsToolCalling: true,
|
||||||
supportsThinking: true,
|
supportsThinking: true,
|
||||||
@@ -46,7 +45,7 @@ export class MimoAdapter extends BaseAdapter {
|
|||||||
'mimo-v2.5': {
|
'mimo-v2.5': {
|
||||||
id: 'mimo-v2.5',
|
id: 'mimo-v2.5',
|
||||||
name: 'MiMo V2.5',
|
name: 'MiMo V2.5',
|
||||||
contextWindow: 131_072,
|
contextWindow: 1_000_000,
|
||||||
maxOutputTokens: 32_768,
|
maxOutputTokens: 32_768,
|
||||||
supportsToolCalling: true,
|
supportsToolCalling: true,
|
||||||
supportsThinking: true,
|
supportsThinking: true,
|
||||||
@@ -143,7 +142,7 @@ export class MimoAdapter extends BaseAdapter {
|
|||||||
return this.config.contextWindow;
|
return this.config.contextWindow;
|
||||||
}
|
}
|
||||||
const modelInfo = MimoAdapter.MODEL_INFO[this.config.defaultModel];
|
const modelInfo = MimoAdapter.MODEL_INFO[this.config.defaultModel];
|
||||||
return modelInfo?.contextWindow ?? 131_072;
|
return modelInfo?.contextWindow ?? 1_000_000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ========== 私有方法 ==========
|
// ========== 私有方法 ==========
|
||||||
@@ -153,6 +152,7 @@ export class MimoAdapter extends BaseAdapter {
|
|||||||
*
|
*
|
||||||
* MiMo 特有参数:
|
* MiMo 特有参数:
|
||||||
* - 多模态图片:user 消息的 images[] → OpenAI content 数组 [{type:"text"}, {type:"image_url"}]
|
* - 多模态图片:user 消息的 images[] → OpenAI content 数组 [{type:"text"}, {type:"image_url"}]
|
||||||
|
* 支持 HTTPS URL 或 base64 Data URI
|
||||||
* - thinking: { type: "enabled" / "disabled" } — 与 DeepSeek 一致
|
* - thinking: { type: "enabled" / "disabled" } — 与 DeepSeek 一致
|
||||||
* - max_completion_tokens — 非 max_tokens(MiMo 使用新字段名)
|
* - max_completion_tokens — 非 max_tokens(MiMo 使用新字段名)
|
||||||
* - stream_options: { include_usage: true } — 流式返回 usage
|
* - stream_options: { include_usage: true } — 流式返回 usage
|
||||||
|
|||||||
@@ -394,8 +394,8 @@ export class DatabaseService {
|
|||||||
// v0.3.1: DeepSeek/Agnes 改为可配置,不再写死 1M
|
// v0.3.1: DeepSeek/Agnes 改为可配置,不再写死 1M
|
||||||
{ key: 'deepseek.contextWindow', value: '1000000', category: 'deepseek' },
|
{ key: 'deepseek.contextWindow', value: '1000000', category: 'deepseek' },
|
||||||
{ key: 'agnes.contextWindow', value: '1000000', category: 'agnes' },
|
{ key: 'agnes.contextWindow', value: '1000000', category: 'agnes' },
|
||||||
// v0.3.4: MiMo 上下文窗口(官方未公布,保守设为 131072)
|
// v0.3.4: MiMo 上下文窗口(与 DeepSeek 一致,1M)
|
||||||
{ key: 'mimo.contextWindow', value: '131072', category: 'mimo' },
|
{ key: 'mimo.contextWindow', value: '1000000', category: 'mimo' },
|
||||||
|
|
||||||
// Onboarding
|
// Onboarding
|
||||||
{ key: 'onboarding.completed', value: 'false', category: 'general' },
|
{ key: 'onboarding.completed', value: 'false', category: 'general' },
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ export const SEED_DEFAULTS: Record<string, unknown> = {
|
|||||||
'ollama.numCtx': null,
|
'ollama.numCtx': null,
|
||||||
'deepseek.contextWindow': 1000000,
|
'deepseek.contextWindow': 1000000,
|
||||||
'agnes.contextWindow': 1000000,
|
'agnes.contextWindow': 1000000,
|
||||||
'mimo.contextWindow': 131072,
|
'mimo.contextWindow': 1000000,
|
||||||
'onboarding.completed': false,
|
'onboarding.completed': false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Generated
+76
-16
@@ -1,16 +1,17 @@
|
|||||||
{
|
{
|
||||||
"name": "metona-ai-desktop",
|
"name": "metona-ai-desktop",
|
||||||
"version": "0.3.18",
|
"version": "0.3.20",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "metona-ai-desktop",
|
"name": "metona-ai-desktop",
|
||||||
"version": "0.3.18",
|
"version": "0.3.20",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@emotion/react": "^11.14.0",
|
"@emotion/react": "^11.14.0",
|
||||||
"@emotion/styled": "^11.14.1",
|
"@emotion/styled": "^11.14.1",
|
||||||
|
"@metona-team/metona-toast": "^2.0.1",
|
||||||
"@modelcontextprotocol/sdk": "^1.12.1",
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
||||||
"@mui/icons-material": "^9.1.1",
|
"@mui/icons-material": "^9.1.1",
|
||||||
"@mui/material": "^9.1.2",
|
"@mui/material": "^9.1.2",
|
||||||
@@ -21,7 +22,6 @@
|
|||||||
"electron-store": "^10.0.1",
|
"electron-store": "^10.0.1",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"lru-cache": "^11.1.0",
|
"lru-cache": "^11.1.0",
|
||||||
"metona-toast": "^2.0.0",
|
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
@@ -1870,6 +1870,12 @@
|
|||||||
"node": ">= 10.0.0"
|
"node": ">= 10.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@metona-team/metona-toast": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://git.metona.cn/api/packages/MetonaTeam/npm/%40metona-team%2Fmetona-toast/-/2.0.1/metona-toast-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-r8q9CYhtYbsz2hH3ffpqNeo7hV0f5qXWiL65boisc0VXFNht0ZDNn/ZbWneYM2/bOqC7Vh7dJlHe0GSVbPJ3Lg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@modelcontextprotocol/sdk": {
|
"node_modules/@modelcontextprotocol/sdk": {
|
||||||
"version": "1.29.0",
|
"version": "1.29.0",
|
||||||
"resolved": "https://registry.npmmirror.com/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
|
"resolved": "https://registry.npmmirror.com/@modelcontextprotocol/sdk/-/sdk-1.29.0.tgz",
|
||||||
@@ -2333,6 +2339,9 @@
|
|||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2347,6 +2356,9 @@
|
|||||||
"arm"
|
"arm"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2361,6 +2373,9 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2375,6 +2390,9 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2389,6 +2407,9 @@
|
|||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2403,6 +2424,9 @@
|
|||||||
"loong64"
|
"loong64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2417,6 +2441,9 @@
|
|||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2431,6 +2458,9 @@
|
|||||||
"ppc64"
|
"ppc64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2445,6 +2475,9 @@
|
|||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2459,6 +2492,9 @@
|
|||||||
"riscv64"
|
"riscv64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2473,6 +2509,9 @@
|
|||||||
"s390x"
|
"s390x"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2487,6 +2526,9 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2501,6 +2543,9 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2750,6 +2795,9 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2767,6 +2815,9 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2784,6 +2835,9 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -2801,6 +2855,9 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -3874,16 +3931,16 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "5.0.7",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.7.tgz",
|
"resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-5.0.8.tgz",
|
||||||
"integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==",
|
"integrity": "sha512-JZyDyq3D4AUifKTPOB7DELf6XsB3WdPuNxCtob1vFXPsSXhdAiHBWJ/tJ8HAc9aH84BK+5JFZLNkJKx3G9kzQg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^4.0.2"
|
"balanced-match": "^4.0.2"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": "18 || 20 || >=22"
|
"node": "20 || >=22"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/browserslist": {
|
"node_modules/browserslist": {
|
||||||
@@ -7369,6 +7426,9 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -7390,6 +7450,9 @@
|
|||||||
"arm64"
|
"arm64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -7411,6 +7474,9 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"glibc"
|
||||||
|
],
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -7432,6 +7498,9 @@
|
|||||||
"x64"
|
"x64"
|
||||||
],
|
],
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"libc": [
|
||||||
|
"musl"
|
||||||
|
],
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"optional": true,
|
"optional": true,
|
||||||
"os": [
|
"os": [
|
||||||
@@ -7942,15 +8011,6 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/metona-toast": {
|
|
||||||
"version": "2.0.0",
|
|
||||||
"resolved": "https://registry.npmmirror.com/metona-toast/-/metona-toast-2.0.0.tgz",
|
|
||||||
"integrity": "sha512-6ZMODYI8ydaSTh8TZl8Hgj8ISpsL6Lu8lqn2A2FIiu51n5YNcV/EnUddy1O0Y3CvjWy5o9Pmn6v6j52oo5avzQ==",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=14.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/micromark": {
|
"node_modules/micromark": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmmirror.com/micromark/-/micromark-4.0.2.tgz",
|
"resolved": "https://registry.npmmirror.com/micromark/-/micromark-4.0.2.tgz",
|
||||||
|
|||||||
+2
-2
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "metona-ai-desktop",
|
"name": "metona-ai-desktop",
|
||||||
"version": "0.3.18",
|
"version": "0.3.20",
|
||||||
"description": "MetonaAI Desktop — 生产级通用 AI Agent 智能体桌面应用",
|
"description": "MetonaAI Desktop — 生产级通用 AI Agent 智能体桌面应用",
|
||||||
"main": "dist-electron/main/main.js",
|
"main": "dist-electron/main/main.js",
|
||||||
"author": "Metona Team",
|
"author": "Metona Team",
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
"electron-store": "^10.0.1",
|
"electron-store": "^10.0.1",
|
||||||
"fuse.js": "^7.1.0",
|
"fuse.js": "^7.1.0",
|
||||||
"lru-cache": "^11.1.0",
|
"lru-cache": "^11.1.0",
|
||||||
"metona-toast": "^2.0.0",
|
"@metona-team/metona-toast": "^2.0.1",
|
||||||
"nanoid": "^5.1.5",
|
"nanoid": "^5.1.5",
|
||||||
"react": "^19.1.0",
|
"react": "^19.1.0",
|
||||||
"react-dom": "^19.1.0",
|
"react-dom": "^19.1.0",
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ export function CommandPalette(): React.JSX.Element {
|
|||||||
useAgentStore.getState().setCurrentSession(r.id);
|
useAgentStore.getState().setCurrentSession(r.id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[CommandPalette]', err);
|
console.error('[CommandPalette]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ export function ContextMenuDialogHost(): React.JSX.Element {
|
|||||||
function copyWithToast(text: string): void {
|
function copyWithToast(text: string): void {
|
||||||
navigator.clipboard.writeText(text).catch((err) => {
|
navigator.clipboard.writeText(text).catch((err) => {
|
||||||
console.error('[Clipboard]', err);
|
console.error('[Clipboard]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +203,7 @@ export function createContextMenuItems(type: ContextMenuType, data?: unknown): C
|
|||||||
// 修复: 4 个 session 操作统一改为 await IPC + 失败回滚,避免 UI 与 DB 状态不一致
|
// 修复: 4 个 session 操作统一改为 await IPC + 失败回滚,避免 UI 与 DB 状态不一致
|
||||||
// 之前 archive 仅调用前端 store 未调用 IPC,rename/pin/delete 未等待 IPC 结果即更新 UI
|
// 之前 archive 仅调用前端 store 未调用 IPC,rename/pin/delete 未等待 IPC 结果即更新 UI
|
||||||
const showError = (msg: string) => {
|
const showError = (msg: string) => {
|
||||||
import('metona-toast').then((mod) => mod.default.error(msg)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(msg)).catch(() => {});
|
||||||
};
|
};
|
||||||
return [
|
return [
|
||||||
{ id: 'rename', icon: Edit, label: '重命名', action: async () => {
|
{ id: 'rename', icon: Edit, label: '重命名', action: async () => {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ import { useEffect } from 'react';
|
|||||||
export function ToastContainer(): null {
|
export function ToastContainer(): null {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
// 动态导入 metona-toast 并配置
|
// 动态导入 metona-toast 并配置
|
||||||
import('metona-toast').then((mod) => {
|
import('@metona-team/metona-toast').then((mod) => {
|
||||||
const MeToast = mod.default;
|
const MeToast = mod.default;
|
||||||
|
|
||||||
// 全局配置(设计规范指定的参数)
|
// 全局配置(设计规范指定的参数)
|
||||||
@@ -52,7 +52,7 @@ export function ToastContainer(): null {
|
|||||||
if (window.metona?.toast?.onShow) {
|
if (window.metona?.toast?.onShow) {
|
||||||
const unsubscribe = window.metona.toast.onShow(async (data) => {
|
const unsubscribe = window.metona.toast.onShow(async (data) => {
|
||||||
try {
|
try {
|
||||||
const MeToast = (await import('metona-toast')).default;
|
const MeToast = (await import('@metona-team/metona-toast')).default;
|
||||||
const { type, message, options } = data;
|
const { type, message, options } = data;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'success': MeToast.success(message, options); break;
|
case 'success': MeToast.success(message, options); break;
|
||||||
|
|||||||
@@ -108,7 +108,7 @@ export function ChatInput(): React.JSX.Element {
|
|||||||
// v0.3.0: 用 Toast 提示用户 DeepSeek 不支持图片
|
// v0.3.0: 用 Toast 提示用户 DeepSeek 不支持图片
|
||||||
const skipped = fileArray.length - filtered.length;
|
const skipped = fileArray.length - filtered.length;
|
||||||
// v0.3.0 修复:记录 Toast 加载失败错误到控制台,而非静默吞掉
|
// v0.3.0 修复:记录 Toast 加载失败错误到控制台,而非静默吞掉
|
||||||
import('metona-toast').then((mod) => {
|
import('@metona-team/metona-toast').then((mod) => {
|
||||||
mod.default.warning(`DeepSeek 不支持图片,已自动跳过 ${skipped} 个图片文件`);
|
mod.default.warning(`DeepSeek 不支持图片,已自动跳过 ${skipped} 个图片文件`);
|
||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error('[ChatInput] Failed to load metona-toast for DeepSeek image warning:', err);
|
console.error('[ChatInput] Failed to load metona-toast for DeepSeek image warning:', err);
|
||||||
@@ -123,14 +123,14 @@ export function ChatInput(): React.JSX.Element {
|
|||||||
(r): r is PromiseFulfilledResult<Attachment> => r.status === 'fulfilled',
|
(r): r is PromiseFulfilledResult<Attachment> => r.status === 'fulfilled',
|
||||||
).map((r) => r.value);
|
).map((r) => r.value);
|
||||||
if (successful.length === 0) {
|
if (successful.length === 0) {
|
||||||
import('metona-toast').then((mod) => {
|
import('@metona-team/metona-toast').then((mod) => {
|
||||||
mod.default.error('文件读取失败,请检查文件是否损坏或被锁定');
|
mod.default.error('文件读取失败,请检查文件是否损坏或被锁定');
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (successful.length < filtered.length) {
|
if (successful.length < filtered.length) {
|
||||||
const failedCount = filtered.length - successful.length;
|
const failedCount = filtered.length - successful.length;
|
||||||
import('metona-toast').then((mod) => {
|
import('@metona-team/metona-toast').then((mod) => {
|
||||||
mod.default.warning(`${failedCount} 个文件读取失败,已跳过`);
|
mod.default.warning(`${failedCount} 个文件读取失败,已跳过`);
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ export function Sidebar(): React.JSX.Element {
|
|||||||
// M-9 修复: 显示错误提示而非静默吞错后创建本地假会话
|
// M-9 修复: 显示错误提示而非静默吞错后创建本地假会话
|
||||||
// 之前的行为:catch 后继续创建本地 s_${Date.now()} 会话,但该会话在主进程不存在,下次刷新消失
|
// 之前的行为:catch 后继续创建本地 s_${Date.now()} 会话,但该会话在主进程不存在,下次刷新消失
|
||||||
console.error('[Sidebar] Failed to create session:', err);
|
console.error('[Sidebar] Failed to create session:', err);
|
||||||
import('metona-toast').then((mod) => {
|
import('@metona-team/metona-toast').then((mod) => {
|
||||||
mod.default.error('创建会话失败,请检查数据库状态');
|
mod.default.error('创建会话失败,请检查数据库状态');
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
return; // 不创建本地假会话
|
return; // 不创建本地假会话
|
||||||
@@ -119,7 +119,7 @@ function SessionItem({ session, isActive, isAgentActive, onClick }: { session: S
|
|||||||
await window.metona.sessions.delete(session.id);
|
await window.metona.sessions.delete(session.id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[Sidebar] Failed to delete session:', err);
|
console.error('[Sidebar] Failed to delete session:', err);
|
||||||
import('metona-toast').then((mod) => {
|
import('@metona-team/metona-toast').then((mod) => {
|
||||||
mod.default.error('删除会话失败,请重试');
|
mod.default.error('删除会话失败,请重试');
|
||||||
}).catch(() => {});
|
}).catch(() => {});
|
||||||
// 不调用 removeSession,保留会话在 UI 中(与数据库状态一致)
|
// 不调用 removeSession,保留会话在 UI 中(与数据库状态一致)
|
||||||
@@ -191,7 +191,7 @@ function ToolManagerPanel() {
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error('[Sidebar]', err);
|
console.error('[Sidebar]', err);
|
||||||
if (!cancelled) {
|
if (!cancelled) {
|
||||||
import('metona-toast').then((mod) => mod.default.error('加载工具列表失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('加载工具列表失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,12 +175,12 @@ export function MemoryViewer(): React.JSX.Element {
|
|||||||
const res = await window.metona.memory.delete(type, id);
|
const res = await window.metona.memory.delete(type, id);
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
// 用户主动操作失败应用 toast(与项目惯例一致),不污染加载/搜索的 Alert
|
// 用户主动操作失败应用 toast(与项目惯例一致),不污染加载/搜索的 Alert
|
||||||
import('metona-toast').then((mod) => mod.default.error(res.error ?? '删除失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '删除失败')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await loadMemories();
|
await loadMemories();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ export function OnboardingWizard(): React.JSX.Element | null {
|
|||||||
const DEFAULT_CTX: Record<string, number | null> = {
|
const DEFAULT_CTX: Record<string, number | null> = {
|
||||||
deepseek: 1_000_000,
|
deepseek: 1_000_000,
|
||||||
agnes: 1_000_000,
|
agnes: 1_000_000,
|
||||||
mimo: 131_072,
|
mimo: 1_000_000,
|
||||||
ollama: null,
|
ollama: null,
|
||||||
};
|
};
|
||||||
// 上下文窗口校验:ollama 允许空,最小 512;其他 provider 最小 4096
|
// 上下文窗口校验:ollama 允许空,最小 512;其他 provider 最小 4096
|
||||||
@@ -110,7 +110,7 @@ export function OnboardingWizard(): React.JSX.Element | null {
|
|||||||
const r = await window.metona.config.setBatch(entries);
|
const r = await window.metona.config.setBatch(entries);
|
||||||
if (r && !r.success) {
|
if (r && !r.success) {
|
||||||
console.error('[OnboardingWizard]', 'Batch config save failed:', r.error);
|
console.error('[OnboardingWizard]', 'Batch config save failed:', r.error);
|
||||||
import('metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败,请重试')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败,请重试')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
useAgentStore.getState().setProvider(provider.trim() || 'deepseek', model.trim() || '');
|
useAgentStore.getState().setProvider(provider.trim() || 'deepseek', model.trim() || '');
|
||||||
@@ -127,7 +127,7 @@ export function OnboardingWizard(): React.JSX.Element | null {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[OnboardingWizard]', 'Failed to save configuration:', err);
|
console.error('[OnboardingWizard]', 'Failed to save configuration:', err);
|
||||||
// 用户主动操作失败必须有反馈,否则向导不关闭、用户卡死
|
// 用户主动操作失败必须有反馈,否则向导不关闭、用户卡死
|
||||||
import('metona-toast').then((mod) => mod.default.error(`保存配置失败:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`保存配置失败:${(err as Error).message}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -210,7 +210,7 @@ export function OnboardingWizard(): React.JSX.Element | null {
|
|||||||
if (!r.canceled && r.path) setWorkspacePath(r.path);
|
if (!r.canceled && r.path) setWorkspacePath(r.path);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[OnboardingWizard]', err);
|
console.error('[OnboardingWizard]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error('选择文件夹失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('选择文件夹失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}>选择文件夹</Button>
|
}}>选择文件夹</Button>
|
||||||
|
|||||||
@@ -96,12 +96,12 @@ function useConfig<T>(key: string, defaultValue: T): [T, (v: T) => void] {
|
|||||||
if (r && !r.success) {
|
if (r && !r.success) {
|
||||||
// 只有当没有后续 set 操作时才回滚,避免覆盖用户的新修改
|
// 只有当没有后续 set 操作时才回滚,避免覆盖用户的新修改
|
||||||
if (seqRef.current === seq) setValue(prev);
|
if (seqRef.current === seq) setValue(prev);
|
||||||
import('metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
}).catch((err: unknown) => {
|
}).catch((err: unknown) => {
|
||||||
console.error('[SettingsModal]', err);
|
console.error('[SettingsModal]', err);
|
||||||
if (seqRef.current === seq) setValue(prev);
|
if (seqRef.current === seq) setValue(prev);
|
||||||
import('metona-toast').then((mod) => mod.default.error('配置保存失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('配置保存失败')).catch(() => {});
|
||||||
});
|
});
|
||||||
}, [key]);
|
}, [key]);
|
||||||
return [value, set];
|
return [value, set];
|
||||||
@@ -159,18 +159,18 @@ function WorkspaceSettings() {
|
|||||||
try {
|
try {
|
||||||
const integrityResult = await window.metona?.workspace?.checkDatabaseIntegrity(currentPath);
|
const integrityResult = await window.metona?.workspace?.checkDatabaseIntegrity(currentPath);
|
||||||
if (!integrityResult?.success) {
|
if (!integrityResult?.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`源数据库校验失败:${integrityResult?.error ?? '未知错误'}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`源数据库校验失败:${integrityResult?.error ?? '未知错误'}`)).catch(() => {});
|
||||||
setApplying(false);
|
setApplying(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!integrityResult.ok) {
|
if (!integrityResult.ok) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`源数据库损坏(${integrityResult.detail}),无法继承`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`源数据库损坏(${integrityResult.detail}),无法继承`)).catch(() => {});
|
||||||
setApplying(false);
|
setApplying(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[SettingsModal] Database integrity check failed:', err);
|
console.error('[SettingsModal] Database integrity check failed:', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error(`源数据库校验异常:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`源数据库校验异常:${(err as Error).message}`)).catch(() => {});
|
||||||
setApplying(false);
|
setApplying(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -186,7 +186,7 @@ function WorkspaceSettings() {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
// 用户勾选了继承文件,失败时必须告知,否则切到新空间才发现文件是空的,潜在数据丢失风险
|
// 用户勾选了继承文件,失败时必须告知,否则切到新空间才发现文件是空的,潜在数据丢失风险
|
||||||
console.error('[SettingsModal] Inherit failed:', err);
|
console.error('[SettingsModal] Inherit failed:', err);
|
||||||
import('metona-toast').then((mod) => mod.default.warning(`部分文件继承失败:${(err as Error).message},请手动检查`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.warning(`部分文件继承失败:${(err as Error).message},请手动检查`)).catch(() => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +200,7 @@ function WorkspaceSettings() {
|
|||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[SettingsModal]', err);
|
console.error('[SettingsModal]', err);
|
||||||
// 用户主动操作(切换工作空间)失败必须有反馈
|
// 用户主动操作(切换工作空间)失败必须有反馈
|
||||||
import('metona-toast').then((mod) => mod.default.error(`切换工作空间失败:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`切换工作空间失败:${(err as Error).message}`)).catch(() => {});
|
||||||
} finally {
|
} finally {
|
||||||
setApplying(false);
|
setApplying(false);
|
||||||
}
|
}
|
||||||
@@ -216,11 +216,11 @@ function WorkspaceSettings() {
|
|||||||
try {
|
try {
|
||||||
const r = await window.metona?.app?.showItemInFolder(workspacePath);
|
const r = await window.metona?.app?.showItemInFolder(workspacePath);
|
||||||
if (r && !r.success) {
|
if (r && !r.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(r.error ?? '打开文件夹失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '打开文件夹失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[SettingsModal]', err);
|
console.error('[SettingsModal]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -364,7 +364,7 @@ function LLMSettings() {
|
|||||||
// v0.3.1: DeepSeek/Agnes/MiMo contextWindow 可配置(不再写死)
|
// v0.3.1: DeepSeek/Agnes/MiMo contextWindow 可配置(不再写死)
|
||||||
const [dsCtxWindow, setDsCtxWindow] = useState<number>(1000000);
|
const [dsCtxWindow, setDsCtxWindow] = useState<number>(1000000);
|
||||||
const [agnesCtxWindow, setAgnesCtxWindow] = useState<number>(1000000);
|
const [agnesCtxWindow, setAgnesCtxWindow] = useState<number>(1000000);
|
||||||
const [mimoCtxWindow, setMimoCtxWindow] = useState<number>(131072);
|
const [mimoCtxWindow, setMimoCtxWindow] = useState<number>(1000000);
|
||||||
const [showKey, setShowKey] = useState(false);
|
const [showKey, setShowKey] = useState(false);
|
||||||
const [loaded, setLoaded] = useState(false);
|
const [loaded, setLoaded] = useState(false);
|
||||||
const [saving, setSaving] = useState(false);
|
const [saving, setSaving] = useState(false);
|
||||||
@@ -466,14 +466,14 @@ function LLMSettings() {
|
|||||||
|
|
||||||
const handleSave = async () => {
|
const handleSave = async () => {
|
||||||
if (hasBlockingError) {
|
if (hasBlockingError) {
|
||||||
import('metona-toast').then((mod) => mod.default.error('请修正表单中的错误后再保存')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('请修正表单中的错误后再保存')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setSaving(true);
|
setSaving(true);
|
||||||
try {
|
try {
|
||||||
const setBatch = window.metona?.config?.setBatch;
|
const setBatch = window.metona?.config?.setBatch;
|
||||||
if (!setBatch) {
|
if (!setBatch) {
|
||||||
import('metona-toast').then((mod) => mod.default.error('配置 API 不可用')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('配置 API 不可用')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// v0.3.9: 批量保存,避免串行保存中间态触发 reloadAdapter 失败
|
// v0.3.9: 批量保存,避免串行保存中间态触发 reloadAdapter 失败
|
||||||
@@ -493,12 +493,12 @@ function LLMSettings() {
|
|||||||
];
|
];
|
||||||
const r = await setBatch(entries);
|
const r = await setBatch(entries);
|
||||||
if (r && !r.success) {
|
if (r && !r.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '配置保存失败')).catch(() => {});
|
||||||
} else {
|
} else {
|
||||||
import('metona-toast').then((mod) => mod.default.success('配置已保存')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.success('配置已保存')).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`保存失败:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`保存失败:${(err as Error).message}`)).catch(() => {});
|
||||||
} finally {
|
} finally {
|
||||||
setSaving(false);
|
setSaving(false);
|
||||||
}
|
}
|
||||||
@@ -608,11 +608,11 @@ function LLMSettings() {
|
|||||||
label="上下文窗口 (contextWindow)"
|
label="上下文窗口 (contextWindow)"
|
||||||
type="number"
|
type="number"
|
||||||
value={mimoCtxWindow}
|
value={mimoCtxWindow}
|
||||||
onChange={(e) => setMimoCtxWindow(Number(e.target.value) || 131072)}
|
onChange={(e) => setMimoCtxWindow(Number(e.target.value) || 1000000)}
|
||||||
placeholder="如 32768、65536、131072"
|
placeholder="如 65536、131072、1000000"
|
||||||
slotProps={{ htmlInput: { min: 4096, step: 4096 } }}
|
slotProps={{ htmlInput: { min: 4096, step: 4096 } }}
|
||||||
error={mimoCtxError}
|
error={mimoCtxError}
|
||||||
helperText={mimoCtxError ? '最小值为 4096' : '官方未公布具体值,默认 131072,用于压缩判断'}
|
helperText={mimoCtxError ? '最小值为 4096' : '默认 1000000(1M),用于上下文压缩判断'}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
@@ -735,12 +735,12 @@ function ToolsSettings() {
|
|||||||
const r = await window.metona?.tools?.toggle(name, enabled);
|
const r = await window.metona?.tools?.toggle(name, enabled);
|
||||||
if (r && !r.success) {
|
if (r && !r.success) {
|
||||||
setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t));
|
setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t));
|
||||||
import('metona-toast').then((mod) => mod.default.error(r.error ?? '切换工具失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '切换工具失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[SettingsModal]', err);
|
console.error('[SettingsModal]', err);
|
||||||
setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t));
|
setTools((p) => p.map((t) => t.name === name ? { ...t, enabled: !enabled } : t));
|
||||||
import('metona-toast').then((mod) => mod.default.error('切换工具失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('切换工具失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -752,11 +752,11 @@ function ToolsSettings() {
|
|||||||
if (r.success) {
|
if (r.success) {
|
||||||
setAutoExecList((p) => enabled ? [...p, name] : p.filter((n) => n !== name));
|
setAutoExecList((p) => enabled ? [...p, name] : p.filter((n) => n !== name));
|
||||||
} else {
|
} else {
|
||||||
import('metona-toast').then((mod) => mod.default.error(r.error ?? '设置自动执行失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r.error ?? '设置自动执行失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[SettingsModal]', err);
|
console.error('[SettingsModal]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error('设置自动执行失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('设置自动执行失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -909,11 +909,11 @@ function MCPSettings() {
|
|||||||
if (r?.success) {
|
if (r?.success) {
|
||||||
setNewName(''); setNewCommand(''); setNewArgs(''); setShowAdd(false); loadServers();
|
setNewName(''); setNewCommand(''); setNewArgs(''); setShowAdd(false); loadServers();
|
||||||
} else {
|
} else {
|
||||||
import('metona-toast').then((mod) => mod.default.error(r?.error ?? '添加 MCP 服务失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r?.error ?? '添加 MCP 服务失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[SettingsModal]', err);
|
console.error('[SettingsModal]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error(`添加 MCP 服务失败:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`添加 MCP 服务失败:${(err as Error).message}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const statusColors: Record<string, string> = { connected: 'success.main', connecting: 'warning.main', disconnected: 'text.secondary', error: 'error.main' };
|
const statusColors: Record<string, string> = { connected: 'success.main', connecting: 'warning.main', disconnected: 'text.secondary', error: 'error.main' };
|
||||||
@@ -955,11 +955,11 @@ function MCPSettings() {
|
|||||||
if (r?.success) {
|
if (r?.success) {
|
||||||
loadServers();
|
loadServers();
|
||||||
} else {
|
} else {
|
||||||
import('metona-toast').then((mod) => mod.default.error(r?.error ?? '操作失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(r?.error ?? '操作失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[SettingsModal]', err);
|
console.error('[SettingsModal]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error(`操作失败:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`操作失败:${(err as Error).message}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
}}>{s.status === 'connected' ? '断开' : '连接'}</Button>
|
}}>{s.status === 'connected' ? '断开' : '连接'}</Button>
|
||||||
{/* L-11 修复: 点击移除打开 MUI Dialog 二次确认,而非原生 confirm() */}
|
{/* L-11 修复: 点击移除打开 MUI Dialog 二次确认,而非原生 confirm() */}
|
||||||
@@ -1244,10 +1244,10 @@ function LogsSettings() {
|
|||||||
try {
|
try {
|
||||||
const r = await window.metona?.app?.showItemInFolder?.(logFilePath);
|
const r = await window.metona?.app?.showItemInFolder?.(logFilePath);
|
||||||
if (r && !r.success) {
|
if (r && !r.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`打开失败: ${r.error ?? '未知错误'}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`打开失败: ${r.error ?? '未知错误'}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`打开失败: ${(e as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`打开失败: ${(e as Error).message}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1260,7 +1260,7 @@ function LogsSettings() {
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
setCopyState('error');
|
setCopyState('error');
|
||||||
setTimeout(() => setCopyState('idle'), 1500);
|
setTimeout(() => setCopyState('idle'), 1500);
|
||||||
import('metona-toast').then((mod) => mod.default.error(`复制失败: ${(e as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`复制失败: ${(e as Error).message}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1272,11 +1272,11 @@ function LogsSettings() {
|
|||||||
const b = new Blob([JSON.stringify(r.data, null, 2)], { type: 'application/json' });
|
const b = new Blob([JSON.stringify(r.data, null, 2)], { type: 'application/json' });
|
||||||
const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = `metona-export-${Date.now()}.json`; a.click();
|
const a = document.createElement('a'); a.href = URL.createObjectURL(b); a.download = `metona-export-${Date.now()}.json`; a.click();
|
||||||
} else {
|
} else {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`导出失败: ${r.error ?? '未知错误'}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`导出失败: ${r.error ?? '未知错误'}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[LogsSettings]', err);
|
console.error('[LogsSettings]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error(`导出失败: ${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`导出失败: ${(err as Error).message}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const labels: Record<string, string> = { sessions: '所有会话', memories: '所有记忆', auditLogs: '审计日志' };
|
const labels: Record<string, string> = { sessions: '所有会话', memories: '所有记忆', auditLogs: '审计日志' };
|
||||||
@@ -1293,7 +1293,7 @@ function LogsSettings() {
|
|||||||
else if (type === 'memories') r = await window.metona?.data?.clearMemories();
|
else if (type === 'memories') r = await window.metona?.data?.clearMemories();
|
||||||
else r = await window.metona?.data?.clearAuditLogs();
|
else r = await window.metona?.data?.clearAuditLogs();
|
||||||
if (r?.success) {
|
if (r?.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.success(`${labels[type]}已清理`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.success(`${labels[type]}已清理`)).catch(() => {});
|
||||||
// 修复: 清理会话后同步清空前端状态,无需重启应用
|
// 修复: 清理会话后同步清空前端状态,无需重启应用
|
||||||
if (type === 'sessions') {
|
if (type === 'sessions') {
|
||||||
useSessionStore.getState().setSessions([]);
|
useSessionStore.getState().setSessions([]);
|
||||||
@@ -1306,10 +1306,10 @@ function LogsSettings() {
|
|||||||
useUIStore.getState().bumpMemoryVersion();
|
useUIStore.getState().bumpMemoryVersion();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`失败: ${r?.error ?? '未知错误'}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`失败: ${r?.error ?? '未知错误'}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(`失败: ${(e as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`失败: ${(e as Error).message}`)).catch(() => {});
|
||||||
}
|
}
|
||||||
setClearing(null);
|
setClearing(null);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export function TaskList(): React.JSX.Element {
|
|||||||
const handleCreate = async () => {
|
const handleCreate = async () => {
|
||||||
if (!sessionId) {
|
if (!sessionId) {
|
||||||
// 用户主动操作失败应用 toast(与项目惯例一致)
|
// 用户主动操作失败应用 toast(与项目惯例一致)
|
||||||
import('metona-toast').then((mod) => mod.default.error('请先选择或创建会话')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('请先选择或创建会话')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!newTitle.trim()) {
|
if (!newTitle.trim()) {
|
||||||
@@ -128,7 +128,7 @@ export function TaskList(): React.JSX.Element {
|
|||||||
priority: newPriority,
|
priority: newPriority,
|
||||||
});
|
});
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(res.error ?? '创建任务失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '创建任务失败')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setNewTitle('');
|
setNewTitle('');
|
||||||
@@ -136,7 +136,7 @@ export function TaskList(): React.JSX.Element {
|
|||||||
setShowAddForm(false);
|
setShowAddForm(false);
|
||||||
await loadTasks(sessionId);
|
await loadTasks(sessionId);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '创建任务失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '创建任务失败')).catch(() => {});
|
||||||
} finally {
|
} finally {
|
||||||
setCreating(false);
|
setCreating(false);
|
||||||
}
|
}
|
||||||
@@ -149,12 +149,12 @@ export function TaskList(): React.JSX.Element {
|
|||||||
try {
|
try {
|
||||||
const res = await window.metona.tasks.update(task.id, { status: nextStatus }, sessionId);
|
const res = await window.metona.tasks.update(task.id, { status: nextStatus }, sessionId);
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(res.error ?? '更新任务失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '更新任务失败')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await loadTasks(sessionId ?? undefined);
|
await loadTasks(sessionId ?? undefined);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '更新任务失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '更新任务失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -164,13 +164,13 @@ export function TaskList(): React.JSX.Element {
|
|||||||
try {
|
try {
|
||||||
const res = await window.metona.tasks.delete(id, sessionId);
|
const res = await window.metona.tasks.delete(id, sessionId);
|
||||||
if (!res.success) {
|
if (!res.success) {
|
||||||
import('metona-toast').then((mod) => mod.default.error(res.error ?? '删除任务失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(res.error ?? '删除任务失败')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (expandedId === id) setExpandedId(null);
|
if (expandedId === id) setExpandedId(null);
|
||||||
await loadTasks(sessionId ?? undefined);
|
await loadTasks(sessionId ?? undefined);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
import('metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除任务失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error((err as Error).message ?? '删除任务失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ export function WorkspaceViewer(): React.JSX.Element {
|
|||||||
await window.metona?.app?.showItemInFolder(path);
|
await window.metona?.app?.showItemInFolder(path);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('[WorkspaceViewer]', err);
|
console.error('[WorkspaceViewer]', err);
|
||||||
import('metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('打开文件夹失败')).catch(() => {});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ export function useKeyboardShortcuts(): void {
|
|||||||
}).catch((err) => {
|
}).catch((err) => {
|
||||||
console.error('[KeyboardShortcuts]', err);
|
console.error('[KeyboardShortcuts]', err);
|
||||||
// 与 Sidebar/CommandPalette 入口对齐:失败时弹 toast 提示用户
|
// 与 Sidebar/CommandPalette 入口对齐:失败时弹 toast 提示用户
|
||||||
import('metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('创建会话失败')).catch(() => {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
@@ -171,7 +171,7 @@ export function useKeyboardShortcuts(): void {
|
|||||||
navigator.clipboard.writeText(lastAssistant.content).catch((err) => {
|
navigator.clipboard.writeText(lastAssistant.content).catch((err) => {
|
||||||
console.error('[KeyboardShortcuts]', err);
|
console.error('[KeyboardShortcuts]', err);
|
||||||
// 复制是用户主动操作,失败时必须有反馈
|
// 复制是用户主动操作,失败时必须有反馈
|
||||||
import('metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error('复制失败')).catch(() => {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ export const useAgentStore = create<AgentState>((set, get) => ({
|
|||||||
|
|
||||||
// v0.3.18 修复: 工具未就绪时阻止发送,避免 MCP 工具不可用
|
// v0.3.18 修复: 工具未就绪时阻止发送,避免 MCP 工具不可用
|
||||||
if (!get().toolsReady) {
|
if (!get().toolsReady) {
|
||||||
import('metona-toast').then((mod) => mod.default.warning('工具正在加载中,请稍候...')).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.warning('工具正在加载中,请稍候...')).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -295,7 +295,7 @@ export const useAgentStore = create<AgentState>((set, get) => ({
|
|||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
});
|
});
|
||||||
// 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见)
|
// 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见)
|
||||||
import('metona-toast').then((mod) => mod.default.error(`无法创建会话:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`无法创建会话:${(err as Error).message}`)).catch(() => {});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -376,7 +376,7 @@ export const useAgentStore = create<AgentState>((set, get) => ({
|
|||||||
timestamp: Date.now(),
|
timestamp: Date.now(),
|
||||||
});
|
});
|
||||||
// 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见)
|
// 额外弹 toast 作为通知,确保用户感知(system message 仅在聊天流内可见)
|
||||||
import('metona-toast').then((mod) => mod.default.error(`消息发送失败:${(err as Error).message}`)).catch(() => {});
|
import('@metona-team/metona-toast').then((mod) => mod.default.error(`消息发送失败:${(err as Error).message}`)).catch(() => {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user