@decipher-sdk/decipher-qa 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +736 -0
- package/package.json +33 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,736 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";var hi=Object.create;var Pe=Object.defineProperty;var ui=Object.getOwnPropertyDescriptor;var pi=Object.getOwnPropertyNames;var mi=Object.getPrototypeOf,fi=Object.prototype.hasOwnProperty;var b=(n,e)=>()=>(e||n((e={exports:{}}).exports,e),e.exports);var gi=(n,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of pi(e))!fi.call(n,s)&&s!==t&&Pe(n,s,{get:()=>e[s],enumerable:!(i=ui(e,s))||i.enumerable});return n};var C=(n,e,t)=>(t=n!=null?hi(mi(n)):{},gi(e||!n||!n.__esModule?Pe(t,"default",{value:n,enumerable:!0}):t,n));var F=b(se=>{"use strict";var W=class extends Error{constructor(e,t,i){super(i),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name,this.code=t,this.exitCode=e,this.nestedError=void 0}},ne=class extends W{constructor(e){super(1,"commander.invalidArgument",e),Error.captureStackTrace(this,this.constructor),this.name=this.constructor.name}};se.CommanderError=W;se.InvalidArgumentError=ne});var B=b(oe=>{"use strict";var{InvalidArgumentError:yi}=F(),re=class{constructor(e,t){switch(this.description=t||"",this.variadic=!1,this.parseArg=void 0,this.defaultValue=void 0,this.defaultValueDescription=void 0,this.argChoices=void 0,e[0]){case"<":this.required=!0,this._name=e.slice(1,-1);break;case"[":this.required=!1,this._name=e.slice(1,-1);break;default:this.required=!0,this._name=e;break}this._name.length>3&&this._name.slice(-3)==="..."&&(this.variadic=!0,this._name=this._name.slice(0,-3))}name(){return this._name}_concatValue(e,t){return t===this.defaultValue||!Array.isArray(t)?[e]:t.concat(e)}default(e,t){return this.defaultValue=e,this.defaultValueDescription=t,this}argParser(e){return this.parseArg=e,this}choices(e){return this.argChoices=e.slice(),this.parseArg=(t,i)=>{if(!this.argChoices.includes(t))throw new yi(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(t,i):t},this}argRequired(){return this.required=!0,this}argOptional(){return this.required=!1,this}};function bi(n){let e=n.name()+(n.variadic===!0?"...":"");return n.required?"<"+e+">":"["+e+"]"}oe.Argument=re;oe.humanReadableArgName=bi});var le=b(Ne=>{"use strict";var{humanReadableArgName:wi}=B(),ae=class{constructor(){this.helpWidth=void 0,this.sortSubcommands=!1,this.sortOptions=!1,this.showGlobalOptions=!1}visibleCommands(e){let t=e.commands.filter(s=>!s._hidden),i=e._getHelpCommand();return i&&!i._hidden&&t.push(i),this.sortSubcommands&&t.sort((s,r)=>s.name().localeCompare(r.name())),t}compareOptions(e,t){let i=s=>s.short?s.short.replace(/^-/,""):s.long.replace(/^--/,"");return i(e).localeCompare(i(t))}visibleOptions(e){let t=e.options.filter(s=>!s.hidden),i=e._getHelpOption();if(i&&!i.hidden){let s=i.short&&e._findOption(i.short),r=i.long&&e._findOption(i.long);!s&&!r?t.push(i):i.long&&!r?t.push(e.createOption(i.long,i.description)):i.short&&!s&&t.push(e.createOption(i.short,i.description))}return this.sortOptions&&t.sort(this.compareOptions),t}visibleGlobalOptions(e){if(!this.showGlobalOptions)return[];let t=[];for(let i=e.parent;i;i=i.parent){let s=i.options.filter(r=>!r.hidden);t.push(...s)}return this.sortOptions&&t.sort(this.compareOptions),t}visibleArguments(e){return e._argsDescription&&e.registeredArguments.forEach(t=>{t.description=t.description||e._argsDescription[t.name()]||""}),e.registeredArguments.find(t=>t.description)?e.registeredArguments:[]}subcommandTerm(e){let t=e.registeredArguments.map(i=>wi(i)).join(" ");return e._name+(e._aliases[0]?"|"+e._aliases[0]:"")+(e.options.length?" [options]":"")+(t?" "+t:"")}optionTerm(e){return e.flags}argumentTerm(e){return e.name()}longestSubcommandTermLength(e,t){return t.visibleCommands(e).reduce((i,s)=>Math.max(i,t.subcommandTerm(s).length),0)}longestOptionTermLength(e,t){return t.visibleOptions(e).reduce((i,s)=>Math.max(i,t.optionTerm(s).length),0)}longestGlobalOptionTermLength(e,t){return t.visibleGlobalOptions(e).reduce((i,s)=>Math.max(i,t.optionTerm(s).length),0)}longestArgumentTermLength(e,t){return t.visibleArguments(e).reduce((i,s)=>Math.max(i,t.argumentTerm(s).length),0)}commandUsage(e){let t=e._name;e._aliases[0]&&(t=t+"|"+e._aliases[0]);let i="";for(let s=e.parent;s;s=s.parent)i=s.name()+" "+i;return i+t+" "+e.usage()}commandDescription(e){return e.description()}subcommandDescription(e){return e.summary()||e.description()}optionDescription(e){let t=[];return e.argChoices&&t.push(`choices: ${e.argChoices.map(i=>JSON.stringify(i)).join(", ")}`),e.defaultValue!==void 0&&(e.required||e.optional||e.isBoolean()&&typeof e.defaultValue=="boolean")&&t.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),e.presetArg!==void 0&&e.optional&&t.push(`preset: ${JSON.stringify(e.presetArg)}`),e.envVar!==void 0&&t.push(`env: ${e.envVar}`),t.length>0?`${e.description} (${t.join(", ")})`:e.description}argumentDescription(e){let t=[];if(e.argChoices&&t.push(`choices: ${e.argChoices.map(i=>JSON.stringify(i)).join(", ")}`),e.defaultValue!==void 0&&t.push(`default: ${e.defaultValueDescription||JSON.stringify(e.defaultValue)}`),t.length>0){let i=`(${t.join(", ")})`;return e.description?`${e.description} ${i}`:i}return e.description}formatHelp(e,t){let i=t.padWidth(e,t),s=t.helpWidth||80,r=2,o=2;function a(g,S){if(S){let ie=`${g.padEnd(i+o)}${S}`;return t.wrap(ie,s-r,i+o)}return g}function l(g){return g.join(`
|
|
3
|
+
`).replace(/^/gm," ".repeat(r))}let c=[`Usage: ${t.commandUsage(e)}`,""],h=t.commandDescription(e);h.length>0&&(c=c.concat([t.wrap(h,s,0),""]));let p=t.visibleArguments(e).map(g=>a(t.argumentTerm(g),t.argumentDescription(g)));p.length>0&&(c=c.concat(["Arguments:",l(p),""]));let w=t.visibleOptions(e).map(g=>a(t.optionTerm(g),t.optionDescription(g)));if(w.length>0&&(c=c.concat(["Options:",l(w),""])),this.showGlobalOptions){let g=t.visibleGlobalOptions(e).map(S=>a(t.optionTerm(S),t.optionDescription(S)));g.length>0&&(c=c.concat(["Global Options:",l(g),""]))}let P=t.visibleCommands(e).map(g=>a(t.subcommandTerm(g),t.subcommandDescription(g)));return P.length>0&&(c=c.concat(["Commands:",l(P),""])),c.join(`
|
|
4
|
+
`)}padWidth(e,t){return Math.max(t.longestOptionTermLength(e,t),t.longestGlobalOptionTermLength(e,t),t.longestSubcommandTermLength(e,t),t.longestArgumentTermLength(e,t))}wrap(e,t,i,s=40){let r=" \\f\\t\\v\xA0\u1680\u2000-\u200A\u202F\u205F\u3000\uFEFF",o=new RegExp(`[\\n][${r}]+`);if(e.match(o))return e;let a=t-i;if(a<s)return e;let l=e.slice(0,i),c=e.slice(i).replace(`\r
|
|
5
|
+
`,`
|
|
6
|
+
`),h=" ".repeat(i),w="\\s\u200B",P=new RegExp(`
|
|
7
|
+
|.{1,${a-1}}([${w}]|$)|[^${w}]+?([${w}]|$)`,"g"),g=c.match(P)||[];return l+g.map((S,ie)=>S===`
|
|
8
|
+
`?"":(ie>0?h:"")+S.trimEnd()).join(`
|
|
9
|
+
`)}};Ne.Help=ae});var ue=b(he=>{"use strict";var{InvalidArgumentError:Ci}=F(),ce=class{constructor(e,t){this.flags=e,this.description=t||"",this.required=e.includes("<"),this.optional=e.includes("["),this.variadic=/\w\.\.\.[>\]]$/.test(e),this.mandatory=!1;let i=ki(e);this.short=i.shortFlag,this.long=i.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}default(e,t){return this.defaultValue=e,this.defaultValueDescription=t,this}preset(e){return this.presetArg=e,this}conflicts(e){return this.conflictsWith=this.conflictsWith.concat(e),this}implies(e){let t=e;return typeof e=="string"&&(t={[e]:!0}),this.implied=Object.assign(this.implied||{},t),this}env(e){return this.envVar=e,this}argParser(e){return this.parseArg=e,this}makeOptionMandatory(e=!0){return this.mandatory=!!e,this}hideHelp(e=!0){return this.hidden=!!e,this}_concatValue(e,t){return t===this.defaultValue||!Array.isArray(t)?[e]:t.concat(e)}choices(e){return this.argChoices=e.slice(),this.parseArg=(t,i)=>{if(!this.argChoices.includes(t))throw new Ci(`Allowed choices are ${this.argChoices.join(", ")}.`);return this.variadic?this._concatValue(t,i):t},this}name(){return this.long?this.long.replace(/^--/,""):this.short.replace(/^-/,"")}attributeName(){return vi(this.name().replace(/^no-/,""))}is(e){return this.short===e||this.long===e}isBoolean(){return!this.required&&!this.optional&&!this.negate}},de=class{constructor(e){this.positiveOptions=new Map,this.negativeOptions=new Map,this.dualOptions=new Set,e.forEach(t=>{t.negate?this.negativeOptions.set(t.attributeName(),t):this.positiveOptions.set(t.attributeName(),t)}),this.negativeOptions.forEach((t,i)=>{this.positiveOptions.has(i)&&this.dualOptions.add(i)})}valueFromOption(e,t){let i=t.attributeName();if(!this.dualOptions.has(i))return!0;let s=this.negativeOptions.get(i).presetArg,r=s!==void 0?s:!1;return t.negate===(r===e)}};function vi(n){return n.split("-").reduce((e,t)=>e+t[0].toUpperCase()+t.slice(1))}function ki(n){let e,t,i=n.split(/[ |,]+/);return i.length>1&&!/^[[<]/.test(i[1])&&(e=i.shift()),t=i.shift(),!e&&/^-[^-]$/.test(t)&&(e=t,t=void 0),{shortFlag:e,longFlag:t}}he.Option=ce;he.DualOptions=de});var $e=b(De=>{"use strict";function _i(n,e){if(Math.abs(n.length-e.length)>3)return Math.max(n.length,e.length);let t=[];for(let i=0;i<=n.length;i++)t[i]=[i];for(let i=0;i<=e.length;i++)t[0][i]=i;for(let i=1;i<=e.length;i++)for(let s=1;s<=n.length;s++){let r=1;n[s-1]===e[i-1]?r=0:r=1,t[s][i]=Math.min(t[s-1][i]+1,t[s][i-1]+1,t[s-1][i-1]+r),s>1&&i>1&&n[s-1]===e[i-2]&&n[s-2]===e[i-1]&&(t[s][i]=Math.min(t[s][i],t[s-2][i-2]+1))}return t[n.length][e.length]}function Ai(n,e){if(!e||e.length===0)return"";e=Array.from(new Set(e));let t=n.startsWith("--");t&&(n=n.slice(2),e=e.map(o=>o.slice(2)));let i=[],s=3,r=.4;return e.forEach(o=>{if(o.length<=1)return;let a=_i(n,o),l=Math.max(n.length,o.length);(l-a)/l>r&&(a<s?(s=a,i=[o]):a===s&&i.push(o))}),i.sort((o,a)=>o.localeCompare(a)),t&&(i=i.map(o=>`--${o}`)),i.length>1?`
|
|
10
|
+
(Did you mean one of ${i.join(", ")}?)`:i.length===1?`
|
|
11
|
+
(Did you mean ${i[0]}?)`:""}De.suggestSimilar=Ai});var Fe=b(Ve=>{"use strict";var Oi=require("events").EventEmitter,pe=require("child_process"),A=require("path"),me=require("fs"),f=require("process"),{Argument:xi,humanReadableArgName:Si}=B(),{CommanderError:fe}=F(),{Help:Ei}=le(),{Option:Le,DualOptions:Ii}=ue(),{suggestSimilar:Me}=$e(),ge=class n extends Oi{constructor(e){super(),this.commands=[],this.options=[],this.parent=null,this._allowUnknownOption=!1,this._allowExcessArguments=!0,this.registeredArguments=[],this._args=this.registeredArguments,this.args=[],this.rawArgs=[],this.processedArgs=[],this._scriptPath=null,this._name=e||"",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._outputConfiguration={writeOut:t=>f.stdout.write(t),writeErr:t=>f.stderr.write(t),getOutHelpWidth:()=>f.stdout.isTTY?f.stdout.columns:void 0,getErrHelpWidth:()=>f.stderr.isTTY?f.stderr.columns:void 0,outputError:(t,i)=>i(t)},this._hidden=!1,this._helpOption=void 0,this._addImplicitHelpCommand=void 0,this._helpCommand=void 0,this._helpConfiguration={}}copyInheritedSettings(e){return this._outputConfiguration=e._outputConfiguration,this._helpOption=e._helpOption,this._helpCommand=e._helpCommand,this._helpConfiguration=e._helpConfiguration,this._exitCallback=e._exitCallback,this._storeOptionsAsProperties=e._storeOptionsAsProperties,this._combineFlagAndOptionalValue=e._combineFlagAndOptionalValue,this._allowExcessArguments=e._allowExcessArguments,this._enablePositionalOptions=e._enablePositionalOptions,this._showHelpAfterError=e._showHelpAfterError,this._showSuggestionAfterError=e._showSuggestionAfterError,this}_getCommandAndAncestors(){let e=[];for(let t=this;t;t=t.parent)e.push(t);return e}command(e,t,i){let s=t,r=i;typeof s=="object"&&s!==null&&(r=s,s=null),r=r||{};let[,o,a]=e.match(/([^ ]+) *(.*)/),l=this.createCommand(o);return s&&(l.description(s),l._executableHandler=!0),r.isDefault&&(this._defaultCommandName=l._name),l._hidden=!!(r.noHelp||r.hidden),l._executableFile=r.executableFile||null,a&&l.arguments(a),this._registerCommand(l),l.parent=this,l.copyInheritedSettings(this),s?this:l}createCommand(e){return new n(e)}createHelp(){return Object.assign(new Ei,this.configureHelp())}configureHelp(e){return e===void 0?this._helpConfiguration:(this._helpConfiguration=e,this)}configureOutput(e){return e===void 0?this._outputConfiguration:(Object.assign(this._outputConfiguration,e),this)}showHelpAfterError(e=!0){return typeof e!="string"&&(e=!!e),this._showHelpAfterError=e,this}showSuggestionAfterError(e=!0){return this._showSuggestionAfterError=!!e,this}addCommand(e,t){if(!e._name)throw new Error(`Command passed to .addCommand() must have a name
|
|
12
|
+
- specify the name in Command constructor or using .name()`);return t=t||{},t.isDefault&&(this._defaultCommandName=e._name),(t.noHelp||t.hidden)&&(e._hidden=!0),this._registerCommand(e),e.parent=this,e._checkForBrokenPassThrough(),this}createArgument(e,t){return new xi(e,t)}argument(e,t,i,s){let r=this.createArgument(e,t);return typeof i=="function"?r.default(s).argParser(i):r.default(i),this.addArgument(r),this}arguments(e){return e.trim().split(/ +/).forEach(t=>{this.argument(t)}),this}addArgument(e){let t=this.registeredArguments.slice(-1)[0];if(t&&t.variadic)throw new Error(`only the last argument can be variadic '${t.name()}'`);if(e.required&&e.defaultValue!==void 0&&e.parseArg===void 0)throw new Error(`a default value for a required argument is never used: '${e.name()}'`);return this.registeredArguments.push(e),this}helpCommand(e,t){if(typeof e=="boolean")return this._addImplicitHelpCommand=e,this;e=e??"help [command]";let[,i,s]=e.match(/([^ ]+) *(.*)/),r=t??"display help for command",o=this.createCommand(i);return o.helpOption(!1),s&&o.arguments(s),r&&o.description(r),this._addImplicitHelpCommand=!0,this._helpCommand=o,this}addHelpCommand(e,t){return typeof e!="object"?(this.helpCommand(e,t),this):(this._addImplicitHelpCommand=!0,this._helpCommand=e,this)}_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}hook(e,t){let i=["preSubcommand","preAction","postAction"];if(!i.includes(e))throw new Error(`Unexpected value for event passed to hook : '${e}'.
|
|
13
|
+
Expecting one of '${i.join("', '")}'`);return this._lifeCycleHooks[e]?this._lifeCycleHooks[e].push(t):this._lifeCycleHooks[e]=[t],this}exitOverride(e){return e?this._exitCallback=e:this._exitCallback=t=>{if(t.code!=="commander.executeSubCommandAsync")throw t},this}_exit(e,t,i){this._exitCallback&&this._exitCallback(new fe(e,t,i)),f.exit(e)}action(e){let t=i=>{let s=this.registeredArguments.length,r=i.slice(0,s);return this._storeOptionsAsProperties?r[s]=this:r[s]=this.opts(),r.push(this),e.apply(this,r)};return this._actionHandler=t,this}createOption(e,t){return new Le(e,t)}_callParseArg(e,t,i,s){try{return e.parseArg(t,i)}catch(r){if(r.code==="commander.invalidArgument"){let o=`${s} ${r.message}`;this.error(o,{exitCode:r.exitCode,code:r.code})}throw r}}_registerOption(e){let t=e.short&&this._findOption(e.short)||e.long&&this._findOption(e.long);if(t){let i=e.long&&this._findOption(e.long)?e.long:e.short;throw new Error(`Cannot add option '${e.flags}'${this._name&&` to command '${this._name}'`} due to conflicting flag '${i}'
|
|
14
|
+
- already used by option '${t.flags}'`)}this.options.push(e)}_registerCommand(e){let t=s=>[s.name()].concat(s.aliases()),i=t(e).find(s=>this._findCommand(s));if(i){let s=t(this._findCommand(i)).join("|"),r=t(e).join("|");throw new Error(`cannot add command '${r}' as already have command '${s}'`)}this.commands.push(e)}addOption(e){this._registerOption(e);let t=e.name(),i=e.attributeName();if(e.negate){let r=e.long.replace(/^--no-/,"--");this._findOption(r)||this.setOptionValueWithSource(i,e.defaultValue===void 0?!0:e.defaultValue,"default")}else e.defaultValue!==void 0&&this.setOptionValueWithSource(i,e.defaultValue,"default");let s=(r,o,a)=>{r==null&&e.presetArg!==void 0&&(r=e.presetArg);let l=this.getOptionValue(i);r!==null&&e.parseArg?r=this._callParseArg(e,r,l,o):r!==null&&e.variadic&&(r=e._concatValue(r,l)),r==null&&(e.negate?r=!1:e.isBoolean()||e.optional?r=!0:r=""),this.setOptionValueWithSource(i,r,a)};return this.on("option:"+t,r=>{let o=`error: option '${e.flags}' argument '${r}' is invalid.`;s(r,o,"cli")}),e.envVar&&this.on("optionEnv:"+t,r=>{let o=`error: option '${e.flags}' value '${r}' from env '${e.envVar}' is invalid.`;s(r,o,"env")}),this}_optionEx(e,t,i,s,r){if(typeof t=="object"&&t instanceof Le)throw new Error("To add an Option object use addOption() instead of option() or requiredOption()");let o=this.createOption(t,i);if(o.makeOptionMandatory(!!e.mandatory),typeof s=="function")o.default(r).argParser(s);else if(s instanceof RegExp){let a=s;s=(l,c)=>{let h=a.exec(l);return h?h[0]:c},o.default(r).argParser(s)}else o.default(s);return this.addOption(o)}option(e,t,i,s){return this._optionEx({},e,t,i,s)}requiredOption(e,t,i,s){return this._optionEx({mandatory:!0},e,t,i,s)}combineFlagAndOptionalValue(e=!0){return this._combineFlagAndOptionalValue=!!e,this}allowUnknownOption(e=!0){return this._allowUnknownOption=!!e,this}allowExcessArguments(e=!0){return this._allowExcessArguments=!!e,this}enablePositionalOptions(e=!0){return this._enablePositionalOptions=!!e,this}passThroughOptions(e=!0){return this._passThroughOptions=!!e,this._checkForBrokenPassThrough(),this}_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)`)}storeOptionsAsProperties(e=!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=!!e,this}getOptionValue(e){return this._storeOptionsAsProperties?this[e]:this._optionValues[e]}setOptionValue(e,t){return this.setOptionValueWithSource(e,t,void 0)}setOptionValueWithSource(e,t,i){return this._storeOptionsAsProperties?this[e]=t:this._optionValues[e]=t,this._optionValueSources[e]=i,this}getOptionValueSource(e){return this._optionValueSources[e]}getOptionValueSourceWithGlobals(e){let t;return this._getCommandAndAncestors().forEach(i=>{i.getOptionValueSource(e)!==void 0&&(t=i.getOptionValueSource(e))}),t}_prepareUserArgs(e,t){if(e!==void 0&&!Array.isArray(e))throw new Error("first parameter to parse must be array or undefined");if(t=t||{},e===void 0&&t.from===void 0){f.versions?.electron&&(t.from="electron");let s=f.execArgv??[];(s.includes("-e")||s.includes("--eval")||s.includes("-p")||s.includes("--print"))&&(t.from="eval")}e===void 0&&(e=f.argv),this.rawArgs=e.slice();let i;switch(t.from){case void 0:case"node":this._scriptPath=e[1],i=e.slice(2);break;case"electron":f.defaultApp?(this._scriptPath=e[1],i=e.slice(2)):i=e.slice(1);break;case"user":i=e.slice(0);break;case"eval":i=e.slice(1);break;default:throw new Error(`unexpected parse option { from: '${t.from}' }`)}return!this._name&&this._scriptPath&&this.nameFromFilename(this._scriptPath),this._name=this._name||"program",i}parse(e,t){let i=this._prepareUserArgs(e,t);return this._parseCommand([],i),this}async parseAsync(e,t){let i=this._prepareUserArgs(e,t);return await this._parseCommand([],i),this}_executeSubCommand(e,t){t=t.slice();let i=!1,s=[".js",".ts",".tsx",".mjs",".cjs"];function r(h,p){let w=A.resolve(h,p);if(me.existsSync(w))return w;if(s.includes(A.extname(p)))return;let P=s.find(g=>me.existsSync(`${w}${g}`));if(P)return`${w}${P}`}this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let o=e._executableFile||`${this._name}-${e._name}`,a=this._executableDir||"";if(this._scriptPath){let h;try{h=me.realpathSync(this._scriptPath)}catch{h=this._scriptPath}a=A.resolve(A.dirname(h),a)}if(a){let h=r(a,o);if(!h&&!e._executableFile&&this._scriptPath){let p=A.basename(this._scriptPath,A.extname(this._scriptPath));p!==this._name&&(h=r(a,`${p}-${e._name}`))}o=h||o}i=s.includes(A.extname(o));let l;f.platform!=="win32"?i?(t.unshift(o),t=Ue(f.execArgv).concat(t),l=pe.spawn(f.argv[0],t,{stdio:"inherit"})):l=pe.spawn(o,t,{stdio:"inherit"}):(t.unshift(o),t=Ue(f.execArgv).concat(t),l=pe.spawn(f.execPath,t,{stdio:"inherit"})),l.killed||["SIGUSR1","SIGUSR2","SIGTERM","SIGINT","SIGHUP"].forEach(p=>{f.on(p,()=>{l.killed===!1&&l.exitCode===null&&l.kill(p)})});let c=this._exitCallback;l.on("close",h=>{h=h??1,c?c(new fe(h,"commander.executeSubCommandAsync","(close)")):f.exit(h)}),l.on("error",h=>{if(h.code==="ENOENT"){let p=a?`searched for local subcommand relative to directory '${a}'`:"no directory for search for local subcommand, use .executableDir() to supply a custom directory",w=`'${o}' does not exist
|
|
15
|
+
- if '${e._name}' is not meant to be an executable command, remove description parameter from '.command()' and use '.description()' instead
|
|
16
|
+
- if the default executable name is not suitable, use the executableFile option to supply a custom name or path
|
|
17
|
+
- ${p}`;throw new Error(w)}else if(h.code==="EACCES")throw new Error(`'${o}' not executable`);if(!c)f.exit(1);else{let p=new fe(1,"commander.executeSubCommandAsync","(error)");p.nestedError=h,c(p)}}),this.runningCommand=l}_dispatchSubcommand(e,t,i){let s=this._findCommand(e);s||this.help({error:!0});let r;return r=this._chainOrCallSubCommandHook(r,s,"preSubcommand"),r=this._chainOrCall(r,()=>{if(s._executableHandler)this._executeSubCommand(s,t.concat(i));else return s._parseCommand(t,i)}),r}_dispatchHelpCommand(e){e||this.help();let t=this._findCommand(e);return t&&!t._executableHandler&&t.help(),this._dispatchSubcommand(e,[],[this._getHelpOption()?.long??this._getHelpOption()?.short??"--help"])}_checkNumberOfArguments(){this.registeredArguments.forEach((e,t)=>{e.required&&this.args[t]==null&&this.missingArgument(e.name())}),!(this.registeredArguments.length>0&&this.registeredArguments[this.registeredArguments.length-1].variadic)&&this.args.length>this.registeredArguments.length&&this._excessArguments(this.args)}_processArguments(){let e=(i,s,r)=>{let o=s;if(s!==null&&i.parseArg){let a=`error: command-argument value '${s}' is invalid for argument '${i.name()}'.`;o=this._callParseArg(i,s,r,a)}return o};this._checkNumberOfArguments();let t=[];this.registeredArguments.forEach((i,s)=>{let r=i.defaultValue;i.variadic?s<this.args.length?(r=this.args.slice(s),i.parseArg&&(r=r.reduce((o,a)=>e(i,a,o),i.defaultValue))):r===void 0&&(r=[]):s<this.args.length&&(r=this.args[s],i.parseArg&&(r=e(i,r,i.defaultValue))),t[s]=r}),this.processedArgs=t}_chainOrCall(e,t){return e&&e.then&&typeof e.then=="function"?e.then(()=>t()):t()}_chainOrCallHooks(e,t){let i=e,s=[];return this._getCommandAndAncestors().reverse().filter(r=>r._lifeCycleHooks[t]!==void 0).forEach(r=>{r._lifeCycleHooks[t].forEach(o=>{s.push({hookedCommand:r,callback:o})})}),t==="postAction"&&s.reverse(),s.forEach(r=>{i=this._chainOrCall(i,()=>r.callback(r.hookedCommand,this))}),i}_chainOrCallSubCommandHook(e,t,i){let s=e;return this._lifeCycleHooks[i]!==void 0&&this._lifeCycleHooks[i].forEach(r=>{s=this._chainOrCall(s,()=>r(this,t))}),s}_parseCommand(e,t){let i=this.parseOptions(t);if(this._parseOptionsEnv(),this._parseOptionsImplied(),e=e.concat(i.operands),t=i.unknown,this.args=e.concat(t),e&&this._findCommand(e[0]))return this._dispatchSubcommand(e[0],e.slice(1),t);if(this._getHelpCommand()&&e[0]===this._getHelpCommand().name())return this._dispatchHelpCommand(e[1]);if(this._defaultCommandName)return this._outputHelpIfRequested(t),this._dispatchSubcommand(this._defaultCommandName,e,t);this.commands.length&&this.args.length===0&&!this._actionHandler&&!this._defaultCommandName&&this.help({error:!0}),this._outputHelpIfRequested(i.unknown),this._checkForMissingMandatoryOptions(),this._checkForConflictingOptions();let s=()=>{i.unknown.length>0&&this.unknownOption(i.unknown[0])},r=`command:${this.name()}`;if(this._actionHandler){s(),this._processArguments();let o;return o=this._chainOrCallHooks(o,"preAction"),o=this._chainOrCall(o,()=>this._actionHandler(this.processedArgs)),this.parent&&(o=this._chainOrCall(o,()=>{this.parent.emit(r,e,t)})),o=this._chainOrCallHooks(o,"postAction"),o}if(this.parent&&this.parent.listenerCount(r))s(),this._processArguments(),this.parent.emit(r,e,t);else if(e.length){if(this._findCommand("*"))return this._dispatchSubcommand("*",e,t);this.listenerCount("command:*")?this.emit("command:*",e,t):this.commands.length?this.unknownCommand():(s(),this._processArguments())}else this.commands.length?(s(),this.help({error:!0})):(s(),this._processArguments())}_findCommand(e){if(e)return this.commands.find(t=>t._name===e||t._aliases.includes(e))}_findOption(e){return this.options.find(t=>t.is(e))}_checkForMissingMandatoryOptions(){this._getCommandAndAncestors().forEach(e=>{e.options.forEach(t=>{t.mandatory&&e.getOptionValue(t.attributeName())===void 0&&e.missingMandatoryOptionValue(t)})})}_checkForConflictingLocalOptions(){let e=this.options.filter(i=>{let s=i.attributeName();return this.getOptionValue(s)===void 0?!1:this.getOptionValueSource(s)!=="default"});e.filter(i=>i.conflictsWith.length>0).forEach(i=>{let s=e.find(r=>i.conflictsWith.includes(r.attributeName()));s&&this._conflictingOption(i,s)})}_checkForConflictingOptions(){this._getCommandAndAncestors().forEach(e=>{e._checkForConflictingLocalOptions()})}parseOptions(e){let t=[],i=[],s=t,r=e.slice();function o(l){return l.length>1&&l[0]==="-"}let a=null;for(;r.length;){let l=r.shift();if(l==="--"){s===i&&s.push(l),s.push(...r);break}if(a&&!o(l)){this.emit(`option:${a.name()}`,l);continue}if(a=null,o(l)){let c=this._findOption(l);if(c){if(c.required){let h=r.shift();h===void 0&&this.optionMissingArgument(c),this.emit(`option:${c.name()}`,h)}else if(c.optional){let h=null;r.length>0&&!o(r[0])&&(h=r.shift()),this.emit(`option:${c.name()}`,h)}else this.emit(`option:${c.name()}`);a=c.variadic?c:null;continue}}if(l.length>2&&l[0]==="-"&&l[1]!=="-"){let c=this._findOption(`-${l[1]}`);if(c){c.required||c.optional&&this._combineFlagAndOptionalValue?this.emit(`option:${c.name()}`,l.slice(2)):(this.emit(`option:${c.name()}`),r.unshift(`-${l.slice(2)}`));continue}}if(/^--[^=]+=/.test(l)){let c=l.indexOf("="),h=this._findOption(l.slice(0,c));if(h&&(h.required||h.optional)){this.emit(`option:${h.name()}`,l.slice(c+1));continue}}if(o(l)&&(s=i),(this._enablePositionalOptions||this._passThroughOptions)&&t.length===0&&i.length===0){if(this._findCommand(l)){t.push(l),r.length>0&&i.push(...r);break}else if(this._getHelpCommand()&&l===this._getHelpCommand().name()){t.push(l),r.length>0&&t.push(...r);break}else if(this._defaultCommandName){i.push(l),r.length>0&&i.push(...r);break}}if(this._passThroughOptions){s.push(l),r.length>0&&s.push(...r);break}s.push(l)}return{operands:t,unknown:i}}opts(){if(this._storeOptionsAsProperties){let e={},t=this.options.length;for(let i=0;i<t;i++){let s=this.options[i].attributeName();e[s]=s===this._versionOptionName?this._version:this[s]}return e}return this._optionValues}optsWithGlobals(){return this._getCommandAndAncestors().reduce((e,t)=>Object.assign(e,t.opts()),{})}error(e,t){this._outputConfiguration.outputError(`${e}
|
|
18
|
+
`,this._outputConfiguration.writeErr),typeof this._showHelpAfterError=="string"?this._outputConfiguration.writeErr(`${this._showHelpAfterError}
|
|
19
|
+
`):this._showHelpAfterError&&(this._outputConfiguration.writeErr(`
|
|
20
|
+
`),this.outputHelp({error:!0}));let i=t||{},s=i.exitCode||1,r=i.code||"commander.error";this._exit(s,r,e)}_parseOptionsEnv(){this.options.forEach(e=>{if(e.envVar&&e.envVar in f.env){let t=e.attributeName();(this.getOptionValue(t)===void 0||["default","config","env"].includes(this.getOptionValueSource(t)))&&(e.required||e.optional?this.emit(`optionEnv:${e.name()}`,f.env[e.envVar]):this.emit(`optionEnv:${e.name()}`))}})}_parseOptionsImplied(){let e=new Ii(this.options),t=i=>this.getOptionValue(i)!==void 0&&!["default","implied"].includes(this.getOptionValueSource(i));this.options.filter(i=>i.implied!==void 0&&t(i.attributeName())&&e.valueFromOption(this.getOptionValue(i.attributeName()),i)).forEach(i=>{Object.keys(i.implied).filter(s=>!t(s)).forEach(s=>{this.setOptionValueWithSource(s,i.implied[s],"implied")})})}missingArgument(e){let t=`error: missing required argument '${e}'`;this.error(t,{code:"commander.missingArgument"})}optionMissingArgument(e){let t=`error: option '${e.flags}' argument missing`;this.error(t,{code:"commander.optionMissingArgument"})}missingMandatoryOptionValue(e){let t=`error: required option '${e.flags}' not specified`;this.error(t,{code:"commander.missingMandatoryOptionValue"})}_conflictingOption(e,t){let i=o=>{let a=o.attributeName(),l=this.getOptionValue(a),c=this.options.find(p=>p.negate&&a===p.attributeName()),h=this.options.find(p=>!p.negate&&a===p.attributeName());return c&&(c.presetArg===void 0&&l===!1||c.presetArg!==void 0&&l===c.presetArg)?c:h||o},s=o=>{let a=i(o),l=a.attributeName();return this.getOptionValueSource(l)==="env"?`environment variable '${a.envVar}'`:`option '${a.flags}'`},r=`error: ${s(e)} cannot be used with ${s(t)}`;this.error(r,{code:"commander.conflictingOption"})}unknownOption(e){if(this._allowUnknownOption)return;let t="";if(e.startsWith("--")&&this._showSuggestionAfterError){let s=[],r=this;do{let o=r.createHelp().visibleOptions(r).filter(a=>a.long).map(a=>a.long);s=s.concat(o),r=r.parent}while(r&&!r._enablePositionalOptions);t=Me(e,s)}let i=`error: unknown option '${e}'${t}`;this.error(i,{code:"commander.unknownOption"})}_excessArguments(e){if(this._allowExcessArguments)return;let t=this.registeredArguments.length,i=t===1?"":"s",r=`error: too many arguments${this.parent?` for '${this.name()}'`:""}. Expected ${t} argument${i} but got ${e.length}.`;this.error(r,{code:"commander.excessArguments"})}unknownCommand(){let e=this.args[0],t="";if(this._showSuggestionAfterError){let s=[];this.createHelp().visibleCommands(this).forEach(r=>{s.push(r.name()),r.alias()&&s.push(r.alias())}),t=Me(e,s)}let i=`error: unknown command '${e}'${t}`;this.error(i,{code:"commander.unknownCommand"})}version(e,t,i){if(e===void 0)return this._version;this._version=e,t=t||"-V, --version",i=i||"output the version number";let s=this.createOption(t,i);return this._versionOptionName=s.attributeName(),this._registerOption(s),this.on("option:"+s.name(),()=>{this._outputConfiguration.writeOut(`${e}
|
|
21
|
+
`),this._exit(0,"commander.version",e)}),this}description(e,t){return e===void 0&&t===void 0?this._description:(this._description=e,t&&(this._argsDescription=t),this)}summary(e){return e===void 0?this._summary:(this._summary=e,this)}alias(e){if(e===void 0)return this._aliases[0];let t=this;if(this.commands.length!==0&&this.commands[this.commands.length-1]._executableHandler&&(t=this.commands[this.commands.length-1]),e===t._name)throw new Error("Command alias can't be the same as its name");let i=this.parent?._findCommand(e);if(i){let s=[i.name()].concat(i.aliases()).join("|");throw new Error(`cannot add alias '${e}' to command '${this.name()}' as already have command '${s}'`)}return t._aliases.push(e),this}aliases(e){return e===void 0?this._aliases:(e.forEach(t=>this.alias(t)),this)}usage(e){if(e===void 0){if(this._usage)return this._usage;let t=this.registeredArguments.map(i=>Si(i));return[].concat(this.options.length||this._helpOption!==null?"[options]":[],this.commands.length?"[command]":[],this.registeredArguments.length?t:[]).join(" ")}return this._usage=e,this}name(e){return e===void 0?this._name:(this._name=e,this)}nameFromFilename(e){return this._name=A.basename(e,A.extname(e)),this}executableDir(e){return e===void 0?this._executableDir:(this._executableDir=e,this)}helpInformation(e){let t=this.createHelp();return t.helpWidth===void 0&&(t.helpWidth=e&&e.error?this._outputConfiguration.getErrHelpWidth():this._outputConfiguration.getOutHelpWidth()),t.formatHelp(this,t)}_getHelpContext(e){e=e||{};let t={error:!!e.error},i;return t.error?i=s=>this._outputConfiguration.writeErr(s):i=s=>this._outputConfiguration.writeOut(s),t.write=e.write||i,t.command=this,t}outputHelp(e){let t;typeof e=="function"&&(t=e,e=void 0);let i=this._getHelpContext(e);this._getCommandAndAncestors().reverse().forEach(r=>r.emit("beforeAllHelp",i)),this.emit("beforeHelp",i);let s=this.helpInformation(i);if(t&&(s=t(s),typeof s!="string"&&!Buffer.isBuffer(s)))throw new Error("outputHelp callback must return a string or a Buffer");i.write(s),this._getHelpOption()?.long&&this.emit(this._getHelpOption().long),this.emit("afterHelp",i),this._getCommandAndAncestors().forEach(r=>r.emit("afterAllHelp",i))}helpOption(e,t){return typeof e=="boolean"?(e?this._helpOption=this._helpOption??void 0:this._helpOption=null,this):(e=e??"-h, --help",t=t??"display help for command",this._helpOption=this.createOption(e,t),this)}_getHelpOption(){return this._helpOption===void 0&&this.helpOption(void 0,void 0),this._helpOption}addHelpOption(e){return this._helpOption=e,this}help(e){this.outputHelp(e);let t=f.exitCode||0;t===0&&e&&typeof e!="function"&&e.error&&(t=1),this._exit(t,"commander.help","(outputHelp)")}addHelpText(e,t){let i=["beforeAll","before","after","afterAll"];if(!i.includes(e))throw new Error(`Unexpected value for position to addHelpText.
|
|
22
|
+
Expecting one of '${i.join("', '")}'`);let s=`${e}Help`;return this.on(s,r=>{let o;typeof t=="function"?o=t({error:r.error,command:r.command}):o=t,o&&r.write(`${o}
|
|
23
|
+
`)}),this}_outputHelpIfRequested(e){let t=this._getHelpOption();t&&e.find(s=>t.is(s))&&(this.outputHelp(),this._exit(0,"commander.helpDisplayed","(outputHelp)"))}};function Ue(n){return n.map(e=>{if(!e.startsWith("--inspect"))return e;let t,i="127.0.0.1",s="9229",r;return(r=e.match(/^(--inspect(-brk)?)$/))!==null?t=r[1]:(r=e.match(/^(--inspect(-brk|-port)?)=([^:]+)$/))!==null?(t=r[1],/^\d+$/.test(r[3])?s=r[3]:i=r[3]):(r=e.match(/^(--inspect(-brk|-port)?)=([^:]+):(\d+)$/))!==null&&(t=r[1],i=r[3],s=r[4]),t&&s!=="0"?`${t}=${i}:${parseInt(s)+1}`:e})}Ve.Command=ge});var Be=b(v=>{"use strict";var{Argument:He}=B(),{Command:ye}=Fe(),{CommanderError:qi,InvalidArgumentError:je}=F(),{Help:Ti}=le(),{Option:We}=ue();v.program=new ye;v.createCommand=n=>new ye(n);v.createOption=(n,e)=>new We(n,e);v.createArgument=(n,e)=>new He(n,e);v.Command=ye;v.Option=We;v.Argument=He;v.Help=Ti;v.CommanderError=qi;v.InvalidArgumentError=je;v.InvalidOptionArgumentError=je});var tt=b((Tn,et)=>{"use strict";et.exports={aliceblue:[240,248,255],antiquewhite:[250,235,215],aqua:[0,255,255],aquamarine:[127,255,212],azure:[240,255,255],beige:[245,245,220],bisque:[255,228,196],black:[0,0,0],blanchedalmond:[255,235,205],blue:[0,0,255],blueviolet:[138,43,226],brown:[165,42,42],burlywood:[222,184,135],cadetblue:[95,158,160],chartreuse:[127,255,0],chocolate:[210,105,30],coral:[255,127,80],cornflowerblue:[100,149,237],cornsilk:[255,248,220],crimson:[220,20,60],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgoldenrod:[184,134,11],darkgray:[169,169,169],darkgreen:[0,100,0],darkgrey:[169,169,169],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkseagreen:[143,188,143],darkslateblue:[72,61,139],darkslategray:[47,79,79],darkslategrey:[47,79,79],darkturquoise:[0,206,209],darkviolet:[148,0,211],deeppink:[255,20,147],deepskyblue:[0,191,255],dimgray:[105,105,105],dimgrey:[105,105,105],dodgerblue:[30,144,255],firebrick:[178,34,34],floralwhite:[255,250,240],forestgreen:[34,139,34],fuchsia:[255,0,255],gainsboro:[220,220,220],ghostwhite:[248,248,255],gold:[255,215,0],goldenrod:[218,165,32],gray:[128,128,128],green:[0,128,0],greenyellow:[173,255,47],grey:[128,128,128],honeydew:[240,255,240],hotpink:[255,105,180],indianred:[205,92,92],indigo:[75,0,130],ivory:[255,255,240],khaki:[240,230,140],lavender:[230,230,250],lavenderblush:[255,240,245],lawngreen:[124,252,0],lemonchiffon:[255,250,205],lightblue:[173,216,230],lightcoral:[240,128,128],lightcyan:[224,255,255],lightgoldenrodyellow:[250,250,210],lightgray:[211,211,211],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightsalmon:[255,160,122],lightseagreen:[32,178,170],lightskyblue:[135,206,250],lightslategray:[119,136,153],lightslategrey:[119,136,153],lightsteelblue:[176,196,222],lightyellow:[255,255,224],lime:[0,255,0],limegreen:[50,205,50],linen:[250,240,230],magenta:[255,0,255],maroon:[128,0,0],mediumaquamarine:[102,205,170],mediumblue:[0,0,205],mediumorchid:[186,85,211],mediumpurple:[147,112,219],mediumseagreen:[60,179,113],mediumslateblue:[123,104,238],mediumspringgreen:[0,250,154],mediumturquoise:[72,209,204],mediumvioletred:[199,21,133],midnightblue:[25,25,112],mintcream:[245,255,250],mistyrose:[255,228,225],moccasin:[255,228,181],navajowhite:[255,222,173],navy:[0,0,128],oldlace:[253,245,230],olive:[128,128,0],olivedrab:[107,142,35],orange:[255,165,0],orangered:[255,69,0],orchid:[218,112,214],palegoldenrod:[238,232,170],palegreen:[152,251,152],paleturquoise:[175,238,238],palevioletred:[219,112,147],papayawhip:[255,239,213],peachpuff:[255,218,185],peru:[205,133,63],pink:[255,192,203],plum:[221,160,221],powderblue:[176,224,230],purple:[128,0,128],rebeccapurple:[102,51,153],red:[255,0,0],rosybrown:[188,143,143],royalblue:[65,105,225],saddlebrown:[139,69,19],salmon:[250,128,114],sandybrown:[244,164,96],seagreen:[46,139,87],seashell:[255,245,238],sienna:[160,82,45],silver:[192,192,192],skyblue:[135,206,235],slateblue:[106,90,205],slategray:[112,128,144],slategrey:[112,128,144],snow:[255,250,250],springgreen:[0,255,127],steelblue:[70,130,180],tan:[210,180,140],teal:[0,128,128],thistle:[216,191,216],tomato:[255,99,71],turquoise:[64,224,208],violet:[238,130,238],wheat:[245,222,179],white:[255,255,255],whitesmoke:[245,245,245],yellow:[255,255,0],yellowgreen:[154,205,50]}});var be=b((Rn,nt)=>{"use strict";var H=tt(),it={};for(let n of Object.keys(H))it[H[n]]=n;var d={rgb:{channels:3,labels:"rgb"},hsl:{channels:3,labels:"hsl"},hsv:{channels:3,labels:"hsv"},hwb:{channels:3,labels:"hwb"},cmyk:{channels:4,labels:"cmyk"},xyz:{channels:3,labels:"xyz"},lab:{channels:3,labels:"lab"},lch:{channels:3,labels:"lch"},hex:{channels:1,labels:["hex"]},keyword:{channels:1,labels:["keyword"]},ansi16:{channels:1,labels:["ansi16"]},ansi256:{channels:1,labels:["ansi256"]},hcg:{channels:3,labels:["h","c","g"]},apple:{channels:3,labels:["r16","g16","b16"]},gray:{channels:1,labels:["gray"]}};nt.exports=d;for(let n of Object.keys(d)){if(!("channels"in d[n]))throw new Error("missing channels property: "+n);if(!("labels"in d[n]))throw new Error("missing channel labels property: "+n);if(d[n].labels.length!==d[n].channels)throw new Error("channel and label counts mismatch: "+n);let{channels:e,labels:t}=d[n];delete d[n].channels,delete d[n].labels,Object.defineProperty(d[n],"channels",{value:e}),Object.defineProperty(d[n],"labels",{value:t})}d.rgb.hsl=function(n){let e=n[0]/255,t=n[1]/255,i=n[2]/255,s=Math.min(e,t,i),r=Math.max(e,t,i),o=r-s,a,l;r===s?a=0:e===r?a=(t-i)/o:t===r?a=2+(i-e)/o:i===r&&(a=4+(e-t)/o),a=Math.min(a*60,360),a<0&&(a+=360);let c=(s+r)/2;return r===s?l=0:c<=.5?l=o/(r+s):l=o/(2-r-s),[a,l*100,c*100]};d.rgb.hsv=function(n){let e,t,i,s,r,o=n[0]/255,a=n[1]/255,l=n[2]/255,c=Math.max(o,a,l),h=c-Math.min(o,a,l),p=function(w){return(c-w)/6/h+1/2};return h===0?(s=0,r=0):(r=h/c,e=p(o),t=p(a),i=p(l),o===c?s=i-t:a===c?s=1/3+e-i:l===c&&(s=2/3+t-e),s<0?s+=1:s>1&&(s-=1)),[s*360,r*100,c*100]};d.rgb.hwb=function(n){let e=n[0],t=n[1],i=n[2],s=d.rgb.hsl(n)[0],r=1/255*Math.min(e,Math.min(t,i));return i=1-1/255*Math.max(e,Math.max(t,i)),[s,r*100,i*100]};d.rgb.cmyk=function(n){let e=n[0]/255,t=n[1]/255,i=n[2]/255,s=Math.min(1-e,1-t,1-i),r=(1-e-s)/(1-s)||0,o=(1-t-s)/(1-s)||0,a=(1-i-s)/(1-s)||0;return[r*100,o*100,a*100,s*100]};function Ri(n,e){return(n[0]-e[0])**2+(n[1]-e[1])**2+(n[2]-e[2])**2}d.rgb.keyword=function(n){let e=it[n];if(e)return e;let t=1/0,i;for(let s of Object.keys(H)){let r=H[s],o=Ri(n,r);o<t&&(t=o,i=s)}return i};d.keyword.rgb=function(n){return H[n]};d.rgb.xyz=function(n){let e=n[0]/255,t=n[1]/255,i=n[2]/255;e=e>.04045?((e+.055)/1.055)**2.4:e/12.92,t=t>.04045?((t+.055)/1.055)**2.4:t/12.92,i=i>.04045?((i+.055)/1.055)**2.4:i/12.92;let s=e*.4124+t*.3576+i*.1805,r=e*.2126+t*.7152+i*.0722,o=e*.0193+t*.1192+i*.9505;return[s*100,r*100,o*100]};d.rgb.lab=function(n){let e=d.rgb.xyz(n),t=e[0],i=e[1],s=e[2];t/=95.047,i/=100,s/=108.883,t=t>.008856?t**(1/3):7.787*t+16/116,i=i>.008856?i**(1/3):7.787*i+16/116,s=s>.008856?s**(1/3):7.787*s+16/116;let r=116*i-16,o=500*(t-i),a=200*(i-s);return[r,o,a]};d.hsl.rgb=function(n){let e=n[0]/360,t=n[1]/100,i=n[2]/100,s,r,o;if(t===0)return o=i*255,[o,o,o];i<.5?s=i*(1+t):s=i+t-i*t;let a=2*i-s,l=[0,0,0];for(let c=0;c<3;c++)r=e+1/3*-(c-1),r<0&&r++,r>1&&r--,6*r<1?o=a+(s-a)*6*r:2*r<1?o=s:3*r<2?o=a+(s-a)*(2/3-r)*6:o=a,l[c]=o*255;return l};d.hsl.hsv=function(n){let e=n[0],t=n[1]/100,i=n[2]/100,s=t,r=Math.max(i,.01);i*=2,t*=i<=1?i:2-i,s*=r<=1?r:2-r;let o=(i+t)/2,a=i===0?2*s/(r+s):2*t/(i+t);return[e,a*100,o*100]};d.hsv.rgb=function(n){let e=n[0]/60,t=n[1]/100,i=n[2]/100,s=Math.floor(e)%6,r=e-Math.floor(e),o=255*i*(1-t),a=255*i*(1-t*r),l=255*i*(1-t*(1-r));switch(i*=255,s){case 0:return[i,l,o];case 1:return[a,i,o];case 2:return[o,i,l];case 3:return[o,a,i];case 4:return[l,o,i];case 5:return[i,o,a]}};d.hsv.hsl=function(n){let e=n[0],t=n[1]/100,i=n[2]/100,s=Math.max(i,.01),r,o;o=(2-t)*i;let a=(2-t)*s;return r=t*s,r/=a<=1?a:2-a,r=r||0,o/=2,[e,r*100,o*100]};d.hwb.rgb=function(n){let e=n[0]/360,t=n[1]/100,i=n[2]/100,s=t+i,r;s>1&&(t/=s,i/=s);let o=Math.floor(6*e),a=1-i;r=6*e-o,(o&1)!==0&&(r=1-r);let l=t+r*(a-t),c,h,p;switch(o){default:case 6:case 0:c=a,h=l,p=t;break;case 1:c=l,h=a,p=t;break;case 2:c=t,h=a,p=l;break;case 3:c=t,h=l,p=a;break;case 4:c=l,h=t,p=a;break;case 5:c=a,h=t,p=l;break}return[c*255,h*255,p*255]};d.cmyk.rgb=function(n){let e=n[0]/100,t=n[1]/100,i=n[2]/100,s=n[3]/100,r=1-Math.min(1,e*(1-s)+s),o=1-Math.min(1,t*(1-s)+s),a=1-Math.min(1,i*(1-s)+s);return[r*255,o*255,a*255]};d.xyz.rgb=function(n){let e=n[0]/100,t=n[1]/100,i=n[2]/100,s,r,o;return s=e*3.2406+t*-1.5372+i*-.4986,r=e*-.9689+t*1.8758+i*.0415,o=e*.0557+t*-.204+i*1.057,s=s>.0031308?1.055*s**(1/2.4)-.055:s*12.92,r=r>.0031308?1.055*r**(1/2.4)-.055:r*12.92,o=o>.0031308?1.055*o**(1/2.4)-.055:o*12.92,s=Math.min(Math.max(0,s),1),r=Math.min(Math.max(0,r),1),o=Math.min(Math.max(0,o),1),[s*255,r*255,o*255]};d.xyz.lab=function(n){let e=n[0],t=n[1],i=n[2];e/=95.047,t/=100,i/=108.883,e=e>.008856?e**(1/3):7.787*e+16/116,t=t>.008856?t**(1/3):7.787*t+16/116,i=i>.008856?i**(1/3):7.787*i+16/116;let s=116*t-16,r=500*(e-t),o=200*(t-i);return[s,r,o]};d.lab.xyz=function(n){let e=n[0],t=n[1],i=n[2],s,r,o;r=(e+16)/116,s=t/500+r,o=r-i/200;let a=r**3,l=s**3,c=o**3;return r=a>.008856?a:(r-16/116)/7.787,s=l>.008856?l:(s-16/116)/7.787,o=c>.008856?c:(o-16/116)/7.787,s*=95.047,r*=100,o*=108.883,[s,r,o]};d.lab.lch=function(n){let e=n[0],t=n[1],i=n[2],s;s=Math.atan2(i,t)*360/2/Math.PI,s<0&&(s+=360);let o=Math.sqrt(t*t+i*i);return[e,o,s]};d.lch.lab=function(n){let e=n[0],t=n[1],s=n[2]/360*2*Math.PI,r=t*Math.cos(s),o=t*Math.sin(s);return[e,r,o]};d.rgb.ansi16=function(n,e=null){let[t,i,s]=n,r=e===null?d.rgb.hsv(n)[2]:e;if(r=Math.round(r/50),r===0)return 30;let o=30+(Math.round(s/255)<<2|Math.round(i/255)<<1|Math.round(t/255));return r===2&&(o+=60),o};d.hsv.ansi16=function(n){return d.rgb.ansi16(d.hsv.rgb(n),n[2])};d.rgb.ansi256=function(n){let e=n[0],t=n[1],i=n[2];return e===t&&t===i?e<8?16:e>248?231:Math.round((e-8)/247*24)+232:16+36*Math.round(e/255*5)+6*Math.round(t/255*5)+Math.round(i/255*5)};d.ansi16.rgb=function(n){let e=n%10;if(e===0||e===7)return n>50&&(e+=3.5),e=e/10.5*255,[e,e,e];let t=(~~(n>50)+1)*.5,i=(e&1)*t*255,s=(e>>1&1)*t*255,r=(e>>2&1)*t*255;return[i,s,r]};d.ansi256.rgb=function(n){if(n>=232){let r=(n-232)*10+8;return[r,r,r]}n-=16;let e,t=Math.floor(n/36)/5*255,i=Math.floor((e=n%36)/6)/5*255,s=e%6/5*255;return[t,i,s]};d.rgb.hex=function(n){let t=(((Math.round(n[0])&255)<<16)+((Math.round(n[1])&255)<<8)+(Math.round(n[2])&255)).toString(16).toUpperCase();return"000000".substring(t.length)+t};d.hex.rgb=function(n){let e=n.toString(16).match(/[a-f0-9]{6}|[a-f0-9]{3}/i);if(!e)return[0,0,0];let t=e[0];e[0].length===3&&(t=t.split("").map(a=>a+a).join(""));let i=parseInt(t,16),s=i>>16&255,r=i>>8&255,o=i&255;return[s,r,o]};d.rgb.hcg=function(n){let e=n[0]/255,t=n[1]/255,i=n[2]/255,s=Math.max(Math.max(e,t),i),r=Math.min(Math.min(e,t),i),o=s-r,a,l;return o<1?a=r/(1-o):a=0,o<=0?l=0:s===e?l=(t-i)/o%6:s===t?l=2+(i-e)/o:l=4+(e-t)/o,l/=6,l%=1,[l*360,o*100,a*100]};d.hsl.hcg=function(n){let e=n[1]/100,t=n[2]/100,i=t<.5?2*e*t:2*e*(1-t),s=0;return i<1&&(s=(t-.5*i)/(1-i)),[n[0],i*100,s*100]};d.hsv.hcg=function(n){let e=n[1]/100,t=n[2]/100,i=e*t,s=0;return i<1&&(s=(t-i)/(1-i)),[n[0],i*100,s*100]};d.hcg.rgb=function(n){let e=n[0]/360,t=n[1]/100,i=n[2]/100;if(t===0)return[i*255,i*255,i*255];let s=[0,0,0],r=e%1*6,o=r%1,a=1-o,l=0;switch(Math.floor(r)){case 0:s[0]=1,s[1]=o,s[2]=0;break;case 1:s[0]=a,s[1]=1,s[2]=0;break;case 2:s[0]=0,s[1]=1,s[2]=o;break;case 3:s[0]=0,s[1]=a,s[2]=1;break;case 4:s[0]=o,s[1]=0,s[2]=1;break;default:s[0]=1,s[1]=0,s[2]=a}return l=(1-t)*i,[(t*s[0]+l)*255,(t*s[1]+l)*255,(t*s[2]+l)*255]};d.hcg.hsv=function(n){let e=n[1]/100,t=n[2]/100,i=e+t*(1-e),s=0;return i>0&&(s=e/i),[n[0],s*100,i*100]};d.hcg.hsl=function(n){let e=n[1]/100,i=n[2]/100*(1-e)+.5*e,s=0;return i>0&&i<.5?s=e/(2*i):i>=.5&&i<1&&(s=e/(2*(1-i))),[n[0],s*100,i*100]};d.hcg.hwb=function(n){let e=n[1]/100,t=n[2]/100,i=e+t*(1-e);return[n[0],(i-e)*100,(1-i)*100]};d.hwb.hcg=function(n){let e=n[1]/100,i=1-n[2]/100,s=i-e,r=0;return s<1&&(r=(i-s)/(1-s)),[n[0],s*100,r*100]};d.apple.rgb=function(n){return[n[0]/65535*255,n[1]/65535*255,n[2]/65535*255]};d.rgb.apple=function(n){return[n[0]/255*65535,n[1]/255*65535,n[2]/255*65535]};d.gray.rgb=function(n){return[n[0]/100*255,n[0]/100*255,n[0]/100*255]};d.gray.hsl=function(n){return[0,0,n[0]]};d.gray.hsv=d.gray.hsl;d.gray.hwb=function(n){return[0,100,n[0]]};d.gray.cmyk=function(n){return[0,0,0,n[0]]};d.gray.lab=function(n){return[n[0],0,0]};d.gray.hex=function(n){let e=Math.round(n[0]/100*255)&255,i=((e<<16)+(e<<8)+e).toString(16).toUpperCase();return"000000".substring(i.length)+i};d.rgb.gray=function(n){return[(n[0]+n[1]+n[2])/3/255*100]}});var rt=b((Pn,st)=>{"use strict";var J=be();function Pi(){let n={},e=Object.keys(J);for(let t=e.length,i=0;i<t;i++)n[e[i]]={distance:-1,parent:null};return n}function Ni(n){let e=Pi(),t=[n];for(e[n].distance=0;t.length;){let i=t.pop(),s=Object.keys(J[i]);for(let r=s.length,o=0;o<r;o++){let a=s[o],l=e[a];l.distance===-1&&(l.distance=e[i].distance+1,l.parent=i,t.unshift(a))}}return e}function Di(n,e){return function(t){return e(n(t))}}function $i(n,e){let t=[e[n].parent,n],i=J[e[n].parent][n],s=e[n].parent;for(;e[s].parent;)t.unshift(e[s].parent),i=Di(J[e[s].parent][s],i),s=e[s].parent;return i.conversion=t,i}st.exports=function(n){let e=Ni(n),t={},i=Object.keys(e);for(let s=i.length,r=0;r<s;r++){let o=i[r];e[o].parent!==null&&(t[o]=$i(o,e))}return t}});var at=b((Nn,ot)=>{"use strict";var we=be(),Li=rt(),$={},Mi=Object.keys(we);function Ui(n){let e=function(...t){let i=t[0];return i==null?i:(i.length>1&&(t=i),n(t))};return"conversion"in n&&(e.conversion=n.conversion),e}function Vi(n){let e=function(...t){let i=t[0];if(i==null)return i;i.length>1&&(t=i);let s=n(t);if(typeof s=="object")for(let r=s.length,o=0;o<r;o++)s[o]=Math.round(s[o]);return s};return"conversion"in n&&(e.conversion=n.conversion),e}Mi.forEach(n=>{$[n]={},Object.defineProperty($[n],"channels",{value:we[n].channels}),Object.defineProperty($[n],"labels",{value:we[n].labels});let e=Li(n);Object.keys(e).forEach(i=>{let s=e[i];$[n][i]=Vi(s),$[n][i].raw=Ui(s)})});ot.exports=$});var pt=b((Dn,ut)=>{"use strict";var lt=(n,e)=>(...t)=>`\x1B[${n(...t)+e}m`,ct=(n,e)=>(...t)=>{let i=n(...t);return`\x1B[${38+e};5;${i}m`},dt=(n,e)=>(...t)=>{let i=n(...t);return`\x1B[${38+e};2;${i[0]};${i[1]};${i[2]}m`},z=n=>n,ht=(n,e,t)=>[n,e,t],L=(n,e,t)=>{Object.defineProperty(n,e,{get:()=>{let i=t();return Object.defineProperty(n,e,{value:i,enumerable:!0,configurable:!0}),i},enumerable:!0,configurable:!0})},Ce,M=(n,e,t,i)=>{Ce===void 0&&(Ce=at());let s=i?10:0,r={};for(let[o,a]of Object.entries(Ce)){let l=o==="ansi16"?"ansi":o;o===e?r[l]=n(t,s):typeof a=="object"&&(r[l]=n(a[e],s))}return r};function Fi(){let n=new Map,e={modifier:{reset:[0,0],bold:[1,22],dim:[2,22],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29]},color:{black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39]},bgColor:{bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]}};e.color.gray=e.color.blackBright,e.bgColor.bgGray=e.bgColor.bgBlackBright,e.color.grey=e.color.blackBright,e.bgColor.bgGrey=e.bgColor.bgBlackBright;for(let[t,i]of Object.entries(e)){for(let[s,r]of Object.entries(i))e[s]={open:`\x1B[${r[0]}m`,close:`\x1B[${r[1]}m`},i[s]=e[s],n.set(r[0],r[1]);Object.defineProperty(e,t,{value:i,enumerable:!1})}return Object.defineProperty(e,"codes",{value:n,enumerable:!1}),e.color.close="\x1B[39m",e.bgColor.close="\x1B[49m",L(e.color,"ansi",()=>M(lt,"ansi16",z,!1)),L(e.color,"ansi256",()=>M(ct,"ansi256",z,!1)),L(e.color,"ansi16m",()=>M(dt,"rgb",ht,!1)),L(e.bgColor,"ansi",()=>M(lt,"ansi16",z,!0)),L(e.bgColor,"ansi256",()=>M(ct,"ansi256",z,!0)),L(e.bgColor,"ansi16m",()=>M(dt,"rgb",ht,!0)),e}Object.defineProperty(ut,"exports",{enumerable:!0,get:Fi})});var ft=b(($n,mt)=>{"use strict";mt.exports=(n,e=process.argv)=>{let t=n.startsWith("-")?"":n.length===1?"-":"--",i=e.indexOf(t+n),s=e.indexOf("--");return i!==-1&&(s===-1||i<s)}});var bt=b((Ln,yt)=>{"use strict";var Hi=require("os"),gt=require("tty"),k=ft(),{env:y}=process,E;k("no-color")||k("no-colors")||k("color=false")||k("color=never")?E=0:(k("color")||k("colors")||k("color=true")||k("color=always"))&&(E=1);"FORCE_COLOR"in y&&(y.FORCE_COLOR==="true"?E=1:y.FORCE_COLOR==="false"?E=0:E=y.FORCE_COLOR.length===0?1:Math.min(parseInt(y.FORCE_COLOR,10),3));function ve(n){return n===0?!1:{level:n,hasBasic:!0,has256:n>=2,has16m:n>=3}}function ke(n,e){if(E===0)return 0;if(k("color=16m")||k("color=full")||k("color=truecolor"))return 3;if(k("color=256"))return 2;if(n&&!e&&E===void 0)return 0;let t=E||0;if(y.TERM==="dumb")return t;if(process.platform==="win32"){let i=Hi.release().split(".");return Number(i[0])>=10&&Number(i[2])>=10586?Number(i[2])>=14931?3:2:1}if("CI"in y)return["TRAVIS","CIRCLECI","APPVEYOR","GITLAB_CI","GITHUB_ACTIONS","BUILDKITE"].some(i=>i in y)||y.CI_NAME==="codeship"?1:t;if("TEAMCITY_VERSION"in y)return/^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(y.TEAMCITY_VERSION)?1:0;if(y.COLORTERM==="truecolor")return 3;if("TERM_PROGRAM"in y){let i=parseInt((y.TERM_PROGRAM_VERSION||"").split(".")[0],10);switch(y.TERM_PROGRAM){case"iTerm.app":return i>=3?3:2;case"Apple_Terminal":return 2}}return/-256(color)?$/i.test(y.TERM)?2:/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(y.TERM)||"COLORTERM"in y?1:t}function ji(n){let e=ke(n,n&&n.isTTY);return ve(e)}yt.exports={supportsColor:ji,stdout:ve(ke(!0,gt.isatty(1))),stderr:ve(ke(!0,gt.isatty(2)))}});var Ct=b((Mn,wt)=>{"use strict";var Wi=(n,e,t)=>{let i=n.indexOf(e);if(i===-1)return n;let s=e.length,r=0,o="";do o+=n.substr(r,i-r)+e+t,r=i+s,i=n.indexOf(e,r);while(i!==-1);return o+=n.substr(r),o},Bi=(n,e,t,i)=>{let s=0,r="";do{let o=n[i-1]==="\r";r+=n.substr(s,(o?i-1:i)-s)+e+(o?`\r
|
|
24
|
+
`:`
|
|
25
|
+
`)+t,s=i+1,i=n.indexOf(`
|
|
26
|
+
`,s)}while(i!==-1);return r+=n.substr(s),r};wt.exports={stringReplaceAll:Wi,stringEncaseCRLFWithFirstIndex:Bi}});var Ot=b((Un,At)=>{"use strict";var Gi=/(?:\\(u(?:[a-f\d]{4}|\{[a-f\d]{1,6}\})|x[a-f\d]{2}|.))|(?:\{(~)?(\w+(?:\([^)]*\))?(?:\.\w+(?:\([^)]*\))?)*)(?:[ \t]|(?=\r?\n)))|(\})|((?:.|[\r\n\f])+?)/gi,vt=/(?:^|\.)(\w+)(?:\(([^)]*)\))?/g,Ji=/^(['"])((?:\\.|(?!\1)[^\\])*)\1$/,zi=/\\(u(?:[a-f\d]{4}|{[a-f\d]{1,6}})|x[a-f\d]{2}|.)|([^\\])/gi,Yi=new Map([["n",`
|
|
27
|
+
`],["r","\r"],["t"," "],["b","\b"],["f","\f"],["v","\v"],["0","\0"],["\\","\\"],["e","\x1B"],["a","\x07"]]);function _t(n){let e=n[0]==="u",t=n[1]==="{";return e&&!t&&n.length===5||n[0]==="x"&&n.length===3?String.fromCharCode(parseInt(n.slice(1),16)):e&&t?String.fromCodePoint(parseInt(n.slice(2,-1),16)):Yi.get(n)||n}function Qi(n,e){let t=[],i=e.trim().split(/\s*,\s*/g),s;for(let r of i){let o=Number(r);if(!Number.isNaN(o))t.push(o);else if(s=r.match(Ji))t.push(s[2].replace(zi,(a,l,c)=>l?_t(l):c));else throw new Error(`Invalid Chalk template style argument: ${r} (in style '${n}')`)}return t}function Ki(n){vt.lastIndex=0;let e=[],t;for(;(t=vt.exec(n))!==null;){let i=t[1];if(t[2]){let s=Qi(i,t[2]);e.push([i].concat(s))}else e.push([i])}return e}function kt(n,e){let t={};for(let s of e)for(let r of s.styles)t[r[0]]=s.inverse?null:r.slice(1);let i=n;for(let[s,r]of Object.entries(t))if(Array.isArray(r)){if(!(s in i))throw new Error(`Unknown Chalk style: ${s}`);i=r.length>0?i[s](...r):i[s]}return i}At.exports=(n,e)=>{let t=[],i=[],s=[];if(e.replace(Gi,(r,o,a,l,c,h)=>{if(o)s.push(_t(o));else if(l){let p=s.join("");s=[],i.push(t.length===0?p:kt(n,t)(p)),t.push({inverse:a,styles:Ki(l)})}else if(c){if(t.length===0)throw new Error("Found extraneous } in Chalk template literal");i.push(kt(n,t)(s.join(""))),s=[],t.pop()}else s.push(h)}),i.push(s.join("")),t.length>0){let r=`Chalk template literal is missing ${t.length} closing bracket${t.length===1?"":"s"} (\`}\`)`;throw new Error(r)}return i.join("")}});var Rt=b((Vn,Tt)=>{"use strict";var j=pt(),{stdout:Ae,stderr:Oe}=bt(),{stringReplaceAll:Xi,stringEncaseCRLFWithFirstIndex:Zi}=Ct(),{isArray:Y}=Array,St=["ansi","ansi","ansi256","ansi16m"],U=Object.create(null),en=(n,e={})=>{if(e.level&&!(Number.isInteger(e.level)&&e.level>=0&&e.level<=3))throw new Error("The `level` option should be an integer from 0 to 3");let t=Ae?Ae.level:0;n.level=e.level===void 0?t:e.level},xe=class{constructor(e){return Et(e)}},Et=n=>{let e={};return en(e,n),e.template=(...t)=>qt(e.template,...t),Object.setPrototypeOf(e,Q.prototype),Object.setPrototypeOf(e.template,e),e.template.constructor=()=>{throw new Error("`chalk.constructor()` is deprecated. Use `new chalk.Instance()` instead.")},e.template.Instance=xe,e.template};function Q(n){return Et(n)}for(let[n,e]of Object.entries(j))U[n]={get(){let t=K(this,Se(e.open,e.close,this._styler),this._isEmpty);return Object.defineProperty(this,n,{value:t}),t}};U.visible={get(){let n=K(this,this._styler,!0);return Object.defineProperty(this,"visible",{value:n}),n}};var It=["rgb","hex","keyword","hsl","hsv","hwb","ansi","ansi256"];for(let n of It)U[n]={get(){let{level:e}=this;return function(...t){let i=Se(j.color[St[e]][n](...t),j.color.close,this._styler);return K(this,i,this._isEmpty)}}};for(let n of It){let e="bg"+n[0].toUpperCase()+n.slice(1);U[e]={get(){let{level:t}=this;return function(...i){let s=Se(j.bgColor[St[t]][n](...i),j.bgColor.close,this._styler);return K(this,s,this._isEmpty)}}}}var tn=Object.defineProperties(()=>{},{...U,level:{enumerable:!0,get(){return this._generator.level},set(n){this._generator.level=n}}}),Se=(n,e,t)=>{let i,s;return t===void 0?(i=n,s=e):(i=t.openAll+n,s=e+t.closeAll),{open:n,close:e,openAll:i,closeAll:s,parent:t}},K=(n,e,t)=>{let i=(...s)=>Y(s[0])&&Y(s[0].raw)?xt(i,qt(i,...s)):xt(i,s.length===1?""+s[0]:s.join(" "));return Object.setPrototypeOf(i,tn),i._generator=n,i._styler=e,i._isEmpty=t,i},xt=(n,e)=>{if(n.level<=0||!e)return n._isEmpty?"":e;let t=n._styler;if(t===void 0)return e;let{openAll:i,closeAll:s}=t;if(e.indexOf("\x1B")!==-1)for(;t!==void 0;)e=Xi(e,t.close,t.open),t=t.parent;let r=e.indexOf(`
|
|
28
|
+
`);return r!==-1&&(e=Zi(e,s,i,r)),i+e+s},_e,qt=(n,...e)=>{let[t]=e;if(!Y(t)||!Y(t.raw))return e.join(" ");let i=e.slice(1),s=[t.raw[0]];for(let r=1;r<t.length;r++)s.push(String(i[r-1]).replace(/[{}\\]/g,"\\$&"),String(t.raw[r]));return _e===void 0&&(_e=Ot()),_e(n,s.join(""))};Object.defineProperties(Q.prototype,U);var X=Q();X.supportsColor=Ae;X.stderr=Q({level:Oe?Oe.level:0});X.stderr.supportsColor=Oe;Tt.exports=X});var Ge=C(Be(),1),{program:bn,createCommand:wn,createArgument:Cn,createOption:vn,CommanderError:kn,InvalidArgumentError:_n,InvalidOptionArgumentError:An,Command:u,Argument:On,Option:xn,Help:Sn}=Ge.default;var Je="decipher-qa",G=process.env.SECRET_MODE_URL||"https://api.getdecipher.com";var te=C(require("fs")),qe=C(require("path"));var ze='---\nname: decipher-qa\ndescription: >-\n Creates QA tests by exploring your frontend codebase to understand pages, components, and UI flows,\n then generates step-by-step test instructions based on what it finds in the code.\n Handles the full lifecycle: create test, link login identity, generate steps, save, and run validation.\n Also manages tests and identities (CRUD) and provides CLI reference.\n---\n\n# /decipher-qa \u2014 Decipher QA Agent\n\nRoute based on the first word(s) of `$ARGUMENTS`:\n\n- **"create-test"** or **"create test"** \u2192 Read `create-test.md` in this skill directory and follow its instructions. Pass the remaining arguments.\n- **"validate"** \u2192 Read `create-test.md` in this skill directory and jump to Phase 6 (Run Validation). The user must provide a test ID. Initialize attemptNumber=1, maxAttempts=3, failureHistory=[].\n- **"test"** \u2192 Read `test.md` in this skill directory and follow its instructions. Pass the remaining arguments after "test".\n- **"identity"** \u2192 Read `identity.md` in this skill directory and follow its instructions. Pass the remaining arguments after "identity".\n- **"steps"** \u2192 Read `steps.md` in this skill directory and follow its instructions. Pass the remaining arguments after "steps".\n- **"cli"** \u2192 Read `cli.md` in this skill directory and follow its instructions.\n- **Natural language test request** (e.g. "make a test for checkout", "test the alert flow", "create a test for login") \u2192 Treat as `create-test`. Read `create-test.md` and follow its instructions. Use the user\'s description as the test description.\n- **Empty or unrecognized** \u2192 Show available commands:\n - `/decipher-qa create-test` \u2014 Create a new test end-to-end (name, identity, steps, validation)\n - `/decipher-qa validate` \u2014 Run validation on an existing test\n - `/decipher-qa test` \u2014 Manage QA tests (create, delete, list)\n - `/decipher-qa identity` \u2014 Manage login identities (create, delete, list)\n - `/decipher-qa steps` \u2014 Generate QA test steps by exploring your codebase\n - `/decipher-qa cli` \u2014 CLI command reference and error handling guide\n\nAll data is managed via the Decipher API through CLI commands.\n\n**IMPORTANT:** Always invoke the CLI as `decipher-qa` \u2014 never use `npx decipher-qa` or any other prefix.\n',Ye=`# Test \u2014 Manage QA Tests
|
|
29
|
+
|
|
30
|
+
**IMPORTANT:** Always invoke the CLI as \`decipher-qa\` \u2014 never use \`npx decipher-qa\` or any other prefix.
|
|
31
|
+
|
|
32
|
+
Route based on arguments:
|
|
33
|
+
|
|
34
|
+
- **"create"** or **"new"** or **"add"** \u2192 go to [Create Test](#create-test)
|
|
35
|
+
- **"delete"** or **"remove"** \u2192 go to [Delete Test](#delete-test)
|
|
36
|
+
- **"list"** or **"search"** or empty \u2192 go to [List Tests](#list-tests)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Create Test
|
|
41
|
+
|
|
42
|
+
1. Ask the user for:
|
|
43
|
+
- **name** (required) \u2014 a short descriptive name for the test
|
|
44
|
+
- **description** (required) \u2014 what this test covers
|
|
45
|
+
|
|
46
|
+
2. **Identity picker** \u2014 run \`decipher-qa identity list\`, present a picker with all identity names (and their URLs) plus a **"None"** option and a **"Create new"** option. If the user picks or creates an identity, note its \`id\`.
|
|
47
|
+
|
|
48
|
+
3. **Derive the test URL:**
|
|
49
|
+
- If an identity was chosen: extract the URL origin (protocol + host) from the identity's login URL (e.g. \`https://app.example.com/login\` \u2192 \`https://app.example.com\`). Use this as the test \`url\`.
|
|
50
|
+
- If no identity: ask the user for the test URL directly.
|
|
51
|
+
|
|
52
|
+
4. Run the CLI command:
|
|
53
|
+
\`\`\`bash
|
|
54
|
+
decipher-qa test create --name "<name>" --url "<url>" --description "<description>"
|
|
55
|
+
\`\`\`
|
|
56
|
+
If an identity was selected, also run:
|
|
57
|
+
\`\`\`bash
|
|
58
|
+
decipher-qa test update --id <testId> --identity-id <identityId>
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
5. Parse the JSON output and **remember** the \`id\` \u2014 you will need it later.
|
|
62
|
+
|
|
63
|
+
6. Confirm: "Created test **<name>** (\`<id>\`)"
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Delete Test
|
|
68
|
+
|
|
69
|
+
1. Run \`decipher-qa test list\` and show a numbered list of tests.
|
|
70
|
+
2. Ask which test to delete (by number or name).
|
|
71
|
+
3. Run:
|
|
72
|
+
\`\`\`bash
|
|
73
|
+
decipher-qa test delete --id <testId>
|
|
74
|
+
\`\`\`
|
|
75
|
+
4. Confirm: "Deleted test **<name>**"
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## List Tests
|
|
80
|
+
|
|
81
|
+
Parse the rest of the arguments after the "list" keyword:
|
|
82
|
+
- If there's a search term, pass it as \`--name\`.
|
|
83
|
+
|
|
84
|
+
Run:
|
|
85
|
+
\`\`\`bash
|
|
86
|
+
decipher-qa test list --name "<search>"
|
|
87
|
+
\`\`\`
|
|
88
|
+
|
|
89
|
+
Display a formatted table from the JSON response:
|
|
90
|
+
|
|
91
|
+
| # | Name | URL | Identity ID | Steps | Tags | Updated |
|
|
92
|
+
|---|------|-----|-------------|-------|------|---------|
|
|
93
|
+
|
|
94
|
+
For the Steps column, show the step count (e.g. "5 steps") or "\u2014" if no steps.
|
|
95
|
+
|
|
96
|
+
If no tests match, say "No tests found."
|
|
97
|
+
`,Qe=`# Identity \u2014 Manage Login Identities
|
|
98
|
+
|
|
99
|
+
**IMPORTANT:** Always invoke the CLI as \`decipher-qa\` \u2014 never use \`npx decipher-qa\` or any other prefix.
|
|
100
|
+
|
|
101
|
+
Route based on arguments:
|
|
102
|
+
|
|
103
|
+
- **"create"** or **"new"** or **"add"** \u2192 go to [Create Identity](#create-identity)
|
|
104
|
+
- **"delete"** or **"remove"** \u2192 go to [Delete Identity](#delete-identity)
|
|
105
|
+
- **"list"** or empty \u2192 go to [List Identities](#list-identities)
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Create Identity
|
|
110
|
+
|
|
111
|
+
1. Ask the user for:
|
|
112
|
+
- **name** (required) \u2014 a descriptive label (e.g. "Admin User", "Test Customer")
|
|
113
|
+
- **url** (required) \u2014 the login page URL (e.g. \`https://app.example.com/login\`)
|
|
114
|
+
- **username** (required) \u2014 the login username or email
|
|
115
|
+
- **password** (required) \u2014 the login password
|
|
116
|
+
|
|
117
|
+
2. Run the CLI command:
|
|
118
|
+
\`\`\`bash
|
|
119
|
+
decipher-qa identity create --name "<name>" --username "<username>" --password "<password>" --url "<url>"
|
|
120
|
+
\`\`\`
|
|
121
|
+
|
|
122
|
+
3. Parse the JSON output and **remember** the \`id\`.
|
|
123
|
+
|
|
124
|
+
4. Confirm: "Created identity **<name>** (\`<id>\`)"
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Delete Identity
|
|
129
|
+
|
|
130
|
+
1. Run \`decipher-qa identity list\` and show a numbered list.
|
|
131
|
+
2. Ask which identity to delete (by number or name).
|
|
132
|
+
3. Run:
|
|
133
|
+
\`\`\`bash
|
|
134
|
+
decipher-qa identity delete --id <identityId>
|
|
135
|
+
\`\`\`
|
|
136
|
+
4. Confirm: "Deleted identity **<name>**"
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## List Identities
|
|
141
|
+
|
|
142
|
+
Run:
|
|
143
|
+
\`\`\`bash
|
|
144
|
+
decipher-qa identity list
|
|
145
|
+
\`\`\`
|
|
146
|
+
|
|
147
|
+
Display a formatted table from the JSON response:
|
|
148
|
+
|
|
149
|
+
| # | Name | URL | Username |
|
|
150
|
+
|---|------|-----|----------|
|
|
151
|
+
|
|
152
|
+
- If no identities exist, say "No identities found."
|
|
153
|
+
`,Ke=`# Steps \u2014 Generate QA Test Steps
|
|
154
|
+
|
|
155
|
+
**IMPORTANT:** Always invoke the CLI as \`decipher-qa\` \u2014 never use \`npx decipher-qa\` or any other prefix.
|
|
156
|
+
|
|
157
|
+
The arguments contain the user's description of what they want to test (e.g. "login flow", "create a new project", "checkout as a guest").
|
|
158
|
+
|
|
159
|
+
If no arguments are provided, ask the user: **"What flow or feature would you like to generate test steps for?"**
|
|
160
|
+
|
|
161
|
+
---
|
|
162
|
+
|
|
163
|
+
## Generate Steps
|
|
164
|
+
|
|
165
|
+
### Phase 1 \u2014 Understand the Request
|
|
166
|
+
|
|
167
|
+
1. Parse the user's description from the arguments.
|
|
168
|
+
2. Confirm your understanding back to the user: "I'll generate test steps for: **<description>**"
|
|
169
|
+
3. **Assume the user is already logged in.** Authentication is handled separately by the identity attached to the test \u2014 never generate login/auth steps unless the user explicitly asks.
|
|
170
|
+
4. Ask any clarifying questions if the description is ambiguous:
|
|
171
|
+
- What page/URL does this flow start on?
|
|
172
|
+
5. Tell the user you'll now explore their codebase to understand the relevant pages.
|
|
173
|
+
|
|
174
|
+
### Phase 2 \u2014 Explore the Codebase
|
|
175
|
+
|
|
176
|
+
Systematically explore the codebase to understand the UI the flow will interact with:
|
|
177
|
+
|
|
178
|
+
1. **Find relevant pages/routes:**
|
|
179
|
+
- Based on the user's description, identify which pages/routes are involved
|
|
180
|
+
- Search for matching route files:
|
|
181
|
+
- \`Glob("**/app/**/page.tsx")\` and \`Glob("**/app/**/page.ts")\` (Next.js App Router)
|
|
182
|
+
- \`Glob("**/pages/**/*.tsx")\` and \`Glob("**/pages/**/*.ts")\` (Next.js Pages Router)
|
|
183
|
+
- \`Grep("router" or route definitions)\` for SPA routers (React Router, Vue Router, etc.)
|
|
184
|
+
- If the base URL is just the root (\`/\`), look for the main entry page
|
|
185
|
+
|
|
186
|
+
2. **Read the page component:**
|
|
187
|
+
- Understand the layout, rendered components, and state management
|
|
188
|
+
- Identify forms, buttons, links, navigation elements, modals, and interactive widgets
|
|
189
|
+
- Note conditional rendering (loading states, auth gates, feature flags)
|
|
190
|
+
|
|
191
|
+
3. **Trace child components:**
|
|
192
|
+
- Follow imports to read key child components
|
|
193
|
+
- Focus on: button labels, input placeholders/labels, link text, dropdown options
|
|
194
|
+
- Note any dynamic content (data from API calls, user-specific content)
|
|
195
|
+
|
|
196
|
+
4. **Check layouts and navigation:**
|
|
197
|
+
- Read layout files (\`layout.tsx\`, \`_app.tsx\`) to understand shared navigation
|
|
198
|
+
- Identify sidebar items, header nav, breadcrumbs, tabs
|
|
199
|
+
|
|
200
|
+
5. **Identify stateful behavior:**
|
|
201
|
+
Every test run starts a **fresh browser session** \u2014 there is no localStorage, no sessionStorage, no cookies, no cached state. Consider how this affects the flow:
|
|
202
|
+
- **First-time user experiences:** onboarding modals, welcome screens, feature tours, cookie consent banners \u2014 these WILL appear on a fresh session
|
|
203
|
+
- **Empty states:** if the page normally shows a list of items but this is a fresh session, the list may be empty. Steps need to account for "no data yet" UI
|
|
204
|
+
- **Default selections:** dropdowns, toggles, or filters may have different defaults than what a returning user sees
|
|
205
|
+
- **Conditional UI:** look for code that checks \`localStorage\`, \`sessionStorage\`, cookies, or feature flags \u2014 the fresh-session path is what will execute
|
|
206
|
+
- **Redirects:** some apps redirect first-time users to onboarding or setup pages
|
|
207
|
+
|
|
208
|
+
Flag any of these to the user in your summary \u2014 they may need \`conditional\` steps to handle them.
|
|
209
|
+
|
|
210
|
+
6. **Determine the navigation strategy:**
|
|
211
|
+
- **Direct URL (preferred):** If the target page has a static, deterministic route (e.g. \`/settings\`, \`/projects/new\`, \`/dashboard\`), use a single \`goto\` step with the full URL. This is simpler and more reliable.
|
|
212
|
+
- **Click-through navigation (when needed):** If the app's home/landing page is dynamic (e.g. redirects based on user state, shows different content per user, or the target page has no stable URL because it uses dynamic IDs), then you must describe the click-by-click navigation from a known page to the target. In this case, explain to the user exactly which UI elements to click through (sidebar items, nav links, tabs, etc.) to reach the target.
|
|
213
|
+
|
|
214
|
+
**Rule of thumb:** Always prefer a direct \`goto\` URL when one exists. Only fall back to click-through navigation when the page cannot be reached by URL alone.
|
|
215
|
+
|
|
216
|
+
7. **Summarize findings to the user** before proceeding. Present a clear picture of:
|
|
217
|
+
- What pages/components you found
|
|
218
|
+
- Key interactive elements (buttons, forms, navigation)
|
|
219
|
+
- Any dynamic or conditional content
|
|
220
|
+
- **Fresh session considerations** \u2014 onboarding flows, empty states, cookie banners, default selections that will appear on a clean session
|
|
221
|
+
- **How to reach the target page** (direct URL or navigation steps needed)
|
|
222
|
+
- Suggested test flows based on what you see
|
|
223
|
+
|
|
224
|
+
### Phase 3 \u2014 Dialogue with User
|
|
225
|
+
|
|
226
|
+
1. Summarize what you found: key pages, components, interactive elements, and navigation structure.
|
|
227
|
+
2. If the user's request is ambiguous or there are **multiple distinct flows**, suggest options and ask which to test. **If the flow is clear, skip straight to generating steps** \u2014 don't ask for permission to proceed.
|
|
228
|
+
3. Note any edge cases worth flagging (empty states, conditional UI, fresh-session behavior) but fold them into your step generation rather than asking about each one individually.
|
|
229
|
+
|
|
230
|
+
### Phase 4 \u2014 Generate Steps
|
|
231
|
+
|
|
232
|
+
Generate **all steps for the entire flow at once**. Do not break into sections or ask for feedback between sections.
|
|
233
|
+
|
|
234
|
+
1. Generate all steps by calling the CLI formatter for each:
|
|
235
|
+
\`\`\`bash
|
|
236
|
+
decipher-qa steps format --type <type> --description "<desc>" --data "<data>"
|
|
237
|
+
\`\`\`
|
|
238
|
+
Add \`--metadata '<json>'\` only when metadata is needed.
|
|
239
|
+
2. Collect the JSON output internally \u2014 **do not show raw JSON to the user**.
|
|
240
|
+
3. Display the **complete step list** in a clean readable format:
|
|
241
|
+
\`\`\`
|
|
242
|
+
1. [goto] https://app.example.com/settings/identities
|
|
243
|
+
2. [default] Click the "+" (Add) button next to the "Identities" header
|
|
244
|
+
3. [default] Click on the "Name" input field
|
|
245
|
+
4. [default] Type "Test Identity {{unique}}" into the "Name" input field
|
|
246
|
+
\`\`\`
|
|
247
|
+
4. Ask once: **"Here are all the steps. Any changes?"**
|
|
248
|
+
5. Apply corrections if requested.
|
|
249
|
+
|
|
250
|
+
**Display format:** \`<step_number>. [<type>] <description or data>\`
|
|
251
|
+
- For \`goto\`: show the URL
|
|
252
|
+
- For \`wait\`: show the duration with "ms" suffix
|
|
253
|
+
- For \`default\`: show the description (typed values are already inline in the description).
|
|
254
|
+
- For other types: show the description or data, whichever is more informative
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Step Writing Rules
|
|
259
|
+
|
|
260
|
+
These rules are **mandatory**. Every generated step must follow them.
|
|
261
|
+
|
|
262
|
+
### 1. One action per step
|
|
263
|
+
Never combine two actions into one step. Each step is exactly one user interaction.
|
|
264
|
+
|
|
265
|
+
### 2. Never skip intermediate steps
|
|
266
|
+
- Close a dropdown/modal before clicking elsewhere \u2192 separate step
|
|
267
|
+
- Click/focus a text field before typing \u2192 separate click step, then type step
|
|
268
|
+
- Dismiss a toast/banner before interacting with elements behind it \u2192 separate step
|
|
269
|
+
|
|
270
|
+
### 3. No short waits
|
|
271
|
+
**Do not generate \`wait\` steps under 2000ms.** Decipher handles short delays automatically. Only add a \`wait\` step when there is a genuinely long operation (e.g. a server-side save, a page navigation, a complex animation) that takes 2 seconds or more.
|
|
272
|
+
|
|
273
|
+
### 4. Description specificity
|
|
274
|
+
|
|
275
|
+
**Static UI elements** \u2014 reference exact text, icons, and location:
|
|
276
|
+
- GOOD: \`Click on the "+" (Add) button next to the "Identities" header in the left sidebar\`
|
|
277
|
+
- BAD: \`Click the add button\`
|
|
278
|
+
|
|
279
|
+
**Icons** \u2014 describe the icon AND the text or element it's next to:
|
|
280
|
+
- GOOD: \`Click on the "Edit" button (pencil icon) in the top-right corner of the "Identity Details" panel\`
|
|
281
|
+
- BAD: \`Click the edit icon\`
|
|
282
|
+
|
|
283
|
+
**Dynamic content** \u2014 use ordinal references instead of specific data values:
|
|
284
|
+
- GOOD: \`Click on the first item in the search results list\`
|
|
285
|
+
- BAD: \`Click on "Some Dynamic Item Name"\`
|
|
286
|
+
|
|
287
|
+
### 5. First step is always \`goto\` \u2014 prefer direct URLs
|
|
288
|
+
The first step must be a \`goto\` step. **If the target page has a stable route, go directly to it** (e.g. \`goto https://app.example.com/settings/identities\`) rather than navigating to the home page and clicking through. Only use the home page as the \`goto\` target when the destination has no stable URL (e.g. it requires a dynamic ID that must be discovered by interacting with the app).
|
|
289
|
+
|
|
290
|
+
### 6. \`default\` steps: \`data\` is ALWAYS empty, everything goes in \`description\`
|
|
291
|
+
For \`default\` type steps, the \`data\` field must **always** be an empty string \`""\`. The action \u2014 including what to click, what to type, and the exact value to type \u2014 must be fully described in the \`description\` field. Never put the value to fill into \`data\`.
|
|
292
|
+
- GOOD: \`--type default --description 'Type "hello@example.com" into the "Email" input field' --data ""\`
|
|
293
|
+
- BAD: \`--type default --description 'Fill in the email field' --data "hello@example.com"\`
|
|
294
|
+
|
|
295
|
+
### 7. Input fields: focus before type
|
|
296
|
+
Always have a click/focus step BEFORE a type step for input fields:
|
|
297
|
+
\`\`\`
|
|
298
|
+
Step N: Click on the "Email" input field
|
|
299
|
+
Step N+1: Type "user@example.com" into the "Email" input field
|
|
300
|
+
\`\`\`
|
|
301
|
+
|
|
302
|
+
### 8. Dropdowns and modals: close after selection
|
|
303
|
+
Always have a close/dismiss step AFTER making a selection in a dropdown or modal, before interacting with elements outside it.
|
|
304
|
+
|
|
305
|
+
### 9. Use \`{{unique}}\` for fields that require uniqueness
|
|
306
|
+
During codebase exploration, look for uniqueness constraints \u2014 database unique indexes, form validations that check for duplicates, unique email/username requirements, slug generation, etc. If a field must be unique (or the test would fail on a second run with duplicate data), use \`{{unique}}\` in the step description. This is resolved to a unique value at runtime.
|
|
307
|
+
|
|
308
|
+
Examples:
|
|
309
|
+
- Email with unique constraint \u2192 \`Type "test+{{unique}}@example.com" into the "Email" input field\`
|
|
310
|
+
- Name that must be unique \u2192 \`Type "My Item {{unique}}" into the "Name" input field\`
|
|
311
|
+
- Username \u2192 \`Type "user-{{unique}}" into the "Username" input field\`
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Step Type Reference
|
|
316
|
+
|
|
317
|
+
| Type | \`data\` field | \`description\` field | When to use |
|
|
318
|
+
|------|-------------|---------------------|-------------|
|
|
319
|
+
| \`goto\` | Full URL | Auto-set to the URL | Navigate to a page. Always step 1. |
|
|
320
|
+
| \`default\` | Always empty \`""\` | Human-readable action (include typed values inline) | Any UI interaction: click, type, hover, press key |
|
|
321
|
+
| \`wait\` | Duration in ms (minimum \`"2000"\`) | Empty \`""\` | Pause for long operations (saves, page loads). Never under 2000ms. |
|
|
322
|
+
| \`assert\` | What to verify (natural language) | Empty \`""\` | Verify page state \u2014 only if user explicitly requests. Optional \`metadata.waitAfterMs\`. |
|
|
323
|
+
| \`conditional\` | Action if condition is true | The condition to check | Handle dynamic states (e.g. dismiss cookie banner if visible) |
|
|
324
|
+
| \`refresh\` | (optional) | Empty \`""\` | Reload the page |
|
|
325
|
+
|
|
326
|
+
### CLI Examples
|
|
327
|
+
|
|
328
|
+
\`\`\`bash
|
|
329
|
+
# Navigate to a page
|
|
330
|
+
decipher-qa steps format --type goto --data "https://app.example.com/dashboard"
|
|
331
|
+
|
|
332
|
+
# Click a button
|
|
333
|
+
decipher-qa steps format --type default --description 'Click the "Sign In" button' --data ""
|
|
334
|
+
|
|
335
|
+
# Type into an input field (value goes in description, data is always empty)
|
|
336
|
+
decipher-qa steps format --type default --description 'Type "admin@example.com" into the "Email" input field' --data ""
|
|
337
|
+
|
|
338
|
+
# Type with {{unique}} variable (resolved at runtime)
|
|
339
|
+
decipher-qa steps format --type default --description 'Type "test+{{unique}}@company.com" into the "Email" input field' --data ""
|
|
340
|
+
|
|
341
|
+
# Press a key
|
|
342
|
+
decipher-qa steps format --type default --description 'Press Tab to move focus from the "Email" field to the "Password" field' --data ""
|
|
343
|
+
|
|
344
|
+
# Wait for a long operation (minimum 2000ms)
|
|
345
|
+
decipher-qa steps format --type wait --data "3000"
|
|
346
|
+
|
|
347
|
+
# Conditional action
|
|
348
|
+
decipher-qa steps format --type conditional --description "A cookie consent banner is visible" --data 'Click the "Accept" button on the cookie banner'
|
|
349
|
+
|
|
350
|
+
# Refresh the page
|
|
351
|
+
decipher-qa steps format --type refresh
|
|
352
|
+
\`\`\`
|
|
353
|
+
|
|
354
|
+
---
|
|
355
|
+
|
|
356
|
+
## Variables Reference
|
|
357
|
+
|
|
358
|
+
| Variable | Use Case |
|
|
359
|
+
|----------|----------|
|
|
360
|
+
| \`{{unique}}\` | Generates a unique value at runtime. Use in step \`description\` for fields that need uniqueness (emails, usernames) to avoid conflicts on repeat runs. |
|
|
361
|
+
|
|
362
|
+
Leave \`{{unique}}\` as-is in step descriptions \u2014 it is resolved by the test runner, not by this skill or the CLI.
|
|
363
|
+
|
|
364
|
+
---
|
|
365
|
+
|
|
366
|
+
## Full Worked Example
|
|
367
|
+
|
|
368
|
+
Here is a complete example. The user asked: **"create a new workspace, invite a team member with the Editor role, verify the invitation, then revoke it"**
|
|
369
|
+
|
|
370
|
+
### Exploration Summary
|
|
371
|
+
|
|
372
|
+
After exploring the codebase, the following was found:
|
|
373
|
+
- The workspaces page is at \`/workspaces\`
|
|
374
|
+
- A "New Workspace" button opens a creation dialog with a name field and a "Create" button
|
|
375
|
+
- After creation, the workspace detail page loads at \`/workspaces/<id>\` with a "Members" tab
|
|
376
|
+
- The Members tab has an "Invite Member" button that opens a dialog with an email input and a role dropdown (Viewer, Editor, Admin)
|
|
377
|
+
- Pending invitations appear in a "Pending Invitations" section with a "Revoke" button per row
|
|
378
|
+
|
|
379
|
+
### Generated Steps
|
|
380
|
+
|
|
381
|
+
\`\`\`bash
|
|
382
|
+
# Step 1: Navigate to the workspaces page
|
|
383
|
+
decipher-qa steps format --type goto --data "https://app.example.com/workspaces"
|
|
384
|
+
|
|
385
|
+
# Step 2: Click the New Workspace button
|
|
386
|
+
decipher-qa steps format --type default --description 'Click the "New Workspace" button in the top-right corner of the page' --data ""
|
|
387
|
+
|
|
388
|
+
# Step 3: Click the Workspace Name input
|
|
389
|
+
decipher-qa steps format --type default --description 'Click on the "Workspace Name" input field in the creation dialog' --data ""
|
|
390
|
+
|
|
391
|
+
# Step 4: Type the workspace name
|
|
392
|
+
decipher-qa steps format --type default --description 'Type "QA Workspace {{unique}}" into the "Workspace Name" input field' --data ""
|
|
393
|
+
|
|
394
|
+
# Step 5: Click Create
|
|
395
|
+
decipher-qa steps format --type default --description 'Click the "Create" button in the creation dialog' --data ""
|
|
396
|
+
|
|
397
|
+
# Step 6: Wait for workspace creation and page navigation
|
|
398
|
+
decipher-qa steps format --type wait --data "3000"
|
|
399
|
+
|
|
400
|
+
# Step 7: Click the Members tab
|
|
401
|
+
decipher-qa steps format --type default --description 'Click the "Members" tab in the workspace detail page' --data ""
|
|
402
|
+
|
|
403
|
+
# Step 8: Click the Invite Member button
|
|
404
|
+
decipher-qa steps format --type default --description 'Click the "Invite Member" button in the Members tab' --data ""
|
|
405
|
+
|
|
406
|
+
# Step 9: Click the Email input
|
|
407
|
+
decipher-qa steps format --type default --description 'Click on the "Email" input field in the invite dialog' --data ""
|
|
408
|
+
|
|
409
|
+
# Step 10: Type the email
|
|
410
|
+
decipher-qa steps format --type default --description 'Type "teammate+{{unique}}@example.com" into the "Email" input field' --data ""
|
|
411
|
+
|
|
412
|
+
# Step 11: Click the Role dropdown
|
|
413
|
+
decipher-qa steps format --type default --description 'Click the "Role" dropdown in the invite dialog' --data ""
|
|
414
|
+
|
|
415
|
+
# Step 12: Select Editor from the dropdown
|
|
416
|
+
decipher-qa steps format --type default --description 'Select "Editor" from the role dropdown options' --data ""
|
|
417
|
+
|
|
418
|
+
# Step 13: Click Send Invite
|
|
419
|
+
decipher-qa steps format --type default --description 'Click the "Send Invite" button in the invite dialog' --data ""
|
|
420
|
+
|
|
421
|
+
# Step 14: Wait for invitation to send
|
|
422
|
+
decipher-qa steps format --type wait --data "2000"
|
|
423
|
+
|
|
424
|
+
# Step 15: Assert the invitation appears
|
|
425
|
+
decipher-qa steps format --type assert --data 'A pending invitation for "teammate+{{unique}}@example.com" with role "Editor" appears in the "Pending Invitations" section'
|
|
426
|
+
|
|
427
|
+
# Step 16: Click the Revoke button
|
|
428
|
+
decipher-qa steps format --type default --description 'Click the "Revoke" button on the pending invitation row for "teammate+{{unique}}@example.com"' --data ""
|
|
429
|
+
|
|
430
|
+
# Step 17: Click Confirm in the revocation dialog
|
|
431
|
+
decipher-qa steps format --type default --description 'Click the "Confirm" button in the revocation confirmation dialog' --data ""
|
|
432
|
+
|
|
433
|
+
# Step 18: Wait for revocation to complete
|
|
434
|
+
decipher-qa steps format --type wait --data "2000"
|
|
435
|
+
|
|
436
|
+
# Step 19: Assert the invitation is removed
|
|
437
|
+
decipher-qa steps format --type assert --data 'The invitation for "teammate+{{unique}}@example.com" is no longer visible in the "Pending Invitations" section'
|
|
438
|
+
\`\`\`
|
|
439
|
+
|
|
440
|
+
After collecting the JSON output, display the steps in the clean readable format:
|
|
441
|
+
|
|
442
|
+
\`\`\`
|
|
443
|
+
1. [goto] https://app.example.com/workspaces
|
|
444
|
+
2. [default] Click the "New Workspace" button in the top-right corner of the page
|
|
445
|
+
3. [default] Click on the "Workspace Name" input field in the creation dialog
|
|
446
|
+
4. [default] Type "QA Workspace {{unique}}" into the "Workspace Name" input field
|
|
447
|
+
5. [default] Click the "Create" button in the creation dialog
|
|
448
|
+
6. [wait] 3000ms \u2014 workspace creating and page navigating
|
|
449
|
+
7. [default] Click the "Members" tab in the workspace detail page
|
|
450
|
+
8. [default] Click the "Invite Member" button in the Members tab
|
|
451
|
+
9. [default] Click on the "Email" input field in the invite dialog
|
|
452
|
+
10. [default] Type "teammate+{{unique}}@example.com" into the "Email" input field
|
|
453
|
+
11. [default] Click the "Role" dropdown in the invite dialog
|
|
454
|
+
12. [default] Select "Editor" from the role dropdown options
|
|
455
|
+
13. [default] Click the "Send Invite" button in the invite dialog
|
|
456
|
+
14. [wait] 2000ms \u2014 invitation sending
|
|
457
|
+
15. [assert] A pending invitation for "teammate+{{unique}}@example.com" with role "Editor" appears in the "Pending Invitations" section
|
|
458
|
+
16. [default] Click the "Revoke" button on the pending invitation row for "teammate+{{unique}}@example.com"
|
|
459
|
+
17. [default] Click the "Confirm" button in the revocation confirmation dialog
|
|
460
|
+
18. [wait] 2000ms \u2014 invitation revoking
|
|
461
|
+
19. [assert] The invitation for "teammate+{{unique}}@example.com" is no longer visible in the "Pending Invitations" section
|
|
462
|
+
\`\`\`
|
|
463
|
+
`,Xe='# CLI \u2014 Decipher QA Agent Command Reference\n\nThis is a reference for the `decipher-qa` CLI tool. Use it to run commands, understand errors, and know when to bring the user into the loop.\n\n**IMPORTANT:** Always invoke the CLI as `decipher-qa` \u2014 never use `npx decipher-qa` or any other prefix.\n\n---\n\n## Commands\n\n### `decipher-qa init`\nScaffold skills into the nearest git repository.\n```bash\ndecipher-qa init # create skill files (skip existing)\ndecipher-qa init --force # overwrite existing skill files\n```\n\n### `decipher-qa screenshot`\nDownload a screenshot to a temp file for viewing. Returns the file path to stdout.\n```bash\ndecipher-qa screenshot --url "<screenshot_url>"\n```\nUse this to view screenshots from `test get` or `validation-progress` responses. After downloading, use the Read tool on the returned file path to view the image.\n\n### `decipher-qa login`\nAuthenticate with the Decipher API. **This is interactive \u2014 the user must run it in their terminal.**\n```bash\ndecipher-qa login\n```\n\n### `decipher-qa whoami`\nShow the currently authenticated user and organization.\n```bash\ndecipher-qa whoami\n```\n\n### `decipher-qa test`\nManage QA tests. All IDs are numeric.\n```bash\ndecipher-qa test list # list all tests (includes steps)\ndecipher-qa test list --name "<search>" # filter by name\ndecipher-qa test create --name "<n>" --url "<u>" --description "<d>" # create a test\ndecipher-qa test get --id <id> # get test with steps and screenshots\ndecipher-qa test update --id <id> --name "<n>" # update a test\ndecipher-qa test update --id <id> --identity-id <id> # link identity\ndecipher-qa test update --id <id> --tags "tag1,tag2" # set tags\ndecipher-qa test delete --id <id> # delete a test\ndecipher-qa test set-steps --id <id> --steps \'<json>\' # set steps array for a test\ndecipher-qa test run-validation --id <id> # trigger validation\ndecipher-qa test validation-progress --id <id> # check validation progress (includes screenshots)\ndecipher-qa test start-run --id <id> # start a test run\n```\n\n### `decipher-qa identity`\nManage login identities. All IDs are numeric.\n```bash\ndecipher-qa identity list # list all identities\ndecipher-qa identity list --name "<search>" # filter by name\ndecipher-qa identity create --name "<n>" --username "<u>" --password "<p>" --url "<url>" # create\ndecipher-qa identity get --id <id> # get identity\ndecipher-qa identity update --id <id> --name "<n>" # update\ndecipher-qa identity delete --id <id> # delete\n```\n\n### `decipher-qa steps format`\nFormat a test step as JSON.\n```bash\ndecipher-qa steps format --type goto --data "https://app.example.com"\ndecipher-qa steps format --type default --description \'Click "Save"\' --data ""\ndecipher-qa steps format --type wait --data "3000"\ndecipher-qa steps format --type conditional --description "Banner is visible" --data \'Dismiss the banner\'\ndecipher-qa steps format --type assert --data "Page title is Dashboard"\ndecipher-qa steps format --type refresh\n```\nValid `--type` values: `goto`, `default`, `wait`, `assert`, `conditional`, `refresh`\n\n---\n\n## Error Handling\n\nWhen a CLI command fails, match the error output against this table to determine the cause and correct action.\n\n| Error pattern | Cause | Action |\n|---|---|---|\n| `Config not found` | User has never logged in | User must run `decipher-qa login` in their terminal |\n| `Token is invalid, revoked, or expired` | 401 from API \u2014 auth token expired | User must re-authenticate with `decipher-qa login` |\n| `Could not connect to Decipher API` | Network failure or API down | Ask user to check their network connection |\n| `not_found_error` | Invalid or stale ID | Use `decipher-qa test get --id <id>` or list items and retry with a valid ID |\n| `validation_error` | Invalid input data | Check the error message for which field is invalid |\n| `Invalid step type` | Wrong `--type` value passed to `steps format` | Use one of: `goto`, `default`, `wait`, `assert`, `conditional`, `refresh` |\n| `Invalid steps JSON` | Malformed JSON or non-array passed to `test set-steps --steps` | Ensure the value is a valid JSON array string |\n\n---\n\n## When to Bring the User Into the Loop\n\n**Always stop and involve the user when:**\n\n- **`login` is needed** \u2014 this command is interactive and must be run in the user\'s terminal. You cannot run it on their behalf.\n- **Token expiration or revocation** \u2014 the user must re-authenticate by running `decipher-qa login`.\n- **Network errors** \u2014 the user may need to check their connection, VPN, or firewall.\n- **Unexpected HTTP status codes** \u2014 if the API returns something other than 200 or a known error, report the status code and response to the user.\n- **Repeated failures** \u2014 if a command fails more than twice for the same reason, stop retrying, explain the issue, and ask the user for guidance.\n',Ze=`# Create Test \u2014 End-to-End Test Creation Workflow
|
|
464
|
+
|
|
465
|
+
**IMPORTANT:** Always invoke the CLI as \`decipher-qa\` \u2014 never use \`npx decipher-qa\` or any other prefix.
|
|
466
|
+
|
|
467
|
+
This skill guides you through the full lifecycle of creating a QA test: gathering info, exploring the codebase to generate steps, getting user confirmation, then creating the test record, linking an identity, saving steps, running validation, and monitoring progress.
|
|
468
|
+
|
|
469
|
+
**Key principle:** Nothing is created until the user explicitly approves. Gather all info, generate steps, show a full summary, and only then create the test record. This avoids orphan records and wasted API calls.
|
|
470
|
+
|
|
471
|
+
---
|
|
472
|
+
|
|
473
|
+
## Phase 1 \u2014 Gather Info
|
|
474
|
+
|
|
475
|
+
Collect all required information from the user. Do NOT proceed until you have clear, complete answers for each field.
|
|
476
|
+
|
|
477
|
+
1. **Determine the base URL** \u2014 run \`decipher-qa identity list\` to get existing identities. Use their URLs to offer choices:
|
|
478
|
+
- **If identities exist:** Extract the unique URL origins (protocol + host) from identity login URLs. Present them as options:
|
|
479
|
+
1. \`https://app.example.com\` \u2014 Production (from identity "Admin User")
|
|
480
|
+
2. Enter a different URL
|
|
481
|
+
- **If no identities exist:** Ask the user for the base URL directly (e.g. \`https://app.example.com\`).
|
|
482
|
+
|
|
483
|
+
2. Ask the user for:
|
|
484
|
+
- **name** (required) \u2014 a short descriptive name for the test (e.g. "Checkout as guest", "Create new project")
|
|
485
|
+
- **description** (required) \u2014 what this test covers and what user actions it should simulate (e.g. "Navigate to the checkout page, add an item to the cart, fill in shipping details, and complete the purchase as a guest user")
|
|
486
|
+
|
|
487
|
+
3. If the description is vague or too broad, ask clarifying questions before proceeding:
|
|
488
|
+
- What specific flow or feature should be tested?
|
|
489
|
+
- What page does the flow start on?
|
|
490
|
+
- What is the expected end state?
|
|
491
|
+
- Are there any edge cases to handle (e.g. popups, banners, empty states)?
|
|
492
|
+
|
|
493
|
+
4. **Confirm the info** \u2014 summarize back to the user:
|
|
494
|
+
\`\`\`
|
|
495
|
+
Test info:
|
|
496
|
+
Name: <name>
|
|
497
|
+
URL: <url>
|
|
498
|
+
Description: <description>
|
|
499
|
+
\`\`\`
|
|
500
|
+
Ask: **"Does this look right?"** \u2014 wait for confirmation before proceeding.
|
|
501
|
+
|
|
502
|
+
5. **Remember** the name, url, and description. Do NOT create the test yet.
|
|
503
|
+
|
|
504
|
+
---
|
|
505
|
+
|
|
506
|
+
## Phase 2 \u2014 Generate Steps
|
|
507
|
+
|
|
508
|
+
Read \`steps.md\` in this skill directory and follow its 4-phase workflow with these overrides:
|
|
509
|
+
|
|
510
|
+
- **Base URL override:** Use the \`url\` from Phase 1 for all URLs in generated steps. Do NOT use \`localhost\` or any other URL unless it matches the user's \`url\`.
|
|
511
|
+
- **Description override:** Use the \`description\` from Phase 1 as the starting context for what to test. Skip the "What flow or feature would you like to generate test steps for?" prompt \u2014 you already know.
|
|
512
|
+
- **All other rules apply:** Follow the full codebase exploration, step writing rules, and step type reference from \`steps.md\`.
|
|
513
|
+
|
|
514
|
+
Collect all generated step JSON objects in memory as an array. Do NOT show raw JSON to the user \u2014 display the clean readable format as described in \`steps.md\`.
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## Phase 3 \u2014 Review & Confirm Steps
|
|
519
|
+
|
|
520
|
+
**STOP here and wait for explicit user approval before proceeding.**
|
|
521
|
+
|
|
522
|
+
1. Display the full step list in readable format:
|
|
523
|
+
\`\`\`
|
|
524
|
+
Steps (<N> total):
|
|
525
|
+
1. [goto] https://app.example.com/dashboard
|
|
526
|
+
2. [default] Click the "New Project" button
|
|
527
|
+
...
|
|
528
|
+
\`\`\`
|
|
529
|
+
|
|
530
|
+
2. Ask: **"Here are the steps. Any changes?"**
|
|
531
|
+
|
|
532
|
+
3. If the user requests changes:
|
|
533
|
+
- Apply corrections
|
|
534
|
+
- Re-display the updated step list
|
|
535
|
+
- Ask for confirmation again
|
|
536
|
+
|
|
537
|
+
4. **Only proceed after the user explicitly confirms the steps.**
|
|
538
|
+
|
|
539
|
+
---
|
|
540
|
+
|
|
541
|
+
## Phase 4 \u2014 Choose Identity
|
|
542
|
+
|
|
543
|
+
1. Run \`decipher-qa identity list\` to check existing identities.
|
|
544
|
+
|
|
545
|
+
2. **If identities exist:**
|
|
546
|
+
- Show a numbered list of identity names (with their URLs)
|
|
547
|
+
- Offer these choices:
|
|
548
|
+
1. Select an existing identity (by number)
|
|
549
|
+
2. **None** \u2014 skip identity linking
|
|
550
|
+
3. **Create new** \u2014 ask for name, url, username, password, then run \`decipher-qa identity create --name "<name>" --username "<username>" --password "<password>" --url "<url>"\`
|
|
551
|
+
|
|
552
|
+
3. **If no identities exist:**
|
|
553
|
+
- Ask: "No identities found. Would you like to create a login identity for this test, or skip?"
|
|
554
|
+
- If create: follow the identity creation flow
|
|
555
|
+
- If skip: continue without linking
|
|
556
|
+
|
|
557
|
+
4. **Remember** the chosen identity (if any). Do NOT create the test yet.
|
|
558
|
+
|
|
559
|
+
---
|
|
560
|
+
|
|
561
|
+
## Phase 5 \u2014 Create the Test, Link Identity & Save Steps
|
|
562
|
+
|
|
563
|
+
1. Create the test:
|
|
564
|
+
\`\`\`bash
|
|
565
|
+
decipher-qa test create --name "<name>" --url "<url>" --description "<description>"
|
|
566
|
+
\`\`\`
|
|
567
|
+
|
|
568
|
+
2. Parse the JSON output and **remember** the \`id\`, \`url\`, and \`decipherUrl\`.
|
|
569
|
+
|
|
570
|
+
3. If an identity was chosen in Phase 4, link it:
|
|
571
|
+
\`\`\`bash
|
|
572
|
+
decipher-qa test update --id <testId> --identity-id <identityId>
|
|
573
|
+
\`\`\`
|
|
574
|
+
|
|
575
|
+
4. Save the steps:
|
|
576
|
+
\`\`\`bash
|
|
577
|
+
decipher-qa test set-steps --id <testId> --steps '<json_array>'
|
|
578
|
+
\`\`\`
|
|
579
|
+
|
|
580
|
+
5. Confirm: "Created test **<name>** (\`<id>\`) with **<N>** steps."
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
## Phase 6 \u2014 Run Validation
|
|
585
|
+
|
|
586
|
+
1. If this is the first attempt, initialize: attemptNumber=1, maxAttempts=3, failureHistory=[]
|
|
587
|
+
2. Run:
|
|
588
|
+
\`\`\`bash
|
|
589
|
+
decipher-qa test run-validation --id <testId>
|
|
590
|
+
\`\`\`
|
|
591
|
+
3. Tell the user: "Validation triggered for test \`<testId>\`. Spawning a monitor to track progress..."
|
|
592
|
+
4. Proceed immediately to Phase 7.
|
|
593
|
+
|
|
594
|
+
---
|
|
595
|
+
|
|
596
|
+
## Phase 7 \u2014 Auto-Polling Validation Monitor & Iteration Loop
|
|
597
|
+
|
|
598
|
+
### Phase 7a \u2014 Spawn Validation Monitor Sub-Agent
|
|
599
|
+
|
|
600
|
+
Use the **Task tool** (subagent_type: "general-purpose") to spawn a sub-agent with the following prompt. Pass the \`testId\` into the prompt:
|
|
601
|
+
|
|
602
|
+
\`\`\`
|
|
603
|
+
You are a validation monitor. Your job is to poll validation progress and return a structured report.
|
|
604
|
+
|
|
605
|
+
**Polling loop:**
|
|
606
|
+
1. Run: \`decipher-qa test validation-progress --id <testId>\`
|
|
607
|
+
2. Check the \`status\` field in the JSON response:
|
|
608
|
+
- "running" \u2192 Log progress (completedSteps/totalSteps), wait ~20 seconds, poll again
|
|
609
|
+
- "completed" \u2192 Go to **Return Success**
|
|
610
|
+
- "failed" or "paused_on_failure" \u2192 Go to **Return Failure**
|
|
611
|
+
- "paused_by_user" \u2192 Return immediately: "STATUS: PAUSED_BY_USER"
|
|
612
|
+
3. Timeout after 30 polls (~10 min) \u2192 Return: "STATUS: TIMEOUT"
|
|
613
|
+
4. If a network error occurs during polling, wait 30 seconds and retry once. If it fails again, return: "STATUS: ERROR\\nDETAILS: <error message>"
|
|
614
|
+
|
|
615
|
+
**Viewing screenshots:**
|
|
616
|
+
To view a screenshot, download it to a temp file and then read it:
|
|
617
|
+
1. Run: \`decipher-qa screenshot --url "<screenshot_url>"\` \u2014 this prints a temp file path
|
|
618
|
+
2. Use the Read tool on the returned file path to view the image
|
|
619
|
+
The user will be asked to approve the Read \u2014 this is expected. Explain that you need to view test screenshots to analyze results.
|
|
620
|
+
|
|
621
|
+
**Return Success:**
|
|
622
|
+
- Go through EVERY step in the \`steps\` array from the response
|
|
623
|
+
- For each step that has \`hasScreenshots: true\`, view each screenshot URL (\`screenshots.before\`, \`screenshots.after\`) using the method above to visually see what the page looked like at each step
|
|
624
|
+
- Return a structured summary:
|
|
625
|
+
\`\`\`
|
|
626
|
+
STATUS: SUCCESS
|
|
627
|
+
STEPS_COMPLETED: <number>
|
|
628
|
+
STEP_SUMMARY:
|
|
629
|
+
- Step 1: [type] <description> \u2014 <visual summary of what screenshots show>
|
|
630
|
+
- Step 2: [type] <description> \u2014 <visual summary>
|
|
631
|
+
... (for all steps)
|
|
632
|
+
\`\`\`
|
|
633
|
+
|
|
634
|
+
**Return Failure:**
|
|
635
|
+
- Extract the \`failure\` object (stepNumber, stepDescription, failureReason, failureScreenshotUrl, browserState)
|
|
636
|
+
- View the failure screenshot URL to visually understand what the page looks like at the point of failure
|
|
637
|
+
- View screenshots from 2-3 steps BEFORE the failing step to understand the progression leading to failure
|
|
638
|
+
- Return a structured failure report:
|
|
639
|
+
\`\`\`
|
|
640
|
+
STATUS: FAILED
|
|
641
|
+
FAILED_AT_STEP: <number>
|
|
642
|
+
STEP_DESCRIPTION: <what the step was trying to do>
|
|
643
|
+
FAILURE_REASON: <error message from the failure object>
|
|
644
|
+
BROWSER_URL: <url from browserState>
|
|
645
|
+
PAGE_TITLE: <title from browserState>
|
|
646
|
+
|
|
647
|
+
Visual analysis:
|
|
648
|
+
- Step N-2: <what the screenshot shows>
|
|
649
|
+
- Step N-1: <what the screenshot shows>
|
|
650
|
+
- Step N (FAILED): <what the failure screenshot shows, what went wrong visually>
|
|
651
|
+
|
|
652
|
+
Diagnosis: <why the step likely failed based on the visual evidence + failure reason>
|
|
653
|
+
|
|
654
|
+
ALL_STEPS_JSON: <full steps array as JSON for reference>
|
|
655
|
+
\`\`\`
|
|
656
|
+
\`\`\`
|
|
657
|
+
|
|
658
|
+
### Phase 7b \u2014 Handle Monitor Result
|
|
659
|
+
|
|
660
|
+
When the sub-agent returns, parse its output by STATUS:
|
|
661
|
+
|
|
662
|
+
- **SUCCESS** \u2192 Tell the user: "Validation passed! All <N> steps completed successfully." \u2192 Proceed to Phase 8.
|
|
663
|
+
- **PAUSED_BY_USER** \u2192 Tell the user: "Validation was paused by user. You can resume it from the Decipher dashboard." \u2192 Proceed to Phase 8.
|
|
664
|
+
- **TIMEOUT** \u2192 Tell the user: "Validation is still running after ~10 minutes. Check the Decipher dashboard for progress." \u2192 Proceed to Phase 8.
|
|
665
|
+
- **ERROR** \u2192 Tell the user: "Encountered an error while monitoring: <details>. Check \`decipher-qa test validation-progress --id <testId>\` manually." \u2192 Proceed to Phase 8.
|
|
666
|
+
- **FAILED** \u2192 Enter the **Iteration Loop** below.
|
|
667
|
+
|
|
668
|
+
### Iteration Loop (on failure)
|
|
669
|
+
|
|
670
|
+
1. **Display the failure to the user:**
|
|
671
|
+
\`\`\`
|
|
672
|
+
Validation failed (attempt <attemptNumber>/<maxAttempts>):
|
|
673
|
+
Step <X>: <step description>
|
|
674
|
+
Reason: <failureReason>
|
|
675
|
+
Visual analysis: <diagnosis from sub-agent>
|
|
676
|
+
\`\`\`
|
|
677
|
+
|
|
678
|
+
2. **Check if max retries reached:** If \`attemptNumber >= maxAttempts\` (3):
|
|
679
|
+
- Stop retrying
|
|
680
|
+
- Display the full failure history (all attempts, what failed, what fixes were tried)
|
|
681
|
+
- Link to the Decipher dashboard: "You can review and fix this test at <decipherUrl>"
|
|
682
|
+
- Proceed to Phase 7.
|
|
683
|
+
|
|
684
|
+
3. **Check for login failures:** If the failure reason indicates a login/authentication problem (credentials invalid, login page error, identity-related failure):
|
|
685
|
+
- Do NOT attempt to fix steps \u2014 the issue is with credentials, not step logic
|
|
686
|
+
- Tell the user: "This appears to be a login/credential issue. Please update the identity credentials and retry."
|
|
687
|
+
- Proceed to Phase 7.
|
|
688
|
+
|
|
689
|
+
4. **Fix and retry** (if \`attemptNumber < maxAttempts\`):
|
|
690
|
+
a. Run \`decipher-qa test get --id <testId>\` to get the current full step list
|
|
691
|
+
b. Analyze the failure context from the sub-agent report:
|
|
692
|
+
- What step failed and why
|
|
693
|
+
- What the page actually looked like (from screenshots)
|
|
694
|
+
- What the page was expected to look like
|
|
695
|
+
c. Check \`failureHistory\` \u2014 if the same step failed with the same reason before, try a fundamentally different approach:
|
|
696
|
+
- Add a \`wait\` step before the failing step
|
|
697
|
+
- Restructure the flow (different navigation path, different UI element)
|
|
698
|
+
- Re-explore the codebase to find the correct selectors/element references
|
|
699
|
+
d. **Re-explore codebase if needed** \u2014 if the failure suggests the UI element doesn't exist or has a different label than expected, use Glob/Grep/Read to re-read the relevant components and find the correct element references
|
|
700
|
+
e. Generate fixed steps following all step-writing rules from \`steps.md\`
|
|
701
|
+
f. Save the fixed steps:
|
|
702
|
+
\`\`\`bash
|
|
703
|
+
decipher-qa test set-steps --id <testId> --steps '<fixed_json_array>'
|
|
704
|
+
\`\`\`
|
|
705
|
+
g. Record in failureHistory: \`{ attempt: <N>, failedStep: <stepNumber>, reason: <failureReason>, fixApplied: <description of what was changed> }\`
|
|
706
|
+
h. Increment attemptNumber
|
|
707
|
+
i. Re-trigger validation:
|
|
708
|
+
\`\`\`bash
|
|
709
|
+
decipher-qa test run-validation --id <testId>
|
|
710
|
+
\`\`\`
|
|
711
|
+
j. Go back to **Phase 7a** \u2014 spawn a new monitor sub-agent
|
|
712
|
+
|
|
713
|
+
---
|
|
714
|
+
|
|
715
|
+
## Phase 8 \u2014 Summary & Next Steps
|
|
716
|
+
|
|
717
|
+
Display a final summary:
|
|
718
|
+
|
|
719
|
+
\`\`\`
|
|
720
|
+
Test created and validated!
|
|
721
|
+
|
|
722
|
+
Name: <name>
|
|
723
|
+
ID: <id>
|
|
724
|
+
URL: <url>
|
|
725
|
+
Decipher: <decipherUrl>
|
|
726
|
+
Identity: <identity name or "None">
|
|
727
|
+
Steps: <N> steps
|
|
728
|
+
Validation: PASSED / FAILED after N attempts / TIMEOUT / PAUSED
|
|
729
|
+
Attempts: <attemptNumber>/<maxAttempts>
|
|
730
|
+
|
|
731
|
+
Next actions:
|
|
732
|
+
decipher-qa test start-run --id <id> \u2014 Start a test run (if validation passed)
|
|
733
|
+
/decipher-qa validate <id> \u2014 Re-run validation
|
|
734
|
+
/decipher-qa create-test \u2014 Create another test end-to-end
|
|
735
|
+
\`\`\`
|
|
736
|
+
`;var I=C(Rt()),Pt=I.default.hex("#6C5CE7"),Ee=I.default.dim,Nt=I.default.bold,N=n=>console.log(I.default.green(" + ")+n),q=n=>console.error(I.default.red(" x ")+n),_=n=>console.log(I.default.cyan(" * ")+n),D=n=>console.log(I.default.yellow(" ! ")+n),O=(n,e)=>console.log(Ee(" "+n.padEnd(14))+Nt(e));function V(n){console.log(),console.log(" "+Pt(">>")+Nt(" Decipher QA ")+Pt("<<")+" "+Ee(n)),console.log()}function Ie(){console.log(Ee(" "+"-".repeat(46)))}var Z=C(require("fs")),Dt=C(require("os")),ee=C(require("path")),T=ee.default.join(Dt.default.homedir(),".decipher","qa-config.json");function R(){Z.default.existsSync(T)||(console.error(JSON.stringify({error:`Config not found at ${T}. Run \`decipher-qa login\` first.`})),process.exit(1));let n=Z.default.readFileSync(T,"utf-8"),e=JSON.parse(n);return e.token||(console.error(JSON.stringify({error:`No token found in ${T}. Run \`decipher-qa login\` to authenticate.`})),process.exit(1)),e}function $t(n){let e=n;for(;;){if(Z.default.existsSync(ee.default.join(e,".git")))return e;let t=ee.default.dirname(e);if(t===e)return null;e=t}}var nn=[{relPath:".claude/skills/decipher-qa/SKILL.md",content:ze},{relPath:".claude/skills/decipher-qa/test.md",content:Ye},{relPath:".claude/skills/decipher-qa/identity.md",content:Qe},{relPath:".claude/skills/decipher-qa/steps.md",content:Ke},{relPath:".claude/skills/decipher-qa/cli.md",content:Xe},{relPath:".claude/skills/decipher-qa/create-test.md",content:Ze}];async function sn(n){V("Initialize"),_("Looking for git repository...");let e=$t(process.cwd());e||(q("No git repository found. Run this command inside a git repo."),process.exit(1)),N("Found: "+e),console.log(),_("Creating skill files...");let t=0;for(let i of nn){let s=qe.default.join(e,i.relPath);if(te.default.existsSync(s)&&!n.force){D(` ${i.relPath} (exists, use --force to overwrite)`),t++;continue}te.default.mkdirSync(qe.default.dirname(s),{recursive:!0}),te.default.writeFileSync(s,i.content,"utf-8"),console.log(` ${i.relPath}`)}console.log(),t>0&&!n.force&&(_(`${t} file(s) skipped. Use --force to overwrite skill files.`),console.log()),N("Decipher QA skills installed!"),console.log(),_("Available commands in Claude Code:"),console.log(" /decipher-qa create-test Create a new test end-to-end (name, identity, steps, validation)"),console.log(" /decipher-qa validate Run validation on an existing test"),console.log(" /decipher-qa test Manage QA tests (create, delete, list)"),console.log(" /decipher-qa identity Manage login identities (create, delete, list)"),console.log(" /decipher-qa steps Generate QA test steps by exploring your codebase"),console.log(" /decipher-qa cli CLI command reference and error handling guide"),console.log()}var Lt=new u("init").description("Scaffold Decipher QA skills into the nearest git repository").option("-f, --force","Overwrite existing skill files",!1).action(sn);var Mt=C(require("crypto"));var Te=["goto","default","wait","assert","conditional","auth","refresh"];function rn(n){let{type:e,description:t,data:i,metadata:s}=n;e==="goto"&&i&&!/^https?:\/\//i.test(i)&&D(`Data "${i}" doesn't look like a URL for a goto step`),e==="wait"&&i&&isNaN(Number(i))&&D(`Data "${i}" doesn't look numeric for a wait step`),e==="auth"&&i!=="magic_link"&&i!=="code"&&D(`Data for auth step should be "magic_link" or "code", got "${i}"`);let r={id:Mt.default.randomUUID(),type:e,description:e==="goto"&&!t?i:e==="wait"?"":t,data:i,setByUser:!0,originFrom:"agent"};if(s)try{r.metadata=JSON.parse(s)}catch{D(`Could not parse --metadata as JSON: ${s}`),r.metadata=s}console.log(JSON.stringify(r,null,2))}var on=new u("format").description("Generate a validated JSON step object").requiredOption("--type <type>",`Step type: ${Te.join(", ")}`).option("--description <text>","Step description","").option("--data <value>","Step data","").option("--metadata <json>","Optional JSON metadata").action(n=>{let e=n.type;Te.includes(e)||(console.error(`Invalid step type "${e}". Must be one of: ${Te.join(", ")}`),process.exit(1)),rn({type:e,description:n.description,data:n.data,metadata:n.metadata})}),Ut=new u("steps").description("QA test step utilities").addCommand(on);async function m(n,e){let t=R(),i=e?.method??"GET",s=new URL(n,G);if(e?.query)for(let[o,a]of Object.entries(e.query))a!==void 0&&s.searchParams.set(o,a);let r;try{r=await fetch(s.toString(),{method:i,headers:{Authorization:`Bearer ${t.token}`,...e?.body!==void 0?{"Content-Type":"application/json"}:{}},body:e?.body!==void 0?JSON.stringify(e.body):void 0})}catch{console.error(JSON.stringify({error:"Could not connect to Decipher API. Check your network connection."})),process.exit(1)}if(!r.ok){let o;try{o=await r.json()}catch{o={error:{message:`HTTP ${r.status} ${r.statusText}`}}}console.error(JSON.stringify(o,null,2)),process.exit(1)}return await r.json()}var Vt=new u("create").description("Create a new test").requiredOption("--name <name>","Test name").requiredOption("--url <url>","URL the test runs against").requiredOption("--description <text>","Test description").option("--identity-id <id>","Identity ID for authentication").option("--tags <tags>","Comma-separated tags").action(async n=>{let e={name:n.name,url:n.url,description:n.description};n.identityId!==void 0&&(e.identityId=Number(n.identityId)),n.tags!==void 0&&(e.tags=n.tags.split(",").map(i=>i.trim()));let t=await m("/api/v1/tests",{method:"POST",body:e});console.log(JSON.stringify(t,null,2))});var Ft=new u("get").description("Get a test by ID").requiredOption("--id <id>","Test ID").action(async n=>{let e=await m(`/api/v1/tests/${n.id}`,{query:{include:"steps,screenshots"}});console.log(JSON.stringify(e,null,2))});var Ht=new u("update").description("Update a test by ID").requiredOption("--id <id>","Test ID").option("--name <name>","New test name").option("--url <url>","New URL").option("--identity-id <id>","New identity ID (use 'null' to clear)").option("--description <text>","New description").option("--tags <tags>","Comma-separated tags").action(async n=>{let e={};n.name!==void 0&&(e.name=n.name),n.url!==void 0&&(e.url=n.url),n.identityId!==void 0&&(e.identityId=n.identityId==="null"?null:Number(n.identityId)),n.description!==void 0&&(e.description=n.description),n.tags!==void 0&&(e.tags=n.tags.split(",").map(i=>i.trim()));let t=await m(`/api/v1/tests/${n.id}`,{method:"PATCH",body:e});console.log(JSON.stringify(t,null,2))});var jt=new u("delete").description("Delete a test by ID").requiredOption("--id <id>","Test ID").action(async n=>{let e=await m(`/api/v1/tests/${n.id}`,{method:"DELETE"});console.log(JSON.stringify(e,null,2))});var Wt=new u("list").description("List all tests").option("--name <search>","Filter by name").action(async n=>{let e=await m("/api/v1/tests",{query:{name:n.name,include:"steps"}});console.log(JSON.stringify(e,null,2))});var Bt=new u("set-steps").description("Set the steps array for a test by ID").requiredOption("--id <id>","Test ID").requiredOption("--steps <json>","Steps as a JSON array string").action(async n=>{let e;try{if(e=JSON.parse(n.steps),!Array.isArray(e))throw new Error("Steps must be a JSON array.")}catch(i){console.error(JSON.stringify({error:`Invalid steps JSON: ${i.message}`})),process.exit(1)}let t=await m(`/api/v1/tests/${n.id}/steps`,{method:"PUT",body:{steps:e}});console.log(JSON.stringify(t,null,2))});var Gt=new u("run-validation").description("Trigger a validation run for a test").requiredOption("--id <id>","Test ID").action(async n=>{let e=await m(`/api/v1/tests/${n.id}/run-validation`,{method:"POST"});console.log(JSON.stringify(e,null,2))});var Jt=new u("validation-progress").description("Check validation progress for a test").requiredOption("--id <id>","Test ID").action(async n=>{let e=await m(`/api/v1/tests/${n.id}/validation-progress`,{query:{include:"screenshots"}});console.log(JSON.stringify(e,null,2))});var zt=new u("start-run").description("Start a test run").requiredOption("--id <id>","Test ID").action(async n=>{let e=await m(`/api/v1/tests/${n.id}/runs`,{method:"POST"});console.log(JSON.stringify(e,null,2))});var Yt=new u("test").description("Manage QA tests (create, get, update, delete, list, set-steps, run-validation, validation-progress, start-run)").hook("preAction",()=>{R()}).addCommand(Vt).addCommand(Ft).addCommand(Ht).addCommand(jt).addCommand(Wt).addCommand(Bt).addCommand(Gt).addCommand(Jt).addCommand(zt);var Qt=new u("create").description("Create a new identity").requiredOption("--name <name>","Identity name").requiredOption("--username <username>","Login username or email").requiredOption("--password <password>","Login password").requiredOption("--url <url>","Login page URL").option("--description <text>","Identity description").action(async n=>{let e={name:n.name,username:n.username,password:n.password,url:n.url};n.description!==void 0&&(e.description=n.description);let t=await m("/api/v1/identities",{method:"POST",body:e});console.log(JSON.stringify(t,null,2))});var Kt=new u("get").description("Get an identity by ID").requiredOption("--id <id>","Identity ID").action(async n=>{let e=await m(`/api/v1/identities/${n.id}`);console.log(JSON.stringify(e,null,2))});var Xt=new u("update").description("Update an identity by ID").requiredOption("--id <id>","Identity ID").option("--name <name>","New identity name").option("--username <username>","New username").option("--password <password>","New password").option("--url <url>","New login URL").option("--description <text>","New description").action(async n=>{let e={};n.name!==void 0&&(e.name=n.name),n.username!==void 0&&(e.username=n.username),n.password!==void 0&&(e.password=n.password),n.url!==void 0&&(e.url=n.url),n.description!==void 0&&(e.description=n.description);let t=await m(`/api/v1/identities/${n.id}`,{method:"PATCH",body:e});console.log(JSON.stringify(t,null,2))});var Zt=new u("delete").description("Delete an identity by ID").requiredOption("--id <id>","Identity ID").action(async n=>{let e=await m(`/api/v1/identities/${n.id}`,{method:"DELETE"});console.log(JSON.stringify(e,null,2))});var ei=new u("list").description("List all identities").option("--name <search>","Filter by name").action(async n=>{let e=await m("/api/v1/identities",{query:{name:n.name}});console.log(JSON.stringify(e,null,2))});var ti=new u("identity").description("Manage login identities (create, get, update, delete, list)").hook("preAction",()=>{R()}).addCommand(Qt).addCommand(Kt).addCommand(Xt).addCommand(Zt).addCommand(ei);var Re=C(require("fs")),ii=C(require("path")),ni=C(require("readline"));var an="https://www.app.getdecipher.com/settings?tab=testing";async function ln(){V("Login"),_("To authenticate, grab your API token from:"),console.log(` ${an}`),console.log();let n=ni.default.createInterface({input:process.stdin,output:process.stdout}),e=await new Promise(i=>{n.question(" Paste your API token: ",s=>{n.close(),i(s.trim())})});e||(q("No token provided. Aborting."),process.exit(1));let t=ii.default.dirname(T);Re.default.mkdirSync(t,{recursive:!0}),Re.default.writeFileSync(T,JSON.stringify({token:e},null,2),"utf-8"),console.log(),N("Token saved to "+T),_("You can now use `decipher-qa test`, `decipher-qa steps`, etc."),console.log()}var si=new u("login").description("Authenticate with Decipher by saving your API token").action(ln);async function cn(){V("Who Am I");let n=R();_("Verifying token..."),console.log();let e;try{e=await fetch(`${G}/api/v1/whoami`,{headers:{Authorization:`Bearer ${n.token}`}})}catch{q("Could not connect to Decipher API."),_("Check your network connection and try again."),process.exit(1)}e.ok||(e.status===401?(q("Token is invalid, revoked, or expired."),_("Run `decipher-qa login` to re-authenticate.")):q(`Unexpected response: ${e.status} ${e.statusText}`),process.exit(1));let t=await e.json();N("Token is valid!"),console.log(),Ie(),O("Key Name",t.key_name),O("Key Prefix",t.key_prefix),O("Organization",t.organization??"\u2014"),O("Scopes",t.scopes.join(", ")||"none"),O("Created By",t.created_by??"\u2014"),O("Created At",t.created_at),O("Expires At",t.expires_at??"never"),O("Last Used",t.last_used_at??"\u2014"),Ie(),console.log()}var ri=new u("whoami").description("Display information about the current API token").action(cn);var oi=C(require("fs")),ai=C(require("os")),li=C(require("path")),ci=C(require("crypto")),di=new u("screenshot").description("Download a Decipher screenshot to a temp file for viewing").requiredOption("--url <url>","The screenshot URL from decipher-qa CLI responses").action(async n=>{let e=n.url;try{let t=new URL(e);t.searchParams.set("format","raw");let i=await fetch(t.toString());i.ok||(console.error(JSON.stringify({error:`Failed to fetch screenshot: HTTP ${i.status} ${i.statusText}`})),process.exit(1));let s=i.headers.get("content-type")||"image/png",r=s.includes("webp")?".webp":s.includes("jpeg")||s.includes("jpg")?".jpg":".png",o=ci.default.createHash("md5").update(e).digest("hex").slice(0,8),a=li.default.join(ai.default.tmpdir(),`decipher-screenshot-${o}${r}`),l=Buffer.from(await i.arrayBuffer());oi.default.writeFileSync(a,l),console.log(a)}catch(t){let i=t instanceof Error?t.message:String(t);console.error(JSON.stringify({error:`Error fetching screenshot: ${i}`})),process.exit(1)}});var x=new u;x.name(Je).description("Decipher QA Agent CLI").version("0.0.1","-v, --version");x.addCommand(Lt);x.addCommand(Ut);x.addCommand(Yt);x.addCommand(ti);x.addCommand(si);x.addCommand(ri);x.addCommand(di);x.parse();
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@decipher-sdk/decipher-qa",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"bin": {
|
|
5
|
+
"decipher-qa": "dist/index.js"
|
|
6
|
+
},
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsup",
|
|
13
|
+
"check-types": "tsc -p tsconfig.json --noEmit",
|
|
14
|
+
"clean": "rm -rf dist tsconfig.tsbuildinfo",
|
|
15
|
+
"dev": "tsup --watch"
|
|
16
|
+
},
|
|
17
|
+
"author": "Decipher AI",
|
|
18
|
+
"license": "UNLICENSED",
|
|
19
|
+
"description": "Decipher QA Agent CLI — scaffolds Claude Code skills for QA test management",
|
|
20
|
+
"engines": {
|
|
21
|
+
"node": ">=18"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"chalk": "^4.1.2",
|
|
25
|
+
"commander": "^12.1.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"tsup": "^8.0.0",
|
|
30
|
+
"typescript": "^5.4.3"
|
|
31
|
+
},
|
|
32
|
+
"keywords": []
|
|
33
|
+
}
|