Complete the registry-first Schema delivery invariants, bind the event command surface, and preserve the event subprocess contract from main.
128 lines
3.8 KiB
Go
128 lines
3.8 KiB
Go
// Copyright 2026 Alibaba Group
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// ToolSchemaHint is reviewed field metadata for an existing registry-owned
|
|
// tool. It intentionally has no command path, alias, visibility, or canonical
|
|
// identity fields: all identity/navigation comes from CommandRegistry.
|
|
type ToolSchemaHint struct {
|
|
Title string
|
|
Description string
|
|
Parameters map[string]ParameterSchemaHint
|
|
}
|
|
|
|
// ParameterSchemaHint overrides the projected flat schema for one parameter.
|
|
// It can be keyed either by the original MCP parameter name (preferred) or by
|
|
// the final CLI flag name when a hint is purely CLI-facing.
|
|
type ParameterSchemaHint struct {
|
|
FlagName string
|
|
Type string
|
|
Description string
|
|
Required *bool
|
|
RequiredWhen string
|
|
}
|
|
|
|
type SchemaVisibility string
|
|
|
|
const (
|
|
SchemaVisibilityPublic SchemaVisibility = "public"
|
|
SchemaVisibilityCompat SchemaVisibility = "compat"
|
|
SchemaVisibilityInternal SchemaVisibility = "internal"
|
|
)
|
|
|
|
type SchemaHintRegistry struct {
|
|
tools map[string]ToolSchemaHint
|
|
}
|
|
|
|
func boolPtr(v bool) *bool { return &v }
|
|
|
|
var defaultSchemaHintRegistry = newSchemaHintRegistry()
|
|
|
|
func newSchemaHintRegistry() *SchemaHintRegistry {
|
|
return &SchemaHintRegistry{
|
|
tools: map[string]ToolSchemaHint{},
|
|
}
|
|
}
|
|
|
|
// RegisterSchemaHints registers curated hints for one product. Keys in tools may
|
|
// be either RPC names ("send_ding_message") or canonical paths
|
|
// ("ding.send_ding_message"). Duplicate canonical paths panic during init so
|
|
// conflicting product hint files are caught early.
|
|
func RegisterSchemaHints(productID string, tools map[string]ToolSchemaHint) {
|
|
defaultSchemaHintRegistry.RegisterProduct(productID, tools)
|
|
}
|
|
|
|
func (r *SchemaHintRegistry) RegisterProduct(productID string, tools map[string]ToolSchemaHint) {
|
|
productID = strings.TrimSpace(productID)
|
|
if productID == "" {
|
|
panic("schema hints: product id is required")
|
|
}
|
|
for name, hint := range tools {
|
|
path := canonicalHintPath(productID, name)
|
|
if path == "" {
|
|
panic(fmt.Sprintf("schema hints: empty tool name for product %q", productID))
|
|
}
|
|
if _, exists := r.tools[path]; exists {
|
|
panic(fmt.Sprintf("schema hints: duplicate hint for %s", path))
|
|
}
|
|
r.tools[path] = hint
|
|
}
|
|
}
|
|
|
|
func (r *SchemaHintRegistry) Lookup(canonicalPath string) (ToolSchemaHint, bool) {
|
|
canonicalPath = strings.TrimSpace(canonicalPath)
|
|
if canonicalPath == "" {
|
|
return ToolSchemaHint{}, false
|
|
}
|
|
hint, ok := r.tools[canonicalPath]
|
|
return hint, ok
|
|
}
|
|
|
|
func canonicalHintPath(productID, name string) string {
|
|
productID = strings.TrimSpace(productID)
|
|
name = strings.TrimSpace(name)
|
|
if name == "" {
|
|
return ""
|
|
}
|
|
if strings.Contains(name, ".") {
|
|
return name
|
|
}
|
|
return productID + "." + name
|
|
}
|
|
|
|
func schemaHintForCanonicalPath(canonicalPath string) ToolSchemaHint {
|
|
if hint, ok := defaultSchemaHintRegistry.Lookup(canonicalPath); ok {
|
|
return hint
|
|
}
|
|
return ToolSchemaHint{}
|
|
}
|
|
|
|
func lookupParameterSchemaHint(hints map[string]ParameterSchemaHint, paramName, flagName string) (ParameterSchemaHint, string, bool) {
|
|
if len(hints) == 0 {
|
|
return ParameterSchemaHint{}, "", false
|
|
}
|
|
if hint, ok := hints[paramName]; ok {
|
|
return hint, paramName, true
|
|
}
|
|
if hint, ok := hints[flagName]; ok {
|
|
return hint, flagName, true
|
|
}
|
|
return ParameterSchemaHint{}, "", false
|
|
}
|