多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

AG-UI Dart SDK 实战指南:用 `ag_ui` 构建强类型 Agent-User 交互客户端

AG-UI Dart SDK 实战指南:用 `ag_ui` 构建强类型 Agent-User 交互客户端 AG-UI Dart SDK 实战指南用ag_ui构建强类型 Agent-User 交互客户端【免费下载链接】ag-uiAG-UI: the Agent-User Interaction Protocol. Bring Agents into Frontend Applications.项目地址: https://gitcode.com/gh_mirrors/agu/ag-ui本文是 AG-UI 协议 Dart SDKag_ui的完整使用指南。内容以仓库中 sdks/community/dart/README.md 为骨架结合lib/源码实现展开覆盖安装接入、客户端配置、SSE 事件流处理、多模态输入、工具调用、共享状态、错误处理、cipher 数据保留与 0.1.0 → 0.3.0 迁移路径。读完本文你将能够用 Dart 语言编写一个连接任意 AG-UI 兼容 Agent 服务器的强类型、支持实时流式输出与工具交互的前端客户端。一、AG-UI 协议与 Dart SDK 概述AG-UIAgent-User Interaction Protocol是一套标准化 Agent 与用户之间交互的协议Agent 侧以事件流文本增量、工具调用、状态快照、推理过程、生命周期等的方式将行为推送出来前端应用侧负责消费这些事件并渲染。ag-ui-dart就是这套协议的 Dart 官方社区实现位于仓库 sdks/community/dart/当前版本0.3.0见 pubspec.yaml。该 SDK 的定位与能力从入口库 lib/ag_ui.dart 的文档注释可以归纳为核心协议支持完整实现 AG-UI 事件类型体系HTTP 客户端生产可用的AgUiClient基于 Server-Sent EventsSSE实时流式接收事件事件流处理实时事件消费内置背压backpressure处理工具交互支持 tool call 与生成式 UIgenerative UI流程状态管理快照snapshot与增量deltaRFC 6902 JSON Patch双通道类型安全全部协议实体均为强类型模型且遵循 Dart 空安全null safety规范。SDK 支持的 Dart SDK 环境为3.3.0 4.0.0运行时依赖仅http与meta两个包依赖面很小方便集成到任意 Dart / Flutter 项目中。二、安装与项目接入在任意 Dart 项目中使用ag_ui有两种等价方式。方式一命令行添加dart pub add ag_ui方式二手动编辑pubspec.yamldependencies: ag_ui: ^0.3.0添加后通过单条 import 引入全部能力import package:ag_ui/ag_ui.dart;ag_ui包内部按关注点拆分并统一再导出见 lib/ag_ui.dart 的 export 列表库职责ag_ui核心客户端库聚合导出下面所有模块ag_ui.clientHTTP 客户端与 SSE 流式支持AgUiClient、AgUiClientConfig、CancelTokenag_ui.events全部事件类型与EventType枚举ag_ui.types消息、工具、上下文等数据模型ag_ui.encoder事件编码 / 解码工具EventDecoder、EventStreamAdapterag_ui.sse底层 SSE 连接、解析与退避重连策略注意ag_ui.encoder中的ValidationError在导出时被隐藏lib/ag_ui.dart以避免与ag_ui.client中的同名类冲突这与 decoder 内部的处理策略一致。三、初始化客户端AgUiClientConfig 全参数解析AgUiClient是连接 AG-UI 服务器的唯一入口构造时必须传入AgUiClientConfig。下面是最小化示例import package:ag_ui/ag_ui.dart; final client AgUiClient( config: AgUiClientConfig( baseUrl: https://api.example.com, defaultHeaders: {Authorization: Bearer token}, requestTimeout: Duration(seconds: 30), ), );对照源码 lib/src/client/config.dartAgUiClientConfig的完整可配置项与默认值如下参数类型默认值说明baseUrlString必填无AG-UI 服务器基础地址如http://localhost:8000拼接 endpoint 时用于组成完整 URLdefaultHeadersMapString, String{}随所有请求附带的默认请求头如鉴权 Bearer TokenrequestTimeoutDuration30 秒单次 HTTP 请求超时connectionTimeoutDuration60 秒SSE 连接的空闲超时即多久没数据就触发重连backoffStrategyBackoffStrategyExponentialBackoff重连 / 重试的退避策略可替换为自定义实现maxRetriesint3最大重试次数withCredentialsboolfalse请求是否携带凭据AgUiClientConfig还提供copyWith(...)方法便于在不重建整个配置的情况下修改单项参数。关于backoffStrategySDK 内置三种实现lib/src/sse/backoff_strategy.dartExponentialBackoff默认指数退避 抖动jitter默认initialDelay 1s、maxDelay 30s、multiplier 2.0、jitterFactor 0.3可分别定制LegacyBackoffStrategy内部持有状态的兼容实现保留nextDelayStateful()旧接口ConstantBackoff每次固定返回同一个延迟适合测试场景。final client AgUiClient( config: AgUiClientConfig( baseUrl: http://localhost:8000, defaultHeaders: {Authorization: Bearer token}, requestTimeout: const Duration(seconds: 30), connectionTimeout: const Duration(seconds: 60), maxRetries: 5, backoffStrategy: ExponentialBackoff( initialDelay: const Duration(milliseconds: 500), maxDelay: const Duration(seconds: 10), ), ), );从 lib/src/client/client.dart 可以看到AgUiClient还允许注入自定义的http.Client、Encoder、Decoder与EventStreamAdapter这为单元测试与自定义编解码提供了依赖注入入口。四、流式事件处理runAgent 与事件类型体系4.1 基本调用模式AgUiClient.runAgent(endpoint, input)接受一个endpoint 名称与一个输入对象返回StreamBaseEventfinal input SimpleRunAgentInput( messages: [ UserMessage( id: msg_${DateTime.now().millisecondsSinceEpoch}, content: Explain quantum computing, ), ], ); await for (final event in client.runAgent(agentic_chat, input)) { switch (event.eventType) { case EventType.textMessageContent: final text (event as TextMessageContentEvent).delta; print(text); // 逐 token 流式输出 break; case EventType.runFinished: print(Complete); break; } }runAgent的第一个参数endpoint既可以是相对路径自动拼接到baseUrl之后也可以是完整 URL会先经过 URL 校验见 lib/src/client/client.dart。4.2 内置端点便捷方法针对 AG-UI 规范中的标准端点SDK 提供了语义化的便捷方法内部都转发给runAgent便捷方法实际端点用途runAgenticChat(input)agentic_chat通用 agentic 对话runHumanInTheLoop(input)human_in_the_loop人机协同human-in-the-loop流程runAgenticGenerativeUi(input)agentic_generative_ui生成式 UI 流程runToolBasedGenerativeUi(input)tool_based_generative_ui基于工具调用的生成式 UI 流程runSharedState(input)shared_state共享状态同步runPredictiveStateUpdates(input)predictive_state_updates预测性状态更新4.3 事件类型全景EventType枚举lib/src/events/event_type.dart覆盖了 AG-UI 规范的全部事件与官方 TypeScript / Python SDK 保持事件类型对齐文本消息TEXT_MESSAGE_START/TEXT_MESSAGE_CONTENT/TEXT_MESSAGE_END/TEXT_MESSAGE_CHUNK工具调用TOOL_CALL_START/TOOL_CALL_ARGS/TOOL_CALL_END/TOOL_CALL_CHUNK/TOOL_CALL_RESULT推理REASONING_START/REASONING_MESSAGE_START/REASONING_MESSAGE_CONTENT/REASONING_MESSAGE_END/REASONING_MESSAGE_CHUNK/REASONING_END/REASONING_ENCRYPTED_VALUE状态STATE_SNAPSHOT/STATE_DELTA/MESSAGES_SNAPSHOT活动ACTIVITY_SNAPSHOT/ACTIVITY_DELTA生命周期RUN_STARTED/RUN_FINISHED/RUN_ERROR/STEP_STARTED/STEP_FINISHED透传RAW/CUSTOM。EventType.fromString对未知类型抛ArgumentErrorBaseEvent.fromJson借此把未知事件类型可恢复与工厂内部缺陷需抛出区分开。4.4 事件解码与校验当 SSE 帧到达后AgUiClient内部会把 JSON 交给EventStreamAdapter转为强类型事件而独立使用的EventDecoderlib/src/encoder/decoder.dart则提供更细粒度的解码 APIdecode(String data)解码一段不含data:前缀的 JSON 字符串decodeJson(MapString, dynamic)从 JSON 对象解码decodeSSE(String sseMessage)解码一帧完整 SSE 消息会自动剔除data:前缀、处理多行 data、识别 keep-alive 注释帧decodeBinary(Uint8List)尝试按 UTF-8 SSE/JSON 解码二进制数据protobuf 尚未端到端支持遇到 protobuf 服务端请协商使用 SSE 传输acceptsProtobuffalsevalidate(BaseEvent)对解码结果做必填字段与非空约束的二次校验例如messageId、toolCallId、toolCallName不允许为空串。解码边界上所有校验失败都会被包装成带结构化字段信息的DecodingError如field、expectedType、actualValue方便定位是哪个字段出了问题。五、Activity 与推理事件结构化消费模式AG-UI 的ACTIVITY_*与REASONING_*事件用于承载过程性信息Agent 正在做什么活动、当前推理到了哪一步。Dart SDK 提供了对应的强类型事件其中ActivitySnapshotEvent.content的类型是Object?——Python 参考服务器可能发出原始值或null因此消费端需要先做类型守卫再按结构化记录处理import dart:io; // 示例中使用 stderr await for (final event in client.runAgent(agentic_chat, input)) { if (event is ActivitySnapshotEvent) { // content 是 Object? —— Python 参考服务器可能发出 // 原始值或 null。先做守卫再按结构化记录处理。 final content event.content; if (content is MapString, dynamic) { // event.replace true → 丢弃该 messageId 之前的 content。 // event.replace false → 在既有 content 之上合并/扩展。 print( Activity (${event.activityType}, replace${event.replace}): $content, ); } else { // 线上协议出现意外记录并跳过而不是崩溃。 stderr.writeln( ActivitySnapshotEvent.content is ${content.runtimeType}, expected MapString, dynamic, ); } } else if (event is ActivityDeltaEvent) { print(Activity patch (${event.activityType}): ${event.patch}); } else if (event is ReasoningMessageContentEvent) { print(Reasoning: ${event.delta}); } else if (event is ReasoningEncryptedValueEvent) { // 不透明的密文载荷 —— 透传给下一个 Agent而非本地尝试解码。 } }这段代码揭示了两个关键设计ActivitySnapshotEvent.replace语义true表示整体替换该消息的活动内容false表示增量合并ReasoningEncryptedValueEvent是不透明密文SDK 不试图解析其中的内容消费方应当把它当作黑盒透传详见第十节cipher-data 保留。另外历史遗留的THINKING_TEXT_MESSAGE_*系列事件在 0.2.0 起已弃用统一迁移到规范的REASONING_*系列详见第九节。六、多模态输入UserMessage 与 typed partsUserMessage既支持纯文本也支持有序的类型化 part 列表text / image / audio / video / document。构造多模态消息使用UserMessage.multimodal// base64 编码的内联数据载荷。 const base64Pdf JVBERi0xLjQKJ...; final input SimpleRunAgentInput( messages: [ UserMessage.multimodal( id: msg_${DateTime.now().millisecondsSinceEpoch}, parts: [ TextInputContent(What is in this image?), ImageInputContent( // UrlSource.mimeType 可选DataSource 则必填。 source: UrlSource( value: https://example.com/photo.png, mimeType: image/png, ), ), DocumentInputContent( source: DataSource(value: base64Pdf, mimeType: application/pdf), ), ], ), ], );内容读取约定纯文本消息的contentgetter 返回字符串多模态消息的content返回null此时应通过messageContent读取类型化联合typed union内容。关于const的细节默认的UserMessage({content})构造器不是const的因为它在运行时把字符串包装成TextContent。需要编译期常量时改用UserMessage.fromContent——这也是从旧的const UserMessage(content: ...)写法迁移的路径// 之前不再是 const // UserMessage(id: u-1, content: Hello) // 之后 —— 兼容 const const msg UserMessage.fromContent( id: u-1, messageContent: TextContent(Hello), );七、工具交互Tool-Based Generative UI 完整闭环工具调用是 Agent 与外部世界交互的核心机制。下面是一个标准的两轮流程第一轮收集工具调用执行工具第二轮把结果回传给 Agent 获取最终回复ListToolCall toolCalls []; // 第一轮收集工具调用 await for (final event in client.runToolBasedGenerativeUi(input)) { if (event is MessagesSnapshotEvent) { for (final msg in event.messages) { if (msg is AssistantMessage msg.toolCalls ! null) { toolCalls.addAll(msg.toolCalls!); } } } } // 执行工具并把结果包装成 ToolMessage final toolResults toolCalls.map((call) ToolMessage( id: tool_${DateTime.now().millisecondsSinceEpoch}, toolCallId: call.id, content: processToolCall(call), )).toList(); // 第二轮携带工具结果继续对话 final followUp SimpleRunAgentInput( threadId: input.threadId, messages: [...input.messages, ...toolResults], ); // 获取最终响应 await for (final event in client.runToolBasedGenerativeUi(followUp)) { // 处理响应 }要点说明ToolMessage.toolCallId必须与ToolCall.id严格对应服务器靠它把结果关联回具体的工具调用保留threadId是为了让两轮请求处于同一会话上下文也可监听ToolCallStartEvent/ToolCallEndEvent等细粒度事件实现正在调用工具的 UI 提示见第十一节的完整示例。从源码层面看SDK 在发送前会做严格的入参校验lib/src/client/client.dart所有外发消息必须有非空id服务器将其作为会话历史的稳定身份键同一输入内message.id不可重复同一AssistantMessage内的toolCall.id也不可重复重复会抛出带field/constraint结构化信息的ValidationError。另外SimpleRunAgentInput.toJson()会始终输出规范要求的state、messages、tools、context、forwardedProps五个必填字段为空时输出空容器避免严格的 pydantic 服务端返回 422。八、共享状态管理Snapshot DeltaRFC 6902runSharedState端点用于与服务器同步共享状态。Dart SDK 采用快照 增量双通道模型STATE_SNAPSHOT给出完整状态STATE_DELTA给出 RFC 6902 JSON Patch 增量MESSAGES_SNAPSHOT给出全量消息列表MapString, dynamic state {}; ListMessage messages []; await for (final event in client.runSharedState(input)) { switch (event.eventType) { case EventType.stateSnapshot: state (event as StateSnapshotEvent).snapshot; break; case EventType.stateDelta: // 应用 JSON Patch (RFC 6902) 操作 applyJsonPatch(state, (event as StateDeltaEvent).delta); break; case EventType.messagesSnapshot: messages (event as MessagesSnapshotEvent).messages; break; } }开发提示applyJsonPatch需要你自己实现或引入 RFC 6902 兼容的 patch 应用函数每次收到STATE_SNAPSHOT时应以快照为准整体替换本地状态STATE_DELTA则用于在快照之上做增量更新从而在网络抖动或断线重连后仍能收敛到一致状态。九、错误处理AGUIError 单一根层次SDK 的所有错误都归在AGUIError这一个根之下lib/src/types/base.dart。完整层次如下AGUIError—— SDK 全局根。on AGUIError能捕获 SDK 可能抛出的所有错误运行时、传输、解码、以及 factory 直调校验。想用单个 catch-all 就用它。AgUiError—— 继承AGUIError覆盖运行时 / 传输 / 解码TransportError、AGUITimeoutError、CancellationError、DecodingError、客户端侧ValidationError。只想捕获SDK 遇到的运行时问题、明确不想捕获 factory 直调校验错误时用这个。AGUIValidationError—— 继承AGUIError不是AgUiError由*.fromJsonfactory 构造器在 wire 解码边界抛出。事件流经EventDecoder时会被包装成DecodingError所以使用解码管线的消费者不会直接看到它直接调用 factory如TextMessageStartEvent.fromJson(...)的调用者会看到。EncoderError及其子类型DecodeError、EncodeError、encoder 侧ValidationError—— 继承AGUIErrorEventDecoder管线原样重抛方便按类型做模式匹配。9.1 生产环境推荐捕获配方final cancelToken CancelToken(); try { await for (final event in client.runAgent(agent, input, cancelToken: cancelToken)) { // 处理事件 if (shouldCancel(event)) { cancelToken.cancel(); break; } } } on TransportError catch (e) { print(Connection error: ${e.message}); } on DecodingError catch (e) { print(Decode error: ${e.message}); } on ValidationError catch (e) { print(Validation error: ${e.message}); } on CancellationError { print(Request cancelled); } on AGUIError catch (e) { // 兜底捕获所有 AG-UI 起源的错误包括未经过 EventDecoder // 管线、由 Type.fromJson 直接抛出的 AGUIValidationError。 print(AG-UI error: $e); }如果代码直接使用EventDecoder推荐的捕获顺序是先on DecodingErrorwire 格式问题记录e.field/e.expectedType/e.actualValue再on TransportErrorHTTP/SSE 传输失败然后on AgUiError运行时/传输家族的其他错误最后on AGUIError兜底。注意捕获顺序有讲究DecodingError等具体类型必须放在AgUiError/AGUIError之前否则会被宽泛的父类先接住。9.2 取消Cancellation语义CancelToken支持对运行中的请求发起取消final cancelToken CancelToken(); // ... 传入 runAgent 的 cancelToken 参数 ... cancelToken.cancel();有两个重要注意点源码与文档共同确认CancelToken是一次性one-shot对象只能用于恰好一个请求。cancel()之后该 token 永久处于取消态若把它复用于第二个runAgent调用第二个调用会在 HTTP 请求发出前立即以CancellationError结束。实现见 lib/src/client/client.dart。取消不等同于断开 socketCancelToken.cancel()只会停止向你的流投递事件不会中止底层 HTTP socket。连接要等服务器关闭或操作系统空闲超时才会释放。若需要真正断开连接请为每个请求提供独立的IOClient。cancelRun(runId)方法则可以从客户端侧按 runId 取消指定运行并关闭其流。9.3 超时错误命名AGUITimeoutErrorTimeoutError在 0.2.0 中更名为AGUITimeoutError目的是避免遮蔽dart:async.TimeoutError由Future.timeout(...)/Stream.timeout(...)抛出。旧名保留为废弃 typedef 别名将在 1.0.0 移除。如果同时导入package:ag_ui/ag_ui.dart与dart:async务必使用新名字避免符号冲突以及本来想捕获 SDK 超时、却把dart:async.TimeoutError也一并吞掉的语义问题。十、Proxy 注意事项wire 拼写规范化camelCase vs snake_caseDart SDK 在每个fromJsonfactory 上同时接受 camelCaseTypeScript 规范拼写如threadId、runId、parentRunId、encryptedValue、rawEvent与 snake_casePython 规范拼写如thread_id、run_id、parent_run_id、encrypted_value、raw_event但在toJson上始终输出 camelCase没有提供输出 snake_case 的开关。这一设计对把 Dart SDK 当作代理中间层的场景有直接影响如果你用 Dart SDK 连接一个输出 snake_case 的 Python 服务器、下游又有一个严格只接受 snake_case的消费者你必须在边界把键名再转换回去好在 TypeScript 与 Python 官方 SDK 在输入侧都能容忍 camelCase所以实际很少遇到问题——但严格 snake_case 消费者在协议上合法且它看到的确实是来自 Dart 中间层的规范化后的载荷在单个BaseEvent.rawEvent往返中拼写由同时读取两个键名rawEvent/raw_event的辅助函数保持原样Dart 侧的 camelCase 输出是唯一的规范化点。十一、完整示例可交互的 CLI 聊天程序下面是 README 中的完整示例——一个从环境变量读取配置、在终端与 Agent 交互的 CLI 程序整合了流式文本、工具调用提示与生命周期结束检测import dart:io; import package:ag_ui/ag_ui.dart; void main() async { // 从环境变量初始化客户端 final client AgUiClient( config: AgUiClientConfig( baseUrl: Platform.environment[AGUI_BASE_URL] ?? http://localhost:8000, defaultHeaders: Platform.environment[AGUI_API_KEY] ! null ? {Authorization: Bearer ${Platform.environment[AGUI_API_KEY]}} : null, ), ); // 交互式对话循环 stdout.write(You: ); final userInput stdin.readLineSync() ?? ; final input SimpleRunAgentInput( messages: [ UserMessage( id: msg_${DateTime.now().millisecondsSinceEpoch}, content: userInput, ), ], ); stdout.write(Assistant: ); await for (final event in client.runAgent(agentic_chat, input)) { if (event is TextMessageContentEvent) { stdout.write(event.delta); } else if (event is ToolCallStartEvent) { print(\nCalling tool: ${event.toolCallName}); } else if (event.eventType EventType.runFinished) { print(\nDone!); break; } } client.dispose(); }运行前提本地或远端存在一个 AG-UI 兼容服务器例如 Python 参考实现且/agentic_chat端点可访问。代码通过AGUI_BASE_URL/AGUI_API_KEY两个环境变量控制连接地址与鉴权未设置时回退到http://localhost:8000。仓库中还提供了更丰富的可运行示例位于 sdks/community/dart/example/交互式 CLI 测试、基于工具调用的生成式 UI 流程、消息流式模式与端到端演示。十二、从 0.1.0 迁移指南0.2.0 引入了一个针对直接构造事件对象调用方的源码级破坏性变更0.3.0 延续该状态1.ToolCallResultEvent.role由String?变为ToolCallResultRole?// 之前 (0.1.0) ToolCallResultEvent( messageId: ..., toolCallId: ..., content: ..., role: tool, ); // 之后 (0.2.0) ToolCallResultEvent( messageId: ..., toolCallId: ..., content: ..., role: ToolCallResultRole.tool, );wire 解码不受影响未知的role字符串会经ToolCallResultRole.fromString吸收并回退到ToolCallResultRole.tool以保持前向兼容。完整动机见 CHANGELOG.md 的 Breaking Changes 章节。2.TimeoutError更名为AGUITimeoutError// 之前 (0.1.0) } on TimeoutError catch (e) { /* ... */ } // 之后 (0.2.0) } on AGUITimeoutError catch (e) { /* ... */ }裸名TimeoutError保留为废弃 typedef 别名将在 1.0.0 移除。迁移后裸TimeoutError将明确指代dart:async.TimeoutError运行时行为随之改变。3.THINKING_TEXT_MESSAGE_*事件弃用THINKING_TEXT_MESSAGE_*系列事件在 0.2.0 起弃用迁移到规范的REASONING_*系列REASONING_MESSAGE_START/REASONING_MESSAGE_CONTENT/REASONING_MESSAGE_END等。解码支持保留至 1.0.0。对应的EventType枚举值同样标记了Deprecatedlib/src/events/event_type.dart迁移映射见CHANGELOG.md的 Deprecated 章节。十三、Cipher-data 保留机制密文载荷的纵深防御部分 AG-UI 事件ReasoningEncryptedValueEvent、ReasoningMessage、ToolMessage携带不透明的密文载荷这些载荷必须在 Agent 之间原样转发。SDK 围绕这类载荷实现了多层次的纵深防御这也是 README 中单独成节强调的内容成功路径——每个BaseEvent的rawEvent字段保存从 SSE 流读到的逐字 wire 格式 map。需要重新发射ReasoningEncryptedValueEvent的代理应当读取rawEvent或自行保存原始字节并原样转发而不要调用toJson()它只输出解析后的字段。错误路径——当 factoryfromJson解码事件失败时抛出的AGUIValidationError会故意省略原始 JSON mapjson:字段防止密文字节通过基于反射的日志采集器或错误序列化器它们会遍历异常 cause 链泄露。解码器封装层的_wrapValidation也会据此把expectedType标记为BaseEvent (cipher-bearing — actualValue suppressed)让运维人员明白缺省 actualValue 是有意为之。ReasoningEncryptedValueEvent特例——它无条件设置rawEvent: null与其它所有 factory 不同转发_readRawEvent(json)会把完整密文载荷存进BaseEvent.rawEvent抵消逐字段的密文擦除。需要逐字 wire 形式的代理运维方必须在调用fromJson之前自行保存一份副本。copyWith与rawEvent——所有事件类型的copyWith把rawEvent视为粘性传null会保留现有值即rawEvent ?? this.rawEvent。要清除rawEvent请直接以rawEvent: null构造事件。这避免了无意的copyWith()调用悄悄保留调用者本打算丢弃的密文载荷。十四、测试单元测试直接使用 Dart 官方测试框架# 运行单元测试 dart test集成测试需要真实的 AG-UI 服务器# 运行集成测试需要服务器 cd test/integration ./helpers/start_server.sh dart test ./helpers/stop_server.sh十五、延伸阅读协议概念与架构仓库根目录 docs/concepts/architecture.mdx 等概念文档或官方文档站点的 Concepts 章节完整 API 参考官方文档 SDK / Dart 分栏client / core / encoder 子页面对应本仓库中的 SDK 说明文档Dart SDK 源码入口lib/ag_ui.dart聚合导出、lib/src/client/client.dart客户端核心、lib/src/client/config.dart配置项、lib/src/encoder/decoder.dart事件解码、lib/src/sse/sse_client.dartSSE 连接与重连版本变更与迁移明细CHANGELOG.md可运行示例sdks/community/dart/example/许可信息本 SDK 属于 AG-UI Protocol 项目许可见仓库根目录 LICENSE。【免费下载链接】ag-uiAG-UI: the Agent-User Interaction Protocol. Bring Agents into Frontend Applications.项目地址: https://gitcode.com/gh_mirrors/agu/ag-ui创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表