Files
玉澜 e705012011 feat(schema): migrate parameter overlays into code declarations
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.
2026-08-01 09:25:40 +08:00

68 lines
2.1 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.
//go:build darwin
package corecmd
import (
"os"
"strings"
"testing"
"unsafe"
"golang.org/x/sys/unix"
)
// openTestPTY allocates a real pty pair so the terminal-only interactive
// prompt branch of ConfirmSafety can run natively on macOS. The slave side is
// a genuine TTY (isatty true); the master side feeds it the scripted answer.
// It reports ok=false instead of failing when the environment cannot allocate
// a pty (e.g. a sandbox without /dev/ptmx), so callers skip gracefully.
func openTestPTY(t *testing.T) (master, slave *os.File, ok bool) {
t.Helper()
m, err := os.OpenFile("/dev/ptmx", os.O_RDWR, 0)
if err != nil {
t.Logf("open /dev/ptmx: %v", err)
return nil, nil, false
}
fd := int(m.Fd())
if err := unix.IoctlSetInt(fd, unix.TIOCPTYGRANT, 0); err != nil {
t.Logf("grantpt: %v", err)
_ = m.Close()
return nil, nil, false
}
if err := unix.IoctlSetInt(fd, unix.TIOCPTYUNLK, 0); err != nil {
t.Logf("unlockpt: %v", err)
_ = m.Close()
return nil, nil, false
}
// ptsname(3): TIOCPTYGNAME fills a 128-byte buffer with the slave path.
buf := make([]byte, 128)
if _, _, errno := unix.Syscall(
unix.SYS_IOCTL, uintptr(fd), uintptr(unix.TIOCPTYGNAME), uintptr(unsafe.Pointer(&buf[0])),
); errno != 0 {
t.Logf("ptsname ioctl: %v", errno)
_ = m.Close()
return nil, nil, false
}
name := strings.TrimRight(string(buf), "\x00")
s, err := os.OpenFile(name, os.O_RDWR, 0)
if err != nil {
t.Logf("open pty slave %s: %v", name, err)
_ = m.Close()
return nil, nil, false
}
return m, s, true
}