Files
玉澜 fe969dad51 refactor(app): unify dynamic server registration and drop dead command surfaces
- Collapse SetDynamicServers/registerDynamicServer/AppendDynamicServer
  into one registration core; the ServerOverride-skip now applies to all
  paths and AppendDynamicServer keeps its cmd-key no-overwrite guard.
- Delete executor.NewWorkflowInvocation (never constructed, no gate
  accepts the kind) and newLegacyHiddenCommands (always returned nil).
- Route the single-profile branch through the runnerResolveProfile seam,
  matching the multi-profile branch.
- Refresh stale discovery-era comments (no wire strings changed).
2026-08-03 23:30:54 +08:00

150 lines
4.0 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 executor
import (
"context"
"encoding/json"
"fmt"
"strings"
apperrors "github.com/DingTalk-Real-AI/dingtalk-workspace-cli/internal/errors"
)
type Invocation struct {
Kind string `json:"kind"`
Stage string `json:"stage"`
Implemented bool `json:"implemented"`
DryRun bool `json:"dry_run,omitempty"`
CanonicalProduct string `json:"canonical_product"`
Tool string `json:"tool"`
CanonicalPath string `json:"canonical_path"`
LegacyPath string `json:"legacy_path,omitempty"`
Params map[string]any `json:"params"`
}
type Result struct {
Invocation Invocation `json:"invocation"`
Response map[string]any `json:"response,omitempty"`
}
type Runner interface {
Run(context.Context, Invocation) (Result, error)
}
type EchoRunner struct{}
func (EchoRunner) Run(_ context.Context, invocation Invocation) (Result, error) {
if invocation.DryRun {
return Result{
Invocation: invocation,
Response: map[string]any{
"dry_run": true,
"request": ToolCallRequest(invocation.Tool, invocation.Params),
"note": "execution skipped by --dry-run",
},
}, nil
}
return Result{Invocation: invocation}, nil
}
func NewCompatibilityInvocation(legacyPath, canonicalProduct, tool string, params map[string]any) Invocation {
if params == nil {
params = map[string]any{}
}
return Invocation{
Kind: "compat_invocation",
Stage: "compat_cli",
Implemented: false,
CanonicalProduct: canonicalProduct,
Tool: tool,
CanonicalPath: canonicalProduct + "." + tool,
LegacyPath: legacyPath,
Params: params,
}
}
func NewHelperInvocation(legacyPath, canonicalProduct, tool string, params map[string]any) Invocation {
if params == nil {
params = map[string]any{}
}
return Invocation{
Kind: "helper_invocation",
Stage: "helper_override",
Implemented: false,
CanonicalProduct: canonicalProduct,
Tool: tool,
CanonicalPath: canonicalProduct + "." + tool,
LegacyPath: legacyPath,
Params: params,
}
}
func MergePayloads(jsonPayload, paramsPayload string, overrides map[string]any) (map[string]any, error) {
merged := make(map[string]any)
for _, payload := range []struct {
label string
raw string
}{
{label: "--json", raw: jsonPayload},
{label: "--params", raw: paramsPayload},
} {
value, err := parseJSONObject(payload.label, payload.raw)
if err != nil {
return nil, err
}
for key, raw := range value {
merged[key] = raw
}
}
for key, value := range overrides {
merged[key] = value
}
return merged, nil
}
func parseJSONObject(label, raw string) (map[string]any, error) {
if strings.TrimSpace(raw) == "" {
return map[string]any{}, nil
}
var value any
if err := json.Unmarshal([]byte(raw), &value); err != nil {
return nil, apperrors.NewValidation(fmt.Sprintf("%s must be valid JSON: %v", label, err))
}
object, ok := value.(map[string]any)
if !ok {
return nil, apperrors.NewValidation(fmt.Sprintf("%s must decode to a JSON object", label))
}
return object, nil
}
func ToolCallRequest(tool string, params map[string]any) map[string]any {
if params == nil {
params = map[string]any{}
}
return map[string]any{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": map[string]any{
"name": tool,
"arguments": params,
},
}
}