Break the remaining corecmd→cli reverse dependency by owning runtimeannotate and contractfinal on the framework side, with cli keeping thin re-exports. Document the three authoring tiers and that Shortcut may use DeclareLeafMetadata. Co-authored-by: Cursor <cursoragent@cursor.com>
367 lines
11 KiB
Go
367 lines
11 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 runtimeannotate
|
|
|
|
import (
|
|
"encoding/json"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/pflag"
|
|
|
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/corecmd/contract"
|
|
)
|
|
|
|
// AttachRuntimeSchema records optional implementation-side identity evidence
|
|
// on a runnable command. Command discovery belongs exclusively to the reviewed
|
|
// CommandRegistry; the Cobra binder accepts an absent annotation and rejects
|
|
// an annotation that disagrees with the registry.
|
|
func AttachRuntimeSchema(cmd *cobra.Command, productID, toolName, source string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
productID = strings.TrimSpace(productID)
|
|
toolName = strings.TrimSpace(toolName)
|
|
if productID == "" || toolName == "" {
|
|
return
|
|
}
|
|
if cmd.Annotations == nil {
|
|
cmd.Annotations = map[string]string{}
|
|
}
|
|
cmd.Annotations[AnnotationProduct] = productID
|
|
cmd.Annotations[AnnotationTool] = toolName
|
|
if source = strings.TrimSpace(source); source != "" {
|
|
cmd.Annotations[AnnotationSource] = source
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeToolMetadata preserves MCP-provided tool metadata on a Cobra
|
|
// leaf so `dws schema` can render richer descriptions without refetching.
|
|
func AnnotateRuntimeToolMetadata(cmd *cobra.Command, title, description, source string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if cmd.Annotations == nil {
|
|
cmd.Annotations = map[string]string{}
|
|
}
|
|
if title = strings.TrimSpace(title); title != "" {
|
|
cmd.Annotations[AnnotationTitle] = title
|
|
}
|
|
if description = strings.TrimSpace(description); description != "" {
|
|
cmd.Annotations[AnnotationDescription] = description
|
|
}
|
|
if source = strings.TrimSpace(source); source != "" {
|
|
cmd.Annotations[AnnotationMetaSource] = source
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeFlag adds parameter metadata to an already-registered flag.
|
|
func AnnotateRuntimeFlag(cmd *cobra.Command, flagName, propertyName, paramType string, required bool, _ string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
flagName = strings.TrimSpace(flagName)
|
|
if flagName == "" {
|
|
return
|
|
}
|
|
flag := CommandFlag(cmd, flagName)
|
|
if flag == nil {
|
|
return
|
|
}
|
|
SetFlagAnnotation(flag, AnnotationFlagProperty, strings.TrimSpace(propertyName))
|
|
SetFlagAnnotation(flag, AnnotationFlagType, strings.TrimSpace(paramType))
|
|
SetFlagAnnotation(flag, AnnotationFlagRequired, strconv.FormatBool(required))
|
|
}
|
|
|
|
// AnnotateRuntimeFlagProperty records only the stable CLI flag to interface
|
|
// property binding.
|
|
func AnnotateRuntimeFlagProperty(cmd *cobra.Command, flagName, propertyName string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if flag := CommandFlag(cmd, flagName); flag != nil {
|
|
SetFlagAnnotation(flag, AnnotationFlagProperty, strings.TrimSpace(propertyName))
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeRequiredFlags records schema-only required semantics.
|
|
func AnnotateRuntimeRequiredFlags(cmd *cobra.Command, flagNames ...string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
for _, name := range flagNames {
|
|
flag := CommandFlag(cmd, name)
|
|
if flag != nil {
|
|
SetFlagAnnotation(flag, AnnotationFlagRequired, "true")
|
|
}
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeFlagRequiredValue sets an explicit required value on a flag.
|
|
func AnnotateRuntimeFlagRequiredValue(cmd *cobra.Command, flagName string, required bool) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if flag := CommandFlag(cmd, flagName); flag != nil {
|
|
v := "false"
|
|
if required {
|
|
v = "true"
|
|
}
|
|
SetFlagAnnotation(flag, AnnotationFlagRequired, v)
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeFlagDescription records the Schema parameter description.
|
|
func AnnotateRuntimeFlagDescription(cmd *cobra.Command, flagName, description string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if flag := CommandFlag(cmd, flagName); flag != nil {
|
|
SetFlagAnnotation(flag, AnnotationDescription, strings.TrimSpace(description))
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeFlagRequiredWhen records a conditional CLI requirement.
|
|
func AnnotateRuntimeFlagRequiredWhen(cmd *cobra.Command, flagName, expression string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if flag := CommandFlag(cmd, flagName); flag != nil {
|
|
SetFlagAnnotation(flag, AnnotationFlagReqWhen, strings.TrimSpace(expression))
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeFlagFormat records a machine-readable value format.
|
|
func AnnotateRuntimeFlagFormat(cmd *cobra.Command, flagName, format string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if flag := CommandFlag(cmd, flagName); flag != nil {
|
|
SetFlagAnnotation(flag, AnnotationFlagFormat, strings.TrimSpace(format))
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeFlagInterfaceType records the wire type for a flag's interface
|
|
// property.
|
|
func AnnotateRuntimeFlagInterfaceType(cmd *cobra.Command, flagName, interfaceType string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if flag := CommandFlag(cmd, flagName); flag != nil {
|
|
SetFlagAnnotation(flag, AnnotationFlagType, strings.TrimSpace(interfaceType))
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeFlagEnum records the accepted values for a flag.
|
|
func AnnotateRuntimeFlagEnum(cmd *cobra.Command, flagName string, values ...string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
flag := CommandFlag(cmd, flagName)
|
|
if flag == nil {
|
|
return
|
|
}
|
|
SetFlagAnnotationValues(flag, AnnotationFlagEnum, values...)
|
|
}
|
|
|
|
// AnnotateRuntimeFlagExample records a valid representative CLI value.
|
|
func AnnotateRuntimeFlagExample(cmd *cobra.Command, flagName, example string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
if flag := CommandFlag(cmd, flagName); flag != nil {
|
|
SetFlagAnnotation(flag, AnnotationFlagExample, strings.TrimSpace(example))
|
|
}
|
|
}
|
|
|
|
// AnnotateRuntimeContract marks a command as carrying a command/LeafSpec
|
|
// Contract surface.
|
|
func AnnotateRuntimeContract(cmd *cobra.Command) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
SetCommandAnnotation(cmd, AnnotationContract, "command")
|
|
}
|
|
|
|
// AnnotateRuntimeRisk records the Contract Risk string for Schema Safety
|
|
// projection. Empty risk is a no-op so write-guard leaves that leave Risk
|
|
// unset keep Contract.Safety / runtime_gate provenance (schema_hints/ is
|
|
// retired and must not be treated as a Safety fallback).
|
|
func AnnotateRuntimeRisk(cmd *cobra.Command, risk string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
risk = strings.TrimSpace(risk)
|
|
if risk == "" {
|
|
return
|
|
}
|
|
AnnotateRuntimeContract(cmd)
|
|
SetCommandAnnotation(cmd, AnnotationRisk, risk)
|
|
}
|
|
|
|
// AnnotateRuntimeGate records a non-Risk confirmation path (e.g.
|
|
// devAppRequireWriteGuard). Homology rule: every confirmation fact is either
|
|
// Contract-declared (SafetySpec / Risk) or explicitly annotated (this gate).
|
|
// schema_hints/ is retired and must not supply confirmation.
|
|
func AnnotateRuntimeGate(cmd *cobra.Command, gate string) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
gate = strings.TrimSpace(gate)
|
|
if gate == "" {
|
|
return
|
|
}
|
|
AnnotateRuntimeContract(cmd)
|
|
SetCommandAnnotation(cmd, AnnotationRuntimeGate, gate)
|
|
}
|
|
|
|
// RuntimeContractRisk returns the Contract Risk annotation when present.
|
|
func RuntimeContractRisk(cmd *cobra.Command) (string, bool) {
|
|
if cmd == nil || cmd.Annotations == nil {
|
|
return "", false
|
|
}
|
|
risk := strings.TrimSpace(cmd.Annotations[AnnotationRisk])
|
|
if risk == "" {
|
|
return "", false
|
|
}
|
|
return risk, true
|
|
}
|
|
|
|
// RuntimeContractGate returns the annotated runtime confirmation gate when present.
|
|
func RuntimeContractGate(cmd *cobra.Command) (string, bool) {
|
|
if cmd == nil || cmd.Annotations == nil {
|
|
return "", false
|
|
}
|
|
gate := strings.TrimSpace(cmd.Annotations[AnnotationRuntimeGate])
|
|
if gate == "" {
|
|
return "", false
|
|
}
|
|
return gate, true
|
|
}
|
|
|
|
// AnnotateRuntimePositionals records ordered positional arguments for agents.
|
|
func AnnotateRuntimePositionals(cmd *cobra.Command, positionals ...contract.RuntimeSchemaPositional) {
|
|
if cmd == nil {
|
|
return
|
|
}
|
|
clean := make([]contract.RuntimeSchemaPositional, 0, len(positionals))
|
|
for _, positional := range positionals {
|
|
positional.Name = strings.TrimSpace(positional.Name)
|
|
positional.Type = strings.TrimSpace(positional.Type)
|
|
positional.Description = strings.TrimSpace(positional.Description)
|
|
if positional.Name == "" || positional.Index < 0 {
|
|
continue
|
|
}
|
|
if positional.Type == "" {
|
|
positional.Type = "string"
|
|
}
|
|
clean = append(clean, positional)
|
|
}
|
|
if len(clean) == 0 {
|
|
return
|
|
}
|
|
sort.SliceStable(clean, func(i, j int) bool { return clean[i].Index < clean[j].Index })
|
|
encoded, _ := json.Marshal(clean)
|
|
SetCommandAnnotation(cmd, AnnotationPositionals, string(encoded))
|
|
}
|
|
|
|
// CommandPositionals reads annotated positionals (nil on miss/error).
|
|
func CommandPositionals(cmd *cobra.Command) []contract.RuntimeSchemaPositional {
|
|
if cmd == nil || cmd.Annotations == nil {
|
|
return nil
|
|
}
|
|
raw := strings.TrimSpace(cmd.Annotations[AnnotationPositionals])
|
|
if raw == "" {
|
|
return nil
|
|
}
|
|
var positionals []contract.RuntimeSchemaPositional
|
|
if json.Unmarshal([]byte(raw), &positionals) != nil {
|
|
return nil
|
|
}
|
|
sort.SliceStable(positionals, func(i, j int) bool { return positionals[i].Index < positionals[j].Index })
|
|
return positionals
|
|
}
|
|
|
|
// ExcludeFromRuntimeSchema keeps a human-facing hint or redirect in --help
|
|
// while preventing it from being advertised as an executable agent tool.
|
|
func ExcludeFromRuntimeSchema(cmd *cobra.Command) {
|
|
SetCommandAnnotation(cmd, AnnotationExclude, "true")
|
|
}
|
|
|
|
// CommandFlag resolves local flags plus product/group persistent flags.
|
|
// Root persistent flags are intentionally available only when explicitly
|
|
// requested; they are global execution controls, not tool parameters.
|
|
func CommandFlag(cmd *cobra.Command, name string) *pflag.Flag {
|
|
if cmd == nil {
|
|
return nil
|
|
}
|
|
name = strings.TrimSpace(name)
|
|
if name == "" {
|
|
return nil
|
|
}
|
|
if flag := cmd.Flags().Lookup(name); flag != nil {
|
|
return flag
|
|
}
|
|
for current := cmd; current != nil; current = current.Parent() {
|
|
if flag := current.PersistentFlags().Lookup(name); flag != nil {
|
|
return flag
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// SetCommandAnnotation writes a non-blank command annotation.
|
|
func SetCommandAnnotation(cmd *cobra.Command, key, value string) {
|
|
if cmd == nil || strings.TrimSpace(value) == "" {
|
|
return
|
|
}
|
|
if cmd.Annotations == nil {
|
|
cmd.Annotations = map[string]string{}
|
|
}
|
|
cmd.Annotations[key] = value
|
|
}
|
|
|
|
// SetFlagAnnotation writes a single non-blank flag annotation value.
|
|
func SetFlagAnnotation(flag *pflag.Flag, key, value string) {
|
|
if flag == nil || strings.TrimSpace(value) == "" {
|
|
return
|
|
}
|
|
if flag.Annotations == nil {
|
|
flag.Annotations = map[string][]string{}
|
|
}
|
|
flag.Annotations[key] = []string{value}
|
|
}
|
|
|
|
// SetFlagAnnotationValues writes a trimmed, non-empty flag annotation list.
|
|
func SetFlagAnnotationValues(flag *pflag.Flag, key string, values ...string) {
|
|
if flag == nil {
|
|
return
|
|
}
|
|
clean := make([]string, 0, len(values))
|
|
for _, value := range values {
|
|
if value = strings.TrimSpace(value); value != "" {
|
|
clean = append(clean, value)
|
|
}
|
|
}
|
|
if len(clean) == 0 {
|
|
return
|
|
}
|
|
if flag.Annotations == nil {
|
|
flag.Annotations = map[string][]string{}
|
|
}
|
|
flag.Annotations[key] = clean
|
|
}
|