Move 121/210 parameter-level Schema field overlays from schema_hints/metadata JSON into in-code ParamDecl declarations on DeclareLeafMetadata commands. The declared values are emitted as dws.schema.* annotations at assembly time via ApplyParamDecls, outranking tool_schema_hint (rank 620 > 500) so the hint overlay becomes redundant once the declaration is in place. Key mechanism changes: - Add SchemaDecl.Parameters []ParamDecl with property/required/ interface_type/description/required_when/enum fields - Add cli.ParamDecl type carried inside ContractFinalPayload - ApplyParamDecls emits dws.schema.* annotations from the payload at assembly time (no sync.Map, no tree-rebuild key issue) - Add cli.AnnotateRuntimeFlagInterfaceType (41 overlays needed it) - Add cli.AnnotateRuntimeFlagRequiredValue for explicit true/false - Compatibility alias check tolerates dws.schema.* annotation differences between primary and alias commands - Remove runtime source_hash recomputation (87ms/997k allocs saved; enforced by check-generated-drift.sh at build time instead) - Add shortcut.Flag.RequiredWhen and wire through FromShortcut - Add boolFlag OR semantics to fix confirmationBypass disagreement - Add bindKey default kebab-to-camel for forgotten Bind - Add schema consumption benchmarks (catalog decode 1.5s/817MB, shortcut load 1.9ms/3MB — three orders of magnitude apart) - Add catalog codegen feasibility probe (34 tools: 0.06s compile, 31ns access, 87KB linked — extrapolates to 2.1MB for 845 tools) Migrated products (29 tools, 121 fields): aisearch(1), chat(12), contact(4), doc(3), drive(1), hrbrain(10), mail(2), report(1), sheet(3), todo(6) Remaining 89 fields across 11 products blocked by: - RPCName not found as string literal (19 tools, shortcut/variable) - No matching DeclareLeafMetadata near callMCPTool (11 tools) - No single RPCName for multi-step commands (drive.upload etc.) All tests green: corecmd, cli, helpers. Generation and drift clean.
51 lines
1.3 KiB
Go
51 lines
1.3 KiB
Go
// Copyright 2026 Alibaba Group
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
package catalogcodegen_test
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"testing"
|
|
|
|
"github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/cli/catalogcodegen"
|
|
)
|
|
|
|
// BenchmarkGoLiteralAccess measures reaching a tool in the compiled-in map. The
|
|
// data is static, so this is a map lookup with no decode and no allocation —
|
|
// the cost model internal/shortcut already gets.
|
|
func BenchmarkGoLiteralAccess(b *testing.B) {
|
|
if len(catalogcodegen.Tools) == 0 {
|
|
b.Fatal("no generated tools")
|
|
}
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
tool, ok := catalogcodegen.Tools["dev.delete_dev_app"]
|
|
if !ok || tool.CLIPath == "" {
|
|
b.Fatal("lookup missed")
|
|
}
|
|
}
|
|
}
|
|
|
|
// BenchmarkJSONDecodeSameShard measures decoding the same product's committed
|
|
// shard into untyped maps, i.e. what the current loader pays for this product.
|
|
func BenchmarkJSONDecodeSameShard(b *testing.B) {
|
|
data, err := os.ReadFile("../schema_catalog/tools/dev.json")
|
|
if err != nil {
|
|
b.Skip("shard unavailable")
|
|
}
|
|
b.ResetTimer()
|
|
b.ReportAllocs()
|
|
for i := 0; i < b.N; i++ {
|
|
var shard struct {
|
|
Tools map[string]map[string]any `json:"tools"`
|
|
}
|
|
if err := json.Unmarshal(data, &shard); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
if len(shard.Tools) == 0 {
|
|
b.Fatal("empty shard")
|
|
}
|
|
}
|
|
}
|