UNPKG

storybook

Version:

Storybook: Develop, document, and test UI components in isolation

5,088 lines • 222 kB
import CJS_COMPAT_NODE_URL_qjinduibsyq from 'node:url';
import CJS_COMPAT_NODE_PATH_qjinduibsyq from 'node:path';
import CJS_COMPAT_NODE_MODULE_qjinduibsyq from "node:module";

var __filename = CJS_COMPAT_NODE_URL_qjinduibsyq.fileURLToPath(import.meta.url);
var __dirname = CJS_COMPAT_NODE_PATH_qjinduibsyq.dirname(__filename);
var require = CJS_COMPAT_NODE_MODULE_qjinduibsyq.createRequire(import.meta.url);

// ------------------------------------------------------------
// end of CJS compatibility banner, injected by Storybook's esbuild configuration
// ------------------------------------------------------------
import {
  readRegistry,
  resolveInstance,
  selectInstances
} from "../_node-chunks/chunk-K36QW2O3.js";
import {
  resolveStorybookConfigDir
} from "../_node-chunks/chunk-S7XIM54L.js";
import {
  instructions
} from "../_node-chunks/chunk-PDN6UNOP.js";
import "../_node-chunks/chunk-HJMGUQVU.js";
import "../_node-chunks/chunk-B6IHDMAH.js";
import "../_node-chunks/chunk-SC2O4JWO.js";
import {
  createTools,
  toolsCommandDimensions,
  wrapMethodTelemetry
} from "../_node-chunks/chunk-VT3VBFAX.js";
import {
  formatMultiInstanceNotice
} from "../_node-chunks/chunk-4CTPDGB7.js";
import {
  ToolsRuntimeError,
  attachGateReasonFromError,
  isAttachGateError
} from "../_node-chunks/chunk-F5UFNM2U.js";
import {
  frameworkToRendererMap,
  isClaudePreviewLaunch,
  resolveSkillInputs
} from "../_node-chunks/chunk-IRIMEJJ3.js";
import "../_node-chunks/chunk-UF3LYQOO.js";
import {
  getMonorepoType,
  version
} from "../_node-chunks/chunk-VBSZV6KY.js";
import {
  detectAgent
} from "../_node-chunks/chunk-GVZSAAZJ.js";
import {
  detectLanguage,
  getStorybookData
} from "../_node-chunks/chunk-MQGAF7D5.js";
import {
  withTelemetry
} from "../_node-chunks/chunk-FTP3QZ7O.js";
import "../_node-chunks/chunk-EEWXQXZP.js";
import {
  getToolName,
  parseToolsetMethodId,
  toCliMethodName
} from "../_node-chunks/chunk-52XR72NR.js";
import {
  globalSettings
} from "../_node-chunks/chunk-7L4K47Q6.js";
import "../_node-chunks/chunk-UAW7LJY2.js";
import {
  array,
  boolean,
  integer,
  lazy,
  looseObject,
  maxValue,
  message,
  minValue,
  number,
  optional,
  pipe,
  record,
  regex,
  safeParse,
  string,
  summarize,
  transform,
  trim,
  union,
  unknown
} from "../_node-chunks/chunk-5EYYAT2W.js";
import "../_node-chunks/chunk-2J2NU66Q.js";
import "../_node-chunks/chunk-IRHRSPSI.js";
import "../_node-chunks/chunk-6WZPWJR4.js";
import "../_node-chunks/chunk-5G6TGQDE.js";
import "../_node-chunks/chunk-7LZUPCQB.js";
import "../_node-chunks/chunk-DW727PJG.js";
import {
  require_dist
} from "../_node-chunks/chunk-FE5AV6EP.js";
import {
  require_picocolors
} from "../_node-chunks/chunk-VGN5LGMI.js";
import "../_node-chunks/chunk-PPVCVHOS.js";
import {
  __commonJS,
  __require,
  __toESM
} from "../_node-chunks/chunk-4US4PNS3.js";

// ../../node_modules/commander/lib/error.js
var require_error = __commonJS({
  "../../node_modules/commander/lib/error.js"(exports) {
    var CommanderError2 = class extends Error {
      /**
       * Constructs the CommanderError class
       * @param {number} exitCode suggested exit code which could be used with process.exit
       * @param {string} code an id string representing the error
       * @param {string} message human-readable description of the error
       */
      constructor(exitCode, code, message2) {
        super(message2), Error.captureStackTrace(this, this.constructor), this.name = this.constructor.name, this.code = code, this.exitCode = exitCode, this.nestedError = void 0;
      }
    }, InvalidArgumentError2 = class extends CommanderError2 {
      /**
       * Constructs the InvalidArgumentError class
       * @param {string} [message] explanation of why argument is invalid
       */
      constructor(message2) {
        super(1, "commander.invalidArgument", message2), Error.captureStackTrace(this, this.constructor), this.name = this.constructor.name;
      }
    };
    exports.CommanderError = CommanderError2;
    exports.InvalidArgumentError = InvalidArgumentError2;
  }
});

// ../../node_modules/commander/lib/argument.js
var require_argument = __commonJS({
  "../../node_modules/commander/lib/argument.js"(exports) {
    var { InvalidArgumentError: InvalidArgumentError2 } = require_error(), Argument2 = class {
      /**
       * Initialize a new command argument with the given name and description.
       * The default is that the argument is required, and you can explicitly
       * indicate this with <> around the name. Put [] around the name for an optional argument.
       *
       * @param {string} name
       * @param {string} [description]
       */
      constructor(name, description) {
        switch (this.description = description || "", this.variadic = !1, this.parseArg = void 0, this.defaultValue = void 0, this.defaultValueDescription = void 0, this.argChoices = void 0, name[0]) {
          case "<":
            this.required = !0, this._name = name.slice(1, -1);
            break;
          case "[":
            this.required = !1, this._name = name.slice(1, -1);
            break;
          default:
            this.required = !0, this._name = name;
            break;
        }
        this._name.endsWith("...") && (this.variadic = !0, this._name = this._name.slice(0, -3));
      }
      /**
       * Return argument name.
       *
       * @return {string}
       */
      name() {
        return this._name;
      }
      /**
       * @package
       */
      _collectValue(value, previous) {
        return previous === this.defaultValue || !Array.isArray(previous) ? [value] : (previous.push(value), previous);
      }
      /**
       * Set the default value, and optionally supply the description to be displayed in the help.
       *
       * @param {*} value
       * @param {string} [description]
       * @return {Argument}
       */
      default(value, description) {
        return this.defaultValue = value, this.defaultValueDescription = description, this;
      }
      /**
       * Set the custom handler for processing CLI command arguments into argument values.
       *
       * @param {Function} [fn]
       * @return {Argument}
       */
      argParser(fn) {
        return this.parseArg = fn, this;
      }
      /**
       * Only allow argument value to be one of choices.
       *
       * @param {string[]} values
       * @return {Argument}
       */
      choices(values) {
        return this.argChoices = values.slice(), this.parseArg = (arg, previous) => {
          if (!this.argChoices.includes(arg))
            throw new InvalidArgumentError2(
              `Allowed choices are ${this.argChoices.join(", ")}.`
            );
          return this.variadic ? this._collectValue(arg, previous) : arg;
        }, this;
      }
      /**
       * Make argument required.
       *
       * @returns {Argument}
       */
      argRequired() {
        return this.required = !0, this;
      }
      /**
       * Make argument optional.
       *
       * @returns {Argument}
       */
      argOptional() {
        return this.required = !1, this;
      }
    };
    function humanReadableArgName(arg) {
      let nameOutput = arg.name() + (arg.variadic === !0 ? "..." : "");
      return arg.required ? "<" + nameOutput + ">" : "[" + nameOutput + "]";
    }
    exports.Argument = Argument2;
    exports.humanReadableArgName = humanReadableArgName;
  }
});

// ../../node_modules/commander/lib/help.js
var require_help = __commonJS({
  "../../node_modules/commander/lib/help.js"(exports) {
    var { humanReadableArgName } = require_argument(), Help2 = class {
      constructor() {
        this.helpWidth = void 0, this.minWidthToWrap = 40, this.sortSubcommands = !1, this.sortOptions = !1, this.showGlobalOptions = !1;
      }
      /**
       * prepareContext is called by Commander after applying overrides from `Command.configureHelp()`
       * and just before calling `formatHelp()`.
       *
       * Commander just uses the helpWidth and the rest is provided for optional use by more complex subclasses.
       *
       * @param {{ error?: boolean, helpWidth?: number, outputHasColors?: boolean }} contextOptions
       */
      prepareContext(contextOptions) {
        this.helpWidth = this.helpWidth ?? contextOptions.helpWidth ?? 80;
      }
      /**
       * Get an array of the visible subcommands. Includes a placeholder for the implicit help command, if there is one.
       *
       * @param {Command} cmd
       * @returns {Command[]}
       */
      visibleCommands(cmd) {
        let visibleCommands = cmd.commands.filter((cmd2) => !cmd2._hidden), helpCommand = cmd._getHelpCommand();
        return helpCommand && !helpCommand._hidden && visibleCommands.push(helpCommand), this.sortSubcommands && visibleCommands.sort((a, b) => a.name().localeCompare(b.name())), visibleCommands;
      }
      /**
       * Compare options for sort.
       *
       * @param {Option} a
       * @param {Option} b
       * @returns {number}
       */
      compareOptions(a, b) {
        let getSortKey = (option) => option.short ? option.short.replace(/^-/, "") : option.long.replace(/^--/, "");
        return getSortKey(a).localeCompare(getSortKey(b));
      }
      /**
       * Get an array of the visible options. Includes a placeholder for the implicit help option, if there is one.
       *
       * @param {Command} cmd
       * @returns {Option[]}
       */
      visibleOptions(cmd) {
        let visibleOptions = cmd.options.filter((option) => !option.hidden), helpOption = cmd._getHelpOption();
        if (helpOption && !helpOption.hidden) {
          let removeShort = helpOption.short && cmd._findOption(helpOption.short), removeLong = helpOption.long && cmd._findOption(helpOption.long);
          !removeShort && !removeLong ? visibleOptions.push(helpOption) : helpOption.long && !removeLong ? visibleOptions.push(
            cmd.createOption(helpOption.long, helpOption.description)
          ) : helpOption.short && !removeShort && visibleOptions.push(
            cmd.createOption(helpOption.short, helpOption.description)
          );
        }
        return this.sortOptions && visibleOptions.sort(this.compareOptions), visibleOptions;
      }
      /**
       * Get an array of the visible global options. (Not including help.)
       *
       * @param {Command} cmd
       * @returns {Option[]}
       */
      visibleGlobalOptions(cmd) {
        if (!this.showGlobalOptions) return [];
        let globalOptions = [];
        for (let ancestorCmd = cmd.parent; ancestorCmd; ancestorCmd = ancestorCmd.parent) {
          let visibleOptions = ancestorCmd.options.filter(
            (option) => !option.hidden
          );
          globalOptions.push(...visibleOptions);
        }
        return this.sortOptions && globalOptions.sort(this.compareOptions), globalOptions;
      }
      /**
       * Get an array of the arguments if any have a description.
       *
       * @param {Command} cmd
       * @returns {Argument[]}
       */
      visibleArguments(cmd) {
        return cmd._argsDescription && cmd.registeredArguments.forEach((argument) => {
          argument.description = argument.description || cmd._argsDescription[argument.name()] || "";
        }), cmd.registeredArguments.find((argument) => argument.description) ? cmd.registeredArguments : [];
      }
      /**
       * Get the command term to show in the list of subcommands.
       *
       * @param {Command} cmd
       * @returns {string}
       */
      subcommandTerm(cmd) {
        let args = cmd.registeredArguments.map((arg) => humanReadableArgName(arg)).join(" ");
        return cmd._name + (cmd._aliases[0] ? "|" + cmd._aliases[0] : "") + (cmd.options.length ? " [options]" : "") + // simplistic check for non-help option
        (args ? " " + args : "");
      }
      /**
       * Get the option term to show in the list of options.
       *
       * @param {Option} option
       * @returns {string}
       */
      optionTerm(option) {
        return option.flags;
      }
      /**
       * Get the argument term to show in the list of arguments.
       *
       * @param {Argument} argument
       * @returns {string}
       */
      argumentTerm(argument) {
        return argument.name();
      }
      /**
       * Get the longest command term length.
       *
       * @param {Command} cmd
       * @param {Help} helper
       * @returns {number}
       */
      longestSubcommandTermLength(cmd, helper) {
        return helper.visibleCommands(cmd).reduce((max, command2) => Math.max(
          max,
          this.displayWidth(
            helper.styleSubcommandTerm(helper.subcommandTerm(command2))
          )
        ), 0);
      }
      /**
       * Get the longest option term length.
       *
       * @param {Command} cmd
       * @param {Help} helper
       * @returns {number}
       */
      longestOptionTermLength(cmd, helper) {
        return helper.visibleOptions(cmd).reduce((max, option) => Math.max(
          max,
          this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option)))
        ), 0);
      }
      /**
       * Get the longest global option term length.
       *
       * @param {Command} cmd
       * @param {Help} helper
       * @returns {number}
       */
      longestGlobalOptionTermLength(cmd, helper) {
        return helper.visibleGlobalOptions(cmd).reduce((max, option) => Math.max(
          max,
          this.displayWidth(helper.styleOptionTerm(helper.optionTerm(option)))
        ), 0);
      }
      /**
       * Get the longest argument term length.
       *
       * @param {Command} cmd
       * @param {Help} helper
       * @returns {number}
       */
      longestArgumentTermLength(cmd, helper) {
        return helper.visibleArguments(cmd).reduce((max, argument) => Math.max(
          max,
          this.displayWidth(
            helper.styleArgumentTerm(helper.argumentTerm(argument))
          )
        ), 0);
      }
      /**
       * Get the command usage to be displayed at the top of the built-in help.
       *
       * @param {Command} cmd
       * @returns {string}
       */
      commandUsage(cmd) {
        let cmdName = cmd._name;
        cmd._aliases[0] && (cmdName = cmdName + "|" + cmd._aliases[0]);
        let ancestorCmdNames = "";
        for (let ancestorCmd = cmd.parent; ancestorCmd; ancestorCmd = ancestorCmd.parent)
          ancestorCmdNames = ancestorCmd.name() + " " + ancestorCmdNames;
        return ancestorCmdNames + cmdName + " " + cmd.usage();
      }
      /**
       * Get the description for the command.
       *
       * @param {Command} cmd
       * @returns {string}
       */
      commandDescription(cmd) {
        return cmd.description();
      }
      /**
       * Get the subcommand summary to show in the list of subcommands.
       * (Fallback to description for backwards compatibility.)
       *
       * @param {Command} cmd
       * @returns {string}
       */
      subcommandDescription(cmd) {
        return cmd.summary() || cmd.description();
      }
      /**
       * Get the option description to show in the list of options.
       *
       * @param {Option} option
       * @return {string}
       */
      optionDescription(option) {
        let extraInfo = [];
        if (option.argChoices && extraInfo.push(
          // use stringify to match the display of the default value
          `choices: ${option.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`
        ), option.defaultValue !== void 0 && (option.required || option.optional || option.isBoolean() && typeof option.defaultValue == "boolean") && extraInfo.push(
          `default: ${option.defaultValueDescription || JSON.stringify(option.defaultValue)}`
        ), option.presetArg !== void 0 && option.optional && extraInfo.push(`preset: ${JSON.stringify(option.presetArg)}`), option.envVar !== void 0 && extraInfo.push(`env: ${option.envVar}`), extraInfo.length > 0) {
          let extraDescription = `(${extraInfo.join(", ")})`;
          return option.description ? `${option.description} ${extraDescription}` : extraDescription;
        }
        return option.description;
      }
      /**
       * Get the argument description to show in the list of arguments.
       *
       * @param {Argument} argument
       * @return {string}
       */
      argumentDescription(argument) {
        let extraInfo = [];
        if (argument.argChoices && extraInfo.push(
          // use stringify to match the display of the default value
          `choices: ${argument.argChoices.map((choice) => JSON.stringify(choice)).join(", ")}`
        ), argument.defaultValue !== void 0 && extraInfo.push(
          `default: ${argument.defaultValueDescription || JSON.stringify(argument.defaultValue)}`
        ), extraInfo.length > 0) {
          let extraDescription = `(${extraInfo.join(", ")})`;
          return argument.description ? `${argument.description} ${extraDescription}` : extraDescription;
        }
        return argument.description;
      }
      /**
       * Format a list of items, given a heading and an array of formatted items.
       *
       * @param {string} heading
       * @param {string[]} items
       * @param {Help} helper
       * @returns string[]
       */
      formatItemList(heading, items, helper) {
        return items.length === 0 ? [] : [helper.styleTitle(heading), ...items, ""];
      }
      /**
       * Group items by their help group heading.
       *
       * @param {Command[] | Option[]} unsortedItems
       * @param {Command[] | Option[]} visibleItems
       * @param {Function} getGroup
       * @returns {Map<string, Command[] | Option[]>}
       */
      groupItems(unsortedItems, visibleItems, getGroup) {
        let result = /* @__PURE__ */ new Map();
        return unsortedItems.forEach((item) => {
          let group = getGroup(item);
          result.has(group) || result.set(group, []);
        }), visibleItems.forEach((item) => {
          let group = getGroup(item);
          result.has(group) || result.set(group, []), result.get(group).push(item);
        }), result;
      }
      /**
       * Generate the built-in help text.
       *
       * @param {Command} cmd
       * @param {Help} helper
       * @returns {string}
       */
      formatHelp(cmd, helper) {
        let termWidth = helper.padWidth(cmd, helper), helpWidth = helper.helpWidth ?? 80;
        function callFormatItem(term, description) {
          return helper.formatItem(term, termWidth, description, helper);
        }
        let output = [
          `${helper.styleTitle("Usage:")} ${helper.styleUsage(helper.commandUsage(cmd))}`,
          ""
        ], commandDescription = helper.commandDescription(cmd);
        commandDescription.length > 0 && (output = output.concat([
          helper.boxWrap(
            helper.styleCommandDescription(commandDescription),
            helpWidth
          ),
          ""
        ]));
        let argumentList = helper.visibleArguments(cmd).map((argument) => callFormatItem(
          helper.styleArgumentTerm(helper.argumentTerm(argument)),
          helper.styleArgumentDescription(helper.argumentDescription(argument))
        ));
        if (output = output.concat(
          this.formatItemList("Arguments:", argumentList, helper)
        ), this.groupItems(
          cmd.options,
          helper.visibleOptions(cmd),
          (option) => option.helpGroupHeading ?? "Options:"
        ).forEach((options, group) => {
          let optionList = options.map((option) => callFormatItem(
            helper.styleOptionTerm(helper.optionTerm(option)),
            helper.styleOptionDescription(helper.optionDescription(option))
          ));
          output = output.concat(this.formatItemList(group, optionList, helper));
        }), helper.showGlobalOptions) {
          let globalOptionList = helper.visibleGlobalOptions(cmd).map((option) => callFormatItem(
            helper.styleOptionTerm(helper.optionTerm(option)),
            helper.styleOptionDescription(helper.optionDescription(option))
          ));
          output = output.concat(
            this.formatItemList("Global Options:", globalOptionList, helper)
          );
        }
        return this.groupItems(
          cmd.commands,
          helper.visibleCommands(cmd),
          (sub) => sub.helpGroup() || "Commands:"
        ).forEach((commands, group) => {
          let commandList = commands.map((sub) => callFormatItem(
            helper.styleSubcommandTerm(helper.subcommandTerm(sub)),
            helper.styleSubcommandDescription(helper.subcommandDescription(sub))
          ));
          output = output.concat(this.formatItemList(group, commandList, helper));
        }), output.join(`
`);
      }
      /**
       * Return display width of string, ignoring ANSI escape sequences. Used in padding and wrapping calculations.
       *
       * @param {string} str
       * @returns {number}
       */
      displayWidth(str) {
        return stripColor(str).length;
      }
      /**
       * Style the title for displaying in the help. Called with 'Usage:', 'Options:', etc.
       *
       * @param {string} str
       * @returns {string}
       */
      styleTitle(str) {
        return str;
      }
      styleUsage(str) {
        return str.split(" ").map((word) => word === "[options]" ? this.styleOptionText(word) : word === "[command]" ? this.styleSubcommandText(word) : word[0] === "[" || word[0] === "<" ? this.styleArgumentText(word) : this.styleCommandText(word)).join(" ");
      }
      styleCommandDescription(str) {
        return this.styleDescriptionText(str);
      }
      styleOptionDescription(str) {
        return this.styleDescriptionText(str);
      }
      styleSubcommandDescription(str) {
        return this.styleDescriptionText(str);
      }
      styleArgumentDescription(str) {
        return this.styleDescriptionText(str);
      }
      styleDescriptionText(str) {
        return str;
      }
      styleOptionTerm(str) {
        return this.styleOptionText(str);
      }
      styleSubcommandTerm(str) {
        return str.split(" ").map((word) => word === "[options]" ? this.styleOptionText(word) : word[0] === "[" || word[0] === "<" ? this.styleArgumentText(word) : this.styleSubcommandText(word)).join(" ");
      }
      styleArgumentTerm(str) {
        return this.styleArgumentText(str);
      }
      styleOptionText(str) {
        return str;
      }
      styleArgumentText(str) {
        return str;
      }
      styleSubcommandText(str) {
        return str;
      }
      styleCommandText(str) {
        return str;
      }
      /**
       * Calculate the pad width from the maximum term length.
       *
       * @param {Command} cmd
       * @param {Help} helper
       * @returns {number}
       */
      padWidth(cmd, helper) {
        return Math.max(
          helper.longestOptionTermLength(cmd, helper),
          helper.longestGlobalOptionTermLength(cmd, helper),
          helper.longestSubcommandTermLength(cmd, helper),
          helper.longestArgumentTermLength(cmd, helper)
        );
      }
      /**
       * Detect manually wrapped and indented strings by checking for line break followed by whitespace.
       *
       * @param {string} str
       * @returns {boolean}
       */
      preformatted(str) {
        return /\n[^\S\r\n]/.test(str);
      }
      /**
       * Format the "item", which consists of a term and description. Pad the term and wrap the description, indenting the following lines.
       *
       * So "TTT", 5, "DDD DDDD DD DDD" might be formatted for this.helpWidth=17 like so:
       *   TTT  DDD DDDD
       *        DD DDD
       *
       * @param {string} term
       * @param {number} termWidth
       * @param {string} description
       * @param {Help} helper
       * @returns {string}
       */
      formatItem(term, termWidth, description, helper) {
        let itemIndentStr = " ".repeat(2);
        if (!description) return itemIndentStr + term;
        let paddedTerm = term.padEnd(
          termWidth + term.length - helper.displayWidth(term)
        ), spacerWidth = 2, remainingWidth = (this.helpWidth ?? 80) - termWidth - spacerWidth - 2, formattedDescription;
        return remainingWidth < this.minWidthToWrap || helper.preformatted(description) ? formattedDescription = description : formattedDescription = helper.boxWrap(description, remainingWidth).replace(
          /\n/g,
          `
` + " ".repeat(termWidth + spacerWidth)
        ), itemIndentStr + paddedTerm + " ".repeat(spacerWidth) + formattedDescription.replace(/\n/g, `
${itemIndentStr}`);
      }
      /**
       * Wrap a string at whitespace, preserving existing line breaks.
       * Wrapping is skipped if the width is less than `minWidthToWrap`.
       *
       * @param {string} str
       * @param {number} width
       * @returns {string}
       */
      boxWrap(str, width) {
        if (width < this.minWidthToWrap) return str;
        let rawLines = str.split(/\r\n|\n/), chunkPattern = /[\s]*[^\s]+/g, wrappedLines = [];
        return rawLines.forEach((line) => {
          let chunks = line.match(chunkPattern);
          if (chunks === null) {
            wrappedLines.push("");
            return;
          }
          let sumChunks = [chunks.shift()], sumWidth = this.displayWidth(sumChunks[0]);
          chunks.forEach((chunk) => {
            let visibleWidth = this.displayWidth(chunk);
            if (sumWidth + visibleWidth <= width) {
              sumChunks.push(chunk), sumWidth += visibleWidth;
              return;
            }
            wrappedLines.push(sumChunks.join(""));
            let nextChunk = chunk.trimStart();
            sumChunks = [nextChunk], sumWidth = this.displayWidth(nextChunk);
          }), wrappedLines.push(sumChunks.join(""));
        }), wrappedLines.join(`
`);
      }
    };
    function stripColor(str) {
      let sgrPattern = /\x1b\[\d*(;\d*)*m/g;
      return str.replace(sgrPattern, "");
    }
    exports.Help = Help2;
    exports.stripColor = stripColor;
  }
});

// ../../node_modules/commander/lib/option.js
var require_option = __commonJS({
  "../../node_modules/commander/lib/option.js"(exports) {
    var { InvalidArgumentError: InvalidArgumentError2 } = require_error(), Option2 = class {
      /**
       * Initialize a new `Option` with the given `flags` and `description`.
       *
       * @param {string} flags
       * @param {string} [description]
       */
      constructor(flags, description) {
        this.flags = flags, this.description = description || "", this.required = flags.includes("<"), this.optional = flags.includes("["), this.variadic = /\w\.\.\.[>\]]$/.test(flags), this.mandatory = !1;
        let optionFlags = splitOptionFlags(flags);
        this.short = optionFlags.shortFlag, this.long = optionFlags.longFlag, this.negate = !1, this.long && (this.negate = this.long.startsWith("--no-")), this.defaultValue = void 0, this.defaultValueDescription = void 0, this.presetArg = void 0, this.envVar = void 0, this.parseArg = void 0, this.hidden = !1, this.argChoices = void 0, this.conflictsWith = [], this.implied = void 0, this.helpGroupHeading = void 0;
      }
      /**
       * Set the default value, and optionally supply the description to be displayed in the help.
       *
       * @param {*} value
       * @param {string} [description]
       * @return {Option}
       */
      default(value, description) {
        return this.defaultValue = value, this.defaultValueDescription = description, this;
      }
      /**
       * Preset to use when option used without option-argument, especially optional but also boolean and negated.
       * The custom processing (parseArg) is called.
       *
       * @example
       * new Option('--color').default('GREYSCALE').preset('RGB');
       * new Option('--donate [amount]').preset('20').argParser(parseFloat);
       *
       * @param {*} arg
       * @return {Option}
       */
      preset(arg) {
        return this.presetArg = arg, this;
      }
      /**
       * Add option name(s) that conflict with this option.
       * An error will be displayed if conflicting options are found during parsing.
       *
       * @example
       * new Option('--rgb').conflicts('cmyk');
       * new Option('--js').conflicts(['ts', 'jsx']);
       *
       * @param {(string | string[])} names
       * @return {Option}
       */
      conflicts(names) {
        return this.conflictsWith = this.conflictsWith.concat(names), this;
      }
      /**
       * Specify implied option values for when this option is set and the implied options are not.
       *
       * The custom processing (parseArg) is not called on the implied values.
       *
       * @example
       * program
       *   .addOption(new Option('--log', 'write logging information to file'))
       *   .addOption(new Option('--trace', 'log extra details').implies({ log: 'trace.txt' }));
       *
       * @param {object} impliedOptionValues
       * @return {Option}
       */
      implies(impliedOptionValues) {
        let newImplied = impliedOptionValues;
        return typeof impliedOptionValues == "string" && (newImplied = { [impliedOptionValues]: !0 }), this.implied = Object.assign(this.implied || {}, newImplied), this;
      }
      /**
       * Set environment variable to check for option value.
       *
       * An environment variable is only used if when processed the current option value is
       * undefined, or the source of the current value is 'default' or 'config' or 'env'.
       *
       * @param {string} name
       * @return {Option}
       */
      env(name) {
        return this.envVar = name, this;
      }
      /**
       * Set the custom handler for processing CLI option arguments into option values.
       *
       * @param {Function} [fn]
       * @return {Option}
       */
      argParser(fn) {
        return this.parseArg = fn, this;
      }
      /**
       * Whether the option is mandatory and must have a value after parsing.
       *
       * @param {boolean} [mandatory=true]
       * @return {Option}
       */
      makeOptionMandatory(mandatory = !0) {
        return this.mandatory = !!mandatory, this;
      }
      /**
       * Hide option in help.
       *
       * @param {boolean} [hide=true]
       * @return {Option}
       */
      hideHelp(hide = !0) {
        return this.hidden = !!hide, this;
      }
      /**
       * @package
       */
      _collectValue(value, previous) {
        return previous === this.defaultValue || !Array.isArray(previous) ? [value] : (previous.push(value), previous);
      }
      /**
       * Only allow option value to be one of choices.
       *
       * @param {string[]} values
       * @return {Option}
       */
      choices(values) {
        return this.argChoices = values.slice(), this.parseArg = (arg, previous) => {
          if (!this.argChoices.includes(arg))
            throw new InvalidArgumentError2(
              `Allowed choices are ${this.argChoices.join(", ")}.`
            );
          return this.variadic ? this._collectValue(arg, previous) : arg;
        }, this;
      }
      /**
       * Return option name.
       *
       * @return {string}
       */
      name() {
        return this.long ? this.long.replace(/^--/, "") : this.short.replace(/^-/, "");
      }
      /**
       * Return option name, in a camelcase format that can be used
       * as an object attribute key.
       *
       * @return {string}
       */
      attributeName() {
        return this.negate ? camelcase(this.name().replace(/^no-/, "")) : camelcase(this.name());
      }
      /**
       * Set the help group heading.
       *
       * @param {string} heading
       * @return {Option}
       */
      helpGroup(heading) {
        return this.helpGroupHeading = heading, this;
      }
      /**
       * Check if `arg` matches the short or long flag.
       *
       * @param {string} arg
       * @return {boolean}
       * @package
       */
      is(arg) {
        return this.short === arg || this.long === arg;
      }
      /**
       * Return whether a boolean option.
       *
       * Options are one of boolean, negated, required argument, or optional argument.
       *
       * @return {boolean}
       * @package
       */
      isBoolean() {
        return !this.required && !this.optional && !this.negate;
      }
    }, DualOptions = class {
      /**
       * @param {Option[]} options
       */
      constructor(options) {
        this.positiveOptions = /* @__PURE__ */ new Map(), this.negativeOptions = /* @__PURE__ */ new Map(), this.dualOptions = /* @__PURE__ */ new Set(), options.forEach((option) => {
          option.negate ? this.negativeOptions.set(option.attributeName(), option) : this.positiveOptions.set(option.attributeName(), option);
        }), this.negativeOptions.forEach((value, key) => {
          this.positiveOptions.has(key) && this.dualOptions.add(key);
        });
      }
      /**
       * Did the value come from the option, and not from possible matching dual option?
       *
       * @param {*} value
       * @param {Option} option
       * @returns {boolean}
       */
      valueFromOption(value, option) {
        let optionKey = option.attributeName();
        if (!this.dualOptions.has(optionKey)) return !0;
        let preset = this.negativeOptions.get(optionKey).presetArg, negativeValue = preset !== void 0 ? preset : !1;
        return option.negate === (negativeValue === value);
      }
    };
    function camelcase(str) {
      return str.split("-").reduce((str2, word) => str2 + word[0].toUpperCase() + word.slice(1));
    }
    function splitOptionFlags(flags) {
      let shortFlag, longFlag, shortFlagExp = /^-[^-]$/, longFlagExp = /^--[^-]/, flagParts = flags.split(/[ |,]+/).concat("guard");
      if (shortFlagExp.test(flagParts[0]) && (shortFlag = flagParts.shift()), longFlagExp.test(flagParts[0]) && (longFlag = flagParts.shift()), !shortFlag && shortFlagExp.test(flagParts[0]) && (shortFlag = flagParts.shift()), !shortFlag && longFlagExp.test(flagParts[0]) && (shortFlag = longFlag, longFlag = flagParts.shift()), flagParts[0].startsWith("-")) {
        let unsupportedFlag = flagParts[0], baseError = `option creation failed due to '${unsupportedFlag}' in option flags '${flags}'`;
        throw /^-[^-][^-]/.test(unsupportedFlag) ? new Error(
          `${baseError}
- a short flag is a single dash and a single character
  - either use a single dash and a single character (for a short flag)
  - or use a double dash for a long option (and can have two, like '--ws, --workspace')`
        ) : shortFlagExp.test(unsupportedFlag) ? new Error(`${baseError}
- too many short flags`) : longFlagExp.test(unsupportedFlag) ? new Error(`${baseError}
- too many long flags`) : new Error(`${baseError}
- unrecognised flag format`);
      }
      if (shortFlag === void 0 && longFlag === void 0)
        throw new Error(
          `option creation failed due to no flags found in '${flags}'.`
        );
      return { shortFlag, longFlag };
    }
    exports.Option = Option2;
    exports.DualOptions = DualOptions;
  }
});

// ../../node_modules/commander/lib/suggestSimilar.js
var require_suggestSimilar = __commonJS({
  "../../node_modules/commander/lib/suggestSimilar.js"(exports) {
    function editDistance(a, b) {
      if (Math.abs(a.length - b.length) > 3)
        return Math.max(a.length, b.length);
      let d = [];
      for (let i = 0; i <= a.length; i++)
        d[i] = [i];
      for (let j = 0; j <= b.length; j++)
        d[0][j] = j;
      for (let j = 1; j <= b.length; j++)
        for (let i = 1; i <= a.length; i++) {
          let cost = 1;
          a[i - 1] === b[j - 1] ? cost = 0 : cost = 1, d[i][j] = Math.min(
            d[i - 1][j] + 1,
            // deletion
            d[i][j - 1] + 1,
            // insertion
            d[i - 1][j - 1] + cost
            // substitution
          ), i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1] && (d[i][j] = Math.min(d[i][j], d[i - 2][j - 2] + 1));
        }
      return d[a.length][b.length];
    }
    function suggestSimilar(word, candidates) {
      if (!candidates || candidates.length === 0) return "";
      candidates = Array.from(new Set(candidates));
      let searchingOptions = word.startsWith("--");
      searchingOptions && (word = word.slice(2), candidates = candidates.map((candidate) => candidate.slice(2)));
      let similar = [], bestDistance = 3, minSimilarity = 0.4;
      return candidates.forEach((candidate) => {
        if (candidate.length <= 1) return;
        let distance = editDistance(word, candidate), length = Math.max(word.length, candidate.length);
        (length - distance) / length > minSimilarity && (distance < bestDistance ? (bestDistance = distance, similar = [candidate]) : distance === bestDistance && similar.push(candidate));
      }), similar.sort((a, b) => a.localeCompare(b)), searchingOptions && (similar = similar.map((candidate) => `--${candidate}`)), similar.length > 1 ? `
(Did you mean one of ${similar.join(", ")}?)` : similar.length === 1 ? `
(Did you mean ${similar[0]}?)` : "";
    }
    exports.suggestSimilar = suggestSimilar;
  }
});

// ../../node_modules/commander/lib/command.js
var require_command = __commonJS({
  "../../node_modules/commander/lib/command.js"(exports) {
    var EventEmitter = __require("node:events").EventEmitter, childProcess = __require("node:child_process"), path = __require("node:path"), fs = __require("node:fs"), process2 = __require("node:process"), { Argument: Argument2, humanReadableArgName } = require_argument(), { CommanderError: CommanderError2 } = require_error(), { Help: Help2, stripColor } = require_help(), { Option: Option2, DualOptions } = require_option(), { suggestSimilar } = require_suggestSimilar(), Command2 = class _Command extends EventEmitter {
      /**
       * Initialize a new `Command`.
       *
       * @param {string} [name]
       */
      constructor(name) {
        super(), this.commands = [], this.options = [], this.parent = null, this._allowUnknownOption = !1, this._allowExcessArguments = !1, this.registeredArguments = [], this._args = this.registeredArguments, this.args = [], this.rawArgs = [], this.processedArgs = [], this._scriptPath = null, this._name = name || "", this._optionValues = {}, this._optionValueSources = {}, this._storeOptionsAsProperties = !1, this._actionHandler = null, this._executableHandler = !1, this._executableFile = null, this._executableDir = null, this._defaultCommandName = null, this._exitCallback = null, this._aliases = [], this._combineFlagAndOptionalValue = !0, this._description = "", this._summary = "", this._argsDescription = void 0, this._enablePositionalOptions = !1, this._passThroughOptions = !1, this._lifeCycleHooks = {}, this._showHelpAfterError = !1, this._showSuggestionAfterError = !0, this._savedState = null, this._outputConfiguration = {
          writeOut: (str) => process2.stdout.write(str),
          writeErr: (str) => process2.stderr.write(str),
          outputError: (str, write) => write(str),
          getOutHelpWidth: () => process2.stdout.isTTY ? process2.stdout.columns : void 0,
          getErrHelpWidth: () => process2.stderr.isTTY ? process2.stderr.columns : void 0,
          getOutHasColors: () => useColor() ?? (process2.stdout.isTTY && process2.stdout.hasColors?.()),
          getErrHasColors: () => useColor() ?? (process2.stderr.isTTY && process2.stderr.hasColors?.()),
          stripColor: (str) => stripColor(str)
        }, this._hidden = !1, this._helpOption = void 0, this._addImplicitHelpCommand = void 0, this._helpCommand = void 0, this._helpConfiguration = {}, this._helpGroupHeading = void 0, this._defaultCommandGroup = void 0, this._defaultOptionGroup = void 0;
      }
      /**
       * Copy settings that are useful to have in common across root command and subcommands.
       *
       * (Used internally when adding a command using `.command()` so subcommands inherit parent settings.)
       *
       * @param {Command} sourceCommand
       * @return {Command} `this` command for chaining
       */
      copyInheritedSettings(sourceCommand) {
        return this._outputConfiguration = sourceCommand._outputConfiguration, this._helpOption = sourceCommand._helpOption, this._helpCommand = sourceCommand._helpCommand, this._helpConfiguration = sourceCommand._helpConfiguration, this._exitCallback = sourceCommand._exitCallback, this._storeOptionsAsProperties = sourceCommand._storeOptionsAsProperties, this._combineFlagAndOptionalValue = sourceCommand._combineFlagAndOptionalValue, this._allowExcessArguments = sourceCommand._allowExcessArguments, this._enablePositionalOptions = sourceCommand._enablePositionalOptions, this._showHelpAfterError = sourceCommand._showHelpAfterError, this._showSuggestionAfterError = sourceCommand._showSuggestionAfterError, this;
      }
      /**
       * @returns {Command[]}
       * @private
       */
      _getCommandAndAncestors() {
        let result = [];
        for (let command2 = this; command2; command2 = command2.parent)
          result.push(command2);
        return result;
      }
      /**
       * Define a command.
       *
       * There are two styles of command: pay attention to where to put the description.
       *
       * @example
       * // Command implemented using action handler (description is supplied separately to `.command`)
       * program
       *   .command('clone <source> [destination]')
       *   .description('clone a repository into a newly created directory')
       *   .action((source, destination) => {
       *     console.log('clone command called');
       *   });
       *
       * // Command implemented using separate executable file (description is second parameter to `.command`)
       * program
       *   .command('start <service>', 'start named service')
       *   .command('stop [service]', 'stop named service, or all if no name supplied');
       *
       * @param {string} nameAndArgs - command name and arguments, args are `<required>` or `[optional]` and last may also be `variadic...`
       * @param {(object | string)} [actionOptsOrExecDesc] - configuration options (for action), or description (for executable)
       * @param {object} [execOpts] - configuration options (for executable)
       * @return {Command} returns new command for action handler, or `this` for executable command
       */
      command(nameAndArgs, actionOptsOrExecDesc, execOpts) {
        let desc = actionOptsOrExecDesc, opts = execOpts;
        typeof desc == "object" && desc !== null && (opts = desc, desc = null), opts = opts || {};
        let [, name, args] = nameAndArgs.match(/([^ ]+) *(.*)/), cmd = this.createCommand(name);
        return desc && (cmd.description(desc), cmd._executableHandler = !0), opts.isDefault && (this._defaultCommandName = cmd._name), cmd._hidden = !!(opts.noHelp || opts.hidden), cmd._executableFile = opts.executableFile || null, args && cmd.arguments(args), this._registerCommand(cmd), cmd.parent = this, cmd.copyInheritedSettings(this), desc ? this : cmd;
      }
      /**
       * Factory routine to create a new unattached command.
       *
       * See .command() for creating an attached subcommand, which uses this routine to
       * create the command. You can override createCommand to customise subcommands.
       *
       * @param {string} [name]
       * @return {Command} new command
       */
      createCommand(name) {
        return new _Command(name);
      }
      /**
       * You can customise the help with a subclass of Help by overriding createHelp,
       * or by overriding Help properties using configureHelp().
       *
       * @return {Help}
       */
      createHelp() {
        return Object.assign(new Help2(), this.configureHelp());
      }
      /**
       * You can customise the help by overriding Help properties using configureHelp(),
       * or with a subclass of Help by overriding createHelp().
       *
       * @param {object} [configuration] - configuration options
       * @return {(Command | object)} `this` command for chaining, or stored configuration
       */
      configureHelp(configuration) {
        return configuration === void 0 ? this._helpConfiguration : (this._helpConfiguration = configuration, this);
      }
      /**
       * The default output goes to stdout and stderr. You can customise this for special
       * applications. You can also customise the display of errors by overriding outputError.
       *
       * The configuration properties are all functions:
       *
       *     // change how output being written, defaults to stdout and stderr
       *     writeOut(str)
       *     writeErr(str)
       *     // change how output being written for errors, defaults to writeErr
       *     outputError(str, write) // used for displaying errors and not used for displaying help
       *     // specify width for wrapping help
       *     getOutHelpWidth()
       *     getErrHelpWidth()
       *     // color support, currently only used with Help
       *     getOutHasColors()
       *     getErrHasColors()
       *     stripColor() // used to remove ANSI escape codes if output does not have colors
       *
       * @param {object} [configuration] - configuration options
       * @return {(Command | object)} `this` command for chaining, or stored configuration
       */
      configureOutput(configuration) {
        return configuration === void 0 ? this._outputConfiguration : (this._outputConfiguration = {
          ...this._outputConfiguration,
          ...configuration
        }, this);
      }
      /**
       * Display the help or a custom message after an error occurs.
       *
       * @param {(boolean|string)} [displayHelp]
       * @return {Command} `this` command for chaining
       */
      showHelpAfterError(displayHelp = !0) {
        return typeof displayHelp != "string" && (displayHelp = !!displayHelp), this._showHelpAfterError = displayHelp, this;
      }
      /**
       * Display suggestion of similar commands for unknown commands, or options for unknown options.
       *
       * @param {boolean} [displaySuggestion]
       * @return {Command} `this` command for chaining
       */
      showSuggestionAfterError(displaySuggestion = !0) {
        return this._showSuggestionAfterError = !!displaySuggestion, this;
      }
      /**
       * Add a prepared subcommand.
       *
       * See .command() for creating an attached subcommand which inherits settings from its parent.
       *
       * @param {Command} cmd - new subcommand
       * @param {object} [opts] - configuration options
       * @return {Command} `this` command for chaining
       */
      addCommand(cmd, opts) {
        if (!cmd._name)
          throw new Error(`Command passed to .addCommand() must have a name
- specify the name in Command constructor or using .name()`);
        return opts = opts || {}, opts.isDefault && (this._defaultCommandName = cmd._name), (opts.noHelp || opts.hidden) && (cmd._hidden = !0), this._registerCommand(cmd), cmd.parent = this, cmd._checkForBrokenPassThrough(), this;
      }
      /**
       * Factory routine to create a new unattached argument.
       *
       * See .argument() for creating an attached argument, which uses this routine to
       * create the argument. You can override createArgument to return a custom argument.
       *
       * @param {string} name
       * @param {string} [description]
       * @return {Argument} new argument
       */
      createArgument(name, description) {
        return new Argument2(name, description);
      }
      /**
       * Define argument syntax for command.
       *
       * The default is that the argument is required, and you can explicitly
       * indicate this with <> around the name. Put [] around the name for an optional argument.
       *
       * @example
       * program.argument('<input-file>');
       * program.argument('[output-file]');
       *
       * @param {string} name
       * @param {string} [description]
       * @param {(Function|*)} [parseArg] - custom argument processing function or default value
       * @param {*} [defaultValue]
       * @return {Command} `this` command for chaining
       */
      argument(name, description, parseArg, defaultValue) {
        let argument = this.createArgument(name, description);
        return typeof parseArg == "function" ? argument.default(defaultValue).argParser(parseArg) : argument.default(parseArg), this.addArgument(argument), this;
      }
      /**
       * Define argument syntax for command, adding multiple at once (without descriptions).
       *
       * See also .argument().
       *
       * @example
       * program.arguments('<cmd> [env]');
       *
       * @param {string} names
       * @return {Command} `this` command for chaining
       */
      arguments(names) {
        return names.trim().split(/ +/).forEach((detail) => {
          this.argument(detail);
        }), this;
      }
      /**
       * Define argument syntax for command, adding a prepared argument.
       *
       * @param {Argument} argument
       * @return {Command} `this` command for chaining
       */
      addArgument(argument) {
        let previousArgument = this.registeredArguments.slice(-1)[0];
        if (previousArgument?.variadic)
          throw new Error(
            `only the last argument can be variadic '${previousArgument.name()}'`
          );
        if (argument.required && argument.defaultValue !== void 0 && argument.parseArg === void 0)
          throw new Error(
            `a default value for a required argument is never used: '${argument.name()}'`
          );
        return this.registeredArguments.push(argument), this;
      }
      /**
       * Customise or override default help command. By default a help command is automatically added if your command has subcommands.
       *
       * @example
       *    program.helpCommand('help [cmd]');
       *    program.helpCommand('help [cmd]', 'show help');
       *    program.helpCommand(false); // suppress default help command
       *    program.helpCommand(true); // add help command even if no subcommands
       *
       * @param {string|boolean} enableOrNameAndArgs - enable with custom name and/or arguments, or boolean to override whether added
       * @param {string} [description] - custom description
       * @return {Command} `this` command for chaining
       */
      helpCommand(enableOrNameAndArgs, description) {
        if (typeof enableOrNameAndArgs == "boolean")
          return this._addImplicitHelpCommand = enableOrNameAndArgs, enableOrNameAndArgs && this._defaultCommandGroup && this._initCommandGroup(this._getHelpCommand()), this;
        let nameAndArgs = enableOrNameAndArgs ?? "help [command]", [, helpName, helpArgs] = nameAndArgs.match(/([^ ]+) *(.*)/), helpDescription = description ?? "display help for command", helpCommand = this.createCommand(helpName);
        return helpCommand.helpOption(!1), helpArgs && helpCommand.arguments(helpArgs), helpDescription && helpCommand.description(helpDescription), this._addImplicitHelpCommand = !0, this._helpCommand = helpCommand, (enableOrNameAndArgs || description) && this._initCommandGroup(helpCommand), this;
      }
      /**
       * Add prepared custom help command.
       *
       * @param {(Command|string|boolean)} helpCommand - custom help command, or deprecated enableOrNameAndArgs as for `.helpCommand()`
       * @param {string} [deprecatedDescription] - deprecated custom description used with custom name only
       * @return {Command} `this` command for chaining
       */
      addHelpCommand(helpCommand, deprecatedDescription) {
        return typeof helpCommand != "object" ? (this.helpCommand(helpCommand, deprecatedDescription), this) : (this._addImplicitHelpCommand = !0, this._helpCommand = helpCommand, this._initCommandGroup(helpCommand), this);
      }
      /**
       * Lazy create help command.
       *
       * @return {(Command|null)}
       * @package
       */
      _getHelpCommand() {
        return this._addImplicitHelpCommand ?? (this.commands.length && !this._actionHandler && !this._findCommand("help")) ? (this._helpCommand === void 0 && this.helpCommand(void 0, void 0), this._helpCommand) : null;
      }
      /**
       * Add hook for life cycle event.
       *
       * @param {string} event
       * @param {Function} listener
       * @return {Command} `this` command for chaining
       */
      hook(event, listener) {
        let allowedValues = ["preSubcommand", "preAction", "postAction"];
        if (!allowedValues.includes(event))
          throw new Error(`Unexpected value for event passed to hook : '${event}'.
Expecting one of '${allowedValues.join("', '")}'`);
        return this._lifeCycleHooks[event] ? this._lifeCycleHooks[event].push(listener) : this._lifeCycleHooks[event] = [listener], this;
      }
      /**
       * Register callback to use as replacement for calling process.exit.
       *
       * @param {Function} [fn] optional callback which will be passed a CommanderError, defaults to throwing
       * @return {Command} `this` command for chaining
       */
      exitOverride(fn) {
        return fn ? this._exitCallback = fn : this._exitCallback = (err) => {
          if (err.code !== "commander.executeSubCommandAsync")
            throw err;
        }, this;
      }
      /**
       * Call process.exit, and _exitCallback if defined.
       *
       * @param {number} exitCode exit code for using with process.exit
       * @param {string} code an id string representing the error
       * @param {string} message human-readable description of the error
       * @return never
       * @private
       */
      _exit(exitCode, code, message2) {
        this._exitCallback && this._exitCallback(new CommanderError2(exitCode, code, message2)), process2.exit(exitCode);
      }
      /**
       * Register callback `fn` for the command.
       *
       * @example
       * program
       *   .command('serve')
       *   .description('start service')
       *   .action(function() {
       *      // do work here
       *   });
       *
       * @param {Function} fn
       * @return {Command} `this` command for chaining
       */
      action(fn) {
        let listener = (args) => {
          let expectedArgsCount = this.registeredArguments.length, actionArgs = args.slice(0, expectedArgsCount);
          return this._storeOptionsAsProperties ? actionArgs[expectedArgsCount] = this : actionArgs[expectedArgsCount] = this.opts(), actionArgs.push(this), fn.apply(this, actionArgs);
        };
        return this._actionHandler = listener, this;
      }
      /**
       * Factory routine to create a new unattached option.
       *
       * See .option() for creating an attached option, which uses this routine to
       * create the option. You can override createOption to return a custom option.
       *
       * @param {string} flags
       * @param {string} [description]
       * @return {Option} new option
       */
      createOption(flags, description) {
        return new Option2(flags, description);
      }
      /**
       * Wrap parseArgs to catch 'commander.invalidArgument'.
       *
       * @param {(Option | Argument)} target
       * @param {string} value
       * @param {*} previous
       * @param {string} invalidArgumentMessage
       * @private
       */
      _callParseArg(target, value, previous, invalidArgumentMessage) {
        try {
          return target.parseArg(value, previous);
        } catch (err) {
          if (err.code === "commander.invalidArgument") {
            let message2 = `${invalidArgumentMessage} ${err.message}`;
            this.error(message2, { exitCode: err.exitCode, code: err.code });
          }
          throw err;
        }
      }
      /**
       * Check for option flag conflicts.
       * Register option if no conflicts found, or throw on conflict.
       *
       * @param {Option} option
       * @private
       */
      _registerOption(option) {
        let matchingOption = option.short && this._findOption(option.short) || option.long && this._findOption(option.long);
        if (matchingOption) {
          let matchingFlag = option.long && this._findOption(option.long) ? option.long : option.short;
          throw new Error(`Cannot add option '${option.flags}'${this._name && ` to command '${this._name}'`} due to conflicting flag '${matchingFlag}'
-  already used by option '${matchingOption.flags}'`);
        }
        this._initOptionGroup(option), this.options.push(option);
      }
      /**
       * Check for command name and alias conflicts with existing commands.
       * Register command if no conflicts found, or throw on conflict.
       *
       * @param {Command} command
       * @private
       */
      _registerCommand(command2) {
        let knownBy = (cmd) => [cmd.name()].concat(cmd.aliases()), alreadyUsed = knownBy(command2).find(
          (name) => this._findCommand(name)
        );
        if (alreadyUsed) {
          let existingCmd = knownBy(this._findCommand(alreadyUsed)).join("|"), newCmd = knownBy(command2).join("|");
          throw new Error(
            `cannot add command '${newCmd}' as already have command '${existingCmd}'`
          );
        }
        this._initCommandGroup(command2), this.commands.push(command2);
      }
      /**
       * Add an option.
       *
       * @param {Option} option
       * @return {Command} `this` command for chaining
       */
      addOption(option) {
        this._registerOption(option);
        let oname = option.name(), name = option.attributeName();
        if (option.negate) {
          let positiveLongFlag = option.long.replace(/^--no-/, "--");
          this._findOption(positiveLongFlag) || this.setOptionValueWithSource(
            name,
            option.defaultValue === void 0 ? !0 : option.defaultValue,
            "default"
          );
        } else option.defaultValue !== void 0 && this.setOptionValueWithSource(name, option.defaultValue, "default");
        let handleOptionValue = (val, invalidValueMessage, valueSource) => {
          val == null && option.presetArg !== void 0 && (val = option.presetArg);
          let oldValue = this.getOptionValue(name);
          val !== null && option.parseArg ? val = this._callParseArg(option, val, oldValue, invalidValueMessage) : val !== null && option.variadic && (val = option._collectValue(val, oldValue)), val == null && (option.negate ? val = !1 : option.isBoolean() || option.optional ? val = !0 : val = ""), this.setOptionValueWithSource(name, val, valueSource);
        };
        return this.on("option:" + oname, (val) => {
          let invalidValueMessage = `error: option '${option.flags}' argument '${val}' is invalid.`;
          handleOptionValue(val, invalidValueMessage, "cli");
        }), option.envVar && this.on("optionEnv:" + oname, (val) => {
          let invalidValueMessage = `error: option '${option.flags}' value '${val}' from env '${option.envVar}' is invalid.`;
          handleOptionValue(val, invalidValueMessage, "env");
        }), this;
      }
      /**
       * Internal implementation shared by .option() and .requiredOption()
       *
       * @return {Command} `this` command for chaining
       * @private
       */
      _optionEx(config, flags, description, fn, defaultValue) {
        if (typeof flags == "object" && flags instanceof Option2)
          throw new Error(
            "To add an Option object use addOption() instead of option() or requiredOption()"
          );
        let option = this.createOption(flags, description);
        if (option.makeOptionMandatory(!!config.mandatory), typeof fn == "function")
          option.default(defaultValue).argParser(fn);
        else if (fn instanceof RegExp) {
          let regex2 = fn;
          fn = (val, def) => {
            let m = regex2.exec(val);
            return m ? m[0] : def;
          }, option.default(defaultValue).argParser(fn);
        } else
          option.default(fn);
        return this.addOption(option);
      }
      /**
       * Define option with `flags`, `description`, and optional argument parsing function or `defaultValue` or both.
       *
       * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space. A required
       * option-argument is indicated by `<>` and an optional option-argument by `[]`.
       *
       * See the README for more details, and see also addOption() and requiredOption().
       *
       * @example
       * program
       *     .option('-p, --pepper', 'add pepper')
       *     .option('--pt, --pizza-type <TYPE>', 'type of pizza') // required option-argument
       *     .option('-c, --cheese [CHEESE]', 'add extra cheese', 'mozzarella') // optional option-argument with default
       *     .option('-t, --tip <VALUE>', 'add tip to purchase cost', parseFloat) // custom parse function
       *
       * @param {string} flags
       * @param {string} [description]
       * @param {(Function|*)} [parseArg] - custom option processing function or default value
       * @param {*} [defaultValue]
       * @return {Command} `this` command for chaining
       */
      option(flags, description, parseArg, defaultValue) {
        return this._optionEx({}, flags, description, parseArg, defaultValue);
      }
      /**
       * Add a required option which must have a value after parsing. This usually means
       * the option must be specified on the command line. (Otherwise the same as .option().)
       *
       * The `flags` string contains the short and/or long flags, separated by comma, a pipe or space.
       *
       * @param {string} flags
       * @param {string} [description]
       * @param {(Function|*)} [parseArg] - custom option processing function or default value
       * @param {*} [defaultValue]
       * @return {Command} `this` command for chaining
       */
      requiredOption(flags, description, parseArg, defaultValue) {
        return this._optionEx(
          { mandatory: !0 },
          flags,
          description,
          parseArg,
          defaultValue
        );
      }
      /**
       * Alter parsing of short flags with optional values.
       *
       * @example
       * // for `.option('-f,--flag [value]'):
       * program.combineFlagAndOptionalValue(true);  // `-f80` is treated like `--flag=80`, this is the default behaviour
       * program.combineFlagAndOptionalValue(false) // `-fb` is treated like `-f -b`
       *
       * @param {boolean} [combine] - if `true` or omitted, an optional value can be specified directly after the flag.
       * @return {Command} `this` command for chaining
       */
      combineFlagAndOptionalValue(combine = !0) {
        return this._combineFlagAndOptionalValue = !!combine, this;
      }
      /**
       * Allow unknown options on the command line.
       *
       * @param {boolean} [allowUnknown] - if `true` or omitted, no error will be thrown for unknown options.
       * @return {Command} `this` command for chaining
       */
      allowUnknownOption(allowUnknown = !0) {
        return this._allowUnknownOption = !!allowUnknown, this;
      }
      /**
       * Allow excess command-arguments on the command line. Pass false to make excess arguments an error.
       *
       * @param {boolean} [allowExcess] - if `true` or omitted, no error will be thrown for excess arguments.
       * @return {Command} `this` command for chaining
       */
      allowExcessArguments(allowExcess = !0) {
        return this._allowExcessArguments = !!allowExcess, this;
      }
      /**
       * Enable positional options. Positional means global options are specified before subcommands which lets
       * subcommands reuse the same option names, and also enables subcommands to turn on passThroughOptions.
       * The default behaviour is non-positional and global options may appear anywhere on the command line.
       *
       * @param {boolean} [positional]
       * @return {Command} `this` command for chaining
       */
      enablePositionalOptions(positional = !0) {
        return this._enablePositionalOptions = !!positional, this;
      }
      /**
       * Pass through options that come after command-arguments rather than treat them as command-options,
       * so actual command-options come before command-arguments. Turning this on for a subcommand requires
       * positional options to have been enabled on the program (parent commands).
       * The default behaviour is non-positional and options may appear before or after command-arguments.
       *
       * @param {boolean} [passThrough] for unknown options.
       * @return {Command} `this` command for chaining
       */
      passThroughOptions(passThrough = !0) {
        return this._passThroughOptions = !!passThrough, this._checkForBrokenPassThrough(), this;
      }
      /**
       * @private
       */
      _checkForBrokenPassThrough() {
        if (this.parent && this._passThroughOptions && !this.parent._enablePositionalOptions)
          throw new Error(
            `passThroughOptions cannot be used for '${this._name}' without turning on enablePositionalOptions for parent command(s)`
          );
      }
      /**
       * Whether to store option values as properties on command object,
       * or store separately (specify false). In both cases the option values can be accessed using .opts().
       *
       * @param {boolean} [storeAsProperties=true]
       * @return {Command} `this` command for chaining
       */
      storeOptionsAsProperties(storeAsProperties = !0) {
        if (this.options.length)
          throw new Error("call .storeOptionsAsProperties() before adding options");
        if (Object.keys(this._optionValues).length)
          throw new Error(
            "call .storeOptionsAsProperties() before setting option values"
          );
        return this._storeOptionsAsProperties = !!storeAsProperties, this;
      }
      /**
       * Retrieve option value.
       *
       * @param {string} key
       * @return {object} value
       */
      getOptionValue(key) {
        return this._storeOptionsAsProperties ? this[key] : this._optionValues[key];
      }
      /**
       * Store option value.
       *
       * @param {string} key
       * @param {object} value
       * @return {Command} `this` command for chaining
       */
      setOptionValue(key, value) {
        return this.setOptionValueWithSource(key, value, void 0);
      }
      /**
       * Store option value and where the value came from.
       *
       * @param {string} key
       * @param {object} value
       * @param {string} source - expected values are default/config/env/cli/implied
       * @return {Command} `this` command for chaining
       */
      setOptionValueWithSource(key, value, source) {
        return this._storeOptionsAsProperties ? this[key] = value : this._optionValues[key] = value, this._optionValueSources[key] = source, this;
      }
      /**
       * Get source of option value.
       * Expected values are default | config | env | cli | implied
       *
       * @param {string} key
       * @return {string}
       */
      getOptionValueSource(key) {
        return this._optionValueSources[key];
      }
      /**
       * Get source of option value. See also .optsWithGlobals().
       * Expected values are default | config | env | cli | implied
       *
       * @param {string} key
       * @return {string}
       */
      getOptionValueSourceWithGlobals(key) {
        let source;
        return this._getCommandAndAncestors().forEach((cmd) => {
          cmd.getOptionValueSource(key) !== void 0 && (source = cmd.getOptionValueSource(key));
        }), source;
      }
      /**
       * Get user arguments from implied or explicit arguments.
       * Side-effects: set _scriptPath if args included script. Used for default program name, and subcommand searches.
       *
       * @private
       */
      _prepareUserArgs(argv, parseOptions) {
        if (argv !== void 0 && !Array.isArray(argv))
          throw new Error("first parameter to parse must be array or undefined");
        if (parseOptions = parseOptions || {}, argv === void 0 && parseOptions.from === void 0) {
          process2.versions?.electron && (parseOptions.from = "electron");
          let execArgv = process2.execArgv ?? [];
          (execArgv.includes("-e") || execArgv.includes("--eval") || execArgv.includes("-p") || execArgv.includes("--print")) && (parseOptions.from = "eval");
        }
        argv === void 0 && (argv = process2.argv), this.rawArgs = argv.slice();
        let userArgs;
        switch (parseOptions.from) {
          case void 0:
          case "node":
            this._scriptPath = argv[1], userArgs = argv.slice(2);
            break;
          case "electron":
            process2.defaultApp ? (this._scriptPath = argv[1], userArgs = argv.slice(2)) : userArgs = argv.slice(1);
            break;
          case "user":
            userArgs = argv.slice(0);
            break;
          case "eval":
            userArgs = argv.slice(1);
            break;
          default:
            throw new Error(
              `unexpected parse option { from: '${parseOptions.from}' }`
            );
        }
        return !this._name && this._scriptPath && this.nameFromFilename(this._scriptPath), this._name = this._name || "program", userArgs;
      }
      /**
       * Parse `argv`, setting options and invoking commands when defined.
       *
       * Use parseAsync instead of parse if any of your action handlers are async.
       *
       * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!
       *
       * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:
       * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that
       * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged
       * - `'user'`: just user arguments
       *
       * @example
       * program.parse(); // parse process.argv and auto-detect electron and special node flags
       * program.parse(process.argv); // assume argv[0] is app and argv[1] is script
       * program.parse(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
       *
       * @param {string[]} [argv] - optional, defaults to process.argv
       * @param {object} [parseOptions] - optionally specify style of options with from: node/user/electron
       * @param {string} [parseOptions.from] - where the args are from: 'node', 'user', 'electron'
       * @return {Command} `this` command for chaining
       */
      parse(argv, parseOptions) {
        this._prepareForParse();
        let userArgs = this._prepareUserArgs(argv, parseOptions);
        return this._parseCommand([], userArgs), this;
      }
      /**
       * Parse `argv`, setting options and invoking commands when defined.
       *
       * Call with no parameters to parse `process.argv`. Detects Electron and special node options like `node --eval`. Easy mode!
       *
       * Or call with an array of strings to parse, and optionally where the user arguments start by specifying where the arguments are `from`:
       * - `'node'`: default, `argv[0]` is the application and `argv[1]` is the script being run, with user arguments after that
       * - `'electron'`: `argv[0]` is the application and `argv[1]` varies depending on whether the electron application is packaged
       * - `'user'`: just user arguments
       *
       * @example
       * await program.parseAsync(); // parse process.argv and auto-detect electron and special node flags
       * await program.parseAsync(process.argv); // assume argv[0] is app and argv[1] is script
       * await program.parseAsync(my-args, { from: 'user' }); // just user supplied arguments, nothing special about argv[0]
       *
       * @param {string[]} [argv]
       * @param {object} [parseOptions]
       * @param {string} parseOptions.from - where the args are from: 'node', 'user', 'electron'
       * @return {Promise}
       */
      async parseAsync(argv, parseOptions) {
        this._prepareForParse();
        let userArgs = this._prepareUserArgs(argv, parseOptions);
        return await this._parseCommand([], userArgs), this;
      }
      _prepareForParse() {
        this._savedState === null ? this.saveStateBeforeParse() : this.restoreStateBeforeParse();
      }
      /**
       * Called the first time parse is called to save state and allow a restore before subsequent calls to parse.
       * Not usually called directly, but available for subclasses to save their custom state.
       *
       * This is called in a lazy way. Only commands used in parsing chain will have state saved.
       */
      saveStateBeforeParse() {
        this._savedState = {
          // name is stable if supplied by author, but may be unspecified for root command and deduced during parsing
          _name: this._name,
          // option values before parse have default values (including false for negated options)
          // shallow clones
          _optionValues: { ...this._optionValues },
          _optionValueSources: { ...this._optionValueSources }
        };
      }
      /**
       * Restore state before parse for calls after the first.
       * Not usually called directly, but available for subclasses to save their custom state.
       *
       * This is called in a lazy way. Only commands used in parsing chain will have state restored.
       */
      restoreStateBeforeParse() {
        if (this._storeOptionsAsProperties)
          throw new Error(`Can not call parse again when storeOptionsAsProperties is true.
- either make a new Command for each call to parse, or stop storing options as properties`);
        this._name = this._savedState._name, this._scriptPath = null, this.rawArgs = [], this._optionValues = { ...this._savedState._optionValues }, this._optionValueSources = { ...this._savedState._optionValueSources }, this.args = [], this.processedArgs = [];
      }
      /**
       * Throw if expected executable is missing. Add lots of help for author.
       *
       * @param {string} executableFile
       * @param {string} executableDir
       * @param {string} subcommandName
       */
      _checkForMissingExecutable(executableFile, executableDir, subcommandName) {
        if (fs.existsSync(executableFile)) return;
        let executableDirMessage = executableDir ? `searched for local subcommand relative to directory '${executableDir}'` : "no directory for search for local subcommand, use .executableDir() to supply a custom directory", executableMissing = `'${executableFile}' does not exist
 - if '${subcommandName}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
 - if the default executable name is not suitable, use the executableFile option to supply a custom name or path
 - ${executableDirMessage}`;
        throw new Error(executableMissing);
      }
      /**
       * Execute a sub-command executable.
       *
       * @private
       */
      _executeSubCommand(subcommand, args) {
        args = args.slice();
        let launchWithNode = !1, sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
        function findFile(baseDir, baseName) {
          let localBin = path.resolve(baseDir, baseName);
          if (fs.existsSync(localBin)) return localBin;
          if (sourceExt.includes(path.extname(baseName))) return;
          let foundExt = sourceExt.find(
            (ext) => fs.existsSync(`${localBin}${ext}`)
          );
          if (foundExt) return `${localBin}${foundExt}`;
        }
        this._checkForMissingMandatoryOptions(), this._checkForConflictingOptions();
        let executableFile = subcommand._executableFile || `${this._name}-${subcommand._name}`, executableDir = this._executableDir || "";
        if (this._scriptPath) {
          let resolvedScriptPath;
          try {
            resolvedScriptPath = fs.realpathSync(this._scriptPath);
          } catch {
            resolvedScriptPath = this._scriptPath;
          }
          executableDir = path.resolve(
            path.dirname(resolvedScriptPath),
            executableDir
          );
        }
        if (executableDir) {
          let localFile = findFile(executableDir, executableFile);
          if (!localFile && !subcommand._executableFile && this._scriptPath) {
            let legacyName = path.basename(
              this._scriptPath,
              path.extname(this._scriptPath)
            );
            legacyName !== this._name && (localFile = findFile(
              executableDir,
              `${legacyName}-${subcommand._name}`
            ));
          }
          executableFile = localFile || executableFile;
        }
        launchWithNode = sourceExt.includes(path.extname(executableFile));
        let proc;
        process2.platform !== "win32" ? launchWithNode ? (args.unshift(executableFile), args = incrementNodeInspectorPort(process2.execArgv).concat(args), proc = childProcess.spawn(process2.argv[0], args, { stdio: "inherit" })) : proc = childProcess.spawn(executableFile, args, { stdio: "inherit" }) : (this._checkForMissingExecutable(
          executableFile,
          executableDir,
          subcommand._name
        ), args.unshift(executableFile), args = incrementNodeInspectorPort(process2.execArgv).concat(args), proc = childProcess.spawn(process2.execPath, args, { stdio: "inherit" })), proc.killed || ["SIGUSR1", "SIGUSR2", "SIGTERM", "SIGINT", "SIGHUP"].forEach((signal) => {
          process2.on(signal, () => {
            proc.killed === !1 && proc.exitCode === null && proc.kill(signal);
          });
        });
        let exitCallback = this._exitCallback;
        proc.on("close", (code) => {
          code = code ?? 1, exitCallback ? exitCallback(
            new CommanderError2(
              code,
              "commander.executeSubCommandAsync",
              "(close)"
            )
          ) : process2.exit(code);
        }), proc.on("error", (err) => {
          if (err.code === "ENOENT")
            this._checkForMissingExecutable(
              executableFile,
              executableDir,
              subcommand._name
            );
          else if (err.code === "EACCES")
            throw new Error(`'${executableFile}' not executable`);
          if (!exitCallback)
            process2.exit(1);
          else {
            let wrappedError = new CommanderError2(
              1,
              "commander.executeSubCommandAsync",
              "(error)"
            );
            wrappedError.nestedError = err, exitCallback(wrappedError);
          }
        }), this.runningCommand = proc;
      }
      /**
       * @private
       */
      _dispatchSubcommand(commandName, operands, unknown2) {
        let subCommand = this._findCommand(commandName);
        subCommand || this.help({ error: !0 }), subCommand._prepareForParse();
        let promiseChain;
        return promiseChain = this._chainOrCallSubCommandHook(
          promiseChain,
          subCommand,
          "preSubcommand"
        ), promiseChain = this._chainOrCall(promiseChain, () => {
          if (subCommand._executableHandler)
            this._executeSubCommand(subCommand, operands.concat(unknown2));
          else
            return subCommand._parseCommand(operands, unknown2);
        }), promiseChain;
      }
      /**
       * Invoke help directly if possible, or dispatch if necessary.
       * e.g. help foo
       *
       * @private
       */
      _dispatchHelpCommand(subcommandName) {
        subcommandName || this.help();
        let subCommand = this._findCommand(subcommandName);
        return subCommand && !subCommand._executableHandler && subCommand.help(), this._dispatchSubcommand(
          subcommandName,
          [],
          [this._getHelpOption()?.long ?? this._getHelpOption()?.short ?? "--help"]
        );
      }
      /**
       * Check this.args against expected this.registeredArguments.
       *
       * @private
       */
      _checkNumberOfArguments() {
        this.registeredArguments.forEach((arg, i) => {
          arg.required && this.args[i] == null && this.missingArgument(arg.name());
        }), !(this.registeredArguments.length > 0 && this.registeredArguments[this.registeredArguments.length - 1].variadic) && this.args.length > this.registeredArguments.length && this._excessArguments(this.args);
      }
      /**
       * Process this.args using this.registeredArguments and save as this.processedArgs!
       *
       * @private
       */
      _processArguments() {
        let myParseArg = (argument, value, previous) => {
          let parsedValue = value;
          if (value !== null && argument.parseArg) {
            let invalidValueMessage = `error: command-argument value '${value}' is invalid for argument '${argument.name()}'.`;
            parsedValue = this._callParseArg(
              argument,
              value,
              previous,
              invalidValueMessage
            );
          }
          return parsedValue;
        };
        this._checkNumberOfArguments();
        let processedArgs = [];
        this.registeredArguments.forEach((declaredArg, index) => {
          let value = declaredArg.defaultValue;
          declaredArg.variadic ? index < this.args.length ? (value = this.args.slice(index), declaredArg.parseArg && (value = value.reduce((processed, v) => myParseArg(declaredArg, v, processed), declaredArg.defaultValue))) : value === void 0 && (value = []) : index < this.args.length && (value = this.args[index], declaredArg.parseArg && (value = myParseArg(declaredArg, value, declaredArg.defaultValue))), processedArgs[index] = value;
        }), this.processedArgs = processedArgs;
      }
      /**
       * Once we have a promise we chain, but call synchronously until then.
       *
       * @param {(Promise|undefined)} promise
       * @param {Function} fn
       * @return {(Promise|undefined)}
       * @private
       */
      _chainOrCall(promise, fn) {
        return promise?.then && typeof promise.then == "function" ? promise.then(() => fn()) : fn();
      }
      /**
       *
       * @param {(Promise|undefined)} promise
       * @param {string} event
       * @return {(Promise|undefined)}
       * @private
       */
      _chainOrCallHooks(promise, event) {
        let result = promise, hooks = [];
        return this._getCommandAndAncestors().reverse().filter((cmd) => cmd._lifeCycleHooks[event] !== void 0).forEach((hookedCommand) => {
          hookedCommand._lifeCycleHooks[event].forEach((callback) => {
            hooks.push({ hookedCommand, callback });
          });
        }), event === "postAction" && hooks.reverse(), hooks.forEach((hookDetail) => {
          result = this._chainOrCall(result, () => hookDetail.callback(hookDetail.hookedCommand, this));
        }), result;
      }
      /**
       *
       * @param {(Promise|undefined)} promise
       * @param {Command} subCommand
       * @param {string} event
       * @return {(Promise|undefined)}
       * @private
       */
      _chainOrCallSubCommandHook(promise, subCommand, event) {
        let result = promise;
        return this._lifeCycleHooks[event] !== void 0 && this._lifeCycleHooks[event].forEach((hook) => {
          result = this._chainOrCall(result, () => hook(this, subCommand));
        }), result;
      }
      /**
       * Process arguments in context of this command.
       * Returns action result, in case it is a promise.
       *
       * @private
       */
      _parseCommand(operands, unknown2) {
        let parsed = this.parseOptions(unknown2);
        if (this._parseOptionsEnv(), this._parseOptionsImplied(), operands = operands.concat(parsed.operands), unknown2 = parsed.unknown, this.args = operands.concat(unknown2), operands && this._findCommand(operands[0]))
          return this._dispatchSubcommand(operands[0], operands.slice(1), unknown2);
        if (this._getHelpCommand() && operands[0] === this._getHelpCommand().name())
          return this._dispatchHelpCommand(operands[1]);
        if (this._defaultCommandName)
          return this._outputHelpIfRequested(unknown2), this._dispatchSubcommand(
            this._defaultCommandName,
            operands,
            unknown2
          );
        this.commands.length && this.args.length === 0 && !this._actionHandler && !this._defaultCommandName && this.help({ error: !0 }), this._outputHelpIfRequested(parsed.unknown), this._checkForMissingMandatoryOptions(), this._checkForConflictingOptions();
        let checkForUnknownOptions = () => {
          parsed.unknown.length > 0 && this.unknownOption(parsed.unknown[0]);
        }, commandEvent = `command:${this.name()}`;
        if (this._actionHandler) {
          checkForUnknownOptions(), this._processArguments();
          let promiseChain;
          return promiseChain = this._chainOrCallHooks(promiseChain, "preAction"), promiseChain = this._chainOrCall(
            promiseChain,
            () => this._actionHandler(this.processedArgs)
          ), this.parent && (promiseChain = this._chainOrCall(promiseChain, () => {
            this.parent.emit(commandEvent, operands, unknown2);
          })), promiseChain = this._chainOrCallHooks(promiseChain, "postAction"), promiseChain;
        }
        if (this.parent?.listenerCount(commandEvent))
          checkForUnknownOptions(), this._processArguments(), this.parent.emit(commandEvent, operands, unknown2);
        else if (operands.length) {
          if (this._findCommand("*"))
            return this._dispatchSubcommand("*", operands, unknown2);
          this.listenerCount("command:*") ? this.emit("command:*", operands, unknown2) : this.commands.length ? this.unknownCommand() : (checkForUnknownOptions(), this._processArguments());
        } else this.commands.length ? (checkForUnknownOptions(), this.help({ error: !0 })) : (checkForUnknownOptions(), this._processArguments());
      }
      /**
       * Find matching command.
       *
       * @private
       * @return {Command | undefined}
       */
      _findCommand(name) {
        if (name)
          return this.commands.find(
            (cmd) => cmd._name === name || cmd._aliases.includes(name)
          );
      }
      /**
       * Return an option matching `arg` if any.
       *
       * @param {string} arg
       * @return {Option}
       * @package
       */
      _findOption(arg) {
        return this.options.find((option) => option.is(arg));
      }
      /**
       * Display an error message if a mandatory option does not have a value.
       * Called after checking for help flags in leaf subcommand.
       *
       * @private
       */
      _checkForMissingMandatoryOptions() {
        this._getCommandAndAncestors().forEach((cmd) => {
          cmd.options.forEach((anOption) => {
            anOption.mandatory && cmd.getOptionValue(anOption.attributeName()) === void 0 && cmd.missingMandatoryOptionValue(anOption);
          });
        });
      }
      /**
       * Display an error message if conflicting options are used together in this.
       *
       * @private
       */
      _checkForConflictingLocalOptions() {
        let definedNonDefaultOptions = this.options.filter((option) => {
          let optionKey = option.attributeName();
          return this.getOptionValue(optionKey) === void 0 ? !1 : this.getOptionValueSource(optionKey) !== "default";
        });
        definedNonDefaultOptions.filter(
          (option) => option.conflictsWith.length > 0
        ).forEach((option) => {
          let conflictingAndDefined = definedNonDefaultOptions.find(
            (defined) => option.conflictsWith.includes(defined.attributeName())
          );
          conflictingAndDefined && this._conflictingOption(option, conflictingAndDefined);
        });
      }
      /**
       * Display an error message if conflicting options are used together.
       * Called after checking for help flags in leaf subcommand.
       *
       * @private
       */
      _checkForConflictingOptions() {
        this._getCommandAndAncestors().forEach((cmd) => {
          cmd._checkForConflictingLocalOptions();
        });
      }
      /**
       * Parse options from `argv` removing known options,
       * and return argv split into operands and unknown arguments.
       *
       * Side effects: modifies command by storing options. Does not reset state if called again.
       *
       * Examples:
       *
       *     argv => operands, unknown
       *     --known kkk op => [op], []
       *     op --known kkk => [op], []
       *     sub --unknown uuu op => [sub], [--unknown uuu op]
       *     sub -- --unknown uuu op => [sub --unknown uuu op], []
       *
       * @param {string[]} args
       * @return {{operands: string[], unknown: string[]}}
       */
      parseOptions(args) {
        let operands = [], unknown2 = [], dest = operands;
        function maybeOption(arg) {
          return arg.length > 1 && arg[0] === "-";
        }
        let negativeNumberArg = (arg) => /^-(\d+|\d*\.\d+)(e[+-]?\d+)?$/.test(arg) ? !this._getCommandAndAncestors().some(
          (cmd) => cmd.options.map((opt) => opt.short).some((short) => /^-\d$/.test(short))
        ) : !1, activeVariadicOption = null, activeGroup = null, i = 0;
        for (; i < args.length || activeGroup; ) {
          let arg = activeGroup ?? args[i++];
          if (activeGroup = null, arg === "--") {
            dest === unknown2 && dest.push(arg), dest.push(...args.slice(i));
            break;
          }
          if (activeVariadicOption && (!maybeOption(arg) || negativeNumberArg(arg))) {
            this.emit(`option:${activeVariadicOption.name()}`, arg);
            continue;
          }
          if (activeVariadicOption = null, maybeOption(arg)) {
            let option = this._findOption(arg);
            if (option) {
              if (option.required) {
                let value = args[i++];
                value === void 0 && this.optionMissingArgument(option), this.emit(`option:${option.name()}`, value);
              } else if (option.optional) {
                let value = null;
                i < args.length && (!maybeOption(args[i]) || negativeNumberArg(args[i])) && (value = args[i++]), this.emit(`option:${option.name()}`, value);
              } else
                this.emit(`option:${option.name()}`);
              activeVariadicOption = option.variadic ? option : null;
              continue;
            }
          }
          if (arg.length > 2 && arg[0] === "-" && arg[1] !== "-") {
            let option = this._findOption(`-${arg[1]}`);
            if (option) {
              option.required || option.optional && this._combineFlagAndOptionalValue ? this.emit(`option:${option.name()}`, arg.slice(2)) : (this.emit(`option:${option.name()}`), activeGroup = `-${arg.slice(2)}`);
              continue;
            }
          }
          if (/^--[^=]+=/.test(arg)) {
            let index = arg.indexOf("="), option = this._findOption(arg.slice(0, index));
            if (option && (option.required || option.optional)) {
              this.emit(`option:${option.name()}`, arg.slice(index + 1));
              continue;
            }
          }
          if (dest === operands && maybeOption(arg) && !(this.commands.length === 0 && negativeNumberArg(arg)) && (dest = unknown2), (this._enablePositionalOptions || this._passThroughOptions) && operands.length === 0 && unknown2.length === 0) {
            if (this._findCommand(arg)) {
              operands.push(arg), unknown2.push(...args.slice(i));
              break;
            } else if (this._getHelpCommand() && arg === this._getHelpCommand().name()) {
              operands.push(arg, ...args.slice(i));
              break;
            } else if (this._defaultCommandName) {
              unknown2.push(arg, ...args.slice(i));
              break;
            }
          }
          if (this._passThroughOptions) {
            dest.push(arg, ...args.slice(i));
            break;
          }
          dest.push(arg);
        }
        return { operands, unknown: unknown2 };
      }
      /**
       * Return an object containing local option values as key-value pairs.
       *
       * @return {object}
       */
      opts() {
        if (this._storeOptionsAsProperties) {
          let result = {}, len = this.options.length;
          for (let i = 0; i < len; i++) {
            let key = this.options[i].attributeName();
            result[key] = key === this._versionOptionName ? this._version : this[key];
          }
          return result;
        }
        return this._optionValues;
      }
      /**
       * Return an object containing merged local and global option values as key-value pairs.
       *
       * @return {object}
       */
      optsWithGlobals() {
        return this._getCommandAndAncestors().reduce(
          (combinedOptions, cmd) => Object.assign(combinedOptions, cmd.opts()),
          {}
        );
      }
      /**
       * Display error message and exit (or call exitOverride).
       *
       * @param {string} message
       * @param {object} [errorOptions]
       * @param {string} [errorOptions.code] - an id string representing the error
       * @param {number} [errorOptions.exitCode] - used with process.exit
       */
      error(message2, errorOptions) {
        this._outputConfiguration.outputError(
          `${message2}
`,
          this._outputConfiguration.writeErr
        ), typeof this._showHelpAfterError == "string" ? this._outputConfiguration.writeErr(`${this._showHelpAfterError}
`) : this._showHelpAfterError && (this._outputConfiguration.writeErr(`
`), this.outputHelp({ error: !0 }));
        let config = errorOptions || {}, exitCode = config.exitCode || 1, code = config.code || "commander.error";
        this._exit(exitCode, code, message2);
      }
      /**
       * Apply any option related environment variables, if option does
       * not have a value from cli or client code.
       *
       * @private
       */
      _parseOptionsEnv() {
        this.options.forEach((option) => {
          if (option.envVar && option.envVar in process2.env) {
            let optionKey = option.attributeName();
            (this.getOptionValue(optionKey) === void 0 || ["default", "config", "env"].includes(
              this.getOptionValueSource(optionKey)
            )) && (option.required || option.optional ? this.emit(`optionEnv:${option.name()}`, process2.env[option.envVar]) : this.emit(`optionEnv:${option.name()}`));
          }
        });
      }
      /**
       * Apply any implied option values, if option is undefined or default value.
       *
       * @private
       */
      _parseOptionsImplied() {
        let dualHelper = new DualOptions(this.options), hasCustomOptionValue = (optionKey) => this.getOptionValue(optionKey) !== void 0 && !["default", "implied"].includes(this.getOptionValueSource(optionKey));
        this.options.filter(
          (option) => option.implied !== void 0 && hasCustomOptionValue(option.attributeName()) && dualHelper.valueFromOption(
            this.getOptionValue(option.attributeName()),
            option
          )
        ).forEach((option) => {
          Object.keys(option.implied).filter((impliedKey) => !hasCustomOptionValue(impliedKey)).forEach((impliedKey) => {
            this.setOptionValueWithSource(
              impliedKey,
              option.implied[impliedKey],
              "implied"
            );
          });
        });
      }
      /**
       * Argument `name` is missing.
       *
       * @param {string} name
       * @private
       */
      missingArgument(name) {
        let message2 = `error: missing required argument '${name}'`;
        this.error(message2, { code: "commander.missingArgument" });
      }
      /**
       * `Option` is missing an argument.
       *
       * @param {Option} option
       * @private
       */
      optionMissingArgument(option) {
        let message2 = `error: option '${option.flags}' argument missing`;
        this.error(message2, { code: "commander.optionMissingArgument" });
      }
      /**
       * `Option` does not have a value, and is a mandatory option.
       *
       * @param {Option} option
       * @private
       */
      missingMandatoryOptionValue(option) {
        let message2 = `error: required option '${option.flags}' not specified`;
        this.error(message2, { code: "commander.missingMandatoryOptionValue" });
      }
      /**
       * `Option` conflicts with another option.
       *
       * @param {Option} option
       * @param {Option} conflictingOption
       * @private
       */
      _conflictingOption(option, conflictingOption) {
        let findBestOptionFromValue = (option2) => {
          let optionKey = option2.attributeName(), optionValue = this.getOptionValue(optionKey), negativeOption = this.options.find(
            (target) => target.negate && optionKey === target.attributeName()
          ), positiveOption = this.options.find(
            (target) => !target.negate && optionKey === target.attributeName()
          );
          return negativeOption && (negativeOption.presetArg === void 0 && optionValue === !1 || negativeOption.presetArg !== void 0 && optionValue === negativeOption.presetArg) ? negativeOption : positiveOption || option2;
        }, getErrorMessage = (option2) => {
          let bestOption = findBestOptionFromValue(option2), optionKey = bestOption.attributeName();
          return this.getOptionValueSource(optionKey) === "env" ? `environment variable '${bestOption.envVar}'` : `option '${bestOption.flags}'`;
        }, message2 = `error: ${getErrorMessage(option)} cannot be used with ${getErrorMessage(conflictingOption)}`;
        this.error(message2, { code: "commander.conflictingOption" });
      }
      /**
       * Unknown option `flag`.
       *
       * @param {string} flag
       * @private
       */
      unknownOption(flag) {
        if (this._allowUnknownOption) return;
        let suggestion = "";
        if (flag.startsWith("--") && this._showSuggestionAfterError) {
          let candidateFlags = [], command2 = this;
          do {
            let moreFlags = command2.createHelp().visibleOptions(command2).filter((option) => option.long).map((option) => option.long);
            candidateFlags = candidateFlags.concat(moreFlags), command2 = command2.parent;
          } while (command2 && !command2._enablePositionalOptions);
          suggestion = suggestSimilar(flag, candidateFlags);
        }
        let message2 = `error: unknown option '${flag}'${suggestion}`;
        this.error(message2, { code: "commander.unknownOption" });
      }
      /**
       * Excess arguments, more than expected.
       *
       * @param {string[]} receivedArgs
       * @private
       */
      _excessArguments(receivedArgs) {
        if (this._allowExcessArguments) return;
        let expected = this.registeredArguments.length, s = expected === 1 ? "" : "s", message2 = `error: too many arguments${this.parent ? ` for '${this.name()}'` : ""}. Expected ${expected} argument${s} but got ${receivedArgs.length}.`;
        this.error(message2, { code: "commander.excessArguments" });
      }
      /**
       * Unknown command.
       *
       * @private
       */
      unknownCommand() {
        let unknownName = this.args[0], suggestion = "";
        if (this._showSuggestionAfterError) {
          let candidateNames = [];
          this.createHelp().visibleCommands(this).forEach((command2) => {
            candidateNames.push(command2.name()), command2.alias() && candidateNames.push(command2.alias());
          }), suggestion = suggestSimilar(unknownName, candidateNames);
        }
        let message2 = `error: unknown command '${unknownName}'${suggestion}`;
        this.error(message2, { code: "commander.unknownCommand" });
      }
      /**
       * Get or set the program version.
       *
       * This method auto-registers the "-V, --version" option which will print the version number.
       *
       * You can optionally supply the flags and description to override the defaults.
       *
       * @param {string} [str]
       * @param {string} [flags]
       * @param {string} [description]
       * @return {(this | string | undefined)} `this` command for chaining, or version string if no arguments
       */
      version(str, flags, description) {
        if (str === void 0) return this._version;
        this._version = str, flags = flags || "-V, --version", description = description || "output the version number";
        let versionOption = this.createOption(flags, description);
        return this._versionOptionName = versionOption.attributeName(), this._registerOption(versionOption), this.on("option:" + versionOption.name(), () => {
          this._outputConfiguration.writeOut(`${str}
`), this._exit(0, "commander.version", str);
        }), this;
      }
      /**
       * Set the description.
       *
       * @param {string} [str]
       * @param {object} [argsDescription]
       * @return {(string|Command)}
       */
      description(str, argsDescription) {
        return str === void 0 && argsDescription === void 0 ? this._description : (this._description = str, argsDescription && (this._argsDescription = argsDescription), this);
      }
      /**
       * Set the summary. Used when listed as subcommand of parent.
       *
       * @param {string} [str]
       * @return {(string|Command)}
       */
      summary(str) {
        return str === void 0 ? this._summary : (this._summary = str, this);
      }
      /**
       * Set an alias for the command.
       *
       * You may call more than once to add multiple aliases. Only the first alias is shown in the auto-generated help.
       *
       * @param {string} [alias]
       * @return {(string|Command)}
       */
      alias(alias) {
        if (alias === void 0) return this._aliases[0];
        let command2 = this;
        if (this.commands.length !== 0 && this.commands[this.commands.length - 1]._executableHandler && (command2 = this.commands[this.commands.length - 1]), alias === command2._name)
          throw new Error("Command alias can't be the same as its name");
        let matchingCommand = this.parent?._findCommand(alias);
        if (matchingCommand) {
          let existingCmd = [matchingCommand.name()].concat(matchingCommand.aliases()).join("|");
          throw new Error(
            `cannot add alias '${alias}' to command '${this.name()}' as already have command '${existingCmd}'`
          );
        }
        return command2._aliases.push(alias), this;
      }
      /**
       * Set aliases for the command.
       *
       * Only the first alias is shown in the auto-generated help.
       *
       * @param {string[]} [aliases]
       * @return {(string[]|Command)}
       */
      aliases(aliases) {
        return aliases === void 0 ? this._aliases : (aliases.forEach((alias) => this.alias(alias)), this);
      }
      /**
       * Set / get the command usage `str`.
       *
       * @param {string} [str]
       * @return {(string|Command)}
       */
      usage(str) {
        if (str === void 0) {
          if (this._usage) return this._usage;
          let args = this.registeredArguments.map((arg) => humanReadableArgName(arg));
          return [].concat(
            this.options.length || this._helpOption !== null ? "[options]" : [],
            this.commands.length ? "[command]" : [],
            this.registeredArguments.length ? args : []
          ).join(" ");
        }
        return this._usage = str, this;
      }
      /**
       * Get or set the name of the command.
       *
       * @param {string} [str]
       * @return {(string|Command)}
       */
      name(str) {
        return str === void 0 ? this._name : (this._name = str, this);
      }
      /**
       * Set/get the help group heading for this subcommand in parent command's help.
       *
       * @param {string} [heading]
       * @return {Command | string}
       */
      helpGroup(heading) {
        return heading === void 0 ? this._helpGroupHeading ?? "" : (this._helpGroupHeading = heading, this);
      }
      /**
       * Set/get the default help group heading for subcommands added to this command.
       * (This does not override a group set directly on the subcommand using .helpGroup().)
       *
       * @example
       * program.commandsGroup('Development Commands:);
       * program.command('watch')...
       * program.command('lint')...
       * ...
       *
       * @param {string} [heading]
       * @returns {Command | string}
       */
      commandsGroup(heading) {
        return heading === void 0 ? this._defaultCommandGroup ?? "" : (this._defaultCommandGroup = heading, this);
      }
      /**
       * Set/get the default help group heading for options added to this command.
       * (This does not override a group set directly on the option using .helpGroup().)
       *
       * @example
       * program
       *   .optionsGroup('Development Options:')
       *   .option('-d, --debug', 'output extra debugging')
       *   .option('-p, --profile', 'output profiling information')
       *
       * @param {string} [heading]
       * @returns {Command | string}
       */
      optionsGroup(heading) {
        return heading === void 0 ? this._defaultOptionGroup ?? "" : (this._defaultOptionGroup = heading, this);
      }
      /**
       * @param {Option} option
       * @private
       */
      _initOptionGroup(option) {
        this._defaultOptionGroup && !option.helpGroupHeading && option.helpGroup(this._defaultOptionGroup);
      }
      /**
       * @param {Command} cmd
       * @private
       */
      _initCommandGroup(cmd) {
        this._defaultCommandGroup && !cmd.helpGroup() && cmd.helpGroup(this._defaultCommandGroup);
      }
      /**
       * Set the name of the command from script filename, such as process.argv[1],
       * or require.main.filename, or __filename.
       *
       * (Used internally and public although not documented in README.)
       *
       * @example
       * program.nameFromFilename(require.main.filename);
       *
       * @param {string} filename
       * @return {Command}
       */
      nameFromFilename(filename) {
        return this._name = path.basename(filename, path.extname(filename)), this;
      }
      /**
       * Get or set the directory for searching for executable subcommands of this command.
       *
       * @example
       * program.executableDir(__dirname);
       * // or
       * program.executableDir('subcommands');
       *
       * @param {string} [path]
       * @return {(string|null|Command)}
       */
      executableDir(path2) {
        return path2 === void 0 ? this._executableDir : (this._executableDir = path2, this);
      }
      /**
       * Return program help documentation.
       *
       * @param {{ error: boolean }} [contextOptions] - pass {error:true} to wrap for stderr instead of stdout
       * @return {string}
       */
      helpInformation(contextOptions) {
        let helper = this.createHelp(), context = this._getOutputContext(contextOptions);
        helper.prepareContext({
          error: context.error,
          helpWidth: context.helpWidth,
          outputHasColors: context.hasColors
        });
        let text = helper.formatHelp(this, helper);
        return context.hasColors ? text : this._outputConfiguration.stripColor(text);
      }
      /**
       * @typedef HelpContext
       * @type {object}
       * @property {boolean} error
       * @property {number} helpWidth
       * @property {boolean} hasColors
       * @property {function} write - includes stripColor if needed
       *
       * @returns {HelpContext}
       * @private
       */
      _getOutputContext(contextOptions) {
        contextOptions = contextOptions || {};
        let error = !!contextOptions.error, baseWrite, hasColors, helpWidth;
        return error ? (baseWrite = (str) => this._outputConfiguration.writeErr(str), hasColors = this._outputConfiguration.getErrHasColors(), helpWidth = this._outputConfiguration.getErrHelpWidth()) : (baseWrite = (str) => this._outputConfiguration.writeOut(str), hasColors = this._outputConfiguration.getOutHasColors(), helpWidth = this._outputConfiguration.getOutHelpWidth()), { error, write: (str) => (hasColors || (str = this._outputConfiguration.stripColor(str)), baseWrite(str)), hasColors, helpWidth };
      }
      /**
       * Output help information for this command.
       *
       * Outputs built-in help, and custom text added using `.addHelpText()`.
       *
       * @param {{ error: boolean } | Function} [contextOptions] - pass {error:true} to write to stderr instead of stdout
       */
      outputHelp(contextOptions) {
        let deprecatedCallback;
        typeof contextOptions == "function" && (deprecatedCallback = contextOptions, contextOptions = void 0);
        let outputContext = this._getOutputContext(contextOptions), eventContext = {
          error: outputContext.error,
          write: outputContext.write,
          command: this
        };
        this._getCommandAndAncestors().reverse().forEach((command2) => command2.emit("beforeAllHelp", eventContext)), this.emit("beforeHelp", eventContext);
        let helpInformation = this.helpInformation({ error: outputContext.error });
        if (deprecatedCallback && (helpInformation = deprecatedCallback(helpInformation), typeof helpInformation != "string" && !Buffer.isBuffer(helpInformation)))
          throw new Error("outputHelp callback must return a string or a Buffer");
        outputContext.write(helpInformation), this._getHelpOption()?.long && this.emit(this._getHelpOption().long), this.emit("afterHelp", eventContext), this._getCommandAndAncestors().forEach(
          (command2) => command2.emit("afterAllHelp", eventContext)
        );
      }
      /**
       * You can pass in flags and a description to customise the built-in help option.
       * Pass in false to disable the built-in help option.
       *
       * @example
       * program.helpOption('-?, --help' 'show help'); // customise
       * program.helpOption(false); // disable
       *
       * @param {(string | boolean)} flags
       * @param {string} [description]
       * @return {Command} `this` command for chaining
       */
      helpOption(flags, description) {
        return typeof flags == "boolean" ? (flags ? (this._helpOption === null && (this._helpOption = void 0), this._defaultOptionGroup && this._initOptionGroup(this._getHelpOption())) : this._helpOption = null, this) : (this._helpOption = this.createOption(
          flags ?? "-h, --help",
          description ?? "display help for command"
        ), (flags || description) && this._initOptionGroup(this._helpOption), this);
      }
      /**
       * Lazy create help option.
       * Returns null if has been disabled with .helpOption(false).
       *
       * @returns {(Option | null)} the help option
       * @package
       */
      _getHelpOption() {
        return this._helpOption === void 0 && this.helpOption(void 0, void 0), this._helpOption;
      }
      /**
       * Supply your own option to use for the built-in help option.
       * This is an alternative to using helpOption() to customise the flags and description etc.
       *
       * @param {Option} option
       * @return {Command} `this` command for chaining
       */
      addHelpOption(option) {
        return this._helpOption = option, this._initOptionGroup(option), this;
      }
      /**
       * Output help information and exit.
       *
       * Outputs built-in help, and custom text added using `.addHelpText()`.
       *
       * @param {{ error: boolean }} [contextOptions] - pass {error:true} to write to stderr instead of stdout
       */
      help(contextOptions) {
        this.outputHelp(contextOptions);
        let exitCode = Number(process2.exitCode ?? 0);
        exitCode === 0 && contextOptions && typeof contextOptions != "function" && contextOptions.error && (exitCode = 1), this._exit(exitCode, "commander.help", "(outputHelp)");
      }
      /**
       * // Do a little typing to coordinate emit and listener for the help text events.
       * @typedef HelpTextEventContext
       * @type {object}
       * @property {boolean} error
       * @property {Command} command
       * @property {function} write
       */
      /**
       * Add additional text to be displayed with the built-in help.
       *
       * Position is 'before' or 'after' to affect just this command,
       * and 'beforeAll' or 'afterAll' to affect this command and all its subcommands.
       *
       * @param {string} position - before or after built-in help
       * @param {(string | Function)} text - string to add, or a function returning a string
       * @return {Command} `this` command for chaining
       */
      addHelpText(position, text) {
        let allowedValues = ["beforeAll", "before", "after", "afterAll"];
        if (!allowedValues.includes(position))
          throw new Error(`Unexpected value for position to addHelpText.
Expecting one of '${allowedValues.join("', '")}'`);
        let helpEvent = `${position}Help`;
        return this.on(helpEvent, (context) => {
          let helpStr;
          typeof text == "function" ? helpStr = text({ error: context.error, command: context.command }) : helpStr = text, helpStr && context.write(`${helpStr}
`);
        }), this;
      }
      /**
       * Output help information if help flags specified
       *
       * @param {Array} args - array of options to search for help flags
       * @private
       */
      _outputHelpIfRequested(args) {
        let helpOption = this._getHelpOption();
        helpOption && args.find((arg) => helpOption.is(arg)) && (this.outputHelp(), this._exit(0, "commander.helpDisplayed", "(outputHelp)"));
      }
    };
    function incrementNodeInspectorPort(args) {
      return args.map((arg) => {
        if (!arg.startsWith("--inspect"))
          return arg;
        let debugOption, debugHost = "127.0.0.1", debugPort = "9229", match;
        return (match = arg.match(/^(--inspect(-brk)?)$/)) !== null ? debugOption = match[1] : (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+)$/)) !== null ? (debugOption = match[1], /^\d+$/.test(match[3]) ? debugPort = match[3] : debugHost = match[3]) : (match = arg.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/)) !== null && (debugOption = match[1], debugHost = match[3], debugPort = match[4]), debugOption && debugPort !== "0" ? `${debugOption}=${debugHost}:${parseInt(debugPort) + 1}` : arg;
      });
    }
    function useColor() {
      if (process2.env.NO_COLOR || process2.env.FORCE_COLOR === "0" || process2.env.FORCE_COLOR === "false")
        return !1;
      if (process2.env.FORCE_COLOR || process2.env.CLICOLOR_FORCE !== void 0)
        return !0;
    }
    exports.Command = Command2;
    exports.useColor = useColor;
  }
});

// ../../node_modules/commander/index.js
var require_commander = __commonJS({
  "../../node_modules/commander/index.js"(exports) {
    var { Argument: Argument2 } = require_argument(), { Command: Command2 } = require_command(), { CommanderError: CommanderError2, InvalidArgumentError: InvalidArgumentError2 } = require_error(), { Help: Help2 } = require_help(), { Option: Option2 } = require_option();
    exports.program = new Command2();
    exports.createCommand = (name) => new Command2(name);
    exports.createOption = (flags, description) => new Option2(flags, description);
    exports.createArgument = (name, description) => new Argument2(name, description);
    exports.Command = Command2;
    exports.Option = Option2;
    exports.Argument = Argument2;
    exports.Help = Help2;
    exports.CommanderError = CommanderError2;
    exports.InvalidArgumentError = InvalidArgumentError2;
    exports.InvalidOptionArgumentError = InvalidArgumentError2;
  }
});

// src/bin/core.ts
import {
  HandledError as HandledError2,
  PackageManagerName,
  getEnvConfig,
  optionalEnvToBoolean as optionalEnvToBoolean2,
  parseList
} from "storybook/internal/common";
import { logTracker, logger as logger5 } from "storybook/internal/node-logger";
import { addToGlobalContext } from "storybook/internal/telemetry";

// ../../node_modules/commander/esm.mjs
var import_index = __toESM(require_commander(), 1), {
  program,
  createCommand,
  createArgument,
  createOption,
  CommanderError,
  InvalidArgumentError,
  InvalidOptionArgumentError,
  // deprecated old name
  Command,
  Argument,
  Option,
  Help
} = import_index.default;

// ../../node_modules/leven/index.js
var array2 = [], characterCodeCache = [];
function leven(first, second, options) {
  if (first === second)
    return 0;
  let maxDistance = options?.maxDistance, swap = first;
  first.length > second.length && (first = second, second = swap);
  let firstLength = first.length, secondLength = second.length;
  for (; firstLength > 0 && first.charCodeAt(~-firstLength) === second.charCodeAt(~-secondLength); )
    firstLength--, secondLength--;
  let start = 0;
  for (; start < firstLength && first.charCodeAt(start) === second.charCodeAt(start); )
    start++;
  if (firstLength -= start, secondLength -= start, maxDistance !== void 0 && secondLength - firstLength > maxDistance)
    return maxDistance;
  if (firstLength === 0)
    return maxDistance !== void 0 && secondLength > maxDistance ? maxDistance : secondLength;
  let bCharacterCode, result, temporary, temporary2, index = 0, index2 = 0;
  for (; index < firstLength; )
    characterCodeCache[index] = first.charCodeAt(start + index), array2[index] = ++index;
  for (; index2 < secondLength; ) {
    for (bCharacterCode = second.charCodeAt(start + index2), temporary = index2++, result = index2, index = 0; index < firstLength; index++)
      temporary2 = bCharacterCode === characterCodeCache[index] ? temporary : temporary + 1, temporary = array2[index], result = array2[index] = temporary > result ? temporary2 > result ? result + 1 : temporary2 : temporary2 > temporary ? temporary + 1 : temporary2;
    if (maxDistance !== void 0) {
      let rowMinimum = result;
      for (index = 0; index < firstLength; index++)
        array2[index] < rowMinimum && (rowMinimum = array2[index]);
      if (rowMinimum > maxDistance)
        return maxDistance;
    }
  }
  return array2.length = firstLength, characterCodeCache.length = firstLength, maxDistance !== void 0 && result > maxDistance ? maxDistance : result;
}

// src/bin/core.ts
var import_picocolors = __toESM(require_picocolors(), 1);

// src/cli/ai/index.ts
import { writeFile } from "node:fs/promises";
import { resolve } from "node:path";
import { cache as cache2 } from "storybook/internal/common";
import { logger } from "storybook/internal/node-logger";
import { telemetry } from "storybook/internal/telemetry";

// src/cli/skills/content/setup-prompts/index.ts
var import_ts_dedent = __toESM(require_dist(), 1);

// src/cli/skills/content/setup-utils/project-overview.ts
function getProjectOverview(projectInfo) {
  let rows = [
    ["Version", projectInfo.storybookVersion || "unknown"],
    ["Renderer", projectInfo.rendererPackage || "unknown"],
    ["Framework", projectInfo.framework || "unknown"],
    ["Builder", projectInfo.builderPackage || "unknown"],
    ["Config Dir", `\`${projectInfo.configDir}\``],
    ["Language", projectInfo.language === "ts" ? "TypeScript" : "JavaScript"]
  ];
  return projectInfo.packageManager && rows.push(["Package Manager", projectInfo.packageManagerName || "unknown"]), rows.push(["Addons", projectInfo.addons.length > 0 ? projectInfo.addons.join(", ") : "none"]), ["## Project Info", "", "| Property | Value |", "|----------|-------|", rows.map(([key, value]) => `| ${key} | ${value} |`).join(`
`)].join(
    `
`
  );
}

// src/cli/skills/content/setup-prompts/index.ts
var DEFAULT_PROMPT_NAME = "optimized-tests", CURRENTLY_USED_PROMPT = {
  [DEFAULT_PROMPT_NAME]: instructions
}, FORMERLY_USED_PROMPTS = {
  monorepo: async () => (await import("../_node-chunks/monorepo-KBAWAMFF.js")).instructions,
  "optimized-tests": async () => (await import("../_node-chunks/optimized-tests-XOQZOPAA.js")).instructions,
  "relaxed-limits": async () => (await import("../_node-chunks/relaxed-limits-WE3GWBOO.js")).instructions,
  setup: async () => (await import("../_node-chunks/setup-ODZF2RFR.js")).instructions,
  "pattern-copy-play": async () => (await import("../_node-chunks/pattern-copy-play-WEHXTRPC.js")).instructions,
  "monorepo-optimized-tests-relaxed-limits-no-story-deletion": async () => (await import("../_node-chunks/monorepo-optimized-tests-relaxed-limits-no-story-deletion-7TDELDWK.js")).instructions
}, PROMPT_NAMES = [
  ...Object.keys(CURRENTLY_USED_PROMPT),
  ...Object.keys(FORMERLY_USED_PROMPTS)
], EVAL_SETUP_PROMPT_ENV = "EVAL_SETUP_PROMPT";
function resolvePromptName() {
  let requested = process.env[EVAL_SETUP_PROMPT_ENV]?.trim();
  return requested && (Object.hasOwn(CURRENTLY_USED_PROMPT, requested) || Object.hasOwn(FORMERLY_USED_PROMPTS, requested)) ? requested : DEFAULT_PROMPT_NAME;
}
async function getSetupPrompt(projectInfo) {
  let name = resolvePromptName();
  return { content: (CURRENTLY_USED_PROMPT[name] ?? await FORMERLY_USED_PROMPTS[name]())(projectInfo), name };
}
async function getSetupMarkdownOutput(projectInfo) {
  let { content, name } = await getSetupPrompt(projectInfo);
  return {
    markdown: import_ts_dedent.dedent`
    # Storybook Setup

    ${getProjectOverview(projectInfo)}

    ${content}
  `,
    prompt: name
  };
}

// src/cli/skills/project-info.ts
import { cache, getPrettyPackageManagerName } from "storybook/internal/common";
import { SupportedLanguage } from "storybook/internal/types";
function parseMajorVersion(version2) {
  let match = version2.match(/^(\d+)/);
  return match ? parseInt(match[1], 10) : void 0;
}
async function getProjectInfo(opts) {
  try {
    let data = await getStorybookData({
      configDir: opts.configDir,
      packageManagerName: opts.packageManager
    });
    if (!data.frameworkPackage || !data.rendererPackage || !data.builderPackage)
      return {
        ok: !1,
        message: "Could not detect framework, renderer, or builder from your Storybook config. Make sure you are running this command from your project root, or specify --config-dir."
      };
    let majorVersion = data.versionInstalled ? parseMajorVersion(data.versionInstalled) : void 0, language = await detectLanguage(data.packageManager, data.workingDir) === SupportedLanguage.TYPESCRIPT ? "ts" : "js", needsUserOnboarding = await cache.get("onboarding-pending", !1);
    return { ok: !0, projectInfo: {
      storybookVersion: data.versionInstalled,
      majorVersion,
      framework: data.frameworkPackage,
      rendererPackage: data.rendererPackage,
      renderer: data.renderer,
      builderPackage: data.builderPackage,
      addons: data.addons ?? [],
      configDir: data.configDir,
      storiesPaths: data.storiesPaths,
      packageManager: data.packageManager,
      packageManagerName: getPrettyPackageManagerName(data.packageManager.type),
      language,
      hasCsfFactoryPreview: data.hasCsfFactoryPreview,
      needsUserOnboarding,
      monorepoType: getMonorepoType()
    } };
  } catch (err) {
    return {
      ok: !1,
      message: `Failed to read Storybook configuration: ${err instanceof Error ? err.message : String(err)}
Make sure you are running this command from your project root, or specify --config-dir.`
    };
  }
}

// src/cli/ai/index.ts
async function aiSetup(options) {
  let { configDir: userConfigDir, packageManager, output } = options;
  process.stderr.write(
    "`storybook ai setup` is deprecated and will be removed in a future release. Use `npx storybook skills setup` instead.\n"
  );
  let result = await getProjectInfo({
    configDir: userConfigDir,
    packageManager
  });
  if (!result.ok) {
    let [firstLine, ...rest] = result.message.split(`
`);
    logger.error(firstLine), rest.length > 0 && logger.log(rest.join(`
`));
    return;
  }
  let { projectInfo } = result;
  if (projectInfo.rendererPackage !== "@storybook/react" || projectInfo.builderPackage !== "@storybook/builder-vite") {
    logger.log(
      "AI-assisted setup is currently only available for projects using the React renderer with Vite builder. Detected renderer: " + projectInfo.rendererPackage + ", builder: " + projectInfo.builderPackage
    );
    return;
  }
  let { markdown: markdownOutput, prompt } = await getSetupMarkdownOutput(projectInfo);
  if (await cache2.set("ai-setup-ran", {
    timestamp: Date.now(),
    runId: options.runId,
    configDir: resolve(projectInfo.configDir)
  }).catch(() => {
  }), await telemetry("ai-setup", {
    cliOptions: {
      output: output ? "file" : void 0,
      configDir: projectInfo.configDir,
      packageManager: projectInfo.packageManager.type,
      prompt
    },
    project: {
      framework: projectInfo.framework,
      renderer: projectInfo.rendererPackage,
      builder: projectInfo.builderPackage,
      language: projectInfo.language
    },
    runId: options.runId
  }), output) {
    let outputPath = resolve(output);
    await writeFile(outputPath, markdownOutput, "utf-8"), logger.log(`Prompt written to ${outputPath}`);
  } else
    process.stdout.write(`${markdownOutput}
`);
}

// src/cli/ai/mcp/register.ts
import { writeFile as writeFile2 } from "node:fs/promises";
import { resolve as resolve3 } from "node:path";
import { optionalEnvToBoolean } from "storybook/internal/common";
import { sendTelemetryError, withTelemetry as withTelemetry2 } from "storybook/internal/core-server";
import { logger as logger2 } from "storybook/internal/node-logger";
import { telemetry as telemetry2 } from "storybook/internal/telemetry";

// src/cli/ai/mcp/run-tool.ts
import { resolve as resolve2 } from "node:path";

// src/cli/tools/mcp-client.ts
import { versions } from "storybook/internal/common";
var ToolResultContentItemSchema = looseObject({
  type: string(),
  text: optional(string())
}), ToolCallResultSchema = looseObject({
  content: optional(array(ToolResultContentItemSchema)),
  /** The JSON matching the tool's published `outputSchema`, when it declares one. */
  structuredContent: optional(record(string(), unknown())),
  isError: optional(boolean())
}), McpToolDescriptorSchema = looseObject({
  name: string(),
  description: optional(string()),
  inputSchema: optional(
    looseObject({
      properties: optional(
        record(
          string(),
          looseObject({
            type: optional(string()),
            description: optional(string())
          })
        )
      ),
      required: optional(array(string()))
    })
  )
}), STORYBOOK_MCP_PROXY_HEADER = "X-Storybook-MCP-Proxy", STORYBOOK_MCP_PROXY_HEADER_VALUE = "true", REQUEST_TIMEOUT_MS = 600 * 1e3, MCP_CLIENT_INFO = { name: "storybook-cli", version: versions.storybook }, MCP_PROTOCOL_VERSION = "2025-06-18";
function resolveMcpEndpointUrl(baseUrl, endpoint) {
  let base = new URL(baseUrl), basePath = base.pathname.replace(/\/+$/, ""), endpointPath = endpoint.startsWith("/") ? endpoint : `/${endpoint}`;
  return base.pathname = `${basePath}${endpointPath}`.replace(/\/{2,}/g, "/") || "/", base.href;
}
var McpJsonRpcError = class extends Error {
  constructor(code, message2) {
    super(`Storybook server error ${code}: ${message2}`);
    this.code = code;
    this.name = "McpJsonRpcError";
  }
}, JsonRpcEnvelopeSchema = looseObject({
  result: optional(unknown()),
  error: optional(looseObject({ code: number(), message: string() }))
}), ToolListResultSchema = looseObject({
  tools: optional(array(McpToolDescriptorSchema))
});
async function callMcpTool(record2, params, fetchImpl = fetch) {
  let { result } = await sendJsonRpcRequest(
    record2,
    "tools/call",
    params,
    ToolCallResultSchema,
    fetchImpl
  );
  return result;
}
async function listMcpTools(record2, fetchImpl = fetch) {
  let { result } = await sendJsonRpcRequest(
    record2,
    "tools/list",
    {},
    ToolListResultSchema,
    fetchImpl
  );
  return result.tools ?? [];
}
var REQUEST_HEADERS = {
  "Content-Type": "application/json",
  Accept: "application/json, text/event-stream",
  [STORYBOOK_MCP_PROXY_HEADER]: STORYBOOK_MCP_PROXY_HEADER_VALUE
};
async function initializeMcpSession(target, fetchImpl) {
  try {
    let response = await fetchImpl(target, {
      method: "POST",
      headers: REQUEST_HEADERS,
      body: JSON.stringify({
        jsonrpc: "2.0",
        id: crypto.randomUUID(),
        method: "initialize",
        params: {
          protocolVersion: MCP_PROTOCOL_VERSION,
          capabilities: {},
          clientInfo: MCP_CLIENT_INFO
        }
      }),
      signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
    }), sessionId = response.headers.get("mcp-session-id");
    if (!response.ok)
      return await response.body?.cancel(), null;
    try {
      await response.text();
    } catch {
    }
    return sessionId;
  } catch {
    return null;
  }
}
async function sendJsonRpcRequest(record2, method, params, resultSchema, fetchImpl) {
  let endpoint = record2.mcp.endpoint;
  if (!endpoint)
    throw new Error(`The Storybook instance at ${record2.cwd} has no server endpoint registered`);
  let target = resolveMcpEndpointUrl(record2.url, endpoint), sessionId = await initializeMcpSession(target, fetchImpl), response = await fetchImpl(target, {
    method: "POST",
    headers: {
      ...REQUEST_HEADERS,
      ...sessionId ? { "Mcp-Session-Id": sessionId } : {}
    },
    body: JSON.stringify({
      jsonrpc: "2.0",
      id: crypto.randomUUID(),
      method,
      params
    }),
    signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
  });
  if (!response.ok)
    throw new Error(
      `The Storybook server at ${target} responded with ${response.status} ${response.statusText}`
    );
  let payload = await readJsonRpcResponse(response, target), unwrapped = unwrapJsonRpcResult(payload, target);
  if (!unwrapped.ok)
    throw unwrapped.error;
  let result = safeParse(resultSchema, unwrapped.result);
  if (!result.success)
    throw unexpectedShapeError(target);
  return { result: result.output };
}
function unexpectedShapeError(target) {
  return new Error(`The Storybook server at ${target} returned an unexpected response shape`);
}
function unwrapJsonRpcResult(payload, target) {
  let envelope = safeParse(JsonRpcEnvelopeSchema, payload);
  return envelope.success ? envelope.output.error ? {
    ok: !1,
    error: new McpJsonRpcError(envelope.output.error.code, envelope.output.error.message)
  } : envelope.output.result === void 0 ? { ok: !1, error: new Error("The Storybook server returned no result") } : { ok: !0, result: envelope.output.result } : { ok: !1, error: unexpectedShapeError(target) };
}
async function readJsonRpcResponse(response, endpoint) {
  let contentType = (response.headers.get("content-type") ?? "").toLowerCase(), body = await response.text();
  if (contentType.includes("application/json"))
    return JSON.parse(body);
  if (contentType.includes("text/event-stream"))
    return parseSseEnvelope(body, endpoint);
  throw new Error(
    `The Storybook server at ${endpoint} returned unsupported content-type "${contentType}". Expected application/json or text/event-stream.`
  );
}
function parseSseEnvelope(body, endpoint) {
  let dataLines = [];
  for (let rawLine of body.split(`
`)) {
    let line = rawLine.replace(/\r$/, "");
    if (line.startsWith("data:")) {
      let value = line.slice(5);
      dataLines.push(value.startsWith(" ") ? value.slice(1) : value);
      continue;
    }
    if (line === "" && dataLines.length > 0)
      break;
  }
  if (dataLines.length === 0)
    throw new Error(
      `The Storybook server at ${endpoint} returned an SSE response with no data event`
    );
  try {
    return JSON.parse(dataLines.join(`
`));
  } catch (error) {
    throw new Error(
      `The Storybook server at ${endpoint} returned an SSE event whose data could not be parsed as JSON: ${error instanceof Error ? error.message : String(error)}`
    );
  }
}

// src/cli/tools/schema-lines.ts
var JsonSchemaNodeSchema = lazy(
  () => looseObject({
    type: optional(string()),
    description: optional(string()),
    properties: optional(record(string(), JsonSchemaNodeSchema)),
    required: optional(array(string())),
    items: optional(union([JsonSchemaNodeSchema, array(JsonSchemaNodeSchema)])),
    anyOf: optional(array(JsonSchemaNodeSchema)),
    oneOf: optional(array(JsonSchemaNodeSchema))
  })
), MAX_SCHEMA_DEPTH = 4;
function schemaItem(schema) {
  return Array.isArray(schema.items) ? schema.items[0] : schema.items;
}
function schemaTypeLabel(schema) {
  if (schema.type === "array") {
    let item = schemaItem(schema);
    return item?.type ? `array of ${item.type}` : "array";
  }
  return schema.anyOf || schema.oneOf ? "one of" : schema.type;
}
function schemaChildLines(schema, indent, depth) {
  if (depth <= 0)
    return [];
  let lines = [];
  if (schema.type === "object" && schema.properties) {
    let required = new Set(schema.required ?? []);
    for (let [name, child] of Object.entries(schema.properties))
      lines.push(...schemaLines(`\`${name}\``, child, required.has(name), indent, depth));
  }
  let item = schemaItem(schema);
  item && (item.type === "object" && item.properties || item.anyOf || item.oneOf) && (lines.push(`${indent}each item:`), lines.push(...schemaChildLines(item, `${indent}  `, depth - 1)));
  let variants = schema.anyOf ?? schema.oneOf;
  return variants && variants.forEach((variant, index) => {
    let suffix = variant.description ? `: ${variant.description}` : "";
    lines.push(`${indent}option ${index + 1}${suffix}`), lines.push(...schemaChildLines(variant, `${indent}  `, depth - 1));
  }), lines;
}
function schemaLines(label, schema, isRequired, indent, depth) {
  let meta = [schemaTypeLabel(schema), isRequired ? "required" : void 0].filter(Boolean).join(", "), description = schema.description ? `: ${schema.description}` : "";
  return [`${indent}- ${label}${meta ? ` (${meta})` : ""}${description}`, ...schemaChildLines(schema, `${indent}  `, depth - 1)];
}

// src/cli/tools/tool-tokens.ts
function parseToolsTokens(tokens, defaults = {}) {
  let rawInput = defaults.input, help = defaults.help ?? !1, json = defaults.json ?? !1, output = defaults.output, attach = defaults.attach, flagArgs = {}, i = 0;
  for (; i < tokens.length; ) {
    let token = tokens[i];
    if (i += 1, token === "--help" || token === "-h") {
      help = !0;
      continue;
    }
    if (token === "--json") {
      json = !0;
      continue;
    }
    if (token === "--attach") {
      if (attach === !1)
        return { ok: !1, error: "Cannot combine `--attach` and `--no-attach`." };
      attach = !0;
      continue;
    }
    if (token === "--no-attach") {
      if (attach === !0)
        return { ok: !1, error: "Cannot combine `--attach` and `--no-attach`." };
      attach = !1;
      continue;
    }
    if (token === "-o") {
      if (i >= tokens.length || tokens[i].startsWith("-"))
        return { ok: !1, error: "`-o` requires a file path." };
      output = tokens[i], i += 1;
      continue;
    }
    if (!token.startsWith("--") || token === "--")
      return {
        ok: !1,
        error: `Unexpected argument \`${token}\`. Tool arguments must be passed as \`--key value\` flags (or via \`--input '<object>'\`).`
      };
    let key = token.slice(2), value, equalsIndex = key.indexOf("=");
    if (equalsIndex !== -1 ? (value = key.slice(equalsIndex + 1), key = key.slice(0, equalsIndex)) : i < tokens.length && !tokens[i].startsWith("--") && (value = tokens[i], i += 1), key === "")
      return { ok: !1, error: `Invalid flag \`${token}\`.` };
    if (key === "help" || key === "json" || key === "attach" || key === "no-attach")
      return { ok: !1, error: `\`--${key}\` does not take a value.` };
    if (key === "output") {
      if (!value)
        return { ok: !1, error: "`--output` requires a file path." };
      output = value;
      continue;
    }
    if (key === "input") {
      if (value === void 0)
        return { ok: !1, error: "`--input` requires a value." };
      rawInput = value;
      continue;
    }
    flagArgs[key] = value === void 0 ? !0 : coerceValue(value);
  }
  let inputArgs = {};
  if (rawInput !== void 0) {
    let parsed;
    try {
      parsed = JSON.parse(rawInput);
    } catch (error) {
      return {
        ok: !1,
        error: `\`--input\` must be valid JSON: ${error instanceof Error ? error.message : String(error)}`
      };
    }
    if (typeof parsed != "object" || parsed === null || Array.isArray(parsed))
      return {
        ok: !1,
        error: '`--input` must be a JSON object, e.g. \'{"id": "button-docs"}\'.'
      };
    inputArgs = parsed;
  }
  return { ok: !0, help, json, output, attach, args: { ...inputArgs, ...flagArgs } };
}
function isJsonToolsRun(tokens, defaults = {}) {
  let parsed = parseToolsTokens(tokens, defaults);
  return parsed.ok && parsed.json && !parsed.help;
}
function coerceValue(raw) {
  try {
    return JSON.parse(raw);
  } catch {
    return raw;
  }
}
function parsePort(rawPort) {
  if (rawPort === void 0)
    return { ok: !0, port: void 0 };
  let port = Number(rawPort);
  return !Number.isInteger(port) || port < 1 || port > 65535 ? {
    ok: !1,
    error: `\`--port\` must be a port number (1-65535), got \`${rawPort}\`.`
  } : { ok: !0, port };
}
var TOOLS_OPTION_SPECS = [
  { flags: "--cwd <path>", description: "Project directory of the target Storybook" },
  {
    flags: "-c, --config-dir <dir-name>",
    description: "Storybook config directory of the target Storybook"
  },
  {
    flags: "-p, --port <number>",
    description: "Port of a running Storybook; targets that instance directly, no --cwd or --config-dir needed"
  },
  {
    flags: "--attach",
    description: "Require attaching to a running Storybook; gate failures are errors instead of a local fallback"
  },
  {
    flags: "--no-attach",
    description: "Load the project configuration without attaching"
  },
  {
    flags: "--input <object>",
    description: "Raw JSON object with the tool arguments (escape hatch for complex values)"
  },
  {
    flags: "--json",
    description: "Print the tool's structured result data as JSON instead of markdown"
  },
  { flags: "-o, --output <path>", description: "Write the result to a file instead of stdout" },
  {
    flags: "-h, --help",
    description: "Show every tool of the target Storybook, or one tool with its arguments"
  }
];

// src/cli/ai/mcp/intercepts.ts
var NO_INSTANCE_EMPTY = "Storybook is not running at this cwd. Start `storybook dev` from the project's cwd and retry the command.", quotePath = (path) => /\s/.test(path) ? `"${path}"` : path, buildNoInstanceWithCandidates = (records) => {
  let instances = records.map((r) => {
    let configDir = r.configDir ? `, config dir \`${r.configDir}\`` : "";
    return `- cwd \`${r.cwd}\`${configDir} (${r.url})`;
  }), examples = [
    ...new Set(
      records.map(
        (r) => r.configDir ? `- \`storybook ai --config-dir ${quotePath(r.configDir)} <command> [args...]\`` : `- \`storybook ai --cwd ${quotePath(r.cwd)} <command> [args...]\``
      )
    )
  ];
  return `No running Storybook matches this project (neither its cwd nor its Storybook config dir). Either start \`storybook dev\` from this project, or retry with \`--cwd\` or \`--config-dir\` pointing at one of the running Storybooks below. Both flags must be placed BEFORE the command name.

Running Storybooks:
${instances.join(`
`)}

Retry examples (replace \`<command>\` with the command you ran):
${examples.join(`
`)}`;
}, buildPortMismatch = (port, records) => `No running Storybook is on port \`${port ?? "unknown"}\`. Retry with one of the running ports below, or omit \`--port\` to route by project (cwd/config dir).

Running Storybooks:
${records.map((r) => `- port \`${r.port}\` (${r.url}, status: \`${r.mcp.status}\`)`).join(`
`)}`, ADDON_MISSING = "Storybook is running but does not provide these commands. The `@storybook/addon-mcp` addon is missing.\n\nInstall it:\n```\nnpx storybook add @storybook/addon-mcp\n```\n\nRestart Storybook, then retry the command.", MCP_STARTING = "Storybook is running but its command server is still starting up. Wait a moment and retry the command.", MCP_ERROR = "Storybook is running but its command server reported an error. Inspect the Storybook terminal output, fix the underlying issue, then retry the command.";
function getInterceptMarkdown(reason, extras = {}) {
  let { records, port } = extras;
  switch (reason) {
    case "no-instance":
      return records && records.length > 0 ? buildNoInstanceWithCandidates(records) : NO_INSTANCE_EMPTY;
    case "port-mismatch":
      return buildPortMismatch(port, records ?? []);
    case "addon-missing":
      return ADDON_MISSING;
    case "mcp-starting":
      return MCP_STARTING;
    case "mcp-error":
      return MCP_ERROR;
    default: {
      let unhandled = reason;
      throw new Error(`Unhandled intercept reason: ${unhandled}`);
    }
  }
}

// src/cli/ai/mcp/local-metadata.ts
import { experimental_loadStorybook as loadStorybook } from "storybook/internal/core-server";
var STORYBOOK_AI_METADATA_PRESET = "experimental_storybookAi", StorybookAiMetadataError = class extends Error {
  constructor(message2) {
    super(message2), this.name = "StorybookAiMetadataError";
  }
};
async function loadStorybookAiMetadata(options = {}) {
  let configDir = resolveStorybookConfigDir(options), metadata = await (await loadStorybook({ configDir })).presets.apply(STORYBOOK_AI_METADATA_PRESET, void 0);
  return normalizeStorybookAiMetadata(metadata);
}
function normalizeStorybookAiMetadata(metadata) {
  if (!metadata || typeof metadata != "object")
    return;
  let rawMetadata = metadata, tools = normalizeTools(rawMetadata.tools);
  return {
    instructions: typeof rawMetadata.instructions == "string" ? rawMetadata.instructions : void 0,
    tools,
    localTools: normalizeLocalTools(rawMetadata.localTools, tools)
  };
}
function normalizeTools(metadata) {
  if (metadata === void 0)
    return [];
  if (!Array.isArray(metadata))
    throw new StorybookAiMetadataError("Storybook AI metadata must expose `tools` as an array");
  return metadata.map((tool) => {
    let result = safeParse(McpToolDescriptorSchema, tool);
    if (!result.success)
      throw new StorybookAiMetadataError(
        "Storybook AI metadata contains an invalid tool descriptor"
      );
    return result.output;
  });
}
function normalizeLocalTools(metadata, tools) {
  if (!metadata || typeof metadata != "object")
    return;
  let visibleToolNames = new Set(tools.map((tool) => tool.name)), entries = Object.entries(metadata).flatMap(([name, tool]) => {
    if (!visibleToolNames.has(name))
      return [];
    if (!tool || typeof tool != "object")
      throw new StorybookAiMetadataError(
        `Storybook AI metadata contains an invalid local tool for \`${name}\``
      );
    let call = tool.call;
    if (typeof call != "function")
      throw new StorybookAiMetadataError(
        `Storybook AI metadata contains an invalid local tool for \`${name}\``
      );
    return [
      [
        name,
        {
          call
        }
      ]
    ];
  });
  return entries.length > 0 ? Object.fromEntries(entries) : void 0;
}

// src/cli/ai/mcp/tool-args.ts
function parseToolArgs(tokens, defaults = {}) {
  let rawJson = defaults.json, help = !1, flagArgs = {}, i = 0;
  for (; i < tokens.length; ) {
    let token = tokens[i];
    if (i += 1, token === "--help" || token === "-h") {
      help = !0;
      continue;
    }
    if (!token.startsWith("--") || token === "--")
      return {
        ok: !1,
        error: `Unexpected argument \`${token}\`. Command arguments must be passed as \`--key value\` flags (or via \`--json '<object>'\`).`
      };
    let key = token.slice(2), value, equalsIndex = key.indexOf("=");
    if (equalsIndex !== -1 ? (value = key.slice(equalsIndex + 1), key = key.slice(0, equalsIndex)) : i < tokens.length && !tokens[i].startsWith("--") && (value = tokens[i], i += 1), key === "")
      return { ok: !1, error: `Invalid flag \`${token}\`.` };
    if (key === "json") {
      if (value === void 0)
        return { ok: !1, error: "`--json` requires a value." };
      rawJson = value;
      continue;
    }
    flagArgs[key] = value === void 0 ? !0 : coerceValue2(value);
  }
  let jsonArgs = {};
  if (rawJson !== void 0) {
    let parsed;
    try {
      parsed = JSON.parse(rawJson);
    } catch (error) {
      return {
        ok: !1,
        error: `\`--json\` must be valid JSON: ${error instanceof Error ? error.message : String(error)}`
      };
    }
    if (typeof parsed != "object" || parsed === null || Array.isArray(parsed))
      return {
        ok: !1,
        error: '`--json` must be a JSON object, e.g. \'{"id": "button-docs"}\'.'
      };
    jsonArgs = parsed;
  }
  return { ok: !0, help, args: { ...jsonArgs, ...flagArgs } };
}
function coerceValue2(raw) {
  try {
    return JSON.parse(raw);
  } catch {
    return raw;
  }
}

// src/cli/ai/mcp/run-tool.ts
var McpToolResultError = class extends Error {
  constructor(options) {
    super("The Storybook AI command returned an error result", options), this.name = "McpToolResultError";
  }
}, LocalAiToolError = class extends Error {
  constructor(options) {
    super("The Storybook local AI command failed", options), this.name = "LocalAiToolError";
  }
};
async function runAiTool(toolName, toolArgTokens, options = {}, deps = {}) {
  let parsed = parseToolArgs(toolArgTokens, {
    json: options.json
  });
  if (!parsed.ok)
    return {
      exitCode: 1,
      output: parsed.error,
      outcome: { kind: "intercept", reason: "invalid-arguments" }
    };
  if (parsed.help)
    return toolHelp(toolName, options.cwd, options.configDir, deps);
  let toolLookup = await lookupAiTool(toolName, options.cwd, options.configDir, deps);
  switch (toolLookup.kind) {
    case "local":
      return runLocalAiTool(toolLookup.localTool, parsed.args);
    case "result":
      return toolLookup.result;
    case "runtime":
      break;
    default:
      return toolLookup;
  }
  let parsedPort = parsePort(options.port);
  if (!parsedPort.ok)
    return {
      exitCode: 1,
      output: parsedPort.error,
      outcome: { kind: "intercept", reason: "invalid-arguments" }
    };
  let resolution = await resolveReadyInstance(
    { cwd: options.cwd, configDir: options.configDir, port: parsedPort.port },
    deps
  );
  if (resolution.kind === "error")
    return {
      exitCode: 1,
      output: resolution.output,
      outcome: { kind: "intercept", reason: resolution.reason }
    };
  let { record: record2, matches } = resolution;
  try {
    let result = await callMcpTool(
      record2,
      { name: toolName, arguments: parsed.args },
      deps.fetchImpl
    );
    if (result.isError) {
      let unknownTool = await describeUnknownTool(record2, toolName, deps.fetchImpl);
      if (unknownTool)
        return {
          exitCode: 1,
          output: unknownTool,
          outcome: { kind: "intercept", reason: "unknown-command" }
        };
    }
    let siblings = matches.filter((r) => r !== record2), toolOutput = formatToolResult(result), output = [
      ...siblings.length > 0 ? [formatMultiInstanceWarning(record2, siblings)] : [],
      toolOutput
    ].join(`

`);
    return result.isError ? {
      exitCode: 1,
      output,
      outcome: { kind: "error", error: new McpToolResultError({ cause: toolOutput }) }
    } : { exitCode: 0, output, outcome: { kind: "success" } };
  } catch (error) {
    if (error instanceof McpJsonRpcError) {
      let unknownTool = await describeUnknownTool(record2, toolName, deps.fetchImpl);
      return unknownTool ? {
        exitCode: 1,
        output: unknownTool,
        outcome: { kind: "intercept", reason: "unknown-command" }
      } : { exitCode: 1, output: error.message, outcome: { kind: "error", error } };
    }
    return {
      exitCode: 1,
      output: formatServerUnreachable(record2, error),
      outcome: { kind: "error", error }
    };
  }
}
async function buildStorybookCommandsHelp(options = {}, deps = {}) {
  let unavailable = (note) => `Storybook commands: (unavailable \u2014 ${note})`, metadataResult = await loadLocalMetadata(options.cwd, options.configDir, deps);
  if (metadataResult.kind === "error")
    return unavailable(
      `the Storybook config at ${metadataResult.configDir} could not be loaded: ${formatErrorMessage(
        metadataResult.error
      )}`
    );
  let { metadata, configDir } = metadataResult;
  if (!metadata)
    return unavailable(formatMetadataMissingHelp(configDir));
  let { tools } = metadata;
  if (tools.length === 0)
    return unavailable(`the Storybook config at ${configDir} provides no commands`);
  let width = Math.max(...tools.map((tool) => tool.name.length)) + 2, localToolNames = getLocalToolNames(metadata), lines = tools.map((tool) => {
    let mode = localToolNames.has(tool.name) ? "[local]" : "[requires Storybook]", summary = tool.description?.trim().split(`
`)[0] ?? "";
    return `  ${tool.name.padEnd(width)}${mode.padEnd(21)}${summary}`;
  }), { instructions: instructions2 } = metadata, trimmedInstructions = instructions2?.trim(), sections = [`Storybook help from the Storybook configuration at ${configDir}:`, ""];
  return trimmedInstructions && sections.push("# Storybook workflow instructions", "", trimmedInstructions, ""), sections.push(
    "# Storybook commands",
    "",
    ...lines,
    "",
    "[local] commands run from configuration metadata without a running Storybook.",
    "[requires Storybook] commands are forwarded to the running Storybook server.",
    "",
    "Run 'storybook ai <command> --help' for a command's description and arguments."
  ), sections.join(`
`);
}
async function runAiToolHelp(toolName, options = {}, deps = {}) {
  return toolHelp(toolName, options.cwd, options.configDir, deps);
}
async function toolHelp(toolName, cwd, configDir, deps) {
  let outcome = { kind: "help" }, metadataResult = await loadLocalMetadata(cwd, configDir, deps);
  if (metadataResult.kind === "error")
    return metadataLoadFailureResult(metadataResult, outcome);
  let { metadata } = metadataResult;
  if (!metadata)
    return metadataMissingResult(metadataResult.configDir, outcome);
  let { tools } = metadata, tool = tools.find((candidate) => candidate.name === toolName);
  return tool ? {
    exitCode: 0,
    output: formatToolHelp(tool, { local: getLocalToolNames(metadata).has(tool.name) }),
    outcome
  } : {
    exitCode: 1,
    output: formatUnknownMetadataTool(toolName, tools, metadataResult.configDir),
    outcome
  };
}
async function lookupAiTool(toolName, cwd, configDir, deps) {
  let metadataResult = await loadLocalMetadata(cwd, configDir, deps);
  if (metadataResult.kind === "error")
    return {
      kind: "result",
      result: metadataLoadFailureResult(metadataResult, {
        kind: "error",
        error: new LocalAiToolError({ cause: metadataResult.error })
      })
    };
  let { metadata } = metadataResult;
  if (!metadata)
    return {
      kind: "result",
      result: metadataMissingResult(metadataResult.configDir, {
        kind: "intercept",
        reason: "addon-missing"
      })
    };
  if (!metadata.tools.find((tool) => tool.name === toolName))
    return {
      kind: "result",
      result: {
        exitCode: 1,
        output: formatUnknownMetadataTool(toolName, metadata.tools, metadataResult.configDir),
        outcome: { kind: "intercept", reason: "unknown-command" }
      }
    };
  let localTool = metadata.localTools?.[toolName];
  return localTool ? { kind: "local", localTool } : { kind: "runtime" };
}
async function runLocalAiTool(localTool, args) {
  try {
    let rawResult = await localTool.call(args), parsedResult = safeParse(ToolCallResultSchema, rawResult);
    if (!parsedResult.success)
      return {
        exitCode: 1,
        output: "The Storybook local AI command returned an unexpected response shape",
        outcome: {
          kind: "error",
          error: new LocalAiToolError({ cause: parsedResult.issues })
        }
      };
    let result = parsedResult.output, output = formatToolResult(result);
    return result.isError ? {
      exitCode: 1,
      output,
      outcome: { kind: "error", error: new McpToolResultError({ cause: output }) }
    } : { exitCode: 0, output, outcome: { kind: "success" } };
  } catch (error) {
    return {
      exitCode: 1,
      output: error instanceof Error ? error.message : String(error),
      outcome: { kind: "error", error: new LocalAiToolError({ cause: error }) }
    };
  }
}
async function loadLocalMetadata(cwd, configDir, deps) {
  let resolvedCwd = resolve2(cwd ?? process.cwd()), resolvedConfigDir = resolveStorybookConfigDir({ cwd: resolvedCwd, configDir }), loadMetadata = deps.loadStorybookAiMetadata ?? loadStorybookAiMetadata;
  try {
    return {
      kind: "ok",
      cwd: resolvedCwd,
      configDir: resolvedConfigDir,
      metadata: await loadMetadata({ cwd: resolvedCwd, configDir: resolvedConfigDir })
    };
  } catch (error) {
    return { kind: "error", cwd: resolvedCwd, configDir: resolvedConfigDir, error };
  }
}
function metadataLoadFailureResult(metadataResult, outcome) {
  return {
    exitCode: 1,
    output: `Storybook command metadata is unavailable for ${metadataResult.configDir}: ${formatErrorMessage(metadataResult.error)}`,
    outcome
  };
}
function metadataMissingResult(configDir, outcome) {
  return {
    exitCode: 1,
    output: `Storybook command metadata is unavailable for ${configDir}. Install or upgrade \`@storybook/addon-mcp\`.`,
    outcome
  };
}
function formatMetadataMissingHelp(configDir) {
  return `the Storybook config at ${configDir} does not expose AI command metadata \u2014 install or upgrade \`@storybook/addon-mcp\``;
}
function formatErrorMessage(error) {
  return error instanceof Error ? error.message : String(error);
}
function formatServerUnreachable(record2, error) {
  return `Failed to reach the Storybook server at ${record2.mcp.endpoint ?? "(no endpoint)"}: ${error instanceof Error ? error.message : String(error)}`;
}
async function resolveReadyInstance(target, deps) {
  let cwd = resolve2(target.cwd ?? process.cwd()), configDir = resolveStorybookConfigDir({ cwd, configDir: target.configDir }), records = await readRegistry(deps.registryDir), resolution = resolveInstance(records, {
    cwd,
    configDir,
    configDirExplicit: target.configDir != null,
    port: target.port,
    agent: detectAgent()?.name
  });
  return resolution.kind === "intercept" ? {
    kind: "error",
    output: getInterceptMarkdown(resolution.reason, {
      records: resolution.records,
      port: target.port
    }),
    reason: resolution.reason
  } : { kind: "ok", record: resolution.record, matches: resolution.matches };
}
async function describeUnknownTool(record2, toolName, fetchImpl) {
  let tools;
  try {
    tools = await listMcpTools(record2, fetchImpl);
  } catch {
    return null;
  }
  return tools.some((tool) => tool.name === toolName) ? null : formatUnknownTool(toolName, tools, `The Storybook running at ${record2.url}`);
}
function formatUnknownTool(toolName, tools, source) {
  return `Unknown command \`${toolName}\`. ${source} provides:

${tools.map((tool) => `- \`${tool.name}\``).join(`
`)}

Run \`storybook ai --help\` for all commands, or \`storybook ai <command> --help\` for a command's arguments.`;
}
function formatUnknownMetadataTool(toolName, tools, configDir) {
  return formatUnknownTool(toolName, tools, `The Storybook configuration at ${configDir}`);
}
function formatToolResult(result) {
  let content = result.content ?? [];
  return content.length === 0 ? "(the command returned no content)" : content.map(
    (item) => item.type === "text" && typeof item.text == "string" ? item.text : `\`\`\`json
${JSON.stringify(item, null, 2)}
\`\`\``
  ).join(`

`);
}
function getLocalToolNames(metadata) {
  return new Set(Object.keys(metadata.localTools ?? {}));
}
function formatToolHelp(tool, { local }) {
  let lines = [`Usage: storybook ai ${tool.name} [--key value ...]`];
  tool.description && lines.push("", tool.description.trim()), lines.push(
    "",
    local ? "Execution: local (no running Storybook required)." : "Execution: requires a running Storybook."
  );
  let properties = Object.entries(tool.inputSchema?.properties ?? {});
  if (properties.length > 0) {
    let required = new Set(tool.inputSchema?.required ?? []);
    lines.push("", "Arguments:");
    for (let [name, schema] of properties) {
      let parsed = safeParse(JsonSchemaNodeSchema, schema), node = parsed.success ? parsed.output : { type: schema.type, description: schema.description };
      lines.push(...schemaLines(`\`--${name}\``, node, required.has(name), "", MAX_SCHEMA_DEPTH));
    }
  }
  return lines.join(`
`);
}
function formatMultiInstanceWarning(chosen, siblings) {
  let lines = [chosen, ...siblings].map((r) => {
    let marker = r === chosen ? " (used)" : "", configDir = r.configDir ? `, config dir \`${r.configDir}\`` : "";
    return `> - pid \`${r.pid}\` at ${r.url} (cwd \`${r.cwd}\`${configDir}, status: \`${r.mcp.status}\`)${marker}`;
  });
  return `> Warning: Multiple Storybook instances match this project. This call was sent to pid \`${chosen.pid}\`.
>
> Matching instances:
${lines.join(`
`)}
>
> If results look unexpected, ask the user whether they want to stop the other instance(s).`;
}

// src/cli/ai/mcp/register.ts
function isAiCliFeatureEnabled(env = process.env) {
  return optionalEnvToBoolean(env.STORYBOOK_FEATURE_AI_CLI) === !0;
}
var CWD_DESCRIPTION = "Project directory of the target Storybook; place before the command name", CONFIG_DIR_DESCRIPTION = "Storybook config directory of the target Storybook; place before the command name", PORT_DESCRIPTION = "Port of a running Storybook; runtime commands target that instance directly. Place before the command name";
function registerAiMcpPassthrough(program2, aiCommand2, handleCommandFailure2) {
  program2.enablePositionalOptions(), aiCommand2.helpOption(!1).usage("[options] [command] [args...]").argument("[command]", "A command loaded from the target Storybook configuration").argument(
    "[args...]",
    "Command arguments as `--key value` flags; values are JSON-parsed when possible"
  ).option("--cwd <path>", CWD_DESCRIPTION).option("-c, --config-dir <dir-name>", CONFIG_DIR_DESCRIPTION).option("-p, --port <number>", PORT_DESCRIPTION).option(
    "--json <object>",
    "Raw JSON object with the command arguments (escape hatch for complex values)"
  ).option(
    "-h, --help",
    "Show help, including commands loaded from the target Storybook configuration"
  ).passThroughOptions().action(
    async (command2, commandArgs, options) => {
      let cliOptions = pickCliOptions(options);
      return withTelemetry2(
        "ai-command",
        { cliOptions, fallbackTelemetryState: !0 },
        async () => {
          let target = {
            cwd: options.cwd,
            configDir: options.configDir,
            port: options.port
          };
          if (options.help && command2) {
            await printResult(await runAiToolHelp(command2, target), options.output);
            return;
          }
          if (options.help || !command2) {
            let commandsSection = await buildStorybookCommandsHelp(target);
            process.stdout.write(`${aiCommand2.helpInformation()}
${commandsSection}
`);
            return;
          }
          let start = Date.now(), result = await runAiTool(command2, commandArgs, { ...target, json: options.json }), duration = Date.now() - start;
          try {
            await printResult(result, options.output);
          } finally {
            await reportAiCommandTelemetry(command2, result.outcome, duration, cliOptions);
          }
        }
      ).catch(handleCommandFailure2(options.logfile));
    }
  );
}
function pickCliOptions(options) {
  let targetCwd = options.cwd ?? process.cwd(), targetConfigDir = options.configDir;
  return {
    disableTelemetry: options.disableTelemetry,
    logfile: options.logfile,
    configDir: resolveStorybookConfigDir({ cwd: targetCwd, configDir: targetConfigDir })
  };
}
function sanitizeCommandName(command2) {
  return /^[\w-]{1,64}$/.test(command2) ? command2 : "(invalid)";
}
async function reportAiCommandTelemetry(command2, outcome, duration, cliOptions) {
  outcome.kind !== "help" && (await telemetry2(
    "ai-command",
    {
      command: sanitizeCommandName(command2),
      success: outcome.kind === "success",
      ...outcome.kind === "intercept" && { interceptReason: outcome.reason },
      duration
    },
    // Metadata must describe the target project, consistent with the opt-out resolution.
    { configDir: cliOptions.configDir }
  ), outcome.kind === "error" && await sendTelemetryError(outcome.error, "ai-command", { cliOptions }));
}
async function printResult({ output, exitCode }, outputPath) {
  if (outputPath) {
    let resolvedPath = resolve3(outputPath);
    await writeFile2(resolvedPath, `${output}
`, "utf-8"), logger2.log(`Output written to ${resolvedPath}`);
  } else
    process.stdout.write(`${output}
`);
  exitCode !== 0 && (process.exitCode = exitCode);
}

// src/cli/skills/register.ts
import { experimental_loadStorybook, withTelemetry as withTelemetry3 } from "storybook/internal/core-server";
import { telemetry as telemetry3 } from "storybook/internal/telemetry";

// src/shared/open-service/toolsets/docs/instructions.ts
function getDocsToolsetInstructions(transport) {
  let ref = getToolName({ transport });
  return `## Documentation Workflow

**CRITICAL: Never hallucinate component properties!** Before using ANY property on a component (even common-sounding ones like \`shadow\`), you MUST verify it is documented via these tools. If it is not documented, it does not exist \u2014 never assume props from naming conventions or other libraries; report it to the user instead.

1. Call **${ref("docs.list")}** once at the start of the task to discover available component and docs IDs.
2. Call **${ref("docs.show")}** with an \`id\` from that list to retrieve full component docs, props, usage examples, and stories.
3. Call **${ref("docs.showStory")}** for extra docs on a story variant not covered by the component docs.

Only use properties explicitly documented or shown in example stories. Only reference IDs returned by these tools; never guess IDs.

## Multi-Source Requests

- With multiple sources configured, **${ref("docs.list")}** returns entries from every source; pass \`storybookId\` to **${ref("docs.show")}** to scope one.
`;
}
var DOCS_TOOLSET_INSTRUCTIONS = getDocsToolsetInstructions("mcp");

// src/cli/skills/content/instructions/dev-instructions.md
var dev_instructions_default = `## UI Building and Story Writing Workflow

- Before creating or editing components or stories, call **{{GET_STORYBOOK_STORY_INSTRUCTIONS}}**; its output is the source of truth for imports, story patterns, and testing conventions.
- {{PREVIEW_STORIES_STEP}}
- {{FINAL_LINKS_STEP}}{{DISPLAY_REVIEW_STEP}}
- Only use story IDs returned by tools \u2014 never derive them from file names or memory. **{{GET_STORIES_BY_COMPONENT}}** maps any input to stories; its description covers the workflow. No matches means no stories exist yet \u2014 say so.
`;

// src/cli/skills/content/instructions/legacy-dev-instructions.md
var legacy_dev_instructions_default = `## UI Building and Story Writing Workflow

- Before creating or editing components or stories, call **{{GET_STORYBOOK_STORY_INSTRUCTIONS}}**.
- Treat its output as the source of truth for imports, story patterns, and testing conventions.
- After editing anything that changes how the UI looks \u2014 components, stories, styles, themes, colors, design tokens \u2014 call **{{PREVIEW_STORIES}}**, no exceptions; a shared file has no stories of its own, so preview its consumers' stories.
- Include every returned preview URL in your final response.
`;

// src/cli/skills/content/instructions/legacy-test-instructions.md
var legacy_test_instructions_default = `## Validation Workflow

- After editing anything that changes how the UI looks, run **{{RUN_STORY_TESTS}}** \u2014 never a package.json test script.
- Use focused runs while iterating, then a broad pass before handoff when scope is unclear or wide.
- Fix failing tests; never report completion while they are failing.
`;

// src/cli/skills/content/instructions/review-docs-instructions.md
var review_docs_instructions_default = `## Documentation Workflow

**CRITICAL: Never hallucinate component properties!** Undocumented props do not exist \u2014 never assume them from naming or other libraries; verify every prop via these tools, not source or types in node_modules.

1. Call **{{DOCS_LIST}}** once at task start for component and docs IDs.
2. Call **{{DOCS_SHOW}}** with an \`id\` from that list for props and usage examples.

Only reference IDs returned by these tools \u2014 never guess; scope multi-source requests with \`storybookId\`.
`;

// src/cli/skills/content/instructions/test-instructions.md
var test_instructions_default = `## Validation Workflow

- After editing anything that changes how the UI looks, run **{{RUN_STORY_TESTS}}** \u2014 never a package.json test script.
- Never report completion while story tests are failing.
`;

// src/cli/skills/content/skill-refs.ts
var MCP_SKILL_TOOL_NAMES = {
  "write-story": "get-storybook-story-instructions"
};
function getSkillRef(transport) {
  return (id) => transport === "mcp" && MCP_SKILL_TOOL_NAMES[id] || `npx storybook skills ${id}`;
}

// src/cli/skills/content/build-server-instructions.ts
function getFinalLinksGuidance(transport, reviewToolAvailable) {
  let ref = getToolName({ transport });
  return reviewToolAvailable ? `In your final user-facing response, show one set of links \u2014 never both. If you published a review with **${ref("review.create")}**, finish your reply with a dedicated review section as the very last thing in the output: its own top-level heading on a line by itself (for example \`## \u{1F440} Review your changes\`), then a one-line explanation that the review shows the handful of stories most relevant to this change and that, because it is AI-curated, results may be inaccurate or incomplete, then on the next line the review page as a markdown link prefixed with a \u{1F449} so it is easy to spot, using the returned \`reviewUrl\` (for example \`\u{1F449} [Open the Storybook review page](<reviewUrl>)\`). Nothing should come after this section. Never also list the individual story or preview URLs. Avoid internal jargon like "collection" or "trigger" in anything the user reads \u2014 those are terms from this tooling, not words that mean anything to them; use plain language unless the user used the term first. A visually observable change is not finished until its review is published \u2014 never substitute preview URLs for the review. Only when there is no review because the change has no visually observable impact, say so plainly; include preview URLs only if the user asked to see specific stories.` : "In your final user-facing response, include every returned preview URL so the user can verify the visual result, ordered consistently (changed-stories fallback first if relevant, then the specific preview URLs).";
}
function buildServerInstructions({
  transport,
  ...options
}) {
  let ref = getToolName({ transport }), skillRef = getSkillRef(transport), sections = [
    options.docsEnabled ? "Follow these workflows when working with UI and/or Storybook. Answer questions about component props, API, or usage with the documentation tools \u2014 never from source or type definitions." : "Follow these workflows when working with UI and/or Storybook."
  ], reviewEnabled = options.reviewEnabled ?? !1;
  if (options.devEnabled && !reviewEnabled)
    sections.push(
      legacy_dev_instructions_default.replaceAll("{{GET_STORYBOOK_STORY_INSTRUCTIONS}}", skillRef("write-story")).replaceAll("{{PREVIEW_STORIES}}", ref("stories.preview")).trim()
    );
  else if (options.devEnabled) {
    let changeDetection = options.changeDetectionEnabled ?? !1, graphSupported = options.moduleGraphSupported ?? !1, previewStoriesStep = changeDetection ? `After editing anything that changes how the UI looks \u2014 components, stories, styles, themes, tokens \u2014 call **${ref("stories.changed")}** to discover the affected stories.` : graphSupported ? `After editing anything that changes how the UI looks, call **${ref("stories.findByComponent")}** with the files you touched.` : "After editing anything that changes how the UI looks, identify the affected stories.", finalLinksStep = `End your final response with the review section from **${ref("review.create")}**'s result \u2014 never substitute preview URLs. **${ref("stories.preview")}** is only for mid-loop iteration or a requested direct link. If nothing visually changed, say so.`;
    sections.push(
      dev_instructions_default.replaceAll("{{GET_STORYBOOK_STORY_INSTRUCTIONS}}", skillRef("write-story")).replaceAll("{{GET_STORIES_BY_COMPONENT}}", ref("stories.findByComponent")).replace("{{PREVIEW_STORIES_STEP}}", previewStoriesStep).replace("{{FINAL_LINKS_STEP}}", finalLinksStep).replace(
        "{{DISPLAY_REVIEW_STEP}}",
        `
- After a visually observable UI change, or when the user asks to see or browse stories/components, call **${ref("review.create")}** (again on each iteration) and follow its description and result. Visual work is not done until the review is published; any newly created story MUST be included.`
      ).trim()
    );
  }
  return options.testSupported && sections.push(
    (reviewEnabled ? test_instructions_default : legacy_test_instructions_default).replaceAll("{{RUN_STORY_TESTS}}", ref("test.run")).trim()
  ), options.docsEnabled && sections.push(
    (reviewEnabled ? review_docs_instructions_default.replaceAll("{{DOCS_LIST}}", ref("docs.list")).replaceAll("{{DOCS_SHOW}}", ref("docs.show")) : getDocsToolsetInstructions(transport)).trim()
  ), sections.length === 1 ? "" : sections.join(`

`);
}

// src/cli/skills/content/instructions/a11y-instructions.md
var a11y_instructions_default = `### Accessibility Violations

**Fix automatically** (semantic/structural, no visual change):

- ARIA attributes, roles, labels, alt text
- Heading hierarchy, landmarks, table structure
- Keyboard access (tabindex, focus, handlers)
- Document-level: lang attr, frame titles, duplicate IDs

**Confirm with user first** (visual/design changes):

- Color contrast ratios
- Font sizes, spacing, layout
- Focus indicator styling

Describe the issue, ask how the user wants to proceed, and provide 2-3 concrete options.
Do not auto-apply visual changes before user confirmation, and do not claim visual issues are fixed until they approve an option.
`;

// src/cli/skills/content/instructions/story-testing-instructions.md
var story_testing_instructions_default = `## Story Testing Requirements

**Run \`{{RUN_STORY_TESTS_TOOL_NAME}}\` after EVERY component or story change.** This includes creating, modifying, or refactoring components, stories, or their dependencies. It is the only way to run story tests \u2014 never run package.json test scripts (like \`npm run test:stories\`) instead.

### Workflow

1. Make your change
2. Run \`{{RUN_STORY_TESTS_TOOL_NAME}}\` with related stories for focused feedback (faster while iterating)
3. If tests fail: analyze, fix{{A11Y_FIX_SUFFIX}}, re-run
4. Repeat until all tests pass

Do not skip tests, ignore failures, or move on with failing tests. If stuck after multiple attempts, report to user.

### Focused vs. full-suite test runs

- Prefer focused runs (\`stories\` input) during development to validate the parts you changed quickly.
- Run all tests (omit \`stories\`) before final handoff, after broad/refactor changes, or when impact is unclear and you need project-wide verification.
`;

// src/cli/skills/content/instructions/storybook-story-instructions.md
var storybook_story_instructions_default = `# Writing User Interfaces

When writing UI, prefer breaking larger components up into smaller parts.

ALWAYS write a Storybook story for any component written. If editing a component, ensure appropriate changes have been made to stories for that component.
{{DOCS_WORKFLOW_GUIDANCE}}

## How to write good stories

Goal: Cover every distinct piece of business logic and state the component can reach (happy paths, error/edge states, loading, permissions/roles, empty states, variations from props/context). Avoid redundant stories that show the same logic.

Interactivity: If the component is interactive, add Interaction tests using play functions that drive the UI with storybook/test utilities (e.g., fn, userEvent, expect). Simulate key user flows: clicking buttons/links, typing, focus/blur, keyboard nav, form submit, async responses, toggle/selection changes, pagination/filters, etc. When passing \`fn\` functions as \`args\` for callback functions, make sure to add a play function which interacts with the component and assert whether the callback function was actually called.

Data/setup: Provide realistic props, state, and mocked data. Include meaningful labels/text to make behaviors observable. Stub network/services with deterministic fixtures; keep stories reliable.

Assertions: In play functions, assert the visible outcome of the interaction (text, aria state, enabled/disabled, class/state changes, emitted events). Prefer role/label-based queries.

Variants to consider (pick only those that change behavior): default vs. alternate themes; loading vs. loaded vs. empty vs. error; validated vs. invalid input; permissions/roles/capabilities; feature flags; size/density/layout variants that alter logic.

Accessibility: Use semantic roles/labels; ensure focusable/keyboard interactions are test-covered where relevant.

Naming/structure: Use clear story names that describe the scenario (\u201CError state after failed submit\u201D). Group related variants logically; don\u2019t duplicate.

Imports/format: Import Meta/StoryObj from the framework package; import test helpers from storybook/test (not @storybook/test). Keep stories minimal\u2014only what's needed to demonstrate behavior.

## Storybook 9 Essential Changes for Story Writing

### Package Consolidation

#### \`Meta\` and \`StoryObj\` imports

Update story imports to use the framework package:

\`\`\`diff
- import { Meta, StoryObj } from '{{RENDERER}}';
+ import { Meta, StoryObj } from '{{FRAMEWORK}}';
\`\`\`

#### Test utility imports

Update test imports to use \`storybook/test\` instead of \`@storybook/test\`

\`\`\`diff
- import { fn } from '@storybook/test';
+ import { fn } from 'storybook/test';
\`\`\`

### Global State Changes

The \`globals\` annotation has be renamed to \`initialGlobals\`:

\`\`\`diff
// .storybook/preview.js
export default {
- globals: { theme: 'light' }
+ initialGlobals: { theme: 'light' }
};
\`\`\`

### Autodocs Configuration

Instead of \`parameters.docs.autodocs\` in main.js, use tags:

\`\`\`js
// .storybook/preview.js or in individual stories
export default {
	tags: ['autodocs'], // generates autodocs for all stories
};
\`\`\`

### Mocking imports in Storybook

To mock imports in Storybook, use Storybook's mocking features. ALWAYS mock external dependencies to ensure stories render consistently.

1. **Register in the mock in Storybook's preview file**:
   To mock dependendencies, you MUST register a module mock in \`.storybook/preview.ts\` (or equivalent):

\`\`\`js
import { sb } from 'storybook/test';

// Prefer spy mocks (keeps functions, but allows to override them and spy on them)
sb.mock(import('some-library'), { spy: true });
\`\`\`

**Important: Use file extensions when referring to relative files!**

\`\`\`js
sb.mock(import('./relative/module.ts'), { spy: true });
\`\`\`

2. **Specify mock values in stories**:
   You can override the behaviour of the mocks per-story using \`beforeEach\` and the \`mocked()\` type function:

\`\`\`js
import { expect, mocked, fn } from 'storybook/test';
import { library } from 'some-library';

const meta = {
  component: AuthButton,
  beforeEach: async () => {
    mocked(library).mockResolvedValue({  user: 'data' });
  },
};

export const LoggedIn: Story = {
  play: async ({ canvas }) => {
    await expect(library).toHaveBeenCalled();
  },
};
\`\`\`

Before doing this ensure you have mocked the import in the preview file.

### Play Function Parameters

- The play function has a \`canvas\` parameter that can be used directly with testing-library-like query methods.
- It also has a \`canvasElement\` which is the actual DOM element.
- The \`within\`-function imported from \`storybook/test\` transforms a DOM element to an object with query methods, similar to \`canvas\`.

**DO NOT** use \`within(canvas)\` - it is redundant because \`canvas\` already has the query methods, \`canvas\` is not a DOM element.

\`\`\`ts
// \u2705 Correct: Use canvas directly
play: async ({ canvas }) => {
	await canvas.getByLabelText('Submit').click();
};

// \u26A0\uFE0F Also acceptable: Use \`canvasElement\` with \`within\`
import { within } from 'storybook/test';

play: async ({ canvasElement }) => {
	const canvas = within(canvasElement);
	await canvas.getByLabelText('Submit').click();
};

// \u274C Wrong: Do NOT use within(canvas)
play: async ({ canvas }) => {
	const screen = within(canvas); // Error!
};
\`\`\`

### Key Requirements

- **Node.js 20+**, **TypeScript 4.9+**
- React Native uses \`.rnstorybook\` directory

## Story Linking Agent Behavior

- ALWAYS provide story links after any changes to stories files, including changes to existing stories.
- {{STORY_LINKING_WORKFLOW}}
- {{FINAL_LINKS_GUIDANCE}}
- When you will share preview/story links (i.e. when you are not collapsing everything into a single review section), pass only the most relevant story IDs into **{{PREVIEW_STORIES}}** (generally no more than 5) so the returned URL list stays manageable. Include every URL returned by that call in your final response \u2014 do not drop links there.
- {{CHANGED_STORY_FALLBACK_LINK_GUIDANCE}}
- After changing any UI components, ALWAYS search for related stories that might cover the changes you've made. If you find any, provide the story links to the user. THIS IS VERY IMPORTANT, as it allows the user to visually inspect the changes you've made. Even later in a session when changing UI components or stories that have already been linked to previously, YOU MUST PROVIDE THE LINKS AGAIN.
`;

// src/cli/skills/content/build-story-instructions.ts
function buildStoryInstructions({
  transport,
  framework,
  renderer,
  changeDetectionEnabled,
  reviewEnabled,
  testSupported,
  a11yEnabled,
  docsEnabled
}) {
  let ref = getToolName({ transport }), resolvedRenderer = renderer ?? frameworkToRendererMap[framework] ?? framework, storyLinkingWorkflow = changeDetectionEnabled ? reviewEnabled ? `After changing any component or story, call \`${ref("stories.changed")}\` to discover the new, modified, and related stories affected by your change. Story IDs must come from that call (or a fallback discovery tool such as ${ref("stories.findByComponent")} for shared-infrastructure changes) \u2014 never construct them from file names, export names, or memory. Feed the discovered IDs into **${ref("review.create")}** when the change is visually observable; use \`${ref("stories.preview")}\` only while iterating on a specific story.` : `After changing UI, call \`${ref("stories.changed")}\` first, then use \`${ref("stories.preview")}\` with selected \`storyId\` values from those results.` : `After changing UI, call \`${ref("stories.preview")}\` and share the most relevant links for the changes.`, changedStoryFallbackLinkGuidance = changeDetectionEnabled ? `When sharing preview/story links (not when ending with a review section): if you did not pass every changed story into \`${ref("stories.preview")}\`, include this Storybook fallback link so the user can view the complete changed list: \`/?statuses=affected;modified;new\`.` : `When sharing preview/story links (not when ending with a review section) and you passed only a subset into \`${ref("stories.preview")}\`, mention that additional relevant stories may exist in Storybook.`, docsWorkflowGuidance = `

## Using library components

This Storybook exposes component documentation tools. Before creating or changing any UI, call **${ref("docs.list")}** once to see what the design system already provides \u2014 build on existing components instead of hand-rolling duplicates \u2014 then call **${ref("docs.show")}** with the \`id\` of each component you build on or get asked about, for its real props and usage examples. When multiple Storybook sources are configured, pass the \`storybookId\` from **${ref("docs.list")}** on follow-up calls. Do this instead of reading the library's source or type definitions out of \`node_modules\` \u2014 stories show intended usage, raw types don't \u2014 and answer props/usage questions from these tools too. Never assume or invent props.`, uiInstructions = storybook_story_instructions_default.replace("{{FRAMEWORK}}", framework).replace("{{RENDERER}}", resolvedRenderer).replace(`
{{DOCS_WORKFLOW_GUIDANCE}}`, docsEnabled ? docsWorkflowGuidance : "").replace("{{STORY_LINKING_WORKFLOW}}", storyLinkingWorkflow).replace("{{FINAL_LINKS_GUIDANCE}}", getFinalLinksGuidance(transport, reviewEnabled)).replace("{{PREVIEW_STORIES}}", ref("stories.preview")).replace("{{CHANGED_STORY_FALLBACK_LINK_GUIDANCE}}", changedStoryFallbackLinkGuidance);
  if (testSupported) {
    let a11yFixSuffix = a11yEnabled ? " (see a11y guidelines below)" : "", storyTestingInstructions = story_testing_instructions_default.replaceAll("{{RUN_STORY_TESTS_TOOL_NAME}}", ref("test.run")).replace("{{A11Y_FIX_SUFFIX}}", a11yFixSuffix);
    uiInstructions += `

${storyTestingInstructions}`, a11yEnabled && (uiInstructions += `
${a11y_instructions_default}`);
  }
  return uiInstructions;
}

// src/cli/skills/content/skills.ts
var SKILL_IDS = ["stories", "write-story", "setup"], SKILLS = {
  stories: {
    blurb: "The mandatory, ordered workflow for UI changes: discover affected stories, test, and present results."
  },
  "write-story": {
    blurb: "How to write, update, and test Storybook stories for this project: imports, patterns, and conventions."
  },
  setup: {
    blurb: "Setup instructions to write stories for the real components in this project."
  }
};
function isSkillId(value) {
  return SKILL_IDS.includes(value);
}

// src/cli/skills/run.ts
var SKILLS_OPTION_SPECS = [
  { flags: "--cwd <path>", description: "Project directory of the target Storybook" },
  {
    flags: "-c, --config-dir <dir-name>",
    description: "Storybook config directory of the target Storybook"
  },
  { flags: "--all", description: "Print every skill in full" },
  { flags: "-h, --help", description: "Show this usage and every skill" }
];
function resolveSkillsIntent({
  tokens,
  help,
  all
}) {
  let [id, ...rest] = tokens;
  return help ? { kind: "catalog" } : id === void 0 ? all ? { kind: "all" } : { kind: "catalog" } : isSkillId(id) ? all ? {
    kind: "error",
    message: `\`--all\` prints every skill and takes no skill id; drop "${id}" or \`--all\`.`
  } : rest.length > 0 ? {
    kind: "error",
    message: `Unexpected arguments: ${rest.map((token) => `"${token}"`).join(" ")}. Run \`npx storybook skills --help\` for usage.`
  } : { kind: "get", id } : {
    kind: "error",
    message: `Unknown skill "${id}". Available skills: ${SKILL_IDS.join(", ")}.`
  };
}
async function runSkillsCommand(input, deps) {
  let intent = resolveSkillsIntent(input);
  if (intent.kind === "catalog")
    return { output: renderCatalogHelp(), exitCode: 0 };
  if (intent.kind === "error")
    return { output: "", errorOutput: intent.message, exitCode: 1 };
  try {
    let ids = intent.kind === "all" ? SKILL_IDS : [intent.id];
    return {
      output: (await serveSkills(ids, resolveStorybookConfigDir(input.target), deps)).join(`

---

`),
      exitCode: 0,
      skill: intent.kind === "all" ? "all" : intent.id
    };
  } catch (error) {
    if (error instanceof SkillsError)
      return { output: "", errorOutput: error.message, exitCode: 1 };
    throw error;
  }
}
var SkillsError = class extends Error {
};
async function serveSkills(ids, configDir, deps) {
  let inputs, docs = [];
  for (let id of ids)
    id === "setup" ? docs.push(await serveSetup(configDir, deps)) : (inputs ??= await loadInputs(configDir, deps), docs.push(assemble(id, inputs)));
  return docs;
}
async function serveSetup(configDir, deps) {
  let probed = await deps.getProjectInfo({ configDir });
  if (!probed.ok)
    throw new SkillsError(probed.message);
  return (await deps.getSetupMarkdown(probed.projectInfo)).markdown;
}
async function loadInputs(configDir, deps) {
  try {
    return await deps.resolveSkillInputs(await deps.loadStorybook({ configDir }));
  } catch (error) {
    throw new SkillsError(
      `Could not load the Storybook configuration for this project: ${error instanceof Error ? error.message : String(error)}`
    );
  }
}
function table(rows) {
  let column = Math.max(...rows.map(([key]) => key.length)) + 2;
  return rows.map(([key, text]) => `  ${key.padEnd(column)}${text}`);
}
function renderCatalogHelp() {
  return [
    "Usage: npx storybook skills [options] [id]",
    "",
    "Agent skills served by this Storybook.",
    "",
    "Options:",
    ...table(SKILLS_OPTION_SPECS.map((spec) => [spec.flags, spec.description])),
    "",
    "Skills:",
    ...table(SKILL_IDS.map((id) => [id, SKILLS[id].blurb])),
    "",
    "Print a skill with `npx storybook skills <id>`, or every skill with `npx storybook skills --all`."
  ].join(`
`);
}
function assemble(id, inputs) {
  let reviewEnabled = inputs.reviewEnabledForCli;
  return id === "stories" ? buildServerInstructions({
    transport: "cli",
    devEnabled: !0,
    testSupported: inputs.testSupported,
    docsEnabled: inputs.docsEnabledForCli,
    changeDetectionEnabled: inputs.changeDetectionEnabled,
    moduleGraphSupported: inputs.moduleGraphSupported,
    reviewEnabled
  }) : buildStoryInstructions({
    transport: "cli",
    framework: inputs.framework,
    renderer: inputs.renderer,
    changeDetectionEnabled: inputs.changeDetectionEnabled,
    reviewEnabled,
    testSupported: inputs.testSupported,
    a11yEnabled: inputs.a11yEnabled,
    docsEnabled: inputs.docsEnabledForCli
  });
}

// src/cli/skills/register.ts
function registerSkillsCommand(program2, skillsCommand2, handleCommandFailure2) {
  program2.enablePositionalOptions(), skillsCommand2.helpOption(!1).helpCommand(!1).usage("[options] [id]").argument("[tokens...]", "A skill id from `storybook skills --help`");
  for (let { flags, description } of SKILLS_OPTION_SPECS)
    skillsCommand2.option(flags, description);
  skillsCommand2.action(async (tokens, options) => {
    let cliOptions = {
      disableTelemetry: options.disableTelemetry,
      logfile: options.logfile,
      configDir: resolveStorybookConfigDir({ cwd: options.cwd, configDir: options.configDir })
    }, invocation = {
      tokens: tokens ?? [],
      help: options.help,
      all: options.all,
      target: { cwd: options.cwd, configDir: options.configDir }
    }, intent = resolveSkillsIntent(invocation), run = async () => {
      let result = await runSkillsCommand(invocation, defaultDeps());
      await printResult2(result), result.skill && await telemetry3("skills-get", { skill: result.skill }, { configDir: cliOptions.configDir });
    };
    intent.kind === "catalog" ? await run() : await withTelemetry3("skills-get", { cliOptions, fallbackTelemetryState: !0 }, run).catch(
      handleCommandFailure2(options.logfile)
    ), process.exit();
  });
}
function defaultDeps() {
  return {
    loadStorybook: experimental_loadStorybook,
    resolveSkillInputs,
    getProjectInfo,
    getSetupMarkdown: getSetupMarkdownOutput
  };
}
async function printResult2(result) {
  result.errorOutput && await new Promise(
    (done) => process.stderr.write(`${result.errorOutput}
`, () => done())
  ), result.output && await new Promise((done) => process.stdout.write(`${result.output}
`, () => done())), result.exitCode !== 0 && (process.exitCode = result.exitCode);
}

// src/cli/tools/register.ts
import { writeFile as writeFile3 } from "node:fs/promises";
import { resolve as resolve5 } from "node:path";
import { sendTelemetryError as sendTelemetryError2, withTelemetry as withTelemetry4 } from "storybook/internal/core-server";
import { logger as logger3 } from "storybook/internal/node-logger";
import { telemetry as telemetry4 } from "storybook/internal/telemetry";

// src/cli/tools/run.ts
import { versions as versions2 } from "storybook/internal/common";

// src/cli/tools/discover-instance.ts
import { resolve as resolve4 } from "node:path";
async function discoverRunningInstance(target, deps = {}) {
  let cwd = resolve4(target.cwd ?? process.cwd()), configDir = resolveStorybookConfigDir({ cwd, configDir: target.configDir }), records = await readRegistry(deps.registryDir), selection = selectInstances(records, {
    cwd,
    configDir,
    configDirExplicit: target.configDir != null,
    port: target.port,
    agent: detectAgent()?.name
  });
  return { currentRecord: selection.kind === "match" ? selection.matches[0] : void 0, records };
}

// src/cli/tools/help.ts
var LOCAL_BADGE = "[local]", DEV_SERVER_BADGE = "[requires running Storybook]";
function optionLines() {
  let column = Math.max(...TOOLS_OPTION_SPECS.map((spec) => spec.flags.length)) + 2;
  return TOOLS_OPTION_SPECS.map((spec) => `  ${spec.flags.padEnd(column)}${spec.description}`);
}
function indented(lines, depth) {
  let pad = " ".repeat(depth);
  return lines.flatMap((line) => line.split(`
`)).map((line) => line && pad + line);
}
function cliPath(method) {
  let { toolsetId, methodName } = parseToolsetMethodId(method.ref);
  return `${toolsetId} ${toCliMethodName(methodName)}`;
}
function badge(method) {
  return method.requiresDevServer ? DEV_SERVER_BADGE : LOCAL_BADGE;
}
function argumentLines(schema, flagPrefix) {
  if (schema !== void 0)
    return propertyLines(schema, { flagPrefix });
}
function methodBodyLines(method) {
  let lines = [method.description.trim()], inputLines = argumentLines(method.input, !0);
  inputLines === void 0 ? lines.push("", "Arguments: (this schema could not be rendered)") : inputLines.length === 0 ? lines.push("", "Arguments: none.") : lines.push("", "Arguments:", ...inputLines);
  let outputLines = argumentLines(method.output, !1);
  return outputLines && outputLines.length > 0 && lines.push("", "Output (`--json`):", ...outputLines), lines;
}
function propertyLines(schema, { flagPrefix }) {
  let properties = Object.entries(
    schema.properties ?? {}
  ), required = new Set(schema.required ?? []), lines = [];
  for (let [name, propertySchema] of properties) {
    let parsed = safeParse(JsonSchemaNodeSchema, propertySchema), node = parsed.success ? parsed.output : {}, label = flagPrefix ? `\`--${name}\`` : `\`${name}\``;
    lines.push(...schemaLines(label, node, required.has(name), "", MAX_SCHEMA_DEPTH));
  }
  return lines;
}
function renderToolsetSection(entry) {
  let sections = [`${entry.id} \u2014 ${entry.description}`];
  for (let method of entry.methods) {
    let heading = `  ${cliPath(method)}  ${badge(method)}`;
    sections.push([heading, "", ...indented(methodBodyLines(method), 4)].join(`
`));
  }
  return sections.join(`

`);
}
function renderToolsHelpFromCatalog(catalog) {
  let commands = catalog.toolsets.flatMap(
    (toolset) => toolset.methods.map((method) => ({
      path: cliPath(method),
      summary: method.title,
      badge: badge(method)
    }))
  ), column = commands.length === 0 ? 0 : Math.max(...commands.map((command2) => command2.path.length)) + 2, commandBlock = commands.length === 0 ? "  (none)" : commands.map((command2) => `  ${command2.path.padEnd(column)}${command2.summary}  ${command2.badge}`).join(`
`), header = [
    "Usage: npx storybook tools [options] [toolset] [tool] [args...]",
    "",
    `Storybook tools from the Storybook configuration at ${catalog.configDir}.`,
    "",
    "Options:",
    ...optionLines(),
    "",
    "Commands:",
    commandBlock
  ].join(`
`), notes = [
    `${LOCAL_BADGE} tools run without a running Storybook.`,
    `${DEV_SERVER_BADGE} tools need a running Storybook dev server; start it first.`,
    "Tool results print as markdown; the Output blocks below describe the `--json` data.",
    "Individual `--key value` flags override entries of `--input`."
  ].join(`
`), sections = [header, notes, "Tool reference \u2014 every command in full (`npx storybook tools <toolset> <tool> --help` shows one alone):"];
  for (let toolset of catalog.toolsets)
    sections.push(renderToolsetSection(toolset));
  return sections.join(`

`);
}
function renderToolsetHelpFromCatalog(entry) {
  return [
    `Usage: npx storybook tools ${entry.id} <tool> [--key value ...]`,
    "",
    renderToolsetSection(entry)
  ].join(`
`);
}
function renderMethodHelpFromCatalog(_entry, method) {
  return [
    `Usage: npx storybook tools ${cliPath(method)} [--key value ...]`,
    "",
    method.requiresDevServer ? "Execution: requires a running Storybook dev server; start it first." : "Execution: local (no running Storybook required).",
    "",
    ...methodBodyLines(method)
  ].join(`
`);
}

// src/cli/tools/run.ts
var CLI_CLIENT_INFO = {
  name: "storybook-cli",
  version: versions2.storybook,
  kind: "cli"
};
function toMethodKey(cliName) {
  return cliName.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
}
function isAgentFacingError(error) {
  return error instanceof Error && error.agentFacing === !0;
}
function isInvalidInputError(error) {
  return error instanceof ToolsRuntimeError && error.data.reason === "invalid-input";
}
function normalizeHelpFlag(invocation) {
  return invocation.tool !== "--help" && invocation.tool !== "-h" ? invocation : {
    ...invocation,
    tool: void 0,
    flags: { ...invocation.flags, help: !0 }
  };
}
function resolveToolsMode(invocationAttach, parsedAttach) {
  let flag = parsedAttach ?? invocationAttach;
  return flag === !0 ? "attached" : flag === !1 ? "local" : "auto";
}
async function runToolsCommand(invocation, deps = {}) {
  let normalized = normalizeHelpFlag(invocation), { tokens, flags = {}, attach } = normalized, parsed = parseToolsTokens(tokens, flags), requestedMode = parsed.ok ? resolveToolsMode(attach, parsed.attach) : resolveToolsMode(attach, void 0);
  if (!parsed.ok)
    return {
      exitCode: 1,
      output: parsed.error,
      outcome: { kind: "intercept", reason: "invalid-arguments" },
      outputPath: flags.output,
      requestedMode,
      attachMode: requestedMode
    };
  let parsedPort = parsePort(normalized.port);
  if (!parsedPort.ok)
    return {
      exitCode: 1,
      output: parsedPort.error,
      outcome: { kind: "intercept", reason: "invalid-arguments" },
      outputPath: parsed.output,
      requestedMode,
      attachMode: requestedMode
    };
  let target = {
    ...normalized.target,
    ...parsedPort.port !== void 0 ? { port: parsedPort.port } : {}
  }, result = (partial) => ({
    ...partial,
    outputPath: parsed.output,
    requestedMode,
    attachMode: requestedMode
  }), tools, create = deps.createTools ?? createTools;
  try {
    tools = await create({
      cwd: target.cwd,
      configDir: target.configDir,
      ...target.port != null ? { port: target.port } : {},
      mode: requestedMode,
      clientInfo: CLI_CLIENT_INFO
    });
  } catch (error) {
    return isAttachGateError(error) ? result({
      exitCode: 1,
      output: error instanceof Error ? error.message : String(error),
      outcome: { kind: "attach-gate", reason: attachGateReasonFromError(error) }
    }) : result({
      exitCode: 1,
      output: error instanceof Error ? error.message : String(error),
      outcome: { kind: "error", error }
    });
  }
  try {
    let methodTelemetry = tools.mode === "local" && deps.methodTelemetry ? wrapMethodTelemetry(
      deps.methodTelemetry,
      toolsCommandDimensions({
        clientInfo: tools.clientInfo,
        requestedMode: tools.requestedMode,
        resolvedMode: tools.mode,
        host: tools.host,
        fallbackReason: tools.fallbackReason
      })
    ) : deps.methodTelemetry, dispatchDeps = { ...deps, methodTelemetry };
    return {
      ...await dispatchTools(
        tools,
        { ...normalized, target },
        parsed,
        dispatchDeps,
        requestedMode,
        result
      ),
      requestedMode: tools.requestedMode,
      attachMode: tools.mode,
      host: tools.host,
      fallbackNotice: tools.fallbackNotice,
      fallbackReason: tools.fallbackReason,
      ...tools.storybook.siblings?.length ? { multiInstanceNotice: formatMultiInstanceNotice(tools.storybook), multipleMatches: !0 } : {}
    };
  } finally {
    await tools.close();
  }
}
async function dispatchTools(tools, invocation, parsed, deps, requestedMode, result) {
  let { toolset: toolsetName, tool: toolName } = invocation, catalog;
  try {
    catalog = await tools.describe();
  } catch (error) {
    return isAgentFacingError(error) ? result({ exitCode: 1, output: error.message, outcome: { kind: "failure" } }) : result({
      exitCode: 1,
      output: error instanceof Error ? error.message : String(error),
      outcome: { kind: "error", error }
    });
  }
  if (!toolsetName)
    return result({
      exitCode: 0,
      output: renderToolsHelpFromCatalog(catalog),
      outcome: { kind: "help" }
    });
  let entry = catalog.toolsets.find((candidate) => candidate.id === toolsetName);
  if (!entry)
    return result({
      exitCode: 1,
      output: formatUnknownToolsetFromCatalog(toolsetName, catalog),
      outcome: { kind: "intercept", reason: "unknown-toolset" }
    });
  if (!toolName)
    return result({
      exitCode: 0,
      output: renderToolsetHelpFromCatalog(entry),
      outcome: { kind: "help" }
    });
  let method = entry.methods.find((candidate) => {
    let { methodName: methodName2 } = parseToolsetMethodId(candidate.ref);
    return methodName2 === toMethodKey(toolName) || toCliMethodName(methodName2) === toolName;
  });
  if (!method)
    return result({
      exitCode: 1,
      output: formatUnknownToolFromCatalog(toolName, entry),
      outcome: { kind: "intercept", reason: "unknown-tool" }
    });
  if (parsed.help)
    return result({
      exitCode: 0,
      output: renderMethodHelpFromCatalog(entry, method),
      outcome: { kind: "help" }
    });
  let { methodName } = parseToolsetMethodId(method.ref), commandPath = `npx storybook tools ${entry.id} ${toCliMethodName(methodName)}`;
  if (tools.mode === "local" && method.requiresDevServer) {
    let discovery = await (deps.discoverInstance ?? discoverRunningInstance)(invocation.target);
    return result({
      exitCode: 1,
      output: formatRequiresDevServer(commandPath, discovery, requestedMode),
      outcome: { kind: "intercept", reason: "requires-dev-server" }
    });
  }
  try {
    let outcome = await tools.call(method.ref, parsed.args, {
      ...tools.storybook.url ? { origin: tools.storybook.url } : {},
      ...deps.methodTelemetry ? { telemetry: deps.methodTelemetry } : {}
    }), output = parsed.json ? JSON.stringify(outcome.data, null, 2) : joinMarkdown(outcome.markdown);
    return result({
      exitCode: outcome.ok ? 0 : 1,
      output,
      outcome: { kind: outcome.ok ? "success" : "failure" }
    });
  } catch (error) {
    return isInvalidInputError(error) ? result({
      exitCode: 1,
      output: formatValidationIssues(commandPath, error.data.issues ?? []),
      outcome: { kind: "intercept", reason: "invalid-arguments" }
    }) : isAgentFacingError(error) ? result({ exitCode: 1, output: error.message, outcome: { kind: "failure" } }) : result({
      exitCode: 1,
      output: error instanceof Error ? error.message : String(error),
      outcome: { kind: "error", error }
    });
  }
}
function formatUnknownToolsetFromCatalog(toolsetName, catalog) {
  let available = catalog.toolsets.map((toolset) => `- \`${toolset.id}\``).join(`
`);
  return `Unknown toolset \`${toolsetName}\`. The Storybook configuration at ${catalog.configDir} provides:

${available}

Run \`npx storybook tools --help\` for every tool.`;
}
function formatUnknownToolFromCatalog(toolName, entry) {
  let available = entry.methods.map((method) => `- \`${toCliMethodName(parseToolsetMethodId(method.ref).methodName)}\``).join(`
`);
  return `Unknown tool \`${toolName}\`. The \`${entry.id}\` toolset provides:

${available}

Run \`npx storybook tools ${entry.id}\` for their descriptions.`;
}
function joinMarkdown(markdown) {
  return Array.isArray(markdown) ? markdown.join(`

`) : markdown;
}
function formatRequiresDevServer(commandPath, discovery, requestedMode) {
  if (discovery.currentRecord && requestedMode === "local")
    return `Found your Storybook running at ${discovery.currentRecord.url}, but \`${commandPath}\` cannot run from a local tools host. Re-run without \`--no-attach\` to attach to that instance.`;
  if (discovery.currentRecord)
    return `Found your Storybook running at ${discovery.currentRecord.url}, but \`${commandPath}\` could not attach to it. Start or restart that Storybook, then re-run this command.`;
  let lines = [
    `\`${commandPath}\` requires a running Storybook dev server, and none was found for this project. Start it first (for example \`npm run storybook\`), then re-run this command.`
  ];
  if (discovery.records.length > 0) {
    let candidates = discovery.records.map((record2) => `- ${record2.url} (cwd \`${record2.cwd}\`)`).join(`
`);
    lines.push(
      "",
      "Running Storybook instances that did not match this project \u2014 target one with `--cwd` or `--config-dir`:",
      candidates
    );
  }
  return lines.join(`
`);
}
function formatValidationIssues(commandPath, issues) {
  let lines = issues.map((issue) => {
    let path = issue.path?.map(
      (segment) => String(typeof segment == "object" && segment !== null ? segment.key : segment)
    ).join(".");
    return path ? `- \`${path}\`: ${issue.message}` : `- ${issue.message}`;
  });
  return `Invalid arguments for \`${commandPath}\`:

${lines.join(`
`)}

Run \`${commandPath} --help\` for the expected arguments.`;
}

// src/cli/tools/register.ts
function registerToolsPassthrough(program2, toolsCommand2, handleCommandFailure2) {
  program2.enablePositionalOptions(), toolsCommand2.helpOption(!1).usage("[options] [toolset] [tool] [args...]").argument("[toolset]", "A toolset provided by the target Storybook configuration").argument("[tool]", "One of the toolset's tools, e.g. `stories find-by-component`").argument(
    "[args...]",
    "Tool arguments as `--key value` flags; values are JSON-parsed when possible"
  );
  for (let { flags, description } of TOOLS_OPTION_SPECS) {
    if (flags === "--no-attach") {
      let option = new Option(flags, description);
      option.negate = !1, toolsCommand2.addOption(option);
      continue;
    }
    toolsCommand2.option(flags, description);
  }
  toolsCommand2.passThroughOptions().action(
    async (toolset, tool, tokens, options) => {
      let cliOptions = pickCliOptions2(options), flags = {
        input: options.input,
        json: options.json,
        output: options.output,
        help: options.help,
        attach: options.noAttach ? !1 : options.attach
      }, originalStdoutWrite = process.stdout.write;
      isJsonToolsRun(tokens, flags) && (process.stdout.write = process.stderr.write.bind(
        process.stderr
      ));
      try {
        await withTelemetry4(
          "tools-command",
          { cliOptions, fallbackTelemetryState: !0 },
          async () => {
            let keepAlive = setInterval(() => {
            }, 6e4), start = Date.now(), result;
            try {
              options.attach && options.noAttach ? result = {
                exitCode: 1,
                output: "Cannot combine `--attach` and `--no-attach`.",
                outcome: { kind: "intercept", reason: "invalid-arguments" },
                requestedMode: "auto",
                attachMode: "auto"
              } : result = await runToolsCommand(
                {
                  toolset,
                  tool,
                  tokens,
                  target: { cwd: options.cwd, configDir: options.configDir },
                  port: options.port,
                  attach: options.noAttach ? !1 : options.attach,
                  flags
                },
                { methodTelemetry: createMethodTelemetrySink(cliOptions) }
              );
            } finally {
              clearInterval(keepAlive);
            }
            let duration = Date.now() - start;
            try {
              await printResult3(result, originalStdoutWrite);
            } finally {
              await reportToolsCommandTelemetry(toolset, tool, result, duration, cliOptions);
            }
          }
        ).catch(handleCommandFailure2(options.logfile));
      } finally {
        process.stdout.write = originalStdoutWrite;
      }
      process.exit();
    }
  );
}
function pickCliOptions2(options) {
  let targetCwd = options.cwd ?? process.cwd();
  return {
    disableTelemetry: options.disableTelemetry,
    logfile: options.logfile,
    configDir: resolveStorybookConfigDir({ cwd: targetCwd, configDir: options.configDir })
  };
}
function createMethodTelemetrySink(cliOptions) {
  return async (event, payload) => {
    try {
      await telemetry4("tools-command", { event, ...payload }, { configDir: cliOptions.configDir });
    } catch (error) {
      logger3.debug(`Error collecting telemetry: ${String(error)}`);
    }
  };
}
function sanitizeNamePart(part) {
  return /^[\w-]{1,64}$/.test(part) ? part : "(invalid)";
}
async function reportToolsCommandTelemetry(toolset, tool, result, duration, cliOptions) {
  let { outcome } = result;
  if (outcome.kind === "help")
    return;
  let command2 = [toolset, tool].filter((part) => part !== void 0).map(sanitizeNamePart).join(" ") || "(none)";
  await telemetry4(
    "tools-command",
    {
      command: command2,
      success: outcome.kind === "success",
      outcome: outcome.kind,
      client: "cli",
      requestedMode: result.requestedMode,
      attachMode: result.attachMode,
      ...result.host && (result.attachMode === "attached" || result.attachMode === "local") ? { resolvedMode: result.attachMode } : {},
      ...result.host ? { host: result.host } : {},
      ...result.multipleMatches ? { multipleMatches: !0 } : {},
      ...result.fallbackReason ? { attachGate: result.fallbackReason } : {},
      ...outcome.kind === "attach-gate" ? { attachGate: outcome.reason } : {},
      ...outcome.kind === "intercept" ? { interceptReason: outcome.reason } : {},
      duration
    },
    // Metadata must describe the target project, consistent with the opt-out resolution.
    { configDir: cliOptions.configDir }
  ), outcome.kind === "error" && await sendTelemetryError2(outcome.error, "tools-command", { cliOptions });
}
async function printResult3({ output, exitCode, outputPath, fallbackNotice, multiInstanceNotice }, stdoutWrite) {
  for (let notice of [fallbackNotice, multiInstanceNotice])
    notice && await new Promise((resolveWrite) => {
      process.stderr.write(`${notice}
`, () => resolveWrite());
    });
  if (outputPath) {
    let resolvedPath = resolve5(outputPath);
    await writeFile3(resolvedPath, `${output}
`, "utf-8"), logger3.log(`Output written to ${resolvedPath}`);
  } else
    await new Promise((resolveWrite) => {
      stdoutWrite.call(process.stdout, `${output}
`, void 0, () => resolveWrite());
    });
  exitCode !== 0 && (process.exitCode = exitCode);
}

// src/cli/build.ts
import { cache as cache3 } from "storybook/internal/common";
import { buildStaticStandalone, withTelemetry as withTelemetry5 } from "storybook/internal/core-server";
var build = async (cliOptions) => {
  let { default: packageJson } = await import("storybook/package.json", { with: { type: "json" } }), options = {
    ...cliOptions,
    configDir: cliOptions.configDir || "./.storybook",
    outputDir: cliOptions.outputDir || "./storybook-static",
    ignorePreview: !!cliOptions.previewUrl && !cliOptions.forceBuildPreview,
    configType: "PRODUCTION",
    cache: cache3,
    packageJson
  };
  await withTelemetry5(
    "build",
    { cliOptions, presetOptions: options },
    () => buildStaticStandalone(options)
  );
};

// src/cli/buildIndex.ts
import { Channel } from "storybook/internal/channels";
import { cache as cache4 } from "storybook/internal/common";
import { buildIndexStandalone, withTelemetry as withTelemetry6 } from "storybook/internal/core-server";
var buildIndex = async (cliOptions) => {
  let options = {
    ...cliOptions,
    configDir: cliOptions.configDir || ".storybook",
    outputFile: cliOptions.outputFile || "index.json",
    ignorePreview: !0,
    configType: "PRODUCTION",
    cache: cache4,
    packageJson: cliOptions.packageJson
  }, presetOptions = {
    ...options,
    corePresets: [],
    overridePresets: [],
    channel: new Channel({})
  };
  await withTelemetry6("index", { cliOptions, presetOptions }, () => buildIndexStandalone(options));
};

// src/cli/dev.ts
var import_ts_dedent2 = __toESM(require_dist(), 1);
import { cache as cache5 } from "storybook/internal/common";
import { buildDevStandalone, withTelemetry as withTelemetry7 } from "storybook/internal/core-server";
import { logger as logger4, instance as npmLog } from "storybook/internal/node-logger";
function printError(error) {
  npmLog.heading = "", error instanceof Error ? error.error ? logger4.error(error.error) : error.stats && error.stats.compilation.errors ? error.stats.compilation.errors.forEach((e) => logger4.log(e)) : logger4.error(error) : error.compilation?.errors && error.compilation.errors.forEach((e) => logger4.log(e)), logger4.warn(
    error.close ? import_ts_dedent2.dedent`
          FATAL broken build!, will close the process,
          Fix the error below and restart storybook.
        ` : import_ts_dedent2.dedent`
          Broken build, fix the error above.
          You may need to refresh the browser.
        `
  );
}
var dev = async (cliOptions) => {
  let { env } = process;
  env.NODE_ENV = env.NODE_ENV || "development";
  let { default: packageJson } = await import("storybook/package.json", { with: { type: "json" } }), options = {
    ...cliOptions,
    configDir: cliOptions.configDir || "./.storybook",
    configType: "DEVELOPMENT",
    ignorePreview: !!cliOptions.previewUrl && !cliOptions.forceBuildPreview,
    cache: cache5,
    packageJson
  };
  await withTelemetry7(
    "dev",
    {
      cliOptions,
      presetOptions: options,
      printError
    },
    () => buildDevStandalone(options)
  );
};

// src/bin/dev-options.ts
import { HandledError } from "storybook/internal/common";
var PortSchema = message(
  pipe(
    union([pipe(string(), trim(), regex(/^\d+$/), transform(Number)), number()]),
    minValue(1),
    integer(),
    maxValue(65535)
  ),
  (issue) => `Port must be a valid number from 1 to 65535, received ${issue.received}.`
), DevOptionsSchema = looseObject({
  ci: optional(union([boolean(), string()])),
  configDir: optional(string()),
  host: optional(string()),
  open: optional(boolean()),
  port: optional(PortSchema),
  staticDir: optional(string())
});
function resolveDevCommandOptions(options, {
  env = process.env,
  agent = detectAgent()
} = {}) {
  let isClaudePreview = isClaudePreviewLaunch(env), isAgentSession = isClaudePreview || !!agent, PORT = env.PORT ?? void 0, SBCONFIG_PORT = env.SBCONFIG_PORT ?? void 0, result = safeParse(DevOptionsSchema, {
    ...options,
    host: env.SBCONFIG_HOSTNAME || options.host,
    staticDir: env.SBCONFIG_STATIC_DIR || options.staticDir,
    configDir: env.SBCONFIG_CONFIG_DIR || options.configDir,
    ci: env.CI || options.ci,
    port: isClaudePreview ? PORT ?? options.port ?? SBCONFIG_PORT : options.port ?? SBCONFIG_PORT ?? PORT,
    open: isAgentSession ? !1 : options.open
  });
  if (!result.success)
    throw new HandledError(summarize(result.issues));
  return result.output;
}

// src/bin/core.ts
addToGlobalContext("cliVersion", version);
process.env.STORYBOOK = "true";
var handleCommandFailure = async (logFilePath) => {
  try {
    let logFile = await logTracker.writeToFile(logFilePath);
    logger5.log(`Debug logs are written to: ${logFile}`);
  } catch {
  }
  logger5.outro("Storybook exited with an error"), process.exit(1);
}, command = (name) => program.command(name).option(
  "--disable-telemetry",
  "Disable sending telemetry data",
  optionalEnvToBoolean2(process.env.STORYBOOK_DISABLE_TELEMETRY)
).option("--debug", "Get more logs in debug mode", !1).option("--enable-crash-reports", "Enable sending crash reports to telemetry data").addOption(
  new Option("--loglevel <level>", "Define log level").choices(["trace", "debug", "info", "warn", "error", "silent"]).default("info")
).option(
  "--logfile [path]",
  "Write all debug logs to the specified file at the end of the run. Defaults to debug-storybook.log when [path] is not provided"
).hook("preAction", async (self) => {
  try {
    let options = self.opts(), loglevel = options.debug ? "debug" : options.loglevel;
    logger5.setLogLevel(loglevel), options.logfile && logTracker.enableLogWriting(), await globalSettings();
  } catch (e) {
    logger5.error(`Error loading global settings:
` + String(e));
  }
}).hook("postAction", async (command2) => {
  if (logTracker.shouldWriteLogsToFile)
    try {
      let logFile = await logTracker.writeToFile(command2.getOptionValue("logfile"));
      logger5.outro(`Debug logs are written to: ${logFile}`);
    } catch {
    }
  command2.name() === "build" && process.exit(0);
});
command("dev").option("-p, --port <number>", "Port to run Storybook").option("-h, --host <string>", "Host to run Storybook").option("-c, --config-dir <dir-name>", "Directory where to load Storybook configurations from").option(
  "--https",
  "Serve Storybook over HTTPS. Note: You must provide your own certificate information."
).option(
  "--ssl-ca <ca>",
  "Provide an SSL certificate authority. (Optional with --https, required if using a self-signed certificate)",
  parseList
).option("--ssl-cert <cert>", "Provide an SSL certificate. (Required with --https)").option("--ssl-key <key>", "Provide an SSL key. (Required with --https)").option("--smoke-test", "Exit after successful start").option("--ci", "CI mode (skip interactive prompts, don't open browser)").option("--no-open", "Do not open Storybook automatically in the browser").option("--quiet", "Suppress verbose build output").option("--no-version-updates", "Suppress update check", !0).option("--debug-webpack", "Display final webpack configurations for debugging purposes").option(
  "--webpack-stats-json [directory]",
  "Write Webpack stats JSON to disk (synonym for `--stats-json`)"
).option("--stats-json [directory]", "Write stats JSON to disk").option(
  "--preview-url <string>",
  "Disables the default storybook preview and lets your use your own"
).option("--force-build-preview", "Build the preview iframe even if you are using --preview-url").option("--docs", "Build a documentation-only site using addon-docs").option("--exact-port", "Exit early if the desired port is not available").option(
  "--initial-path [path]",
  "URL path to be appended when visiting Storybook for the first time"
).option("--preview-only", "Use the preview without the manager UI").action(async (options) => {
  let { default: packageJson } = await import("storybook/package.json", { with: { type: "json" } });
  logger5.intro(`${packageJson.name} v${packageJson.version}`);
  let resolvedOptions;
  try {
    resolvedOptions = resolveDevCommandOptions(options);
  } catch (error) {
    return logger5.error(error instanceof Error ? error.message : String(error)), handleCommandFailure(options.logfile);
  }
  await dev({ ...resolvedOptions, packageJson }).catch(() => {
    handleCommandFailure(options.logfile);
  });
});
command("build").option("-o, --output-dir <dir-name>", "Directory where to store built files").option("-c, --config-dir <dir-name>", "Directory where to load Storybook configurations from").option("--quiet", "Suppress verbose build output").option("--debug-webpack", "Display final webpack configurations for debugging purposes").option(
  "--webpack-stats-json [directory]",
  "Write Webpack stats JSON to disk (synonym for `--stats-json`)"
).option("--stats-json [directory]", "Write stats JSON to disk").option(
  "--preview-url <string>",
  "Disables the default storybook preview and lets your use your own"
).option("--force-build-preview", "Build the preview iframe even if you are using --preview-url").option("--docs", "Build a documentation-only site using addon-docs").option("--test", "Build stories optimized for testing purposes.").option("--preview-only", "Use the preview without the manager UI").action(async (options) => {
  let { env } = process;
  env.NODE_ENV = env.NODE_ENV || "production";
  let { default: packageJson } = await import("storybook/package.json", { with: { type: "json" } });
  logger5.intro(`Building ${packageJson.name} v${packageJson.version}`), getEnvConfig(options, {
    staticDir: "SBCONFIG_STATIC_DIR",
    outputDir: "SBCONFIG_OUTPUT_DIR",
    configDir: "SBCONFIG_CONFIG_DIR"
  }), await build({
    ...options,
    packageJson,
    test: !!options.test || optionalEnvToBoolean2(process.env.SB_TESTBUILD)
  }).catch(() => {
    logger5.outro("Storybook exited with an error"), process.exit(1);
  }), logger5.outro("Storybook build completed successfully");
});
command("index").option("-o, --output-file <file-name>", "JSON file to output index").option("-c, --config-dir <dir-name>", "Directory where to load Storybook configurations from").option("--quiet", "Suppress verbose build output").action(async (options) => {
  let { env } = process;
  env.NODE_ENV = env.NODE_ENV || "production";
  let { default: packageJson } = await import("storybook/package.json", { with: { type: "json" } });
  logger5.log(import_picocolors.default.bold(`${packageJson.name} v${packageJson.version}
`)), getEnvConfig(options, {
    configDir: "SBCONFIG_CONFIG_DIR",
    outputFile: "SBCONFIG_OUTPUT_FILE"
  }), await buildIndex({
    ...options,
    packageJson
  }).catch(() => process.exit(1));
});
var handleCliCommandFailure = (logFilePath) => async (error) => (error instanceof HandledError2 || logger5.error(String(error)), handleCommandFailure(logFilePath ?? !1)), aiCommand = command("ai").description("AI agent helpers for Storybook (deprecated \u2014 see `storybook skills`)").option(
  "-o, --output <path>",
  "Write the prompt output to a file instead of printing it to stdout"
);
aiCommand.command("setup").description(
  "Generate setup instructions to write stories for real components (deprecated: use `storybook skills setup`)"
).addOption(
  new Option("--package-manager <type>", "Force package manager for installing deps").choices(
    Object.values(PackageManagerName)
  )
).option("-c, --config-dir <dir-name>", "Directory of Storybook configuration").action(async (options, cmd) => {
  let parentOptions = cmd.parent?.opts() ?? {}, runId = Math.random().toString(36), mergedOptions = { ...parentOptions, ...options, runId };
  await withTelemetry("ai-setup", { cliOptions: mergedOptions }, async () => {
    await aiSetup(mergedOptions);
  }).catch(handleCliCommandFailure(mergedOptions.logfile));
});
aiCommand.action(() => {
  aiCommand.outputHelp();
});
isAiCliFeatureEnabled() && registerAiMcpPassthrough(program, aiCommand, handleCliCommandFailure);
var toolsCommand = command("tools").description(
  "Run the agent tools provided by the target Storybook configuration"
);
registerToolsPassthrough(program, toolsCommand, handleCliCommandFailure);
var skillsCommand = command("skills").description(
  "Agent skills served by the target Storybook configuration"
);
registerSkillsCommand(program, skillsCommand, handleCliCommandFailure);
program.on("command:*", ([invalidCmd]) => {
  let errorMessage = ` Invalid command: ${import_picocolors.default.bold(invalidCmd)}.
 See --help for a list of available commands.`, suggestion = program.commands.map((cmd) => cmd.name()).find((cmd) => leven(cmd, invalidCmd) < 3);
  suggestion && (errorMessage += `
 Did you mean ${import_picocolors.default.yellow(suggestion)}?`), logger5.error(errorMessage), process.exit(1);
});
program.usage("<command> [options]").version(String(version)).parse(process.argv);