【根因(main.log 实证)】 2026-08-22 20:31:22 / 20:32:31 两次 + 20:37:01 最终终止,完整因果链: 模型写大文件(22KB HTML,write_file)时输出 token 达上限 (finish_reason=length),流正常收尾但 tool_call 的 arguments JSON 半截 ("Unterminated string in JSON at position 21890/22686")。 缺陷链: 1. SSE 解析器对 parse 失败的 tool call 静默丢弃(log.warn 后 continue — #25 时代为防单个坏 JSON 丢弃全部而引入) 2. 该轮模型输出全部是这一个 tool call → 丢弃后引擎看到"零工具调用 + 零文本"→ 误判为模型已完成 → COMPLETED + 空回复(OutputValidator 报 "Output is empty" 仅 warn 不阻断) 3. 用户感知:AI 干了 16 轮 10.5 分钟后会话无声停止、没有最终回复 20:31/20:32 两次截断后模型自行重试(日志可见继续 EXECUTING), 但 20:37 最后一轮再次截断且无重试机会 → 空回复终止。 【修复(sse-stream.ts — DeepSeek/Agnes/MiMo 三家共享)】 - flushToolCallBuffer: parse 失败的 tool call 不再丢弃 — 转为携带 _truncatedArguments + _truncatedReason(明确告知模型"参数因输出长度 限制被截断,请分块重试、勿复用原参数")的 TOOL_CALL_COMPLETE。 工具执行将因参数缺失失败,错误结果回传模型 → 模型感知截断后分块 写入(ReAct 自愈路径)。无限循环由引擎死循环检测器兜底 - 流断开兜底: read() done 但从未收到 [DONE](连接中断)时补 flush + DONE — 原实现缓冲整体丢失且引擎收尾路径行为未定义 - finish_reason=length 显式 warn 日志(含缓冲字节数)— 归因能力 - 空 argsBuffer 的 tool call(无参工具)显式产出 args={}(原实现走 JSON.parse('') 会进 catch,行为巧合正确但语义混乱) 【测试】 +5 用例(sse-truncation.test.ts): 截断转错误说明 / 无 [DONE] 兜底 / 完整 JSON 回归 / 空 args 回归 / finish_reason=tool_calls 提前 flush 更新 1 旧用例: "损坏 JSON 跳过" → "损坏 JSON 转截断错误 tool call" (行为变更的契约级断言) 【验证】 lint 0/0;typecheck 双工程 0 错误;test:electron 264/264(+5); electron-vite build 成功
99 lines
3.0 KiB
JSON
99 lines
3.0 KiB
JSON
{
|
|
"name": "metona-ai-desktop",
|
|
"version": "0.6.3",
|
|
"description": "MetonaAI Desktop — 生产级通用 AI Agent 智能体桌面应用",
|
|
"main": "dist-electron/main/main.js",
|
|
"author": "Metona Team",
|
|
"license": "MIT",
|
|
"type": "module",
|
|
"scripts": {
|
|
"dev": "electron-vite dev",
|
|
"build": "npm run prebuild && electron-vite build && electron-builder",
|
|
"prebuild": "npm dedupe && node -e \"require('fs').rmSync('release',{recursive:true,force:true})\"",
|
|
"build:renderer": "electron-vite build --rendererOnly",
|
|
"build:electron": "tsc -p tsconfig.node.json",
|
|
"preview": "vite preview",
|
|
"lint": "eslint .",
|
|
"lint:fix": "eslint . --fix",
|
|
"format": "prettier --write \"src/**/*.{ts,tsx,css}\" \"electron/**/*.ts\"",
|
|
"typecheck": "tsc --noEmit -p tsconfig.node.json && tsc --noEmit -p tsconfig.web.json",
|
|
"typecheck:node": "tsc -p tsconfig.node.json --noEmit",
|
|
"test": "vitest run",
|
|
"test:watch": "vitest",
|
|
"test:electron": "cross-env ELECTRON_RUN_AS_NODE=1 electron node_modules/vitest/vitest.mjs run",
|
|
"prepare": "husky"
|
|
},
|
|
"lint-staged": {
|
|
"electron/**/*.{ts,tsx}": [
|
|
"eslint --fix",
|
|
"prettier --write"
|
|
],
|
|
"src/**/*.{ts,tsx}": [
|
|
"eslint --fix",
|
|
"prettier --write"
|
|
],
|
|
"src/**/*.css": [
|
|
"prettier --write"
|
|
]
|
|
},
|
|
"dependencies": {
|
|
"@emotion/react": "^11.14.0",
|
|
"@emotion/styled": "^11.14.1",
|
|
"@metona-team/metona-toast": "^0.5.0",
|
|
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
"@mui/icons-material": "^9.1.1",
|
|
"@mui/material": "^9.1.2",
|
|
"better-sqlite3": "^11.9.1",
|
|
"date-fns": "^4.1.0",
|
|
"dotenv": "^17.4.2",
|
|
"electron-log": "^5.3.3",
|
|
"fuse.js": "^7.1.0",
|
|
"lru-cache": "^11.1.0",
|
|
"nanoid": "^5.1.5",
|
|
"node-html-parser": "^6.1.13",
|
|
"react": "^19.1.0",
|
|
"react-dom": "^19.1.0",
|
|
"react-markdown": "^10.1.0",
|
|
"react-virtuoso": "^4.18.12",
|
|
"rehype-highlight": "^7.0.2",
|
|
"remark-gfm": "^4.0.1",
|
|
"shell-quote": "^1.10.0",
|
|
"zustand": "^5.0.5"
|
|
},
|
|
"devDependencies": {
|
|
"@electron-toolkit/preload": "^3.0.1",
|
|
"@electron-toolkit/utils": "^4.0.0",
|
|
"@eslint/js": "^9.39.5",
|
|
"@tailwindcss/typography": "^0.5.16",
|
|
"@tailwindcss/vite": "^4.1.7",
|
|
"@types/better-sqlite3": "^7.6.13",
|
|
"@types/node": "^22.15.29",
|
|
"@types/react": "^19.1.6",
|
|
"@types/react-dom": "^19.1.6",
|
|
"@types/shell-quote": "^1.7.5",
|
|
"@vitejs/plugin-react": "^4.5.2",
|
|
"autoprefixer": "^10.4.21",
|
|
"cross-env": "^10.1.0",
|
|
"electron": "^35.5.1",
|
|
"electron-builder": "^26.0.12",
|
|
"electron-vite": "^3.1.0",
|
|
"eslint": "^9.28.0",
|
|
"husky": "^9.1.7",
|
|
"lint-staged": "^17.3.0",
|
|
"lucide-react": "^0.511.0",
|
|
"postcss": "^8.5.4",
|
|
"prettier": "^3.5.3",
|
|
"tailwindcss": "^4.1.7",
|
|
"typescript": "^5.8.3",
|
|
"typescript-eslint": "^8.67.0",
|
|
"vite": "^6.3.5",
|
|
"vitest": "^3.2.1"
|
|
},
|
|
"allowScripts": {
|
|
"electron@35.7.5": true,
|
|
"better-sqlite3@11.10.0": true,
|
|
"esbuild@0.25.12": true,
|
|
"electron-winstaller@5.4.0": true
|
|
}
|
|
}
|