- AliasHandler: normalise model-generated flag casing (--userId → --user-id) - StickyHandler: split glued flag values (--limit100 → --limit 100) - ParamNameHandler: fix near-miss flag typos (--limt → --limit) - ParamValueHandler: normalise structured parameter values after parsing
159 lines
4.9 KiB
Go
159 lines
4.9 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 pipeline
|
|
|
|
// Phase represents a named stage in the CLI execution pipeline.
|
|
// Handlers are grouped by phase and executed in chain order within
|
|
// each phase. Phases themselves execute in a fixed order defined
|
|
// by the engine.
|
|
type Phase int
|
|
|
|
const (
|
|
// Register runs at CLI startup when the Cobra command tree is
|
|
// being built. Handlers can add, remove, or modify commands.
|
|
Register Phase = iota
|
|
|
|
// PreParse runs before Cobra parses the raw argv. Handlers
|
|
// receive the raw argument slice and can rewrite it — for
|
|
// example to fix flag-name typos or split glued values.
|
|
PreParse
|
|
|
|
// PostParse runs after Cobra has successfully parsed flags and
|
|
// args. Handlers receive structured parameters plus the tool
|
|
// schema, enabling value-level corrections such as date format
|
|
// normalisation.
|
|
PostParse
|
|
|
|
// PreRequest runs after validation, just before the JSON-RPC
|
|
// call is dispatched. Handlers can inspect or mutate the final
|
|
// payload.
|
|
PreRequest
|
|
|
|
// PostResponse runs after the transport returns a result and
|
|
// before the output is written to stdout.
|
|
PostResponse
|
|
)
|
|
|
|
// String returns the human-readable name of the phase.
|
|
func (p Phase) String() string {
|
|
switch p {
|
|
case Register:
|
|
return "register"
|
|
case PreParse:
|
|
return "pre-parse"
|
|
case PostParse:
|
|
return "post-parse"
|
|
case PreRequest:
|
|
return "pre-request"
|
|
case PostResponse:
|
|
return "post-response"
|
|
default:
|
|
return "unknown"
|
|
}
|
|
}
|
|
|
|
// phases returns all phases in execution order.
|
|
func phases() []Phase {
|
|
return []Phase{Register, PreParse, PostParse, PreRequest, PostResponse}
|
|
}
|
|
|
|
// Context carries mutable state through the handler chain. Each phase
|
|
// populates additional fields; earlier-phase fields remain available in
|
|
// later phases so that handlers can correlate raw input with structured
|
|
// parameters.
|
|
type Context struct {
|
|
// Args is the raw argv slice (available from PreParse onward).
|
|
// PreParse handlers may rewrite this in place.
|
|
Args []string
|
|
|
|
// Command is the resolved product.tool canonical path
|
|
// (available from PostParse onward).
|
|
Command string
|
|
|
|
// Params holds structured key→value parameters after Cobra
|
|
// parsing (available from PostParse onward). Handlers may
|
|
// mutate values or add/remove keys.
|
|
Params map[string]any
|
|
|
|
// Schema is the JSON Schema for the resolved tool's input
|
|
// (available from PostParse onward). Handlers must treat this
|
|
// as read-only.
|
|
Schema map[string]any
|
|
|
|
// Payload is the merged, validated payload ready to be sent
|
|
// over the wire (available from PreRequest onward).
|
|
Payload map[string]any
|
|
|
|
// Response is the JSON-RPC result returned by the server
|
|
// (available from PostResponse onward). Handlers may mutate
|
|
// the response before it is written to stdout.
|
|
Response map[string]any
|
|
|
|
// FlagSpecs provides the list of known flag names for the
|
|
// current tool, derived from the input schema. PreParse
|
|
// handlers use this to match against raw argv tokens.
|
|
FlagSpecs []FlagInfo
|
|
|
|
// Corrections records every correction applied by handlers,
|
|
// enabling downstream logging and debugging.
|
|
Corrections []Correction
|
|
}
|
|
|
|
// FlagInfo describes a single CLI flag derived from a tool's input
|
|
// schema. PreParse handlers use this to recognise valid flag names
|
|
// when performing fuzzy matching or alias resolution.
|
|
type FlagInfo struct {
|
|
// Name is the canonical kebab-case flag name (e.g. "user-id").
|
|
Name string
|
|
|
|
// PropertyName is the original schema property key (e.g. "userId").
|
|
PropertyName string
|
|
|
|
// Type is the JSON Schema type ("string", "integer", etc.).
|
|
Type string
|
|
}
|
|
|
|
// Correction records a single input correction applied by a handler.
|
|
type Correction struct {
|
|
// Handler is the name of the handler that applied the correction.
|
|
Handler string
|
|
|
|
// Phase is the pipeline phase in which the correction occurred.
|
|
Phase Phase
|
|
|
|
// Field identifies the affected flag or parameter name.
|
|
Field string
|
|
|
|
// Original is the value before correction.
|
|
Original string
|
|
|
|
// Corrected is the value after correction.
|
|
Corrected string
|
|
|
|
// Kind classifies the correction (e.g. "alias", "sticky", "case").
|
|
Kind string
|
|
}
|
|
|
|
// AddCorrection appends a correction record to the context.
|
|
func (c *Context) AddCorrection(handler string, phase Phase, field, original, corrected, kind string) {
|
|
c.Corrections = append(c.Corrections, Correction{
|
|
Handler: handler,
|
|
Phase: phase,
|
|
Field: field,
|
|
Original: original,
|
|
Corrected: corrected,
|
|
Kind: kind,
|
|
})
|
|
}
|