package inbox import ( "errors" "fmt" "io" "strings" "ai-workflow-skill/packages/coord-core/protocol" "ai-workflow-skill/packages/coord-core/store" ) func Execute(args []string, stdout, stderr io.Writer) int { cmd := NewRootCmd() cmd.SetOut(stdout) cmd.SetErr(stderr) cmd.SetArgs(args) if err := cmd.Execute(); err != nil { jsonOutput := hasJSONFlag(args) renderError(stdout, stderr, jsonOutput, err) return exitCodeForError(err) } return 0 } func exitCodeForError(err error) int { var cliErr *protocol.CLIError if errors.As(err, &cliErr) { return cliErr.ExitCode } switch { case isUsageError(err): return 30 case errors.Is(err, store.ErrLeaseConflict): return 20 case errors.Is(err, store.ErrThreadNotFound), errors.Is(err, store.ErrMessageNotFound): return 40 case errors.Is(err, store.ErrInvalidInput), errors.Is(err, store.ErrInvalidState), errors.Is(err, store.ErrNoActiveLease): return 30 default: return 50 } } func errorCodeForError(err error) string { var cliErr *protocol.CLIError if errors.As(err, &cliErr) { return cliErr.Code } switch { case isUsageError(err): return "invalid_input" case errors.Is(err, store.ErrLeaseConflict): return "lease_conflict" case errors.Is(err, store.ErrThreadNotFound), errors.Is(err, store.ErrMessageNotFound): return "not_found" case errors.Is(err, store.ErrInvalidInput): return "invalid_input" case errors.Is(err, store.ErrInvalidState), errors.Is(err, store.ErrNoActiveLease): return "invalid_state" default: return "internal_error" } } func renderError(stdout, stderr io.Writer, jsonOutput bool, err error) { message := errorMessage(err) if jsonOutput { _ = protocol.WriteJSON(stdout, protocol.Error{ OK: false, Error: protocol.ErrorPayload{ Code: errorCodeForError(err), Message: message, }, }) return } _, _ = fmt.Fprintln(stderr, message) } func errorMessage(err error) string { var cliErr *protocol.CLIError if errors.As(err, &cliErr) { return cliErr.Message } return err.Error() } func hasJSONFlag(args []string) bool { for _, arg := range args { if arg == "--json" { return true } if strings.HasPrefix(arg, "--json=") { return !strings.HasSuffix(arg, "=false") } } return false } func isUsageError(err error) bool { message := err.Error() return strings.HasPrefix(message, "required flag(s)") || strings.HasPrefix(message, "unknown flag:") || strings.HasPrefix(message, "unknown command ") || strings.Contains(message, " accepts ") || strings.Contains(message, "invalid argument ") }