
local-deep-research 1.9.3 发布解析OrcaRouter 接入、DNS 重绑定加固与索引/检索缺陷修复【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research本文解读 local-deep-research 1.9.3 版本发布说明docs/release_notes/1.9.3.md逐项拆解该版本的 1 项安全修复、1 项新功能OrcaRouter LLM 提供方与 5 项缺陷修复。读完本篇后你将了解OrcaRouter 作为 OpenAI 兼容路由网关的配置方式与底层实现DNS 重绑定 TOCTOU 时间窗口是如何被单一解析遍次关闭的以及向量存储失败却标记为已索引、Flask 应用上下文丢失、余弦/点积索引排序反转等典型缺陷的根因与验证路径。一、1.9.3 版本全景1.9.3 是一次以正确性与安全性收口为主题的版本条目按发布说明分为四类分类条目数内容摘要 Security1通知Test按钮的 admin-hint 判定与默认级 URL 拒绝共享单次 DNS 解析关闭 DNS-rebinding TOCTOU 窗口✨ New Features1新增 OrcaRouter 可选 LLM 提供方OpenAI 兼容路由网关 Bug Fixes5索引状态误标记、focused-iteration 应用上下文丢失、cosine/dot 排序反转、队列状态残留、设置接口错误吞没 Other Changes3langgraph-agent 缺失引用可诊断化、npm-update 工作流加固、pytest 队列处理器默认关闭下面逐项展开并给出对应的源码与测试证据路径。二、安全关闭通知 Webhook 的 DNS 重绑定 TOCTOU 窗口2.1 问题背景本地服务向用户配置的 Webhook 地址发送通知时必须做 SSRF 防护在发起请求前解析 URL 的 DNS拒绝指向内网/受保护地址的目标。经典的TOCTOUTime-of-Check to Time-of-Use风险在于检查时的 DNS 解析结果与真正发请求时的解析结果可能不同——攻击者可通过让域名在两次解析间切换 A 记录DNS 重绑定绕过校验。发布说明指出的具体窗口是此前通知 Test 按钮的 admin-hint管理提示判定与默认级 URL 拒绝是两次独立调用拒绝检查通过之后、hint 检查之前又发起了一次解析两次解析之间正好构成一个 TOCTOU 缝隙。2.2 修复方式修复后的实现让 admin-hint 判定与默认级 URL 拒绝共享同一次 DNS 解析遍次single DNS-resolution pass域名只解析一次后续所有判定都基于这一次解析得到的 IP 集合从根上消除了两次调用之间记录被换掉的可能。2.3 源码与测试证据通知服务的 DNS 解析与校验逻辑集中在 notifications/service.py 与 notifications/manager.pyURL 级校验器见 security/notification_validator.py。对应的回归测试有两处DNS 固定pinning行为的 test_ssrf_dns_pinning.py以及通知 Webhook 场景下 DNS pin 的 test_notification_webhook_dns_pin.py。该安全机制的设计文档可参考 security/egress/README.md出口策略本身由 security/egress/policy.py 承载。三、新功能OrcaRouter 作为可选 LLM 提供方3.1 使用方式OrcaRouter 是一个OpenAI 兼容的路由网关它把众多上游模型统一到一个 API 后面按vendor/model命名空间寻址例如openai/gpt-5并提供虚拟模型orcarouter/auto由网关按请求自动选择上游——后续新模型上线无需客户端改代码。按发布说明接入步骤为在设置Settings中填入sk-orca-…开头的 OrcaRouter API key在模型选择中挑选一个带命名空间的模型如orcarouter/auto或openai/gpt-5请求即被路由经过 OrcaRouter 网关下发。3.2 源码实现要点提供方实现位于 orcarouter.py继承自OpenAICompatibleProvider基类关键属性值得注意provider_name OrcaRouter api_key_setting llm.orcarouter.api_key default_base_url https://api.orcarouter.ai/v1 default_model # User must explicitly pick a model — no silent fallback无默认模型default_model为空字符串注释明确用户必须显式选择模型不做静默回退避免请求意外落到非预期上游。模型列表必须带真实密钥requires_auth_for_models()返回True。源码注释解释了一个很实际的差异——OrcaRouter 的GET /v1/models在无Authorization 头时是开放的但给一个无效token 会返回 401而基类无认证列模型路径会发送占位密钥dummy-key-for-models-list会被 OrcaRouter 拒绝。因此该提供方要求先配置真实 key 才去拉模型列表这与 OpenRouter 的/models完全忽略 token 的行为不同。对应的设置项定义在 orcarouter_settings.jsonllm.orcarouter.api_keyUI 元素为password类型属于llm_general分类。前端设置界面research.html、components/research.js 等中同样能看到 OrcaRouter 相关的选项接线。更完整的 LLM 提供方配置背景可查阅 docs/CONFIGURATION.md。提供方行为的回归测试见 test_orcarouter_provider.py。四、缺陷修复五项 Bug Fix 逐项拆解4.1 向量存储失败后不再误标已索引#4855症状某文档嵌入embedding生成成功但写入向量存储失败时该文档仍被标记为已索引。结果是0 条向量落盘、文档在检索中静默不可见而后台 reconciler对账器只会重试未索引的文档因此这份假已索引文档永远不会被再次拾取。修复索引失败时保持文档的未索引状态使其能被后台对账流程重试。这是一个典型的状态机不变量破坏indexed标志必须与向量确实已持久化保持原子一致任何一步失败都不能越过它。文档级索引与重试链路属于研究库research library的存储层相关行为在tests/research_library与tests/storage目录下有覆盖。4.2 focused-iteration 检索恢复 Flask 应用上下文#4904症状focused-iteration 策略中针对每个子问题的检索被派发到工作线程但没有传播 Flask 应用上下文。任何触及current_app/g的搜索都会抛出 Working outside of application context该错误被逐查询吞掉策略因此静默返回空结果——排查时看不到报错只看到没搜到东西。修复改为与 source-based 策略一致传入context_factorythread_context让工作线程继承请求的 app context。源码证据两个策略文件都在 advanced search system 的策略层focused_iteration_strategy.py本次修复对象已引入...utilities.thread_context工具source_based_strategy.py作为对照的既有正确实现回归测试见 test_focused_iteration_strategy.py。这一修复也提示了一个通用教训在 Python 多线程/线程池场景中app context、数据库会话等线程绑定资源必须显式传播本仓库的thread_context工具即为此设计否则失败往往以静默空结果而非异常的形式出现。4.3 集合检索对 cosine / dot-product 索引正确排序#4963症状集合Collection检索计算相关性分数时假定所有索引都使用 L2 距离。对于余弦相似度或点积索引距离越小越近的假设不成立导致排序反转——最接近的匹配反而得分最低极端情况下还会在反相关anti-correlated匹配上直接报错。修复按索引实际的距离/相似度度量计算分数使 cosine 与 dot-product 索引的排序与 L2 一致地反映真实相关性。这是检索质量层面的修复同一份语料修复前的Top-N实际上是Bottom-N。4.4 删除/取消排队研究时清理队列状态此前删除或取消一条处于排队状态的研究后其队列状态残留可能继续占用并发槽位或在父任务已不存在时失败。修复后删除/取消操作会同步移除其队列状态槽位立即释放。队列的后台处理位于 scheduler/background.py。4.5 设置请求不再把失败响应当成有效数据设置Settings接口此前对服务端错误如 5xx的响应可能按有效设置数据处理掩盖了真实故障。修复后此类失败按服务器错误上报让运维/用户能第一时间看到问题而不是拿到一份内容未知的成功响应。五、其他变更可观测性与工程化5.1 langgraph-agent 缺失行内引用可诊断化#4969此前langgraph-agent策略的答案偶尔缺少行内[N]引用且无从查证原因——报告内容照常生成只是引用丢失。本版本在服务端日志加入两类警告让问题可诊断某次调用在已有累积来源的情况下跳过了引用citation处理环节——这正是 #4969 背后detailed-report 小节场景一次已完成的合成synthesis存在可用来源却没有产生任何行内[N]标记。报告内容本身不变变化只在可观测性。源码中可看到对应的告警逻辑例如合成完成后的检查langgraph_agent_strategy.py 中的 Synthesis produced no inline [N] citation markers 分支以及引用处理环节的历史注释同文件 #L897 附近的#4969 citation pass说明。5.2 npm-update 矩阵工作流加固PR #4997动态 npm-update 矩阵工作流经过加固并配套 guardian 行为测试套件发现阶段剪枝遍历目录时跳过node_modules、.claude、.githubfail-loud 原则发现的 lockfile 目录若既不在仓库根、也不在tests/之下工作流会大声失败而不是静默跳过其 build/test消除注入面发现的路径通过环境变量传递而非在 change-detection 步骤中直接插值${{ }}表达式。测试分两层guardian 层锁定接线wiring不被无意改动行为层用合成的与真实仓库目录树实际执行find | jq管道零漂移并覆盖空矩阵与未知路径的 fail-loud 分支。5.3 pytest 应用夹具默认跳过后台队列处理器Pytest 的 app 夹具现在默认不启动后台研究队列处理器让绝大多数测试不再受后台任务干扰确实需要验证队列行为的测试可通过环境变量LDR_WEB_QUEUE_PROCESSOR_ENABLEDtrue显式开启见 test_uvicorn_integration.py 等使用处。这是测试确定性的常规收口把默认安静、按需开启作为夹具契约。六、版本小结与升级提示1.9.3 没有引入新的架构组件但对 local-deep-research 的三个核心质量面做了精准加固安全面通知 Webhook 的 DNS 判定收敛为单次解析遍次消除 DNS 重绑定 TOCTOU若你在生产环境运行自托管实例这一项直接受益于升级。检索面#4855 与 #4963 都是结果看起来正常但实际是错的的缺陷——文档静默不可检索、相似度排序反转。如果你使用向量检索集合建议升级后重新核对既有语料的召回情况升级前的 cosine/dot 索引结果排序是不可信的。可观测面引用缺失告警、设置接口错误上报、测试夹具默认安静让后续排障成本显著下降。若你接入了 OrcaRouter建议先按第三节配置llm.orcarouter.api_key并显式选择orcarouter/auto等命名空间模型完整 LLM 配置项参考 docs/CONFIGURATION.md。各条修复对应的回归测试分布于tests/security、tests/notifications、tests/llm_providers、tests/strategies目录可作为行为契约的直接依据。【免费下载链接】local-deep-research~95% on SimpleQA (e.g. Qwen3.6-27B on a 3090). Supports all local and cloud LLMs (llama.cpp, Ollama, Google, ...). 10 search engines - arXiv, PubMed, your private documents. Everything Local Encrypted.项目地址: https://gitcode.com/GitHub_Trending/lo/local-deep-research创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考