
后端前端协同办公即时通讯企业应用CRMAI Agent人工智能【免费下载链接】macroMacro is a unified workspace for teams: email, chat, docs, tasks, agents, calls, and CRM — -linked together with shared AI memory.项目地址https://gitcode.com/GitHub_Trending/macro3/macro点击查看免费下载在 Macro 的 Agent Harness 体系里不同编码代理Macro 内置 in-memory agent、用户的 Cursor 账户、配对的 macrod 运行时都会向客户端“自报”一组可调会话设置例如模型、思考等级等。AgentConfigOptionDto就是这套设置在对外 SDK 中的统一结构。本文以该类型文档为核心骨架结合仓库中的 Rust 投影实现、HTTP 适配器、测试用例与 TypeScript 生成代码逐字段拆解它的类型契约、来源与使用方式读完后你可以独立完成“发现设置 → 渲染 UI → 下发修改”的完整闭环。一、类型定位它是协议里的哪一层原文档对该类型只有一句定义性描述AgentConfigOptionDtoAgentConfigKindDto{ category?: string | null; description?: string | null; id: string; name: string }One agent-advertised ACP session setting.这短短几行包含三个关键信息值得先展开它是 TypeScript 的交叉类型intersection type不是单一接口。AgentConfigOptionDto 通用外壳字段id/name/description/category交叉AgentConfigKindDto形态相关的type、currentValue以及 select 专属的options。因此它同时具备“元数据”和“值状态”两类信息。它是 ACPAgent Client Protocol语义的投影。仓库中的类型注释直接写明 “One agent-advertisedACPsession setting”说明这些字段并非 Macro 自己发明的业务概念而是把 ACP 的SessionConfigOption转换成了稳定的对外词汇。它是“被代理声明的”而不是“被 Macro 定义的”。字段注释里反复出现 “supplied by the agent”“advertised by the agent”“Opaque”意味着 Macro 只做搬运与规范化不解释具体语义也不对取值做枚举约束。AgentConfigOptionDto在仓库中有两处权威来源互为镜像角色文件说明Rust 定义真相源crates/agent_harness/src/inbound/capability_discovery.rs带utoipa::ToSchema的 DTO用于生成 OpenAPITypeScript 定义生成物packages/sdk/generated/agent-harness/types.gen.ts由hey-api/openapi-ts自动生成文件头即声明自动生成文档页本文主体AgentConfigOptionDto.md由类型定义派生的参考文档在 Rust 侧DTO 与领域对象之间还有一层转换领域层用AgentCapabilities { config_options: VecSessionConfigOption }表达同一份数据crates/agent_harness/src/domain/capability_discovery.rsHTTP 层再通过FromAgentCapabilities for DiscoverAgentCapabilitiesResponse把它映射成AgentConfigOptionDto同文件。这条“ACP → 领域 → DTO → SDK”的链路是理解每个字段含义的最佳切入点。二、逐字段拆解2.1 通用外壳字段交叉部分字段类型是否必填原文档描述技术含义idstring必填Opaque id used to change this setting.修改该设置时回传的不透明标识对应 ACP 的option.id最终用于session/set_config_option的configIdnamestring必填Display label supplied by the agent.代理给出的展示名例如ModelUI 直接渲染不做翻译映射description?string \| null可选Optional explanatory copy.补充说明文案可能为空category?string \| null可选ACP semantic category, such asmodelorthought_level.ACP 语义分类用于客户端做分组/图标/排序等启发式处理id的“不透明”opaque属性非常关键文档没有承诺它一定是可枚举常量虽然后测用例中确实出现了model但契约层面应视为字符串。仓库测试就断言了首个选项的id为modelcrates/agent_harness/src/domain/capability_discovery/test.rs这属于测试夹具的取值而非类型保证。category同样是“语义提示”而不是“值域约束”。原文档只举了model与thought_level两个例子。从源码结构看它的取值是从 ACP 枚举经serde_json序列化后取字符串得到的category: option .category .as_ref() .and_then(|category| serde_json::to_value(category).ok()) .and_then(|value| value.as_str().map(str::to_owned)),这段代码位于 crates/folds/agent_fold/src/domain/session_config.rs。它意味着能被序列化成字符串的分类会被保留无法序列化的情形会退化为None在 TS 中表现为undefined或null。因此客户端必须容忍category缺失不能把category model当作前提。2.2 形态字段AgentConfigKindDto 的两种联合成员AgentConfigKindDto是一个以type为判别字段的联合类型AgentConfigKindDto.mdexport type AgentConfigKindDto { currentValue: string; // Current opaque value. options: ArrayAgentConfigSelectOptionDto; // Ordered values supplied by the agent. type: select; } | { currentValue: boolean; // Current value. type: boolean; };成员字段类型含义selecttypeselect单值选择器selectcurrentValuestring当前选中的不透明值与options[].value同一取值空间selectoptionsAgentConfigSelectOptionDto[]由代理给出、保持顺序的候选项booleantypeboolean开关型设置booleancurrentValueboolean当前开/关状态注意currentValue在两种成员下类型不同select是stringboolean是boolean。这正是使用type做判别收窄narrowing的原因也是不能把它统一当作字符串处理的根本原因。2.3 候选项AgentConfigSelectOptionDtoselect.options的元素类型见 AgentConfigSelectOptionDto.md字段类型必填含义valuestring必填被选中时回传给代理的不透明值namestring必填展示标签description?string \| null可选该取值的提供方说明group?string \| null可选提供方给出的分组标题value与currentValue的关系是“候选项集合中的一员”。文档没有要求currentValue一定出现在options中也没有要求value全局唯一因此比较时建议直接用严格相等而不是依赖索引位置。group字段的来源值得一提ACP 允许 select 的选项以“分组”形式下发Macro 在投影时会把分组拍平为一维数组同时把组名写入每一项的groupSessionConfigSelectOptions::Grouped(groups) groups .iter() .flat_map(|group| { group .options .iter() .map(|option| project_select_option(option, Some(group.name.as_str()))) }) .collect(),见 crates/folds/agent_fold/src/domain/session_config.rs。因此客户端若要还原分组 UI应按group字段做稳定分组保留首次出现顺序而不是假设数组本身是二维的。未分组场景下group为None。三、从 ACP 到 DTO投影过程的三个实现细节理解投影实现可以解释文档中那些“看起来没写”的边界行为。3.1 只保留已识别的形态未知形态被静默丢弃session_config_options使用filter_mapproject_optionpub fn session_config_options(options: [AcpConfigOption]) - VecSessionConfigOption { options.iter().filter_map(project_option).collect() }其中project_option对AcpConfigKind做matchSelect与Boolean之外的分支直接return NoneSelect内部若options既不是Ungrouped也不是Grouped同样返回Nonecrates/folds/agent_fold/src/domain/session_config.rs。结论很明确configOptions是“Macro 能理解的子集”而不是“代理宣称的全部”。当你看到数组长度小于代理实际能力时这不是丢包而是投影层的有意收敛。这一点在原类型文档中无法直接看出但对排障非常重要。3.2 两种“无能力”场景返回空数组而非报错领域服务提供AgentCapabilities::unsupported()返回config_options: Vec::new()crates/agent_harness/src/domain/capability_discovery.rs。也就是说某些 provider 天生不提供会话设置时HTTP 仍然是 200只是configOptions: []。客户端应把空数组视作正常状态隐藏设置面板而不是异常。3.3 DTO 转换保留了字段顺序与层级FromAgentCapabilities的实现把领域结构逐层克隆到 DTOid、name、description、category原样传递kind按Select/Boolean分支映射options逐项映射crates/agent_harness/src/inbound/capability_discovery.rs。序列化层面结构体标了#[serde(rename_all camelCase)]枚举内部又用rename_all_fields camelCase并显式rename currentValue这解释了为什么 Rust 侧叫current_value而对外的 JSON/TS 是currentValue。四、获取这些选项POST /agent-capabilities/discoverAgentConfigOptionDto的数组并不是随便就能拿到的它是能力发现接口响应体DiscoverAgentCapabilitiesResponse.configOptions的元素类型types.gen.ts。4.1 请求结构请求体DiscoverAgentCapabilitiesRequesttypes.gen.ts字段类型必填说明harnessCapabilityHarnessDto必填要探测的 providerharnessIdstring \| null视情况macrod必填其它目标禁止传modelstring \| null可选指定要检查哪个模型下的会话设置harness的取值来自CapabilityHarnessDto其枚举标注了#[serde(rename_all kebab-case)]crates/agent_harness/src/inbound/capability_discovery.rs因此线上取值为字符串枚举成员线上取值含义InMemoryin-memoryMacro 进程内 agentCursorcursor调用者自己的 Cursor 账户Macrodmacrod已配对的 macrod 运行时一个探测 Cursor 账户在特定模型下可调项的最小请求POST /agent-capabilities/discover Authorization: Bearer token Content-Type: application/json { harness: cursor, model: claude-sonnet-4-5 }响应示例字段形态与文档一致取值为示例数据{ configOptions: [ { id: model, name: Model, description: The model this session runs on., category: model, type: select, currentValue: fast, options: [ { value: fast, name: Fast }, { value: deep, name: Deep, description: Slower, more thorough. } ] }, { id: auto_approve, name: Auto approve tools, category: null, description: null, type: boolean, currentValue: false } ] }注意description与category可以是nulltype决定后面是否存在options。4.2harnessId的强约束领域服务的分发逻辑对(harness, harness_id)组合做了显式校验crates/agent_harness/src/domain/capability_discovery.rsin-memory/cursor目标必须不传harnessId否则BadRequestmacrod目标必须传harnessId缺失时报harnessId is required for macrodmacrod目标在探测前会先经过HarnessCapabilityAccess::can_use授权检查未通过直接Forbidden不会触发一次无谓的运行时调用。这点在测试中也有直接覆盖macrod_authorizes_before_dispatch_and_projects_the_catalog验证了“先授权后分发”的顺序crates/agent_harness/src/domain/capability_discovery/test.rs。4.3 错误码与 DTO 的关系HTTP 适配器把领域错误映射为状态码crates/agent_harness/src/inbound/capability_discovery.rs状态码触发条件客户端应如何处理200探测成功含空数组正常渲染设置400harnessId与该 harness 组合非法修正请求不重试401未认证重新登录403配对 harness 对调用者不可见提示无权限409macrod 运行时或 Cursor 账户未连接引导用户连接后重试504macrod 探测超时可退避重试502provider 探测失败记录原始错误文本其中超时是领域服务的构造参数之一AgentCapabilitiesServiceImpl::new(..., timeout)同文件由组合根注入类型定义本身不承载该语义。五、下发修改与 AgentConfigOptionDto 配套的 AgentSetConfigOptionAction拿到id与候选项value之后修改设置依靠AgentSetConfigOptionActionAgentSetConfigOptionAction.mdAgentSetConfigOptionAction{ configId: string; value: string }Ask the agent to change one advertised select-style session setting.字段类型说明configIdstring由代理声明的不透明 ACP config id即AgentConfigOptionDto.idvaluestring该选项声明的某个 select 值即options[].value这是一个两字段动作正好与AgentConfigOptionDto的id和options[].value一一对应。原文档特意强调 “select-style”说明该动作只适用于type: select。boolean型设置没有配套的 DTO 动作类型不应把布尔值塞进value字符串字段否则会破坏契约。在动作联合体中该结构以type: setConfigOption作为判别值types.gen.tsexport type AgentAction (AgentPromptAction { type: prompt }) | (AgentSetModelAction { type: setModel }) | (AgentSetConfigOptionAction { type: setConfigOption }) | { type: compact } | { type: stop } | (AgentRespondElicitationAction { type: respondElicitation }) | (AgentPermissionAction { type: respondToPermission });请求示例{ type: setConfigOption, configId: model, value: deep }5.1 服务端如何消费这个动作Rust 领域层把动作转换为 ACP 的 JSON-RPC 请求。测试changing_the_model_persists_it_and_tells_the_running_agent明确断言了线上方法名为session/set_config_option并且修改是持久化 通知运行中代理双写assert!( sent.iter().any(|message| matches!( message, ToRuntimeMessage::Acp(AcpMessage(RawJsonRpcMessage::Request(request))) if request.method.as_ref() session/set_config_option )), the running agent is told, got {sent:?} );见 crates/agent_harness/src/domain/service/test.rs。这条测试原本针对“切换模型”场景而模型切换在协议层走的正是同一个session/set_config_option通道——这也解释了为什么AgentConfigOptionDto的示例id常常是model。5.2 队列中的不可编辑性AgentSetConfigOptionAction进入动作队列后属于不可编辑的一类。队列实现里对edit_prompt显式拒绝这些动作crates/agent_harness/src/domain/queue.rsAgentAction::SetModel(_) | AgentAction::SetConfigOption(_) | AgentAction::Compact | AgentAction::Stop | AgentAction::RespondElicitation(_) | AgentAction::RespondToPermission(_) Err(QueueError::NotEditable),因此 UI 层不应把“设置变更”当作可自由改写的草稿提示词若要撤销应重新提交一次相反取值的动作而不是编辑历史条目。六、TypeScript 侧的完整用法生成的 SDK 已经封装了发现接口方法名为discoverAgentCapabilitiesHandler使用 Bearer 认证并固定Content-Type: application/jsonpackages/sdk/generated/agent-harness/sdk.gen.ts。6.1 发现并渲染import type { AgentConfigOptionDto } from ./generated/agent-harness/types.gen; const { data } await sdk.discoverAgentCapabilitiesHandler({ body: { harness: macrod, harnessId: paired-harness-uuid }, }); const options: AgentConfigOptionDto[] data.configOptions; // 按 type 收窄后分别渲染 for (const option of options) { if (option.type select) { renderSelect(option.id, option.name, option.currentValue, option.options); } else { // option.type boolean renderToggle(option.id, option.name, option.currentValue); } }option.type select分支内currentValue会被收窄为string并且options字段才存在else分支中currentValue为boolean。这就是为什么文档把AgentConfigKindDto设计成带判别字段的联合类型而不是可选字段的大对象。6.2 按group还原分组function groupOptions(options: AgentConfigSelectOptionDto[]) { const groups new Mapstring, AgentConfigSelectOptionDto[](); for (const opt of options) { const key opt.group ?? ; // 未分组归入空串分组 (groups.get(key) ?? groups.set(key, []).get(key)!).push(opt); } return groups; }由于投影层已经把 ACP 的分组拍平见第 3 节这里的分组是基于字段重建的顺序依赖数组本身的有序性。6.3 提交变更await sdk.controlAgentSessionHandler({ body: { action: { type: setConfigOption, configId: option.id, value: chosen.value }, }, });上面示例中的方法名与请求外层字段属于调用方视角的示意真正与本文类型契约绑定的是两点动作对象必须携带type: setConfigOption并且只包含configId与value两个字段。七、容易被忽略的六个工程细节不要枚举id。id被定义为 “Opaque id”具体取值由代理决定测试夹具里的model只是夹具。不要假设currentValue一定在options里。文档未作此保证UI 应先查找匹配项找不到时降级展示原始值。configOptions可能为空数组。AgentCapabilities::unsupported()就是这种形态属于正常语义。未知形态会被丢弃。投影层只保留select/boolean见 session_config.rs。boolean设置没有对应动作类型。AgentSetConfigOptionAction的value是string文档也只承诺 select-style。macrod探测先鉴权再分发因此403与409的语义不同前者是权限问题重试无益后者是连接问题可引导重连。八、相关文档与源码索引主类型文档AgentConfigOptionDto形态联合AgentConfigKindDto候选项结构AgentConfigSelectOptionDto配套动作AgentSetConfigOptionActionDTO 定义crates/agent_harness/src/inbound/capability_discovery.rs领域服务与分发校验crates/agent_harness/src/domain/capability_discovery.rsACP 投影实现crates/folds/agent_fold/src/domain/session_config.rs领域测试crates/agent_harness/src/domain/capability_discovery/test.rs动作下发测试crates/agent_harness/src/domain/service/test.rs生成 SDKpackages/sdk/generated/agent-harness/sdk.gen.ts、types.gen.ts赞分享后端前端协同办公即时通讯企业应用CRMAI Agent人工智能【免费下载链接】macroMacro is a unified workspace for teams: email, chat, docs, tasks, agents, calls, and CRM — -linked together with shared AI memory.项目地址https://gitcode.com/GitHub_Trending/macro3/macro点击查看免费下载相关推荐IB_Robot 统一模型推理架构策略、感知、TTS 与抓取模型共享的 ModelRuntimeHandle 控制面IB_Robot 统一模型推理架构策略、感知、TTS 与抓取模型共享的 ModelRuntimeHandle 控制面 IB_RobotopenEuler E后端前端协同办公即时通讯企业应用CRMAI Agent人工智能Macro agent_trigger 深度解析Agent 会话触发判定与 Prompt 上下文装配Macro agent_trigger 深度解析Agent 会话触发判定与 Prompt 上下文装配 本篇聚焦 Macro 仓库中的 agent_trigge后端前端协同办公即时通讯企业应用CRMAI Agent人工智能agent_trigger 深度解析Macro 中 Agent 会话的触发判定与提示上下文装配agent_trigger 深度解析Macro 中 Agent 会话的触发判定与提示上下文装配 agent_trigger 是 Macro 里负责要不要为一后端前端协同办公即时通讯企业应用CRMAI Agent人工智能上一篇终极指南bsdiff/bspatch二进制补丁工具完全解析下一篇Maple Mono 等宽字体3 步装好开启圆角连字与终端图标创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考