AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载Operit 的 PR Check 工作流通过android_jvm与android_full两条车道分别执行 Android JVM 单元测试与完整 Android 构建而应用源码中的System.loadLibrary(operit_ripgrep)决定了这两条车道都必须先拿到原生liboperit_ripgrep.so。本文以docs/TODO/native_ripgrep_pr_check_20260809/下的修复方案文档为主线完整还原JVM 测试车道缺少原生 ripgrep 库导致 test-only PR 在测试执行前即失败这一问题的成因、修复设计与验证方式并结合仓库中的工作流、Rust 源码、JNI 绑定与 Gradle 校验任务深入讲解该原生搜索库的构建与接入全貌。读完本文你将掌握 Operit 中 lane 化 CI 的准备逻辑、native ripgrep 的离线构建命令以及Gradle 前置校验 工作流准备这一原生依赖保障模式的实现细节。问题背景PR Check 中的三条 Android 车道Operit 的 PR Check 工作流.github/workflows/pr-check.yml根据 PR 改动范围通过fastjob 中的plan步骤动态决定需要执行的检查车道。与 Android 相关的输出有三个输出含义典型触发改动android_resources仅资源检查翻译字符串、locales_config.xml等纯资源改动android_jvmAndroid JVM 单元测试app/src/main下的 Kotlin/Java 代码改动android_full完整 Android 构建原生模块、CMake、Gradle 配置、CI 工作流改动车道的判定逻辑集中在 ci/script/pr_check.py 的classify_paths改动路径命中ANDROID_FULL_PATTERNS包括tools/native_ripgrep/**、app/src/main/cpp/**、cmake/**、各原生模块根目录等即归入android_full其余落在app/下的非资源改动归入android_jvm纯翻译资源改动归入android_resources。三者互斥且android_full优先级最高。在pr-check.yml中android_testsjob 的触发条件是if: - needs.fast.result success (needs.fast.outputs.android_jvm true || needs.fast.outputs.android_full true)也就是说只要改动涉及 Android 代码无论 JVM 车道还是完整车道都会运行:app:testDebugUnitTest。这正是问题爆发的入口。现有行为为什么 test-only PR 会提前失败修复方案文档 1_PrepareNativeRipgrep.md 中记录的问题描述非常明确pr-check.ymlruns:app:testDebugUnitTestwhenandroid_jvmis enabled. Gradle requiresliboperit_ripgrep.sobefore its pre-build phase. The workflow installs the NDK and builds that library only whenandroid_fullis enabled, so test-only Android pull requests fail before their test suite executes.根因链条可以拆解为三步应用启动即加载原生库app/src/main/java/com/ai/assistance/operit/util/ripgrep/NativeRipgrep.kt中的 JNI 对象在init块执行System.loadLibrary(operit_ripgrep)并将searchJson声明为external函数internal object NativeRipgrep { init { System.loadLibrary(operit_ripgrep) } JvmStatic external fun searchJson( path: String, patterns: ArrayString, filePattern: String, caseInsensitive: Boolean, literal: Boolean, contextLines: Int, maxResults: Int ): String }这条加载语句使得任何 JVM 侧编译与打包路径都依赖liboperit_ripgrep.so的存在。Gradle 有前置校验app/build.gradle.kts中注册了verifyExternallyBuiltNativeLibraries任务app/build.gradle.kts把src/main/jniLibs/arm64-v8a/liboperit_ripgrep.so列入必须在 Gradle 之外预先构建的原生库清单校验规则为library.isFile library.length() 0L否则直接抛出错误并提示运行tools/native_ripgrep/build_native_ripgrep.ps1Missing or empty externally built native library: ... . Run tools/native_ripgrep/build_native_ripgrep.ps1 before packaging.因此只要jniLibs/arm64-v8a/下没有非空的.sotestDebugUnitTest会在测试真正执行前就失败。旧工作流只在完整车道准备原生库修复前的pr-check.yml仅在android_buildandroid_full车道job 中安装 NDK 并执行 native ripgrep 构建android_testsjob 虽然负责运行 JVM 测试却没有对应的原生准备步骤。于是只改了 Kotlin 测试或普通 Kotlin 代码、完全不触及原生模块的 PR 也会因缺少.so而在测试套件执行前挂掉——这本应是最轻量的检查车道之一却成了最容易失败的一环。预期修正让原生准备跟随 JVM 与完整车道方案文档给出了明确的修复边界Android JVM 检查必须获得非空的liboperit_ripgrep.so完整 Android 检查保留其既有的原生准备逻辑纯资源检查resource-only不安装 NDK、不构建原生库。对应的实现原则是Install the NDK and build native ripgrep for eitherandroid_jvmorandroid_full. Keep CMake, full dependency preparation, and all resource-only paths scoped to the full lane.即NDK native ripgrep 构建的准备动作从android_full专属提升为android_jvm || android_full共同需要而 CMake 工具链安装、完整依赖下载download_android_dependencies.sh full/prepare_android_dependencies.py --profile full、STT 资产生成等重活仍然只属于完整车道。这样既修复了 test-only PR 的失败又避免了资源改动例如新增一种语言翻译被拖入昂贵的原生构建流程。仓库现状修复在android_testsjob 中的落地形态从当前仓库的 .github/workflows/pr-check.yml 看修复后的android_testsjob 内已经包含一组无车道条件限制的Restore native ripgrep cache Build native ripgrep步骤只要 job 本身因 JVM 或完整车道被触发即执行与方案文档的预期一致- name: Restore native ripgrep cache uses: actions/cache... with: path: | ~/.cargo/registry ~/.cargo/git tools/native_ripgrep/target key: native-ripgrep-arm64-${{ runner.os }}-${{ runner.arch }}-ndk-${{ env.ANDROID_NDK_VERSION }}-api-${{ env.ANDROID_API_LEVEL }}-rust-${{ env.RUST_VERSION }}-${{ hashFiles(tools/native_ripgrep/Cargo.toml, tools/native_ripgrep/Cargo.lock, tools/native_ripgrep/**/*.rs, tools/native_ripgrep/build_native_ripgrep.ps1) }} - name: Build native ripgrep shell: bash run: | set -euo pipefail export ANDROID_NDK_HOME$ANDROID_HOME/ndk/$ANDROID_NDK_VERSION export CARGO_TARGET_AARCH64_LINUX_ANDROID_LINKER$ANDROID_NDK_HOME/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android${ANDROID_API_LEVEL}-clang rustup toolchain install $RUST_VERSION --profile minimal rustup target add --toolchain $RUST_VERSION aarch64-linux-android cargo $RUST_VERSION build \ --manifest-path tools/native_ripgrep/Cargo.toml \ --release \ --target aarch64-linux-android \ --locked install -Dm755 \ tools/native_ripgrep/target/aarch64-linux-android/release/liboperit_ripgrep.so \ app/src/main/jniLibs/arm64-v8a/liboperit_ripgrep.so test -s app/src/main/jniLibs/arm64-v8a/liboperit_ripgrep.so关键点在于android_testsjob 的环境变量pr-check.yml为这条命令提供了全部输入——ANDROID_NDK_VERSION: 25.1.8937393、ANDROID_API_LEVEL: 26、RUST_VERSION: 1.88.0同 job 更早的Install required Android toolchain步骤sdkmanager --install ... ndk;$ANDROID_NDK_VERSION则负责把 NDK 装进$ANDROID_HOME/ndk/二者配合才构成完整的原生准备链路。末尾的test -s断言确保产物非空与 Gradle 校验任务前后呼应。同样地android_build完整车道job 保留了独立的 NDK/CMake 安装、CMake 源码缓存恢复、full 依赖下载/准备以及相同的 native ripgrep 构建与缓存步骤pr-check.yml满足full Android checks retain their existing native preparation的要求。而android_resources车道只跑aapt2 compile资源编译完全不涉及 NDK 与 Rust 工具链验证了resource-only checks do not install the NDK or build the native library。原生库本体operit_ripgrep 的 Rust 实现与构建方式crate 结构与依赖tools/native_ripgrep/目录下是一个完整的 Rustcdylibcratetools/native_ripgrep/Cargo.toml[package] name operit_ripgrep version 0.1.0 edition 2021 [lib] crate-type [cdylib] [dependencies] globset 0.4 grep-matcher 0.1 grep-regex 0.1 ignore 0.4 jni 0.21 serde { version 1, features [derive] } serde_json 1依赖选型直接对应其功能定位grep-regex/grep-matcher提供 ripgrep 同源的 Rust 正则匹配引擎ignore负责WalkBuilder目录遍历自动识别.gitignoreglobset用于文件包含/排除 glob 匹配jni提供 JNI 桥接serde/serde_json负责把搜索结果序列化为 JSON 字符串回传给 Kotlin。JNI 导出与搜索语义入口函数是 tools/native_ripgrep/src/lib.rs 中的Java_com_ai_assistance_operit_util_ripgrep_NativeRipgrep_searchJson其 JNI 签名与 Kotlin 侧external fun searchJson(path, patterns, filePattern, caseInsensitive, literal, contextLines, maxResults): String一一对应。从源码可以看到几个值得注意的实现细节多模式支持patterns是字符串数组每个模式独立编译为RegexMatcher逐行做任一匹配判定gitignore 感知遍历WalkBuilder开启git_ignore(true)、git_global(true)、git_exclude(true)、parents(true)与 ripgrep 的遍历语义一致内置排除build_exclude_globs硬编码排除.backup/**、.operit/**、backup/**等目录lib.rs二进制探测读取文件头 8KB 检查是否含\0字节来跳过疑似二进制文件结果聚合命中文件输出SearchBlockfilePath、firstMatchLine、lineContent、matchContext、matchCount上下文行、单行内容、摘要均做了字符截断400/300/80/4000 字符上限防止超大文件撑爆模型上下文。Kotlin 侧的消费方是app/src/main/java/com/ai/assistance/operit/core/tools/defaultTool/standard/StandardFileSystemTools.ktsearchNativeRipgrepBlocks在Dispatchers.IO中调用NativeRipgrep.searchJson随后parseNativeRipgrepBlocks把 JSON 解析为RipgrepBlock列表与filesSearched计数StandardFileSystemTools.kt最终经由grepCodeWithNativeRipgrep供 Agent 的代码检索工具使用。这也解释了为何该库对 JVM 测试是硬性前置编译期链接与运行期加载都离不开.so。本地构建命令面向本地开发者的构建入口有两个Windows 下直接运行 tools/native_ripgrep/build_native_ripgrep.bat内部转发到 PowerShell 脚本或直接执行 tools/native_ripgrep/build_native_ripgrep.ps1。脚本支持三个参数参数默认值说明-Targets(aarch64-linux-android)目标三元组列表支持aarch64-linux-android、armv7-linux-androideabi、x86_64-linux-android、i686-linux-android-SdkDir空Android SDK 路径缺省时依次读取local.properties的sdk.dir、ANDROID_HOME、ANDROID_SDK_ROOT-ApiLevel23链接器使用的 Android API 级别如aarch64-linux-android23-clang.cmd脚本按目标三元组维护 ABI 映射arm64-v8a/armeabi-v7a/x86_64/x86依次执行rustup target add、设置CARGO_TARGET_TARGET_LINKER环境变量指向 NDK 的 LLVM 链接器、cargo build --release --target最后把产物复制到app/src/main/jniLibs/ABI/liboperit_ripgrep.so。NDK 路径同样支持ANDROID_NDK_HOME、ANDROID_NDK_ROOT环境变量或在 SDK 的ndk/目录下自动选取版本号最高的 NDK。CI 中的 bash 版构建命令正是这套流程在 Linux runner 上的等价实现。车道分类的测试保障修复不只是改工作流 YAML车道判定逻辑本身也有单元测试守护。ci/test/test_pr_check.pyci/test/test_pr_check.py覆盖了关键场景test_default_strings_use_jvm_lane改默认values/strings.xml归入android_jvm会触发 JVM 测试因此必须走原生准备test_translation_only_uses_resource_lane只改values-ro/strings.xml与locales_config.xml时归入android_resources不安装 NDK、不构建原生库test_native_change_uses_full_lane改cmake/operit_git_source.cmake归入android_fulltest_android_workflow_changes_use_full_lane改动pr-check.yml等三个工作流文件均归入android_fulltest_relocated_native_modules_use_full_lane改avator/dragonbones、llm/llama等原生模块的CMakeLists.txt归入android_full。这些用例印证了三车道互斥且优先级正确的设计为JVM 车道必然获得原生准备、资源车道必然跳过原生准备提供了回归保障。工作流侧还有一个兜底fastjob 中candidate判定 job 会根据android_build/android_tests的实际结果汇总成 PR 门禁任何一条被要求但失败的车道都会让候选提交整体失败。验证方式方案文档记录的验证策略是Validate the workflow diff statically, then use the PR Check run as the build verification. No local build or test command is run because repository guidance requires explicit user authorization.即两步走第一步对pr-check.yml的 diff 做静态审查确认 NDK 安装与 native ripgrep 构建步骤出现在android_testsjob 中且未被android_full条件包裹android_resources路径无原生准备第二步直接以真实 PR 的 PR Check 运行结果作为构建验证——提交一个仅含 Kotlin 代码/测试改动的 PR观察android_testsjob 是否成功走到:app:testDebugUnitTest执行阶段而非在 Gradle 前置校验处失败。对复现问题感兴趣的读者也可以在本地复刻验证链条删除或清空app/src/main/jniLibs/arm64-v8a/liboperit_ripgrep.so后运行./gradlew :app:testDebugUnitTest即可看到verifyExternallyBuiltNativeLibraries抛出的 Missing or empty externally built native library 错误随后按提示执行 build_native_ripgrep.ps1 重新生成.so测试任务即可正常推进。这一先失败、后修复的过程正是 CI 与本地构建共享同一套原生库契约的直观体现。小结本次修复的本质是把原生搜索库准备从完整车道下沉到所有会运行 Gradle 测试的车道同时严格守住资源车道不做原生工作的成本边界。整条链路中pr_check.py负责车道分类pr-check.yml的android_testsjob 负责在 JVM/完整车道安装 NDK 并构建liboperit_ripgrep.soverifyExternallyBuiltNativeLibraries负责在 Gradle 侧兜底校验产物非空NativeRipgrep.kt Rustlib.rs则定义了库的最终消费方式。四者环环相扣构成了 Operit 中原生依赖由 CI 显式准备、Gradle 只做一致性校验的工程范式可供其他同时含有 JVM 测试与原生库的大型 Android 项目直接借鉴。赞分享AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆【免费下载链接】OperitThe most powerful AI agent and AI chat software on Android/Operit是一款Android上能力最为强大、发展最久的AI Agent项目地址https://gitcode.com/gh_mirrors/op/Operit点击查看免费下载相关推荐Onyx 仓库实战用 Greptile check-pr 技能实现 GitHub / GitLab / Perforce 全平台 PR 自动检查与修复Onyx 仓库实战用 Greptile check pr 技能实现 GitHub / GitLab / Perforce 全平台 PR 自动检查与修复 导读AI 应用大模型RAGAI Agent后端前端Cilium 实战用 cilium-dbg bpf ipcache delete 精确删除 BPF IPCache 中的 IP 与身份条目Cilium 实战用 cilium dbg bpf ipcache delete 精确删除 BPF IPCache 中的 IP 与身份条目 凌晨三点一台节点AI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化深度学习图像处理终极指南如何用TensorFlow-Course快速掌握CNN技术深度学习图像处理终极指南如何用TensorFlow Course快速掌握CNN技术 TensorFlow Course是一个专注于提供简单易用TensorFlAI Agent人工智能大模型AI 应用工具调用本地部署MCP ClientsAgent 记忆GUI 自动化上一篇PyWxDump微信聊天记录恢复4条命令完成PC微信备份但官方仓库已移除下一篇解密pdftotext深入理解基于Poppler的高性能PDF解析原理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考