Documentation
¶
Index ¶
- Constants
- Variables
- func ApplyHostMutations(out map[string]any)
- func ClassifyMCPResponseText(text string) error
- func ClassifyToolResultContent(content map[string]any) error
- func ExitCode(err error) int
- func HostControlBlock() map[string]any
- func HumanRecoveryActions(err error) []string
- func IsConfirmationRequired(err error) bool
- func IsMCPToolNotFound(err error) bool
- func IsPATError(err error) bool
- func IsPATNoPermissionCode(code string) bool
- func NewAPI(message string, opts ...Option) error
- func NewAuth(message string, opts ...Option) error
- func NewDiscovery(message string, opts ...Option) error
- func NewInternal(message string, opts ...Option) error
- func NewValidation(message string, opts ...Option) error
- func PATAuthorizationURL(rawURI string) string
- func PATOpenBrowserValue() bool
- func PrintHuman(w io.Writer, err error) error
- func PrintHumanAt(w io.Writer, err error, v Verbosity) error
- func PrintJSON(w io.Writer, err error) error
- func RecoveryActions(err error) []string
- func RejectCRLF(value, fieldName string) error
- func RejectControlChars(value, flagName string) error
- func ResourceName(name string) error
- func SafeInputPath(path string) (string, error)
- func SafeLocalFlagPath(flagName, value string) (string, error)
- func SafeOutputPath(path string) (string, error)
- func SafePath(path string) error
- func ServerGuidance(diag ServerDiagnostics) (string, string)
- func SetHostControlProvider(fn func() string)
- func SetPATOpenBrowserProvider(fn func() bool)
- func StripQueryFragment(path string) string
- type Category
- type Error
- type ExitCoder
- type Option
- func WithActions(actions ...string) Option
- func WithAvailableFlags(names ...string) Option
- func WithCause(err error) Option
- func WithDetails(details map[string]any) Option
- func WithExecutionStarted(started bool) Option
- func WithFailureStage(stage string) Option
- func WithHint(hint string) Option
- func WithNextRetryAt(next time.Time) Option
- func WithOperation(operation string) Option
- func WithOrigin(origin string) Option
- func WithRPCCode(code int) Option
- func WithRPCData(data json.RawMessage) Option
- func WithReason(reason string) Option
- func WithRetryAfterSeconds(seconds int64) Option
- func WithRetryable(retryable bool) Option
- func WithServerDiag(diag ServerDiagnostics) Option
- func WithServerKey(serverKey string) Option
- func WithSnapshot(path string) Option
- func WithTraceID(id string) Option
- type PATError
- type RawStderrError
- type ServerDiagnostics
- type Verbosity
Constants ¶
const ( ExitCodeAPI = 1 ExitCodeAuth = 2 ExitCodeValidation = 3 ExitCodeDiscovery = 6 ExitCodeInternal = 5 )
类别专属退出码常量(B171/B172,权威 = 规划 v1.2 OQ-1 定案,契约规范 §4)。 ExitCode() 的 switch 用内联字面量,本组常量由 exitcodes.go 的 exitCodeByCategory 映射表引用,值与内联字面量一一对应(同源不双轨)。 修改任一值必须先同步 ExitCode() 的 switch 分支与 internal/output 侧码表。
const DoctorCommand = "dws doctor --json"
DoctorCommand 是机器错误信封中的稳定体检入口。 actions 字段承载可直接执行的补救命令,因此这里保持纯命令形式,不混入说明文字。
const DoctorHumanCommand = "dws doctor"
DoctorHumanCommand 保留 doctor 面向真人的默认可读输出。
const ExitCodePartial = 7
退出码表(规划 v1.2 OQ-1 定案;契约规范 §4;轮10裁决⑬——保留现行码表, 仅新增 partial_failure 专用码,不做 wire 破坏性重排):
0 success / pending(异步受理不是失败)
1 api (CategoryAPI)
2 auth (CategoryAuth)
3 validation (CategoryValidation;confirmation_required 子类共享此码,
以 reason/subtype 区分,AC-13)
4 PAT (PATError 专属,见 pat.go ExitCodePermission;Category 不占用)
5 internal (CategoryInternal 与兜底:非结构化错误、panic 收敛均归 5)
6 discovery (CategoryDiscovery)
7 partial_failure(部分成功专用码,见 ExitCodePartial)
ExitCodePartial is the partial-result exit code shared with internal/output. It is not returned for CategoryPartial errors because they lack the typed succeeded/failed/unknown payload required for an honest partial result.
const ExitCodePermission = 4
ExitCodePermission is the process exit code for PAT authorisation failures.
Variables ¶
var ( ErrInvalidResourceName = stderrors.New("invalid resource name") ErrUnsafePath = stderrors.New("unsafe path detected") )
var WireStableErrorBodyFields = []string{
"type",
"subtype",
"code",
"retryable",
"retry_after_seconds",
"message",
"hint",
"actions",
"trace_id",
"rpc_code",
"rpc_data",
}
WireStableErrorBodyFields 是 error 对象体(不含顶层 outcome)的 wire-stable 字段名子集。
var WireStableFields = []string{
"type",
"subtype",
"code",
"retryable",
"retry_after_seconds",
"message",
"hint",
"actions",
"trace_id",
"rpc_code",
"rpc_data",
"outcome",
}
WireStableFields 是错误信封 wire-stable 字段名全集(含 outcome)。
Functions ¶
func ApplyHostMutations ¶ added in v1.0.18
ApplyHostMutations writes the two stderr-JSON fields the host integration contract requires onto out["data"]:
- data.hostControl: present iff the CLI is in host-owned mode (i.e. HostControlBlock returns non-nil); legacy data.callbacks is stripped in the same pass so passive classifier and active retry paths stay byte-for-byte aligned.
- data.openBrowser: always present; reflects the user's PAT browser policy.
Centralizing the two writes here is the single-injection invariant — any caller that produces a PAT-shaped stderr payload (cleanPATJSON, active-retry enrichers, scope-required builders) MUST go through this function instead of writing the fields directly. out["data"] is promoted to map[string]any if missing or of the wrong type.
func ClassifyMCPResponseText ¶ added in v1.0.11
ClassifyMCPResponseText classifies a text response returned by an MCP tool call. Returns a typed error for known gateway auth failures, PAT interceptions, and business-level errors embedded in HTTP-200 JSON bodies.
Check order: DWS gateway > PAT permission > generic business error.
func ClassifyToolResultContent ¶ added in v1.0.11
ClassifyToolResultContent checks a raw MCP tool result content map for DWS gateway auth errors and PAT permission error codes. This is intended for use as the edition.Hooks.ClassifyToolResult callback so the framework's runner returns a typed error before its generic business-error classification.
Check order: DWS gateway auth > PAT permission.
func HostControlBlock ¶ added in v1.0.18
HostControlBlock returns the canonical hostControl map injected into PAT stderr JSON when the CLI is operating in host-owned mode, or nil when it is not. The returned map is safe for the caller to mutate because a new map is constructed on each call.
callbackOwner is kept as a legacy compatibility key for hosts that adopted it before the contract converged on the hostControl single injection point.
func HumanRecoveryActions ¶ added in v1.0.61
HumanRecoveryActions 与 RecoveryActions 使用同一适用性策略,但把规范的 Agent 体检命令投影为 doctor 默认的人类可读模式。
func IsConfirmationRequired ¶ added in v1.0.60
IsConfirmationRequired reports whether err (or any wrapped cause) is a typed framework confirmation-gate failure carrying reason confirmation_required. Downstream classifiers must pass such errors through verbatim: the "re-run with --yes" semantics can only be carried by the machine-readable reason, while message-text classification actively misroutes them (a command path containing "permission" would be reported as an auth failure, and any other wording degrades to an unclassified error).
func IsMCPToolNotFound ¶ added in v1.0.62
IsMCPToolNotFound reports whether an MCP call failed because the selected server does not expose that tool name. Callers may use it to fall back between reviewed read-only aliases, never to replay a write.
func IsPATError ¶ added in v1.0.11
IsPATError reports whether err is a *PATError.
func IsPATNoPermissionCode ¶ added in v1.0.11
IsPATNoPermissionCode reports whether code is a known PAT permission error code.
func NewDiscovery ¶
NewDiscovery returns a discovery-category error.
func NewInternal ¶
NewInternal returns an internal-category error.
func NewValidation ¶
NewValidation returns a validation-category error.
func PATAuthorizationURL ¶ added in v1.0.26
PATAuthorizationURL returns the best URL for hosts to open or show to users. It keeps already-complete PAT URLs unchanged. For DingTalk's legacy /fe/old#%2FpersonalAuthorization?... hash-route form, it adds the explicit hash query and decoded fragment route used by the working authorization page.
func PATOpenBrowserValue ¶ added in v1.0.18
func PATOpenBrowserValue() bool
PATOpenBrowserValue returns the effective browser-open recommendation to embed in PAT JSON payloads. The open-source fallback is true to preserve historical behavior when no provider is wired.
func PrintHuman ¶
PrintHuman writes a concise human-readable error rendering at normal verbosity.
func PrintHumanAt ¶ added in v1.0.5
PrintHumanAt writes a human-readable error rendering at the given verbosity level.
func PrintJSON ¶
PrintJSON writes the legacy machine-readable JSON error object.
This wire predates the unified result framework and is intentionally kept byte-compatible for commands whose rollout is legacy_only or dual_validate. Unified commands publish outcome/type/subtype through internal/output only.
func RecoveryActions ¶ added in v1.0.61
RecoveryActions 返回错误最终应该交付的恢复动作。
命令构造侧仍可声明更具体的动作;本函数只在 doctor 能诊断的认证或网络故障上 补齐稳定入口。权限、参数、确认门禁和上游业务错误不会被机械地 引导到 doctor,避免用本地体检掩盖明确的业务修复路径。 路由只读取 wire-stable 的 Category/Reason,不根据 Message/Hint 文案分支。
func RejectCRLF ¶
RejectCRLF rejects strings containing carriage return (\r) or line feed (\n). These characters enable MIME/HTTP header injection and must never appear in header field names, values, Content-ID, or filename parameters.
func RejectControlChars ¶
RejectControlChars rejects C0 control characters (except \t and \n) and dangerous Unicode characters from user input.
Control characters cause subtle security issues:
- Null bytes truncate strings at the C layer
- \r\n enables HTTP header injection
- Unicode Bidi characters allow visual spoofing (e.g. making "report.exe" display as "report.txt")
Tab and newline are allowed as they may appear in legitimate multi-line input.
func ResourceName ¶
func SafeInputPath ¶
SafeInputPath validates an upload/read source path for --file flags. It applies the same rules as SafeOutputPath — rejecting absolute paths, resolving symlinks, and enforcing working directory containment — to prevent an AI Agent from being tricked into reading sensitive files like /etc/passwd.
func SafeLocalFlagPath ¶
SafeLocalFlagPath validates a flag value as a local file path. Empty values and http/https URLs are returned unchanged without validation, allowing the caller to handle non-path inputs (e.g. API keys, URLs) upstream. For all other values, SafeInputPath rules apply. The original relative path is returned unchanged (not resolved to absolute) so upload helpers can re-validate at the actual I/O point via SafeUploadPath.
func SafeOutputPath ¶
SafeOutputPath validates a download/export target path for --output flags. It rejects absolute paths, resolves symlinks to their real location, and verifies the canonical result is still under the current working directory. This prevents an AI Agent from being tricked into writing files outside the working directory (e.g. "../../.ssh/authorized_keys") or following symlinks to sensitive locations.
The returned absolute path MUST be used for all subsequent I/O to prevent time-of-check-to-time-of-use (TOCTOU) race conditions.
func SafePath ¶
SafePath performs basic path validation checking for dangerous patterns. For full security (symlink resolution, CWD containment), use SafeOutputPath or SafeInputPath.
func ServerGuidance ¶ added in v1.0.58
func ServerGuidance(diag ServerDiagnostics) (string, string)
ServerGuidance exposes the same recovery projection to repository-local adapters so legacy JSON and unified-result errors stay semantically aligned.
func SetHostControlProvider ¶ added in v1.0.18
func SetHostControlProvider(fn func() string)
SetHostControlProvider wires up the classifier's hostControl injection. It MUST be called once during CLI bootstrap (e.g. from internal/app init()) so that the first cleanPATJSON call observes a valid provider. Passing nil disables injection (useful for isolated tests).
func SetPATOpenBrowserProvider ¶ added in v1.0.18
func SetPATOpenBrowserProvider(fn func() bool)
SetPATOpenBrowserProvider wires the PAT JSON serializer to the current browser policy. Passing nil restores the open-source fallback (true).
func StripQueryFragment ¶
StripQueryFragment removes any ?query or #fragment suffix from a URL path. API parameters must go through structured --params flags, not embedded in the path, to prevent parameter injection and behaviour confusion.
Types ¶
type Category ¶
type Category string
Category represents a stable error class with a documented exit code.
const ( CategoryAPI Category = "api" CategoryAuth Category = "auth" CategoryValidation Category = "validation" CategoryDiscovery Category = "discovery" CategoryInternal Category = "internal" // CategoryPartial is retained for source compatibility, but an error cannot // reconstruct the per-item data required by a partial result. It therefore // fails closed as internal; callers must use output.Partial for exit code 7. CategoryPartial Category = "partial_failure" )
type Error ¶
type Error struct {
Category Category
Message string
Operation string
ServerKey string
Origin string
FailureStage string
ExecutionStarted *bool
Retryable bool
RetryableSet bool
RetryAfterSeconds *int64
NextRetryAt *time.Time
Reason string
Hint string
Actions []string
AvailableFlags []string
Snapshot string
Details map[string]any
RPCCode int `json:"rpc_code,omitempty"`
RPCData json.RawMessage `json:"rpc_data,omitempty"`
ServerDiag ServerDiagnostics `json:"-"`
Cause error `json:"-"`
}
Error is the structured repository-local error model for the Go rewrite.
func (*Error) ExitCode ¶
ExitCode returns the documented process exit code for the error category. exit=4 is reserved exclusively for PATError (see internal/errors/pat.go ExitCodePermission and the exit-code table in docs/reference.md); Discovery therefore uses 6 so hosts can tell "catalog lookup broke" apart from "PAT permission insufficient".
confirmation_required 是 validation 的子类而非独立类别(B171,AC-13, 规划 v1.2 OQ-1 定案):门禁拦截错误挂 CategoryValidation 并以 reason=confirmation_required 区分,与 validation 共享 rc=3。信封侧 internal/output exitCodeForErrorInfo 的「subtype 优先于 type、 confirmation_required 恒 3」规则与本表同源(轮10裁决⑬;远期独立码 保留于规划 OQ-9,落地前不得双轨)。
type ExitCoder ¶ added in v1.0.9
type ExitCoder interface {
ExitCode() int
}
ExitCoder is implemented by errors that provide their own exit code. Edition-specific error types (e.g. PATError, CLIError) implement this so the framework can resolve exit codes without importing edition packages.
type Option ¶
type Option func(*Error)
Option mutates a structured error before it is returned.
func WithActions ¶
WithActions records suggested next actions for recovery.
func WithAvailableFlags ¶ added in v1.0.27
WithAvailableFlags records visible local flag names for agent recovery.
func WithDetails ¶ added in v1.0.57
WithDetails records an additive machine-readable payload for errors whose recovery needs typed context, such as ambiguous target-resolution candidates. Callers must keep credentials and other secrets out of details.
func WithExecutionStarted ¶ added in v1.0.57
WithExecutionStarted records whether the downstream business operation was known to have started. Unknown state must be represented by omitting this option, which is important for safe retry decisions on write operations.
func WithFailureStage ¶ added in v1.0.57
WithFailureStage records the execution stage at which the failure occurred.
func WithNextRetryAt ¶ added in v1.0.56
WithNextRetryAt records the absolute time at which a retry may be attempted.
func WithOperation ¶
WithOperation records the operation that failed.
func WithOrigin ¶ added in v1.0.57
WithOrigin records the component that produced the failure, such as the client, MCP gateway, or DingTalk API. It is independent from Category, which remains the stable exit-code contract.
func WithRPCCode ¶
WithRPCCode records the original JSON-RPC error code.
func WithRPCData ¶
func WithRPCData(data json.RawMessage) Option
WithRPCData records the original JSON-RPC error data payload.
func WithReason ¶
WithReason records a stable machine-readable failure reason.
func WithRetryAfterSeconds ¶ added in v1.0.56
WithRetryAfterSeconds records the server-recommended delay before a retry. A zero delay is meaningful and is therefore preserved; negative values are ignored as invalid server guidance.
本通道只存原值、不钳制(B195/B199,AC-24):服务端给多少存多少,wire 上 retry_after_seconds 原样透传。transport 侧的 RetryMaxDelay 钳制只作用于 重试延迟选择(retryDelayForAttempt),不得回写或截断本字段(B196 草案: 钳制上限可配置化后仍须保持「钳制延迟、不钳制透传」双通道分离)。
func WithRetryable ¶
WithRetryable marks whether the error can be retried safely.
func WithServerDiag ¶ added in v1.0.5
func WithServerDiag(diag ServerDiagnostics) Option
WithServerDiag attaches server diagnostics to the error.
func WithServerKey ¶
WithServerKey records the server identifier associated with the failure.
func WithSnapshot ¶
WithSnapshot records the recovery snapshot path associated with the failure.
func WithTraceID ¶ added in v1.0.5
WithTraceID records the server-provided trace identifier. Used when only the trace ID is available (e.g. from HTTP headers) without a full ServerDiagnostics struct.
type PATError ¶ added in v1.0.11
type PATError struct {
RawJSON string
}
PATError represents a PAT (Personal Action Token) authorization failure that should be passed through to stderr as raw JSON without any CLI-layer wrapping. The host application parses the JSON to display its own authorization UI. The wire schema is fixed: a single-line, directly json.Unmarshal-able payload of the form {"success":false,"code":<frozen enum>,"data":{...}}.
When the payload includes data.uri/authUrl/authorizationUrl, that value is the authoritative server-provided authorization link. The CLI accepts all legacy aliases, normalizes the known DingTalk hash-route variant, and emits a single data.uri field so terminals and hosts do not need to deduplicate links.
func AsPatAuthCheckError ¶ added in v1.0.11
AsPatAuthCheckError extracts a *PATError from an error chain.
func ClassifyPatAuthCheck ¶ added in v1.0.11
ClassifyPatAuthCheck is the open-source fallback that checks a tool-call Content map for PAT permission codes and auth-required codes. Returns a non-nil *PATError when the content carries a recognised PAT/auth error.
type RawStderrError ¶ added in v1.0.9
RawStderrError is implemented by errors that must output raw content directly to stderr, bypassing all CLI formatting (e.g. "Error:" prefix). PAT authorization errors use this to pass JSON through to the desktop runtime.
type ServerDiagnostics ¶ added in v1.0.5
type ServerDiagnostics struct {
TraceID string `json:"trace_id,omitempty"`
ServerErrorCode string `json:"server_error_code,omitempty"`
TechnicalDetail string `json:"technical_detail,omitempty"`
FriendlyHint string `json:"friendly_hint,omitempty"`
ActionURL string `json:"action_url,omitempty"`
ServerRetryable *bool `json:"server_retryable,omitempty"`
}
ServerDiagnostics holds server-side diagnostic fields extracted from MCP response bodies or HTTP response headers. Fields are populated on a best-effort basis during error construction.
func (ServerDiagnostics) IsEmpty ¶ added in v1.0.5
func (d ServerDiagnostics) IsEmpty() bool
IsEmpty returns true when no diagnostic field has been populated.
type Verbosity ¶ added in v1.0.5
type Verbosity int
Verbosity controls how much detail PrintHuman includes.
const ( // VerbosityNormal shows essential info: error, hint, actions, trace_id, server_code. VerbosityNormal Verbosity = 0 // VerbosityVerbose adds technical_detail, snapshot, execution context. VerbosityVerbose Verbosity = 1 // VerbosityDebug adds all internal diagnostics (category, operation, reason, rpc_code). VerbosityDebug Verbosity = 2 )