Documentation
¶
Overview ¶
Package field 提供声明插件契约的 builder。
为什么不用 struct tag(docs/plugin-sdk-multilang.md):
- tag 是字符串,`lable:"..."` 拼错时**编译器一声不吭**;builder 写错方法名直接编译失败
- 结构化信息塞进字符串已经在吃力——enum 的显示名要发明 `=` 分隔,oneof 的类型名只能写字符串
- `oneof` 在这里是**真实类型引用**,类型改名/删除立刻编译失败,不必等生成期
- 无结构的 json 必须 .Opaque(理由) 才能声明:API 里压根没有"随手 map"这个省事选项
声明是纯数据,可直接序列化为 JSON 供其他语言 SDK 生成对应类型。 与契约同模块:builder 只用契约类型,没有一点传输的东西,故不该压在 SDK 里—— 压在那里的话,内核(httpcore/llmcore)想声明自己的契约就得反过来依赖 SDK。
Index ¶
- func Opt(value string, label ...string) contract.Option
- type B
- func Any(name, reason string) *B
- func Array(name string, shape any) *B
- func ArrayOf(name string, variants ...any) *B
- func Bool(name string) *B
- func Bools(name string) *B
- func Enum(name string, opts ...contract.Option) *B
- func File(name string) *B
- func Files(name string) *B
- func Int(name string) *B
- func Ints(name string) *B
- func Json(name string, shape any) *B
- func Number(name string) *B
- func Numbers(name string) *B
- func Object(name, reason string) *B
- func OneOf(name string, variants ...any) *B
- func Secret(name string) *B
- func Select(name string, options ...string) *B
- func String(name string) *B
- func Strings(name string) *B
- func Text(name string) *B
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type B ¶
type B struct {
// contains filtered or unexported fields
}
B:字段 builder。实现 contract.FieldSpec,可直接放进 Inputs()/Outputs() 返回值。
func Any ¶
Any 声明「任意 JSON 值」:连是不是对象都不定。
与 Object 的区别值得记住:Object 是「**是**对象,但键不定」(→ map[string]any, 校验要求必须是对象);Any 是「可能是对象、数组、字符串、数字、布尔」(→ any,校验放行一切)。 http 的请求体/响应体就是后者:json 模式给对象,raw 模式给字符串。
实现上用已有的联合类型表达——any 本就是所有类型的联合。于是校验放行任何值、 生成 any、审计仍看得见理由,三件事都不必新造机制。理由同样必填。
func Array ¶
Array 数组,**元素类型由切片给出**:
field.Array("hosts", []string{}) // 标量元素
field.Array("blocks", []Block{}) // 结构元素
一个参数同时覆盖两种情况:标量落 ItemType,结构落 Fields。
func ArrayOf ¶
ArrayOf 声明「数组,且元素是联合类型」:[]OneOf<A, B, …>。
多模态消息的 parts 就是这个形状——一条消息里逐段可能是文本、也可能是图片。 没有它就只能退化成单一元素类型(丢掉其余形状)或 Opaque(正是要避免的)。
契约上不加新字段:type=array + oneOf 即「**元素**是联合」, 与 OneOf 的 type=json + oneOf(**字段本身**是联合)区分开。
func Int ¶
Int 整数。**契约类型仍是 number**——线协议没有 int,平台也不认; 靠 GoType 带一个「其实是整数」的生成提示,让 Go/Python 侧生成 int 而不是 float64。 只在插件侧区分:为它改线协议不值当,而实现里每个数字字段都 float64(...) 转一道太难看。
func Json ¶
Json 对象,**结构由 Go 类型给出**:
field.Json("os", OSInfo{})
结构定义只有一处——类型改了契约自动跟着,不会出现「声明与实际不同步」。 确实没有结构可言时用 Object(是对象、键不定)或 Any(连类别都不定)。
func Object ¶
Object 声明「是一个对象,但键不由本插件决定」——如上游原样透传的元数据。
与 Json 的区别是结构从哪来:Json 的结构由 Go 类型给出,Object 压根没有可给的结构。 与 Any 的区别见 Any。
**理由必填**。拦住随手使用的不是名字而是这个参数:想省事也得先写清楚为什么省不掉。 这类字段(Object 与 Any)在契约里统称不透明字段,审计会逐一列出。
func OneOf ¶
OneOf 声明「这个字段接受多种可能」。**标量类型与 Go 类型都能传,自动分流**:
field.OneOf("chat_id", contract.TNumber, contract.TString) // 标量联合:值是数字或字符串
field.OneOf("doc", DocObject{}, BlocksArray{}) // 结构联合:形状不同,各有字段
field.OneOf("x", contract.TString, DocObject{}) // 混用也行
为什么声明层只有一个概念、契约层却是两个字段(Types / OneOf): 前端对二者的**渲染方式不同**——标量联合是一个输入框接受多种类型,结构联合是分段 选择器先选形状再渲染该分支的字段。契约里分开存,UI 不必靠"分支有没有 fields"去猜; 而作者不该为这个区别分心,所以声明层合并。
结构分支用**真实类型**:类型改名/删除立刻编译失败,不必等生成期。
func Secret ¶
Secret 密文字段(**凭证专用**):表单打码、平台加密存储。
与 String 的分别不在 Go 类型(都是 string),而在平台怎么对待它—— 所以必须是独立的构造函数,不能靠调用方记得加一个可选链式调用。
func Select ¶
Select 下拉选择(**凭证专用**):候选值作必填参数。
类型名是 "select" 而不是 Enum 的 "enum"——凭证表单认的是前者。 两个名字确实别扭,但改任何一边都要动存量契约,而这里只需要选对。