Repository navigation
Feat/agent runtime node - #1
Conversation
新增 docs/agent-protocol.md 作为协议单一真源,覆盖 SSE 字段派生规则、事件生产者边界、请求体契约、18 个工具规格与循环行为。新增 scripts/agent-baseline 工具链:mock LLM 服务(支持分片 tool_call arguments)、golden SSE 抓取、归一化与逐事件 diff。已针对 Python 实现抓取 11 个场景作为冻结基准。 Co-authored-by: Cursor <cursoragent@cursor.com>
新增 src/main/agent:utilityProcess 入口(runtime.ts)、主进程宿主(host.ts)、对称 RPC 桥(bridge.ts)、主进程能力面(ipcSurface.ts)、回环 HTTP 服务(server.ts)与路由表(routes.ts,阶段 1 为 501 骨架)。webpack 增加 agentRuntime 入口。workspace handler 回调体抽为 workspaceOperations.ts,供渲染层 IPC 与运行时 RPC 双端复用,保证授权根校验与 file-system 广播行为一致。serverProcess.ts 增加 LR_AGENT_RUNTIME 开关(默认仍走 Python,Node 侧阶段 2 前只有骨架)。新增 Electron fork 冒烟脚本,已通过真实 utilityProcess 验证 fork/ready/RPC/优雅退出。 Co-authored-by: Cursor <cursoragent@cursor.com>
新增 SSE 契约模块(toSseDict 逐条复刻字段派生规则)、OpenAI 兼容流式客户端与 tool_call 分片累积器、Assist 循环(轮次预算、五道过滤、阶段门禁、tool_choice=any 兜底、取消)、工具注册表(zod 为校验与 schema 单一来源)与只读工具(读取/搜索/列目录/元信息)。新增 workspacePath 移植路径解析与安全校验,fileSearch 用异步 I/O 实现栈式 DFS 遍历。golden diff 结果:11 个场景中 7 个通过(含 reasoning 的已记录差异),剩余 4 个属阶段 3/6 范围。修复过程中发现真实缺陷:工具可执行性必须以模式裁剪后的工具集为准而非全量注册表,否则越界调用会错误执行且 tool_choice=any 兜底会误触发。 Co-authored-by: Cursor <cursoragent@cursor.com>
移植 ProposalStreamInterceptor:在 astream 期间按 tc_index 增量解析半截 JSON(含 uXXXX 转义与代理对合成),实时发出 file_proposal_start / file_proposal_delta / file_edit_delta;按码点而非 UTF-16 码元计数,避免 emoji 内容被切在代理对中间。移植 4 个写入类提案工具与 pendingProposals 基线接力(同轮多次 str_replace 累积为同一份提案)。新增 pythonJsonDumps 对齐 json.dumps 的分隔符空格,修正提案失败时原样回灌完整 JSON 的分支赋值语义。golden diff 11 场景通过 10(仅余 subagent 属阶段 6 范围);主进程测试 269/269 通过。 Co-authored-by: Cursor <cursoragent@cursor.com>
新增 agentImage 模块:文件头解析(PNG/JPEG/GIF/WebP/BMP/ICO 的尺寸与格式)+ 基于 nativeImage 的裁剪/缩放/JPEG 编码,零新增依赖替代 Pillow;显式把 RGBA 合成到白底以对齐 Pillow 的 JPEG 输出。新增 imageService 分层:探测为纯函数(独立模式亦可),编码经 RPC 走主进程。补齐 read_file_annotation(直接 import 主进程 annotationDataStore 复用 sha256 fileKey,无重复实现)、read_document_file(DOCX 用 mammoth 懒加载,PDF 用自研轻量提取器,覆盖 FlateDecode 与 Tj/TJ/引号算子、转义、UTF-16BE)、read_image_for_vision(附图标记与路径存在性校验)。顺带修正 Python 侧 pypdf/python-docx 未声明依赖导致该工具在干净环境不可用的问题。golden diff 保持 10/11;主进程测试 308/308。 Co-authored-by: Cursor <cursoragent@cursor.com>
新增 context/multimodal(路径优先的附图构造,编码失败退化为纯文本)与 vision/autoLoader(VisionAutoLoader 等价实现:触发条件严格合取,仅首轮无 tool call 时兜底一次)。接通 nativeImage 编码能力。修正一处语义:视觉结果显示用 stripInternalMarkers 的完整缩进 JSON,而非 formatToolResultForDisplay 的 summary/message 折叠。golden diff 保持 10/11;主进程测试 336/336。 Co-authored-by: Cursor <cursoragent@cursor.com>
新增 subagent/exploreReadonly:嵌套只读循环(8 个内层工具白名单、禁用名单含记忆与视觉工具、子代理轮上限、收尾摘要轮不带工具),产出完整 subagent_* 事件族;保留三处与主循环的刻意差异(不做父级去重/门禁、allowed 回灌原文而 blocked 用完整 JSON、收尾轮不绑工具)。接入主循环时为 explore 调用单开一路(tool_start 只发一次,与基线一致)。新增 mcp/client:用已依赖的 @modelcontextprotocol/sdk 替换 langchain-mcp-adapters,保留 TTL 缓存 + stale-while-revalidate + 单台失败隔离 + 名字去重;MCP 工具自带 JSON Schema 直接透传(新增 rawParameters)。接通 /agent/mcp/probe。golden diff 达成 11/11 全通过;主进程测试 362/362。 Co-authored-by: Cursor <cursoragent@cursor.com>
新增 annotate 模块:公共基础(extractJsonObject 对齐 Python 的三步解析、invokeJsonModel 刻意不用 response_format、Unicode 孤立代理清洗、LLM 错误分流)、zod 重建的四个请求 schema、mutation-prepare(含 Pydantic model_dump 等价实现:输出全部 28 个字段并把未设值者置 null)、llm-generate(图片三分支:加载失败 400 / 路径优先 base64 兜底 / 压缩失败回退原图)、质量报告流式撰写(payload 512KB 校验 + 48k 截断,异常时发 error 事件)。扩展 AgentSettings 补全标注相关配置项。主进程测试 422/422。 Co-authored-by: Cursor <cursoragent@cursor.com>
新增 5 个支撑模块:scope(中文范围推断,含贪婪正则导致的「同一行合并」行为)、visionPolicy(81 项 COCO 类名表)、heuristic(三级优先级的类名/OCR 匹配)、validation(四条校验规则 + 逐框重试候选)、labelPool(整图 preflight 缩池,user_request 刻意不参与缩池以免误伤)。mapLabels 实现两条映射路径(vision_crop 走 nativeImage 批量裁剪 + 校验重试;heuristic 无 LLM)与 single_label 快捷路径。修正 cropImageBatch 的钳位以完全对齐 Python 的 max(left+1, ...) 语义。新增 pyRepr/pyIntListRepr 使含 {name!r} 的错误文案与映射理由逐字一致。四个标注端点至此全部迁移;golden diff 保持 11/11;主进程测试 513/513。
Co-authored-by: Cursor <cursoragent@cursor.com>
删除 vendor/local-agent(125 个文件、约 16000 行)与 src/main/localAgent/serverProcess.ts;主进程改为直接启动 Node 运行时(utilityProcess)。移除嵌入式 Python 运行时:删除 scripts/fetchPythonRuntimes.mjs、assets/python-runtime 与对应 extraResources,package 脚本不再拉取运行时。env 体系收敛:LocalAgentEnvStatus 去掉全部 Python 字段(改为仅报告服务是否运行)、InstallTarget 只剩 inference、环境向导与横幅不再要求 Python(Agent 编排面板改为纯状态展示)、skillScriptRunner 的 .py 解释器降级为系统 Python。inference 保留为可选自装(conda),安装入口在缺少内置运行时后给出明确的自建指引。README 与基线文档同步更新;冻结基准 .baseline/python 保留(原实现已删,无法重新生成)。主进程测试 513/513;golden diff 11/11。 Co-authored-by: Cursor <cursoragent@cursor.com>
electronForkSmoke 的 /chat/cancel 断言从「骨架 501」更新为「已实现 200 + {ok:true}」。三处 SSE 字段兜底补充注释,说明主字段为 camelCase、snake_case 分支仅用于历史数据渲染(运行时不会产出),保留而不删除。全部测试 935/935。
Co-authored-by: Cursor <cursoragent@cursor.com>
四类缺陷: 1) 流式故障静默(src/main/agent/loop/assistLoop.ts、sse.ts):主循环的 astream 缺 try/catch,LLM 失败时异常被 SSE 层吞掉、客户端读到 EOF 后合成 done,用户只看到回复被截断而无任何提示。新增 sse.error 事件与 streamAssist 兜底外壳;取消(isCancelled/AbortError)不报错,避免「点了停止却弹错误」。 2) 凭据错误码误报(src/main/agent/annotate/common.ts):requireCredentials 抛出的 400 provider_credentials_required 被 httpFromLlmError 落进 502 兜底分支,把「凭据没填」报成「上游坏了」。改为 AnnotateHttpError 原样透传,并读取 LlmRequestError.status 正确映射上游 4xx。 3) 运行时崩溃后永久失联(src/main/agent/host.ts):退出后无人重启且渲染层缓存 baseUrl,后续请求全部打向死端口。新增指数退避自动重启(500ms→8s、上限 5 次、稳定 30s 清零),启动阶段失败同样计入预算;stopAgentRuntime 置 intentionalStop 并取消待触发定时器。 4) 标注文档错位(src/renderer/context/AnnotationWorkspaceContext.tsx):加载流水线分开赋值 currentPairRef/loadedMetaRef/dirtyRef,在 React 异步提交窗口内防抖保存会把 A 的文档写进 B 的槽位,导致 filePath/source/annotations 全部错位。改为同步原子写 ref、加载前取消悬挂保存,并在 persistFromRefs 加「meta.filePath 与 relPath 必须一致」守卫(不一致则跳过保存而非写坏数据);加载时就地修正历史脏 filePath,使其可继续保存。annotationDoc 返回时按请求路径对齐 filePath,避免把历史脏数据当作工具字段错位反馈给模型。 验证:tsc 通过;jest 935/935 + 新增 16 个用例(退避策略 9、标注文档 7);golden diff 11/11 无回归。 Co-authored-by: Cursor <cursoragent@cursor.com>
补齐上一提交的配套缺陷:运行时会换端口与 token,但渲染层把地址缓存为模块级常量且永不失效,导致重启后请求全部打向已死端口且无法自愈(表现为 network error 后必须手动刷新页面)。 config.ts:新增 invalidateLocalAgentAuth/hasLocalAgentAuth;localAgentFetch 增加一次自愈重试——网络异常时清缓存并重新向主进程解析地址后重试(覆盖「旧端口已死」与「此前回退到默认端口」两种情形),401 且此前发过 token 时同样重试(覆盖「端口复用但 token 已换」);用户取消不重试;重试后仍失败统一抛「本机 Agent 服务未就绪」,不再把裸 Failed to fetch 漏给 UI。重试按 URL 改写 protocol+host,5 个调用点无需改动。 EnvironmentContext:订阅 localAgent:status 时失效缓存,使主进程推送的 running(新端口)立即生效。 docs/agent-protocol.md:error 事件的生产者边界由「仅渲染层合成」更正为「运行时在非取消故障时也会发射」,并说明取消不报错的语义。 验证:tsc 通过;jest 962/962(新增 config 缓存自愈 11 例);golden diff 11/11。 Co-authored-by: Cursor <cursoragent@cursor.com>
按「结果可审阅性 × 错误代价」分层,而非「是否文件改写」: 免确认(直接落盘)—— 工作区文件写入/替换/删除/移动(4 个 PROPOSAL 工具)与标注编辑(mutate_annotation)。前者 diff 可扫读、指令明确;后者是定点修改且有改前快照兜底。两者都随时可撤销。 保留确认 —— 标注生成(auto_annotate)。由模型推理产出、审阅需逐框看图、replace_matching 会覆盖已有标注,错误代价最高。 实现: 1. agentProposalApply 新增 selectAutoApplicableProposals / applyAutoApplicableProposals,按 sourceKind==='mutation' 与 file_proposal 筛选;必须等 contentFinalized 为真才落盘(否则会写入空内容/半截内容);sourceKind 缺失时用与 agentChatStore 同一份 inferAnnotationProposalKind 做内容推断(该函数已提到 pipelineKinds.ts 共用)。 2. AgentChatContext 以响应式 effect 触发自动应用(覆盖重启恢复与历史重放),带重入守卫与失败去重(失败保持 pending 并提示,不静默吞掉、不反复刷错)。 3. agentJobRegistry 的 formatAnnotationToolResult 新增 autoApplied:mutate_annotation 报 proposal_pending=false + file_written=true,因此不再进入 AwaitingConfirm 断点(该断点现仅由标注生成与终端审批触发)。 4. 撤销入口显式化:复用已有 undoAssistantChanges,落到消息的 Files Changed 汇总卡右上角与消息工具栏。 5. checkpoint 每会话上限 20 → 50,避免免确认后写入变多时最早(也最可能需回滚)的快照被先行清除。 文案同步:fileProposal 的工具结果、registry 的工具描述、contextService 的 resume 提示、协议文档与类型注释均改为「已直接落盘、可撤销」。 验证:tsc 通过;jest 977/977(新增 15 例:筛选 9、格式化 3、checkpoint 上限 1 等);golden diff 11/11 —— 其中 proposal-write / proposal-edit 的 tool_result 文案差异属本次有意变更,已在 KNOWN_DIVERGENCES 中以**字段级**豁免记录(其余字段、事件顺序与条数仍严格校验),并用负向测试确认 gate 未被削弱。 Co-authored-by: Cursor <cursoragent@cursor.com>
1) 竞态修复(方案 B):标注工具是 ASYNC,每次调用会发 tool_pending 并 resume;resume 前会同步构建 proposal_states,若此时提案仍是 pending,阶段机会误判 AWAIT_CONFIRM,把紧随其后的 auto_annotate(重新标注)拦掉——表现为「删除已落盘、但重新标注被拒」。改为 ClientToolContext 提供 applyAutoApplicable 回调,客户端工具在产出提案后 await 它完成落盘,再据实组合工具结果(成功→proposal_pending=false;失败→保持 true 并如实报告,job 停在确认断点等用户处理,绝不谎报已写盘)。AgentChatContext 中的 effect 退化为兜底(覆盖重启恢复与历史重放),并把落盘逻辑提为 flushAutoApplicable 供两条路径共用。 2) 措辞清理:模型此前会提到 Keep All,因为 RESUME_APPLIED_NEXT_HINT 声称「用户已 Keep All」、VERIFY 阶段提示写「已由用户 Keep All 并写盘」——但免确认后落盘由系统完成。改为「改动已落盘/标注变更已落盘」,AWAIT_CONFIRM 文案明确指向「标注生成提案」(该断点现在只由标注生成与终端审批触发)。同步修正 4 处「经用户确认落盘」与若干过时注释。 3) UI:删除 Files Changed 卡片里重复的撤销入口,只保留消息工具栏的撤销图标。 验证:tsc 通过;jest 979/979(新增自动落盘失败与优先级 2 例,修正 1 处措辞断言);golden diff 11/11。 Co-authored-by: Cursor <cursoragent@cursor.com>
运行时与协议:LlmClient 增加网络层重试(指数退避,取消/超时/HTTP 错误不重试);MCP 客户端区分传输类型,SSE 复用发现连接供 invoke 使用(会话绑定服务端不再「列出成功、调用失败」),连接加超时兜底、清缓存时统一关闭;新增内置 async 工具 start_terminal_command(锁定工作区 cwd,需用户批准)。 任务阶段门禁:�pplied 只看本轮且只看生成类操作(append/replace/replace_bboxes),修复「先删除再重新标注」被自身前置删除拦死;pending 仍按全会话聚合。proposal_states 新增 sourceKind / inCurrentTurn 判据并贯通 schema 与前端账本。 标注与快照:新增标注文档 ilePath 冗余字段幂等修复(归属真源是存储键),避免加载时改写字节导致 Undo 误判脏;检查点只要捕获成功即可回滚, estore 支持 orce 跳过完整性与脏检查。 预标注体验:模型下拉空态给出可读原因,检测模式声明与权重路径证据矛盾时内联告警;补充相应单测与协议文档。 Co-authored-by: Cursor <cursoragent@cursor.com>
CI 的 npm run lint 一直是红的(330 error / 248 warning、涉及 61 个文件), 根因是迁移期新写的文件从未经过 prettier 校验——该分支此前一次 CI 都没跑过。 其中 325 个可自动修,本次用 eslint --fix 一次性清干净。 剩余 6 个为不可自动修,逐一最小改动处理(语义等价): - heuristic.ts: 两处 chosen = arr[0] 改数组解构 - proposalStreamer.ts: indexOfSequence 的带标签循环改为 matched 标志位; mergeArgs 中「已见前缀重复投递 → 忽略」的空分支补注释(no-empty 允许含注释块) - llm/client.ts: 3 个类同属单一协议层(错误契约 / 客户端 / 流式累积器), 拆分只会切碎契约,故加带理由的文件级 max-classes-per-file 豁免 prettier 之后 lint 从 330 error 降到 0;248 个 warning (no-console 142 / react-hooks/exhaustive-deps 52 / no-unused-vars 41)按现状保留,不阻塞 CI。 顺带修 lockfile 与 package.json 不同步:zod 只加进了 package.json 而 package-lock.json 未更新(root deps 缺失,仅 node_modules 里有), npm install 重新生成后 +zod 一行。修掉后 CI 才具备切换到 npm ci 的前提。 验证:npm run lint 0 error;npm exec tsc 通过;npx jest --ci 113 suites / 1036 tests 全通过。 Co-authored-by: Cursor <cursoragent@cursor.com>
编排已迁到 Node 运行时,但 workflow 一行没动,导致两处必挂: - python-envs 的 npm run fetch-python-runtimes 脚本与 fetchPythonRuntimes.mjs 都已删除(本地实测 Missing script),后续 smoke-test 连坐 skip; 即便过了,scripts/ciInstallAndTest.mjs 也硬引用已删的 vendor/local-agent/requirements.txt 与 assets/python-runtime/py312。 - frontend 的 Cache embedded Python runtimes 步指向不存在的路径, hashFiles 取到空哈希,退化为空转。 test.yml 重写为 5 个互不依赖的 job(原先 lint 一挂就把 typecheck / test 全 skip,一次只能拿到三分之一信号): - lint / typecheck / test / package 拆开,各自独立给信号 - test 先跑 npm run build,因为 jest 的 setupFiles 里 check-build-exists.ts 会断言 dist 产物存在 - 新增 baseline-selftest:Agent 运行时的协议契约测试,此前完全没进 CI; 该脚本零外部依赖(scenarios.mjs 无 import),故不装 node_modules - python-envs 重做为 inference-lite:不再建 venv 装 torch/sam2 跑 90 分钟 冒烟(嵌入式运行时已移除,产品语义也变成用户自备 conda),改为零依赖静态校验 新增 scripts/ciCheckInferenceManifests.mjs,把原来只靠注释互相声称的 「envInstaller.ts 与 requirements 保持字面同步」变成 CI 可验证的断言: SAM-2 改写链真能命中、torch 索引 URL 与清单本地版本标签一致、 cpu/gpu 两份清单除 torch 系列外零漂移、VERIFY_IMPORTS 每个 import 名 都能落到发行包、Python 编排残留引用不得回归、推理服务仍在打包清单内。 清理死代码:删 scripts/ciInstallAndTest.mjs;.eslintignore 移除 assets/python-runtime/ 与 .ci-venvs/;.gitignore 移除对应段; envInstaller.ts 头部注释不再声称使用嵌入式运行时。 CodeQL 注释对齐(python 矩阵现在只覆盖 vendor/inference)。 验证:npm run lint 0 error;npm exec tsc 通过;npm run build 成功 (产出 dist/main/agentRuntime.js);npx jest --ci 113 suites / 1036 tests 全通过;npm run baseline:selftest 全通过;新检查脚本全通过 (并已实测其在残留引用存在时确实报错)。 Co-authored-by: Cursor <cursoragent@cursor.com>
SECURITY.md 通篇仍是 Python 编排时代的描述,其中『本地 Agent(vendor/local-agent) 经 FastAPI require_local_token 鉴权』与『cd vendor/local-agent && python -m pytest』 两处已经跑不了。按现状改写: - 头部定位改为 Electron + Node 版 Agent 运行时 - 本地服务鉴权:改为 utilityProcess.fork 启动 agentRuntime.js、随机 token 经 LR_AGENT_LOCAL_TOKEN 注入、server.ts 除 /health 外常量时间 Bearer 校验、 未配置 token 时拒绝启动(与迁移前同一失败关闭语义) - 写盘白名单去掉已不存在的 Python 副本引用,唯一真源仍是 src/shared/workspaceTextExtensions.ts - 测试一节改为实际的 npm run lint / npm exec tsc / npm test / baseline:selftest, 并说明推理侧(vendor/inference)无单测、由 CI 做语法与清单校验 - 反序列化审计去掉 vendor/local-agent(其替代实现是 TS,由 javascript 矩阵覆盖) 另:.erb/scripts/check-build-exists.ts 原先只断言 dist/main/main.js 与 dist/renderer/renderer.js。Agent 运行时是独立 webpack 入口,缺失时只在运行期 才失败,构建与 jest 都无感,故补上 agentRuntime.js 的断言 (已实测:移走产物后 jest 立即以明确提示失败)。 Co-authored-by: Cursor <cursoragent@cursor.com>
CodeQL 的 code-scanning 门禁(check 名也叫 CodeQL,与 workflow run 的 success 是两回事)在 PR 上一直红,3 个告警自分支首次推送 485419c 即存在,与本次 CI 改造 无关(只是 prettier 格式化让 server.ts 的行号移了一位)。 真问题(已修):路由 handler 抛出未预期异常时,500 响应把 err.message 回传给 调用方,命中 js/stack-trace-exposure —— 异常消息常夹带绝对路径与依赖库内部片段。 改为响应体只含 { detail: 'internal_error' },完整消息只进服务端日志 (onLog → 主进程),开发期看日志即可。 没有采用「加开关按环境回传」的方案:那样污点流在静态上依然存在,告警不会消失。 误报(按 query id 排除,附理由): - js/cors-misconfiguration-for-credentials:本仓库的 CORS 实现正是该查询官方文档 给出的 GOOD 写法 —— Origin 必须命中显式白名单才回显(未命中连 ACAO 头都不设), 且启动期 assertCorsConfig 拒绝 '*'。CodeQL 看不穿 resolveCorsOrigin 这层 helper。 - js/clear-text-logging:唯一命中点是本地冒烟脚本 electronForkSmoke.cjs(不参与 打包),被判「敏感」的实际只有 HTTP 状态码与 {"ok":true} 这类响应体。 新增 .github/codeql/codeql-config.yml 按 query id 排除这两条,不改动查询集(保持 默认 code-scanning suite),每条排除附理由与依据链接;workflow 以 config-file 引用。 SECURITY.md 同步记录该排除策略与「错误详情不外泄」的约定。 验证:npm run lint 0 error;npm exec tsc 通过;npx jest --ci 113 suites / 1036 tests 全通过(server.test.ts 新增用例断言 500 响应体不含内部细节、 但完整消息仍进服务端日志)。 Co-authored-by: Cursor <cursoragent@cursor.com>
CI 改造与 CodeQL 处置说明分支此前从未推送过,因此这条流水线一次都没跑过。首次推送后暴露的问题分三类,已全部处理: 一、原
|
| commit | 内容 |
|---|---|
bb4c6e6 |
chore(lint):330 error → 0(325 自动 + 6 手工),同步 package-lock.json 补 zod |
2f63a48 |
ci:test.yml 重写为 6 个独立 job、新增清单校验脚本、删失效脚本、codeql/eslintignore/gitignore 清理 |
457333e |
docs:SECURITY.md 对齐 Node 运行时 + check-build-exists 补 agentRuntime 断言 |
e19defa |
fix(agent):不再回传异常消息 + 排除两条 CodeQL 误报 |
.github/workflows/test.yml:2 job → 6 个互不依赖的 job
lint / typecheck / test / package 拆开,各自独立给信号;test 因 jest 的 setupFiles(.erb/scripts/check-build-exists.ts)会断言 dist 产物存在,故先跑一次 npm run build。
新增两个 job:
baseline-selftest—— Agent 运行时的协议契约测试(起 mock LLM server 校验 SSE chunk 序列与 tool_call 分片重组),此前完全没进 CI。该脚本零外部依赖,故不装node_modules。inference-lite—— 替代原python-envs。预标注推理(vendor/inference)仍是发布产物,但它依赖的嵌入式运行时已移除、产品语义也变成「用户自备 conda」,无法再在 CI 里建环境冒烟,改为零依赖的静态校验。
新增 scripts/ciCheckInferenceManifests.mjs
把原来只靠注释互相声称的「envInstaller.ts 与 requirements 保持字面同步」变成 40 条可执行断言:SAM-2 改写链在真实清单上确实命中、torch 索引 URL 与清单本地版本标签一致、cpu/gpu 两份清单除 torch 系列外零漂移、VERIFY_IMPORTS 每个 import 名都能落到发行包、Python 编排残留引用不得回归、推理服务仍在打包清单内。
CodeQL:1 修 + 2 排除
- 真问题(已修)
js/stack-trace-exposure@src/main/agent/server.ts:500 响应把err.message回传调用方。改为只回{ detail: 'internal_error' },完整消息只进服务端日志。没有采用「按环境开关回传」的方案 —— 那样污点流静态上依然存在,告警不会消失。 - 误报(排除,附理由)
js/cors-misconfiguration-for-credentials:本仓库实现正是该查询官方文档给出的 GOOD 写法 —— Origin 必须命中显式白名单才回显(未命中连 ACAO 头都不设),且启动期assertCorsConfig拒绝*。CodeQL 看不穿resolveCorsOrigin这层 helper。js/clear-text-logging:唯一命中点是本地冒烟脚本electronForkSmoke.cjs(不参与打包),被判「敏感」的实际只有 HTTP 状态码与{"ok":true}这类响应体。- 新增
.github/codeql/codeql-config.yml按 query id 排除,不改动查询集(保持默认 code-scanning suite),每条附理由与依据链接。
验证
本地:npm run lint 0 error(248 warning 按现状保留,不阻塞)/npm exec tsc 通过/npm test -- --ci 113 suites、1036 tests 全通过/npm run build 成功(产出 dist/main/agentRuntime.js)/npm run baseline:selftest 全通过/清单检查脚本全通过。
两个断言脚本均做过「反向验证」,确认不是空跑:移走 agentRuntime.js 后 jest 立即以明确提示失败;清单检查脚本在残留引用存在时确实报错。
CI:push 与 pull_request 两轮 Test 各 6/6 job success,CodeQL 报 No new alerts in code changed by this pull request。
两点待办(未做,供决策)
- job runner 仍是
windows-latest。原计划改用ubuntu-latest提速(除package外),但本机无法验证 Linux 上npm install的postinstall(electron-builder install-app-deps→electron-rebuild,含@parcel/watcher等原生模块)能否正常跑完,因此先保留当前已实证可行的 windows。若要切换,建议单独试一次。 - 可选切
npm ci。lockfile 与package.json现已同步(本次补上了遗漏的zod),具备切换前提;切换后安装更快更可复现,但需要确认postinstall在--ignore-scripts等变体下的取舍。
No description provided.