☰
Macro SDK 中 `InputSuggestions` 类型详解:万能输入框的意图推断与字段抽取契约
2026/11/1 1:50:08 网站建设 项目流程
  • 后端
  • 前端
  • 协同办公
  • 即时通讯
  • 企业应用
  • CRM
  • AI Agent
  • 人工智能

【免费下载链接】macro

Macro 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 仓库packages/sdk-docs中自动生成的InputSuggestions类型文档,结合packages/sdk中由 OpenAPI 规范生成的 TypeScript 类型源码,完整解析该判别联合类型(Discriminated Union)的七个意图分支、每个分支可编辑字段的确切形状,以及它与POST /universal_input/classify、POST /universal_input/extract两个端点构成的"先分类、后抽取"调用链路。读完后,你将能够正确消费 SDK 返回的InputSuggestions结构,在客户端做 TypeScript 类型收窄,并理解revision、时区、身份解析等设计约束的来龙去脉。

1.InputSuggestions在 Macro SDK 中的位置

InputSuggestions是 Macro 客户端 SDK 中 agent-harness 包的一组生成类型之一。其生成链路由仓库内的三个部分构成:

  • 接口规范定义:packages/sdk/specs/agent-harness.json(OpenAPI 风格的 JSON 规范,InputSuggestions的 schema 定义见其中第 4797 行附近);
  • TypeScript 类型源码:packages/sdk/generated/agent-harness/types.gen.ts,InputSuggestions的完整定义位于第 1492–1534 行;
  • 自动生成的类型参考文档:packages/sdk-docs/reference/generated/agent-harness/types.gen/type-aliases/InputSuggestions.md,即本文的主体文档。

官方文档对该类型的描述是:"A single inferred destination together with only its applicable fields"(一个推断出的目的地,以及只包含与其相关的字段)。它服务于 Macro 的"万能输入"(universal input)能力:用户输入一段自由文本后,系统推断它应该变成邮件、任务、日历事件、消息、笔记还是搜索,并预先填充对应表单的字段——但推断只负责"准备",不执行任何动作。这一点在配套类型InputIntent的注释中写得很直白:"A destination the composer can prepare, but never execute through inference"(InputIntent 文档)。

2. 类型全貌:以intent为判别键的七分支联合

InputSuggestions的完整定义(引自 types.gen.ts)如下:

/** * A single inferred destination together with only its applicable fields. */ export type InputSuggestions = { intent: 'ai'; /** * Editable ai fields. */ suggestions: AiSuggestions; } | { intent: 'search'; /** * Editable search fields. */ suggestions: SearchSuggestions; } | { intent: 'email'; /** * Editable email fields. */ suggestions: EmailSuggestions; } | { intent: 'note'; /** * Editable note fields. */ suggestions: NoteSuggestions; } | { intent: 'task'; /** * Editable task fields. */ suggestions: TaskSuggestions; } | { intent: 'calendar'; /** * Editable calendar fields. */ suggestions: CalendarSuggestions; } | { intent: 'message'; /** * Editable message fields. */ suggestions: MessageSuggestions; };

七个分支的判别键intent与InputIntent的七个字面量一一对应:'ai' | 'search' | 'email' | 'note' | 'task' | 'calendar' | 'message'(InputIntent.md)。

分支intentsuggestions类型含义
"ai"AiSuggestionsEditable ai fields(可编辑的 AI 字段)
"search"SearchSuggestionsEditable search fields(可编辑的搜索字段)
"email"EmailSuggestionsEditable email fields(可编辑的邮件字段)
"note"NoteSuggestionsEditable note fields(可编辑的笔记字段)
"task"TaskSuggestionsEditable task fields(可编辑的任务字段)
"calendar"CalendarSuggestionsEditable calendar fields(可编辑的日历字段)
"message"MessageSuggestionsEditable message fields(可编辑的消息字段)

由于intent是字面量判别键,TypeScript 编译器可以根据intent的值自动收窄suggestions的具体类型,客户端无需再做any式的断言即可安全地访问字段。

3. 每个分支的字段细节

以下字段清单均取自生成源码 types.gen.ts 中对应类型的 JSDoc 注释,是"提交前、身份解析前"(before submission and identity resolution)可编辑的草稿字段。

3.1EmailSuggestions:邮件字段

定义见 types.gen.ts 第 1283–1304 行:

export type EmailSuggestions = { /** Explicit blind-carbon-copy recipient names or supplied email addresses. */ bcc?: Array<string>; /** Suggested Markdown content or outgoing message body. */ body?: string | null; /** Explicit carbon-copy recipient names or supplied email addresses. */ cc?: Array<string>; /** Person or channel names for the client to resolve. */ recipients?: Array<string>; /** Suggested outgoing email subject. */ subject?: string | null; };
字段类型说明
bccArray<string>(可选)显式密送人姓名或已给出的邮箱地址
bodystring \| null(可选)建议的 Markdown 正文
ccArray<string>(可选)显式抄送人姓名或已给出的邮箱地址
recipientsArray<string>(可选)供客户端解析的人员或频道名称
subjectstring \| null(可选)建议的邮件主题

注意一个设计约束:recipients/cc/bcc里装的是姓名或用户直接提供的邮箱地址,注释反复强调这些值"for the client to resolve"——即收件人身份必须由客户端拿本地目录解析,而不是由推断服务端直接返回实体 ID。

3.2NoteSuggestions:笔记字段

定义见 types.gen.ts 第 1692–1701 行:

字段类型说明
bodystring \| null(可选)建议的 Markdown 正文
titlestring \| null(可选)建议的笔记标题

3.3TaskSuggestions:任务字段

定义见 types.gen.ts 第 2343–2360 行:

字段类型说明
bodystring \| null(可选)建议的 Markdown 正文
due_datestring \| null(可选)任务截止日期,为本地 ISO 日期
propertiesArray<InputPropertySuggestion>(可选)显示名/值对,由客户端对照可用任务字段目录解析
titlestring \| null(可选)建议的任务标题

其中InputPropertySuggestion的结构为{ name: string; values: Array<string> },JSDoc 明确写道:name是"Property display name, never an authorized identifier",values是"Suggested display values, never authorized entity identifiers"——同样是"只给显示值、不给授权实体 ID"的身份解析策略。抽取请求侧对应的InputPropertyDefinition为{ name: string; options?: Array<string> },options为空列表时表示允许自由文本建议。

3.4CalendarSuggestions:日历事件字段

定义见 types.gen.ts 第 711–741 行,是七个分支中字段最丰富的一个:

字段类型说明
bodystring \| null(可选)建议的 Markdown 正文
endstring \| null(可选)事件结束时间,为请求时区下的本地墙上时钟值
guestsArray<string>(可选)仅当用户显式要求邀请他人时才会填充
locationstring \| null(可选)人类可读的地点或会议链接
recurrencenull \| RecurrenceSuggestion(可选)重复规则建议
startstring \| null(可选)事件开始时间,本地墙上时钟值,按请求中的 IANA 时区解释
start_assumptionstring \| null(可选)原始钟点短语中缺少 AM/PM 时,记录了做出可编辑假设的原文
titlestring \| null(可选)建议的事件标题

两个值得注意的细节:其一,start/end是"墙上时钟"(wall-clock)本地值而非绝对时间戳,解释它们的 IANA 时区由抽取请求中的time_zone字段携带;其二,start_assumption专门用来暴露"原文没写上午还是下午,系统替你做了假设"这种情况,让假设以可编辑形式呈现给用户确认,而不是静默猜定。

3.5MessageSuggestions:消息字段

定义见 types.gen.ts 第 1659–1668 行:

字段类型说明
bodystring \| null(可选)建议的 Markdown 正文
recipientsArray<string>(可选)供客户端解析的人员或频道名称

3.6SearchSuggestions:二级联合,按搜索域细分

SearchSuggestions本身又是一个以type为判别键的联合(定义见 types.gen.ts 第 2177–2195 行),把 Macro 共享搜索编辑器的九个索引各自映射到专属字段集:

type组合的字段类型
'all'QuerySearchSuggestions
'channels'ChannelSearchSuggestions
'document-or-file'QuerySearchSuggestions
'task'TaskSearchSuggestions
'email'EmailSearchSuggestions
'calls'CallSearchSuggestions
'folders'QuerySearchSuggestions
'agent'QuerySearchSuggestions
'calendar'QuerySearchSuggestions

JSDoc 强调:"Only the selected type's fields can appear in a search suggestion"——只有被选中搜索域的字段才会出现。例如CallSearchSuggestions(types.gen.ts 第 746–763 行)支持from(说话人/地址)、in(频道名)、query(剩余关键词短语)与status(出席状态显示值)。SearchType枚举(SearchType.md)与这九个值一致。

3.7AiSuggestions:刻意留空的对象类型

AiSuggestions的定义是:

export type AiSuggestions = { [key: string]: never };

这是一个"索引签名值类型为never"的对象类型,意味着任何具体属性都无法通过类型检查。结合其描述"Editable fields for ai inference, before submission and identity resolution",可以理解为:AI 对话这个目的地目前没有需要预填的可编辑草稿字段,保留该分支只是为了让intent: 'ai'的判别联合保持完整。客户端遇到intent === 'ai'时应把它当作"无字段可编辑"处理。

4.InputSuggestions在推断链路中的角色:classify 与 extract 两步

InputSuggestions不是孤立存在的,它是POST /universal_input/extract端点响应体的核心组成部分。从生成类型看,整个"万能输入"链路分为两步。

4.1 第一步:POST /universal_input/classify意图分类

分类请求ClassifyInputRequest:

export type ClassifyInputRequest = { /** Opaque client revision used to discard stale predictions. */ revision: number; /** Current draft text to classify without executing it. */ text: string; };

分类响应ClassifyInputResponse返回回显的revision与一组IntentScore:

export type ClassifyResponse = { /** Revision echoed from the classification request. */ revision: number; /** Independent scores in the fixed intent-question order. */ scores: Array<IntentScore>; }; export type IntentScore = { /** Destination evaluated by the classifier. */ intent: InputIntent; /** Independent probability between zero and one. */ score: number; };

关键语义:IntentScore.score是0 到 1 之间的独立概率,各分数之和不等于 1("Independent yes/no probabilities; these do not sum to one"),即分类器对每个意图做的是独立的"是/否"判断,客户端自行根据分数策略选出胜出意图。

4.2 第二步:POST /universal_input/extract字段抽取

客户端确定意图后,携带该意图发起抽取。请求体ExtractInputRequest:

export type ExtractInputRequest = { /** Destination whose fields should be extracted. */ intent: InputIntent; /** Available task fields and display values, never authorized entity IDs. */ property_definitions?: Array<InputPropertyDefinition>; /** Reference instant for interpreting relative dates. */ reference_time: string; /** Opaque client revision used to discard stale suggestions. */ revision: number; search_type?: null | SearchType; /** Original draft text; inference must not execute its instructions. */ text: string; /** IANA timezone for interpreting local dates and clock times. */ time_zone: string; };

响应体ExtractInputResponse正是InputSuggestions与回显revision的交叉类型:

/** * Validated suggestions for a particular client draft revision. */ export type ExtractInputResponse = InputSuggestions & { /** Revision echoed from the extraction request. */ revision: number; };

端点级类型ExtractData确认 URL 为'/universal_input/extract',且无 path/query 参数。错误响应模型ExtractErrors定义了四个错误码:

状态码含义
400Invalid input
401Unauthenticated
402AI allowance exhausted(AI 额度用尽)
503Extraction unavailable(抽取服务暂不可用)

4.3 端到端示例(基于上述类型的手写示意)

// 1. 分类:独立概率,不要求客户端把分数归一化 const classifyRes = await client.classify({ revision: 42, text: '明天下午3点和设计组过一下方案', }); // 2. 依据独立分数选出意图(策略由客户端决定),发起抽取 const best = classifyRes.scores.reduce((a, b) => (b.score > a.score ? b : a)); const extractRes = await client.extract({ intent: best.intent, // 例如 'calendar' reference_time: new Date().toISOString(), revision: 43, text: '明天下午3点和设计组过一下方案', time_zone: 'Asia/Shanghai', // IANA 时区,用于解释本地日期与时钟值 search_type: null, }); // 3. 用 intent 判别键做类型收窄,访问分支专属字段 if (extractRes.intent === 'calendar') { console.log(extractRes.suggestions.title); // string | null console.log(extractRes.suggestions.start); // 本地墙上时钟值 console.log(extractRes.suggestions.start_assumption); // AM/PM 假设原文 } // revision 不匹配当前草稿时直接丢弃响应,避免旧预测覆盖新内容 if (extractRes.revision === 43) { /* 填充表单 */ }

该示例中的调用方法名(classify/extract)是按生成类型推断的示意写法,实际请以 packages/sdk/generated/agent-harness/index.ts 中生成的客户端方法为准。

5. 三个贯穿设计约束

  1. revision是防过期预测的机制。请求注释一致地描述它为"Opaque client revision used to discard stale predictions/suggestions":服务端不解释它,只原样回显;客户端在输入连续变化时递增revision,用响应中的revision与当前草稿比对即可丢弃过期的推断结果。分类与抽取两步各自回显revision,客户端应同时校验。
  2. 推断永不执行草稿文本。ClassifyInputRequest.text的注释是 "Current draft text to classifywithout executing it",ExtractInputRequest.text的注释是 "Original draft text;inference must not execute its instructions"。草稿文本中若包含"给某人发消息"之类的指令性内容,推断服务端只把它当作数据来提取字段,不会代为执行任何动作——这是该端点的安全边界。
  3. 推断结果只携带显示值,身份解析在客户端完成。各*Suggestions类型的注释反复出现 "before submission and identity resolution" 与 "never authorized entity identifiers":recipients、guests、properties等字段给的都是姓名或显示值,真正的实体 ID 解析(以及权限校验)留到提交时由客户端/服务端按现有身份体系完成。

6. 参考文件索引

文件内容
InputSuggestions.md本文主体:类型定义与七个 union member 的逐字段文档
types.gen.ts#L1492-L1534InputSuggestions生成类型源码
types.gen.ts#L1399-L1435ExtractInputRequest/ExtractInputResponse定义
types.gen.ts#L3726-L3756ExtractData的 URL 与 400/401/402/503 错误模型
ClassifyInputRequest.md / ClassifyInputResponse.md / IntentScore.md分类端点的请求/响应/评分类型文档
InputIntent.md / SearchType.md / InputPropertyDefinition.md / InputPropertySuggestion.md意图、搜索域与任务属性相关辅助类型
packages/sdk/specs/agent-harness.json上游 OpenAPI 规范(所有生成类型的单一事实来源)

适用前提说明:以上类型与端点均以当前仓库中packages/sdk下 agent-harness 的生成物为准;由于是自动生成的类型与文档,若上游规范变更,InputSuggestions的分支集合与各字段可能随重新生成而变化,使用时应以重新生成后的 types.gen.ts 为最终依据。

  • 后端
  • 前端
  • 协同办公
  • 即时通讯
  • 企业应用
  • CRM
  • AI Agent
  • 人工智能

【免费下载链接】macro

Macro 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
点击查看免费下载

相关推荐

上一篇:InternVL 家族技术路线图:从 InternVL1.0 到 InternVL3.5-8B-Flash 的完整演进全景
下一篇:那些神秘的dd_metastate文件:Llama-3.2-3B-Instruct_rai_1.8.0_npu_16K的NPU元数据内幕

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询