拓冰建站拓冰建站
首页 / 资讯中心 / 正文

goose-sdk(GDK):用 UniFFI 让同一套 Goose API 跑通 Rust、Python 与 Kotlin

goose-sdkGDK用 UniFFI 让同一套 Goose API 跑通 Rust、Python 与 Kotlin【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goosegoose-sdk 是开源 AI Agent 项目 goose 的绑定层bindings layer对外以 goose Development KitGDK形式发布。它既承载 ACPAgent Client Protocol与 GDK 访问所需的共享类型也通过 UniFFI 把 goose 的核心能力编译成 Python 与 Kotlin 原生绑定让开发者可以在这些语言里直接构造 Provider、发起流式与非流式补全并把富文本消息、工具等内容安全地跨过 FFI 边界传递。读完本文你将掌握 GDK 的整体架构、其跨语言 API 形态、结构化可观测性钩子的用法以及 Python 包与 Maven 产物的完整构建流程。goose-sdk 在 goose 中的定位goose 是一个可扩展的开源 AI Agent其代码库采用多 crate 工作区结构。crates/goose-sdk位于绑定层从其 Cargo.toml 的描述可以确认它的双重身份The goose Development Kit (GDK) for Rust, with optional uniffi bindings for Python/Kotlin从源码看goose-sdk 的默认行为是只读共享类型、不直接引入重量级 Provider 逻辑。在 lib.rs 中可以看到不开启uniffi特性时crate 直接重导出goose-sdk-types位于crates/goose-sdk-types中的 GDK 线协议类型例如custom_notifications、custom_requests开发者可以基于它们构建一个与goose acp通过 stdio 通信的 ACP 客户端仓库中提供了现成示例 acp_client.rs。开启--features uniffi时crate 以cdylib/staticlib/rlib三种形式编译见 Cargo.toml 中的crate-type调用uniffi::setup_scaffolding!(goose)生成绑定脚手架并暴露bindings与observability两个模块——前者是面向 Python/Kotlin 的进程内 API后者是请求生命周期可观测性钩子。这意味着 goose-sdk 提供的是两个互补的接入维度要么走进程外的 ACP 协议默认特性要么走进程内的 FFI 绑定uniffi特性。UniFFI 特性一套 API多种语言README 指出启用--features uniffi后 crate 会编译为 Python 与 Kotlin 的原生绑定命名空间分别为语言命名空间 / 包PythongoosePyPI 上的包名为goose-sdkKotlinio.github.aaif_gooseUniFFI 表面surface允许调用方完成四类核心操作构造 Provider——既可以从声明式 JSON 构造declarative_provider_from_json也可以使用内置的便捷构造器流式补全 Provider 响应stream非流式补全complete在 FFI 边界传递富媒体消息与工具内容MessageContent、ProviderTool等类型。从 bindings.rs 的#[uniffi::export]标注可以看到 FFI 暴露的具体函数清单例如declarative_provider_from_json(json: String) - ResultArcProvider, GooseError——从 JSON 构造声明式 Provideropenai_provider(api_key)、anthropic_provider(...)、groq_provider(api_key)、databricks_provider(host, token)、databricks_v2_provider(...)以及配套的*_default_model()函数default_compaction_templates()——返回默认的对话压缩模板install_request_logger(...)——安装请求日志回调。Provider对象本身见 bindings.rs暴露name()、supported_features()、context_limit(model)、stream(...)、complete(...)、compact(...)等方法流式请求返回ProviderStream通过next_chunk()逐块拉取StreamChunk包括TextChunk、EndChunk、ErrorChunk、ToolChunk等变体。快速上手just python与just kotlingoose-sdk 仓库内自带的justfilecrates/goose-sdk/justfile把编译、绑定生成和示例运行串成一条命令just --justfile crates/goose-sdk/justfile python # 构建绑定并运行 examples/uniffi/provider.py just --justfile crates/goose-sdk/justfile kotlin # 构建 Maven 工件并运行 examples/uniffi/kotlin 示例说明原 README 中简写为just python/just kotlin二者等价--justfile只是显式指定 justfile 的位置。注意该 justfile 内设置working-directory : ../..即所有构建命令都以仓库根目录为工作目录执行。Python 示例 provider.py 演示了完整的“构造 Provider → 流式补全”链路from goose import ( MessageContent, MessageRole, ProviderMessage, ProviderModelConfig, StreamChunk, declarative_provider_from_json, ) async def main() - None: provider declarative_provider_from_json((HERE.parent / deepseek.json).read_text()) model ProviderModelConfig(model_namedeepseek-v4-flash) messages [ ProviderMessage( roleMessageRole.USER, content[MessageContent.Text(textwhat is the capital of France?)], ) ] stream await provider.stream( model, You are a knowledgable geography expert, messages, [], ) while chunk : await stream.next_chunk(): if isinstance(chunk, StreamChunk.TextChunk): print(chunk.text, end) elif isinstance(chunk, StreamChunk.EndChunk) and chunk.usage: print(f\nusage: {chunk.usage}) elif isinstance(chunk, StreamChunk.ErrorChunk): print(f\nerror: {chunk.error.message}, filesys.stderr)其中声明式 Provider 的 JSON 配置来自 deepseek.json这正是“从 JSON 构造 Provider”用法的真实样例。Kotlin 示例 Main.kt 展示了从io.github.aaif_goose命名空间导入并使用 OpenAI Provider 的对应写法读取环境变量OPENAI_API_KEY通过openAiProvider(apiKey)构造 Provider再用streamFlow(...)以协程 Flow 的形式消费StreamChunkimport io.github.aaif_goose.MessageContent import io.github.aaif_goose.MessageRole import io.github.aaif_goose.ProviderMessage import io.github.aaif_goose.ProviderModelConfig import io.github.aaif_goose.StreamChunk import io.github.aaif_goose.streamFlow import io.github.aaif_goose.providers.openai.defaultModel import io.github.aaif_goose.providers.openai.provider as openAiProvider import kotlinx.coroutines.runBlocking fun main() runBlocking { val apiKey System.getenv(OPENAI_API_KEY) require(!apiKey.isNullOrBlank()) { Set OPENAI_API_KEY before running this example. } val provider openAiProvider(apiKey) val model ProviderModelConfig(modelName defaultModel()) val messages listOf( ProviderMessage( role MessageRole.USER, content listOf(MessageContent.Text(text What is the capital of France? Answer in one sentence.)), ), ) provider.streamFlow(model, You are a knowledgeable geography expert., messages) .collect { chunk - when (chunk) { is StreamChunk.TextChunk - print(chunk.text) is StreamChunk.EndChunk - chunk.usage?.let { println(\nusage: $it) } is StreamChunk.ErrorChunk - System.err.println(\nerror: ${chunk.error.message}) is StreamChunk.ToolChunk - Unit } } println() }两种语言示例几乎一一对应都包含MessageRole.USER、MessageContent.Text、EndChunk.usage、ErrorChunk.error.message印证了 UniFFI 保证跨语言 API 形态一致的设计目标。结构化可观测性ObservabilityHook传统的观测手段是解析 Provider 的调试日志脆弱且难以复用。goose-sdk 提供了类型化的可观测性钩子注册一个ObservabilityHook就能收到结构化的 Provider 请求生命周期事件而无需在日志文本里做字符串匹配。钩子的生命周期契约README 明确了事件的严格顺序与不变量每个请求先触发onRequestStart当 Provider 响应可用时触发onResponseStart——对于流式请求这发生在流刚打开时最后恰好触发一次onRequestEnd携带结果Success或带类型化GooseStreamError的Failure、durationMs毫秒耗时以及 tokenusage。三个事件共享同一个requestId因此可以与应用自身的遥测如 trace/span关联起来。README 特别强调一个细节流式读取若超时会以该错误结束 trace因此即使之后继续读取该流也绝不会再产生第二个onRequestEnd。对照源码 observability.rs 可以看到这些保证的实现方式事件类型均为uniffi::Record派生包含request_id、provider、model、operationComplete/Stream等字段RequestEndEvent额外携带outcome: RequestOutcomeSuccess或Failure { error: GooseStreamError }、duration_ms、usage、response_json钩子注册采用进程级全局单例HOOK: RwLockOptionArcRegisteredHook每个钩子带一个revoked: AtomicBoolRequestObserver::end使用AtomicBool::swap保证onRequestEnd至多触发一次request_id通过AtomicU64自增生成格式为req-N无论是调用set_observability_hook替换旧钩子还是调用clear_observability_hook清空钩子旧钩子都会被立即revoke()因此仍在飞行in-flight中的请求也不会再向旧钩子投递任何事件。observability.rs末尾的单元测试对这些不变量做了逐一验证如success_emits_start_response_and_end_with_usage、end_is_emitted_at_most_once、clearing_hook_mid_request_stops_in_flight_events读者可以据此理解钩子的精确语义。最小实现示例KotlinREADME 给出了一个把事件桥接到 tracing 系统的 Kotlin 示例class TracingHook : ObservabilityHook { override fun onRequestStart(event: RequestStartEvent) { tracer.startSpan(event.requestId, event.provider, event.model) } override fun onResponseStart(event: ResponseStartEvent) { tracer.recordTimeToFirstByte(event.requestId, event.elapsedMs) } override fun onRequestEnd(event: RequestEndEvent) { tracer.finishSpan(event.requestId, event.outcome, event.durationMs, event.usage) } } setObservabilityHook(TracingHook(), capturePayloads false)这个模式可以自然映射到常见的 trace/semantic conventions 场景onRequestStart建立 span 并记录 Provider 与模型名onResponseStart记录“首字节时间”Time To First Byteevent.elapsedMsonRequestEnd汇总最终结果、耗时与 token 用量。性能与安全语义READMA 明确了两点使用约束源码也给出了对应实现同步回调 崩溃隔离钩子在调用线程上同步执行且被catch_unwind包裹见 observability.rs 中RegisteredHook::emit的实现所以一个抛异常的钩子回调不会导致请求失败。反过来钩子回调必须足够快否则会直接增加被观测请求的延迟。单元测试panicking_hook_does_not_stop_later_events验证了onRequestStart 抛异常后后续 onResponseStart / onRequestEnd 仍能正常投递。默认不捕获负载set_observability_hook的capturePayloads参数默认值为false对应 Rust 侧#[uniffi::export(default(capture_payloads false))]。该模式下RequestStartEvent.payload与RequestEndEvent.responseJson恒为null事件里只剩下非敏感元数据provider、model、延迟、用量。安全指引Security guidance这是使用钩子时最重要的边界负载捕获默认关闭是有意为之。一旦开启capturePayloadsRequestStartEvent.payload会携带系统提示词system、完整对话messages与工具模式tools它们通常包含凭据、客户数据和其他机密。因此仅在**你完全掌控 sink日志/遥测后端**时才开启capturePayloads在持久化或导出这些字段之前务必自行做脱敏redaction。另有一个容易踩坑的不对称性RequestEndEvent.responseJson只对complete非流式调用填充对stream调用恒为null。原因是流式响应是按块chunk直接交付给调用方的SDK从不缓冲整个响应体源码中stream路径的事件结束不携带response_json。如果应用需要完整的流式响应正文应当从自己已经收到的 chunks 中自行拼接而不是依赖钩子事件。Python 包构建本地 wheelGDK 的 Python 产物通过 PyPI 发布包名为goose-sdkimport 名是goose。其 python/README.md 说明了本地构建方式——在仓库根目录执行just --justfile crates/goose-sdk/justfile python-wheel这条命令背后对应 justfile 中的python-wheel→python-bindings release链实际完成的工作包括cargo build -p goose-sdk --features uniffi --release以 release 模式编译原生库在 Linux/macOS/Windows 上分别产出libgoose_sdk.so/.dylib/.dll见 justfile 顶部的平台推导运行goose-uniffi-bindgen generate --library ... --config ... --language python --no-format --out-dir ...重新生成 Python 绑定把生成的goose.py重命名为__init__.py将 release 原生库拷入包目录并生成py.typed标记以支持类型检查用uvxpyproject-build构建 wheel产物写入crates/goose-sdk/python/dist/。如果需要快速验证产物可用justfile 还提供了python-check目标强制重装 wheel 并执行import goose冒烟测试以及python-publish目标twine checktwine upload默认发往 PyPI也可通过repository参数指定其他仓库。Maven 包gdk artifactGoose 的 JVM/Kotlin 侧产物发布在 Maven Central坐标为io.github.aaif-goose:gdk版本号直接跟随 Rust crate 的版本当前为 Cargo.toml 中的0.1.0-alpha.7。本地构建命令just --justfile crates/goose-sdk/justfile maven-package这条命令对应maven-package→maven-bindings release→crates/goose-sdk/scripts/prepare-maven-package.sh→./gradlew publishToMavenLocal。它同样先以 release 模式构建原生库然后调用 prepare-maven-package.sh 脚本重新生成 Kotlin 绑定UniFFI 生成 Kotlin 代码并放入maven/src/main/kotlin把原生库放入 JVM jar 的资源目录maven/src/main/resources在 maven 目录下用 Gradle 执行publishToMavenLocal发布到本地 Maven 仓库。CI 负责为受支持的平台构建原生库并可选择把整合后的产物发布到 Maven Central对应 justfile 中的maven-publish目标。Kotlin 示例工程examples/uniffi/kotlin依赖本地发布的gdk产物这也是just kotlin能直接运行示例的前提。版本、路径与构建入口速查项目说明位置Rust crategoose-sdk版本0.1.0-alpha.7Cargo.tomlUniFFI 配置绑定生成参数uniffi.tomlRust 源码重导出 / 绑定 / 可观测性src/lib.rs、src/bindings.rs、src/observability.rs构建任务python、kotlin、python-wheel、python-publish、maven-package、maven-publish等justfile示例ACP 客户端示例、声明式 Provider JSONexamples/acp_client.rs、examples/deepseek.jsonPython 示例 / Kotlin 示例流式补全的跨语言对照examples/uniffi/provider.py、examples/uniffi/kotlin/src/main/kotlin/Main.kt小结goose-sdk 是 goose 生态中连接“Rust 核心实现”与“多语言调用方”的枢纽默认特性下它提供构建 ACP 客户端所需的共享线协议类型启用uniffi特性后它把 Provider 构造、流式/非流式补全、上下文压缩等能力以命名空间goosePython与io.github.aaif_gooseKotlin的形式原样输出并通过ObservabilityHook提供默认关闭、负载可选、语义严格恰好一次onRequestEnd、可关联的requestId的请求生命周期观测。对想要在自有应用里嵌入 goose 能力的开发者来说just python/just kotlin是零成本体验入口python-wheel/maven-package则是把 GDK 接入自己构建链的标准姿势。【免费下载链接】goosean open source, extensible AI agent that goes beyond code suggestions - install, execute, edit, and test with any LLM项目地址: https://gitcode.com/GitHub_Trending/goose3/goose创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门