package sdk // Origin 描述一个能力的**上游来源**:它是谁提供的,而不是它叫什么。 // // 它存在的理由是「归属不能从名字里解析」:MCP server 的工具名由 server 自己给, // 宿主不在上面加任何前缀(同名的两把工具在注册表里至多一个 owner,见 // internal/capability/mcp/registry.go),因此「这把工具来自哪台 server」只能由 // **注册那一刻的元数据**回答,不能靠字符串推断(改名、重名、前缀碰撞都会错)。 // // 宿主内置能力(plugins/tools/**、web_search、read_file ……)**不实现** OriginAware, // 它们的来源是「宿主自己」,不需要也不应该编一个章出来 —— 管理层面上「没有 origin // 键」正是「宿主内置」的表达。 type Origin struct { // Kind 是来源种类。目前只有 OriginKindMCP;空串 = 无来源。 Kind string `json:"kind"` // Server 是提供该能力的上游 server 名(= plugins.json / MCP_SERVERS_JSON 里的 // name),不是工具名。 Server string `json:"server,omitempty"` // Transport 是该 server 的传输形态(stdio / sse / http),来自配置而不是 // 工具的自我描述。 Transport string `json:"transport,omitempty"` } // OriginKindMCP 表示该能力由一台外部 MCP server 提供。 const OriginKindMCP = "mcp" // OriginAware 由**自带来源**的能力实现:宿主在注册时据此给能力条目盖章。 // // 它是可选接口 —— 没实现的一律按「宿主内置 / 来源未知」处理,因此既有的工具 // 实现零改动。实现方只需回报自己的来源,不参与任何路由或权限判定。 type OriginAware interface { // Origin 返回该能力的上游来源;返回零值 Origin 表示「无可归属的来源」。 Origin() Origin } // IsZero 报告 o 是否是「没有来源」的零值。 func (o Origin) IsZero() bool { return o.Kind == "" && o.Server == "" && o.Transport == "" } // OriginOf 返回 v 自报的来源。v 没实现 OriginAware,或自报的是零值(= 无来源)时, // ok 为 false —— 调用方据此**省略**来源字段,而不是下发一个空对象。 func OriginOf(v any) (Origin, bool) { oa, ok := v.(OriginAware) if !ok { return Origin{}, false } o := oa.Origin() if o.IsZero() { return Origin{}, false } return o, true }