Files
dingtalk-workspace-cli/internal/pipeline/phase.go
T
audanye-sudo f75227aad1 feat: add pipeline engine for pre-parse and post-parse input correction
- 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
2026-03-29 16:28:19 +08:00

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,
})
}