@hhsw2015/task-master-ai 0.43.10 → 0.43.11

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.
@@ -0,0 +1 @@
1
+ import{a as e,i as t,n,r,t as i}from"./ai-services-unified-CEISDqFA.js";import"./config-manager-3pTgfD7M.js";import"./git-utils-DllbRE35.js";import"./sentry-BU9KKY_b.js";export{i as generateObjectService,n as generateTextService,r as logAiUsage,t as streamObjectService,e as streamTextService};
@@ -1,4 +1,4 @@
1
- import{A as e,C as t,D as n,Et as r,F as i,H as a,I as o,J as s,M as c,N as l,P as u,S as d,T as f,_ as p,a as m,b as h,d as g,ht as ee,j as _,l as v,o as te,p as y,s as ne,ut as b,v as x,yt as S}from"./config-manager-CynteFcs.js";import{n as C,t as w}from"./sentry-DMIPmMuT.js";import{createRequire as T}from"node:module";import E,{promises as D}from"fs";import O,{join as k}from"path";import{homedir as A}from"os";import{execSync as j,spawn as M}from"child_process";import*as N from"ai";import{jsonrepair as P}from"jsonrepair";import{EnvHttpProxyAgent as F}from"undici";import{createAnthropic as re}from"@ai-sdk/anthropic";import{createPerplexity as ie}from"@ai-sdk/perplexity";import{createGoogleGenerativeAI as ae}from"@ai-sdk/google";import{createOpenAI as oe}from"@ai-sdk/openai";import{createXai as se}from"@ai-sdk/xai";import{createGroq as ce}from"@ai-sdk/groq";import{createOpenRouter as le}from"@openrouter/ai-sdk-provider";import{createOllama as ue}from"ollama-ai-provider-v2";import{createAmazonBedrock as de}from"@ai-sdk/amazon-bedrock";import{fromNodeProviderChain as fe}from"@aws-sdk/credential-providers";import{createAzure as pe}from"@ai-sdk/azure";import{createVertex as me}from"@ai-sdk/google-vertex";import{createClaudeCode as he}from"ai-sdk-provider-claude-code";import{createGeminiProvider as ge}from"ai-sdk-provider-gemini-cli";import{APICallError as I,LoadAPIKeyError as _e,NoSuchModelError as L}from"@ai-sdk/provider";import{generateId as R}from"@ai-sdk/provider-utils";import{parse as ve}from"jsonc-parser";import{createCodexCli as ye}from"ai-sdk-provider-codex-cli";import{createOpenAICompatible as be}from"@ai-sdk/openai-compatible";var xe=Object.defineProperty,Se=e=>{let t={};for(var n in e)xe(t,n,{get:e[n],enumerable:!0});return t},z=T(import.meta.url);let B=null;var V=class e{constructor(){this._providers=new Map,this._initialized=!1}static getInstance(){return B||=new e,B}initialize(){return this._initialized||=!0,this}registerProvider(e,t,n={}){if(!e||typeof e!=`string`)throw Error(`Provider name must be a non-empty string`);if(!t)throw Error(`Provider instance is required`);if(typeof t.generateText!=`function`||typeof t.streamText!=`function`||typeof t.generateObject!=`function`)throw Error(`Provider must implement BaseAIProvider interface`);return this._providers.set(e,{instance:t,options:n,registeredAt:new Date}),this}hasProvider(e){return this._providers.has(e)}getProvider(e){let t=this._providers.get(e);return t?t.instance:null}getAllProviders(){return new Map(this._providers)}unregisterProvider(e){return this._providers.has(e)?(this._providers.delete(e),!0):!1}reset(){this._providers.clear(),this._initialized=!1}};V.getInstance().initialize();var H=V;const{JSONParseError:Ce,NoObjectGeneratedError:we,generateObject:Te,generateText:Ee,streamObject:De,streamText:Oe,zodSchema:ke}=N,U=N.jsonSchema,Ae=new Set([`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`]),je=[`additionalProperties`,`contains`,`if`,`then`,`else`,`not`,`propertyNames`],Me=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],Ne=[`definitions`,`$defs`,`dependentSchemas`,`patternProperties`,`properties`],Pe=e=>e?Array.isArray(e)?e.includes(`integer`):e===`integer`:!1,W=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(W);let t={...e};if(Pe(t.type))for(let e of Ae)e in t&&delete t[e];for(let e of je)t[e]&&(t[e]=W(t[e]));for(let e of Me)Array.isArray(t[e])&&(t[e]=t[e].map(W));for(let e of Ne)if(t[e]&&typeof t[e]==`object`){let n={};for(let[r,i]of Object.entries(t[e]))n[r]=W(i);t[e]=n}return t.items&&=W(t.items),t},G=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(G);let t={};for(let[n,r]of Object.entries(e))t[n]=G(r);let n=t.type===`object`,r=t.properties&&typeof t.properties==`object`&&!Array.isArray(t.properties),i=Object.prototype.hasOwnProperty.call(t,`additionalProperties`),a=r?Object.keys(t.properties):[],o=Array.isArray(t.required),s=o?new Set(t.required):new Set,c=o&&a.every(e=>s.has(e))&&t.required.length===a.length;return n&&r&&!i&&(t.additionalProperties=!1),n&&r&&!c&&(t.required=a),t},K=e=>{let t=ke(e);if(!t||typeof t!=`object`||!t.jsonSchema)return t;let n=G(W(t.jsonSchema));return typeof U==`function`?U(n,{validate:t.validate}):{...t,jsonSchema:n}};var q=class e{constructor(){if(this.constructor===e)throw Error(`BaseAIProvider cannot be instantiated directly`);this.name=this.constructor.name,this._proxyAgent=null,this.needsExplicitJsonSchema=!1,this.supportsTemperature=!0}validateAuth(e){if(!e.apiKey)throw Error(`${this.name} API key is required`)}createProxyFetch(){this._projectRoot||=b();let e=this._projectRoot;if(a(null,e))return this._proxyAgent||=new F,(e,t={})=>fetch(e,{...t,dispatcher:this._proxyAgent})}validateParams(e){if(this.validateAuth(e),!e.modelId)throw Error(`${this.name} Model ID is required`);this.validateOptionalParams(e)}validateOptionalParams(e){if(e.temperature!==void 0&&(e.temperature<0||e.temperature>1))throw Error(`Temperature must be between 0 and 1`);if(e.maxTokens!==void 0){let t=Number(e.maxTokens);if(!Number.isFinite(t)||t<=0)throw Error(`maxTokens must be a finite number greater than 0`)}}validateMessages(e){if(!e||!Array.isArray(e)||e.length===0)throw Error(`Invalid or empty messages array provided`);for(let t of e)if(!t.role||!t.content)throw Error(`Invalid message format. Each message must have role and content`)}handleError(e,t){let n=t.message||`Unknown error occurred`;throw S(`error`,`${this.name} ${e} failed: ${n}`,{error:t}),Error(`${this.name} API error during ${e}: ${n}`)}getClient(e){throw Error(`getClient must be implemented by provider`)}isRequiredApiKey(){return!0}getRequiredApiKeyName(){throw Error(`getRequiredApiKeyName must be implemented by provider`)}prepareTokenParam(e,t){return t===void 0?{}:{maxOutputTokens:Math.floor(Number(t))}}async generateText(e){try{this.validateParams(e),this.validateMessages(e.messages),S(`debug`,`Generating ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.generateText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await Ee({model:t(e.modelId),messages:e.messages,...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});S(`debug`,`${this.name} generateText completed successfully for model: ${e.modelId}`);let a=i.usage?.inputTokens??i.usage?.promptTokens??0,o=i.usage?.outputTokens??i.usage?.completionTokens??0,s=i.usage?.totalTokens??a+o;return{text:i.text,usage:{inputTokens:a,outputTokens:o,totalTokens:s}}}catch(e){this.handleError(`text generation`,e)}}async streamText(e){try{this.validateParams(e),this.validateMessages(e.messages),S(`debug`,`Streaming ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.streamText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await Oe({model:t(e.modelId),messages:e.messages,...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r},...e.experimental_transform&&{experimental_transform:e.experimental_transform}});return S(`debug`,`${this.name} streamText initiated successfully for model: ${e.modelId}`),i}catch(e){this.handleError(`text streaming`,e)}}async streamObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object streaming`);S(`debug`,`Streaming ${this.name} object with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.streamObject`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=K(e.schema),a=await De({model:t(e.modelId),messages:e.messages,schema:i,mode:e.mode||`auto`,maxOutputTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});return S(`debug`,`${this.name} streamObject initiated successfully for model: ${e.modelId}`),a}catch(e){this.handleError(`object streaming`,e)}}async generateObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object generation`);if(!e.objectName)throw Error(`Object name is required for object generation`);S(`debug`,`Generating ${this.name} object ('${e.objectName}') with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.generateObject.${e.objectName}`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=K(e.schema),a=await Te({model:t(e.modelId),messages:e.messages,schema:i,mode:this.needsExplicitJsonSchema?`json`:`auto`,schemaName:e.objectName,schemaDescription:`Generate a valid JSON object for ${e.objectName}`,maxTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});S(`debug`,`${this.name} generateObject completed successfully for model: ${e.modelId}`);let o=a.usage?.inputTokens??a.usage?.promptTokens??0,s=a.usage?.outputTokens??a.usage?.completionTokens??0,c=a.usage?.totalTokens??o+s;return{object:a.object,usage:{inputTokens:o,outputTokens:s,totalTokens:c}}}catch(e){if(we.isInstance(e)&&e.cause instanceof Ce&&e.cause.text){S(`warn`,`${this.name} generated malformed JSON, attempting to repair...`);try{let t=P(e.cause.text),n=JSON.parse(t);return S(`info`,`Successfully repaired ${this.name} JSON output`),{object:n,usage:{inputTokens:e.usage?.promptTokens||e.usage?.inputTokens||0,outputTokens:e.usage?.completionTokens||e.usage?.outputTokens||0,totalTokens:e.usage?.totalTokens||0}}}catch(e){S(`error`,`Failed to repair ${this.name} JSON: ${e.message}`)}}this.handleError(`object generation`,e)}}},Fe=class extends q{constructor(){super(),this.name=`Anthropic`}getRequiredApiKeyName(){return`ANTHROPIC_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return re({apiKey:t,...n&&{baseURL:n},headers:{"anthropic-beta":`output-128k-2025-02-19`},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Ie=class extends q{constructor(){super(),this.name=`Perplexity`}getRequiredApiKeyName(){return`PERPLEXITY_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ie({apiKey:t,baseURL:n||`https://api.perplexity.ai`,...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}async generateObject(e){return super.generateObject({...e,mode:`json`})}},Le=class extends q{constructor(){super(),this.name=`Google`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ae({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Re=class extends q{constructor(){super(),this.name=`OpenAI`}getRequiredApiKeyName(){return`OPENAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return oe({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},ze=class extends q{constructor(){super(),this.name=`xAI`}getRequiredApiKeyName(){return`XAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return se({apiKey:t,baseURL:n||`https://api.x.ai/v1`})}catch(e){this.handleError(`client initialization`,e)}}},Be=class extends q{constructor(){super(),this.name=`Groq`}getRequiredApiKeyName(){return`GROQ_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return ce({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},Ve=class extends q{constructor(){super(),this.name=`OpenRouter`}getRequiredApiKeyName(){return`OPENROUTER_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return le({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},He=class extends q{constructor(){super(),this.name=`Ollama`}validateAuth(e){}getClient(e){try{let{baseURL:t}=e;return ue({...t&&{baseURL:t}})}catch(e){this.handleError(`client initialization`,e)}}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`OLLAMA_API_KEY`}},Ue=class extends q{constructor(){super(),this.name=`Bedrock`}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`AWS_ACCESS_KEY_ID`}validateAuth(e){}getClient(e){try{let e=fe(),t=this.createProxyFetch();return de({credentialProvider:e,...t&&{fetch:t}})}catch(e){this.handleError(`client initialization`,e)}}},We=class extends q{constructor(){super(),this.name=`Azure OpenAI`}getRequiredApiKeyName(){return`AZURE_OPENAI_API_KEY`}validateAuth(e){if(!e.apiKey)throw Error(`Azure API key is required`);if(!e.baseURL)throw Error(`Azure endpoint URL is required. Set it in .taskmasterconfig global.azureBaseURL or models.[role].baseURL`)}normalizeBaseURL(e){if(!e)return e;try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``);return n.endsWith(`/openai`)||(n=`${n}/openai`),t.pathname=n,t.toString()}catch{let t=e.replace(/\/+$/,``);return t.endsWith(`/openai`)?t:`${t}/openai`}}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.normalizeBaseURL(n),i=this.createProxyFetch();return pe({apiKey:t,baseURL:r,...i&&{fetch:i}})}catch(e){this.handleError(`client initialization`,e)}}},J=class extends Error{constructor(e){super(e),this.name=`VertexAuthError`,this.code=`vertex_auth_error`}},Y=class extends Error{constructor(e){super(e),this.name=`VertexConfigError`,this.code=`vertex_config_error`}},Ge=class extends Error{constructor(e,t){super(e),this.name=`VertexApiError`,this.code=`vertex_api_error`,this.statusCode=t}},Ke=class extends q{constructor(){super(),this.name=`Google Vertex AI`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}isRequiredApiKey(){return!1}isAuthenticationRequired(){return!0}isValidCredential(e){return e?typeof e==`string`?e.trim().length>0:typeof e==`object`:!1}validateAuth(e){let{apiKey:t,projectId:n,location:r,credentials:i}=e,a=this.isValidCredential(t),o=this.isValidCredential(i);if(!a&&!o)throw new J(`Vertex AI requires authentication. Provide one of the following:
1
+ import{A as e,C as t,D as n,Et as r,F as i,H as a,I as o,J as s,M as c,N as l,P as u,S as d,T as f,_ as p,a as m,b as h,d as g,ht as ee,j as _,l as v,o as te,p as y,s as ne,ut as b,v as x,yt as S}from"./config-manager-3pTgfD7M.js";import{n as C,t as w}from"./sentry-BU9KKY_b.js";import{createRequire as T}from"node:module";import E,{promises as D}from"fs";import O,{join as k}from"path";import{homedir as A}from"os";import{execSync as j,spawn as M}from"child_process";import*as N from"ai";import{jsonrepair as P}from"jsonrepair";import{EnvHttpProxyAgent as F}from"undici";import{createAnthropic as re}from"@ai-sdk/anthropic";import{createPerplexity as ie}from"@ai-sdk/perplexity";import{createGoogleGenerativeAI as ae}from"@ai-sdk/google";import{createOpenAI as oe}from"@ai-sdk/openai";import{createXai as se}from"@ai-sdk/xai";import{createGroq as ce}from"@ai-sdk/groq";import{createOpenRouter as le}from"@openrouter/ai-sdk-provider";import{createOllama as ue}from"ollama-ai-provider-v2";import{createAmazonBedrock as de}from"@ai-sdk/amazon-bedrock";import{fromNodeProviderChain as fe}from"@aws-sdk/credential-providers";import{createAzure as pe}from"@ai-sdk/azure";import{createVertex as me}from"@ai-sdk/google-vertex";import{createClaudeCode as he}from"ai-sdk-provider-claude-code";import{createGeminiProvider as ge}from"ai-sdk-provider-gemini-cli";import{APICallError as I,LoadAPIKeyError as _e,NoSuchModelError as L}from"@ai-sdk/provider";import{generateId as R}from"@ai-sdk/provider-utils";import{parse as ve}from"jsonc-parser";import{createCodexCli as ye}from"ai-sdk-provider-codex-cli";import{createOpenAICompatible as be}from"@ai-sdk/openai-compatible";var xe=Object.defineProperty,Se=e=>{let t={};for(var n in e)xe(t,n,{get:e[n],enumerable:!0});return t},z=T(import.meta.url);let B=null;var V=class e{constructor(){this._providers=new Map,this._initialized=!1}static getInstance(){return B||=new e,B}initialize(){return this._initialized||=!0,this}registerProvider(e,t,n={}){if(!e||typeof e!=`string`)throw Error(`Provider name must be a non-empty string`);if(!t)throw Error(`Provider instance is required`);if(typeof t.generateText!=`function`||typeof t.streamText!=`function`||typeof t.generateObject!=`function`)throw Error(`Provider must implement BaseAIProvider interface`);return this._providers.set(e,{instance:t,options:n,registeredAt:new Date}),this}hasProvider(e){return this._providers.has(e)}getProvider(e){let t=this._providers.get(e);return t?t.instance:null}getAllProviders(){return new Map(this._providers)}unregisterProvider(e){return this._providers.has(e)?(this._providers.delete(e),!0):!1}reset(){this._providers.clear(),this._initialized=!1}};V.getInstance().initialize();var H=V;const{JSONParseError:Ce,NoObjectGeneratedError:we,generateObject:Te,generateText:Ee,streamObject:De,streamText:Oe,zodSchema:ke}=N,U=N.jsonSchema,Ae=new Set([`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`]),je=[`additionalProperties`,`contains`,`if`,`then`,`else`,`not`,`propertyNames`],Me=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],Ne=[`definitions`,`$defs`,`dependentSchemas`,`patternProperties`,`properties`],Pe=e=>e?Array.isArray(e)?e.includes(`integer`):e===`integer`:!1,W=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(W);let t={...e};if(Pe(t.type))for(let e of Ae)e in t&&delete t[e];for(let e of je)t[e]&&(t[e]=W(t[e]));for(let e of Me)Array.isArray(t[e])&&(t[e]=t[e].map(W));for(let e of Ne)if(t[e]&&typeof t[e]==`object`){let n={};for(let[r,i]of Object.entries(t[e]))n[r]=W(i);t[e]=n}return t.items&&=W(t.items),t},G=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(G);let t={};for(let[n,r]of Object.entries(e))t[n]=G(r);let n=t.type===`object`,r=t.properties&&typeof t.properties==`object`&&!Array.isArray(t.properties),i=Object.prototype.hasOwnProperty.call(t,`additionalProperties`),a=r?Object.keys(t.properties):[],o=Array.isArray(t.required),s=o?new Set(t.required):new Set,c=o&&a.every(e=>s.has(e))&&t.required.length===a.length;return n&&r&&!i&&(t.additionalProperties=!1),n&&r&&!c&&(t.required=a),t},K=e=>{let t=ke(e);if(!t||typeof t!=`object`||!t.jsonSchema)return t;let n=G(W(t.jsonSchema));return typeof U==`function`?U(n,{validate:t.validate}):{...t,jsonSchema:n}};var q=class e{constructor(){if(this.constructor===e)throw Error(`BaseAIProvider cannot be instantiated directly`);this.name=this.constructor.name,this._proxyAgent=null,this.needsExplicitJsonSchema=!1,this.supportsTemperature=!0}validateAuth(e){if(!e.apiKey)throw Error(`${this.name} API key is required`)}createProxyFetch(){this._projectRoot||=b();let e=this._projectRoot;if(a(null,e))return this._proxyAgent||=new F,(e,t={})=>fetch(e,{...t,dispatcher:this._proxyAgent})}validateParams(e){if(this.validateAuth(e),!e.modelId)throw Error(`${this.name} Model ID is required`);this.validateOptionalParams(e)}validateOptionalParams(e){if(e.temperature!==void 0&&(e.temperature<0||e.temperature>1))throw Error(`Temperature must be between 0 and 1`);if(e.maxTokens!==void 0){let t=Number(e.maxTokens);if(!Number.isFinite(t)||t<=0)throw Error(`maxTokens must be a finite number greater than 0`)}}validateMessages(e){if(!e||!Array.isArray(e)||e.length===0)throw Error(`Invalid or empty messages array provided`);for(let t of e)if(!t.role||!t.content)throw Error(`Invalid message format. Each message must have role and content`)}handleError(e,t){let n=t.message||`Unknown error occurred`;throw S(`error`,`${this.name} ${e} failed: ${n}`,{error:t}),Error(`${this.name} API error during ${e}: ${n}`)}getClient(e){throw Error(`getClient must be implemented by provider`)}isRequiredApiKey(){return!0}getRequiredApiKeyName(){throw Error(`getRequiredApiKeyName must be implemented by provider`)}prepareTokenParam(e,t){return t===void 0?{}:{maxOutputTokens:Math.floor(Number(t))}}async generateText(e){try{this.validateParams(e),this.validateMessages(e.messages),S(`debug`,`Generating ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.generateText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await Ee({model:t(e.modelId),messages:e.messages,...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});S(`debug`,`${this.name} generateText completed successfully for model: ${e.modelId}`);let a=i.usage?.inputTokens??i.usage?.promptTokens??0,o=i.usage?.outputTokens??i.usage?.completionTokens??0,s=i.usage?.totalTokens??a+o;return{text:i.text,usage:{inputTokens:a,outputTokens:o,totalTokens:s}}}catch(e){this.handleError(`text generation`,e)}}async streamText(e){try{this.validateParams(e),this.validateMessages(e.messages),S(`debug`,`Streaming ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.streamText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await Oe({model:t(e.modelId),messages:e.messages,...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r},...e.experimental_transform&&{experimental_transform:e.experimental_transform}});return S(`debug`,`${this.name} streamText initiated successfully for model: ${e.modelId}`),i}catch(e){this.handleError(`text streaming`,e)}}async streamObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object streaming`);S(`debug`,`Streaming ${this.name} object with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.streamObject`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=K(e.schema),a=await De({model:t(e.modelId),messages:e.messages,schema:i,mode:e.mode||`auto`,maxOutputTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});return S(`debug`,`${this.name} streamObject initiated successfully for model: ${e.modelId}`),a}catch(e){this.handleError(`object streaming`,e)}}async generateObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object generation`);if(!e.objectName)throw Error(`Object name is required for object generation`);S(`debug`,`Generating ${this.name} object ('${e.objectName}') with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.generateObject.${e.objectName}`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=K(e.schema),a=await Te({model:t(e.modelId),messages:e.messages,schema:i,mode:this.needsExplicitJsonSchema?`json`:`auto`,schemaName:e.objectName,schemaDescription:`Generate a valid JSON object for ${e.objectName}`,maxTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});S(`debug`,`${this.name} generateObject completed successfully for model: ${e.modelId}`);let o=a.usage?.inputTokens??a.usage?.promptTokens??0,s=a.usage?.outputTokens??a.usage?.completionTokens??0,c=a.usage?.totalTokens??o+s;return{object:a.object,usage:{inputTokens:o,outputTokens:s,totalTokens:c}}}catch(e){if(we.isInstance(e)&&e.cause instanceof Ce&&e.cause.text){S(`warn`,`${this.name} generated malformed JSON, attempting to repair...`);try{let t=P(e.cause.text),n=JSON.parse(t);return S(`info`,`Successfully repaired ${this.name} JSON output`),{object:n,usage:{inputTokens:e.usage?.promptTokens||e.usage?.inputTokens||0,outputTokens:e.usage?.completionTokens||e.usage?.outputTokens||0,totalTokens:e.usage?.totalTokens||0}}}catch(e){S(`error`,`Failed to repair ${this.name} JSON: ${e.message}`)}}this.handleError(`object generation`,e)}}},Fe=class extends q{constructor(){super(),this.name=`Anthropic`}getRequiredApiKeyName(){return`ANTHROPIC_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return re({apiKey:t,...n&&{baseURL:n},headers:{"anthropic-beta":`output-128k-2025-02-19`},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Ie=class extends q{constructor(){super(),this.name=`Perplexity`}getRequiredApiKeyName(){return`PERPLEXITY_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ie({apiKey:t,baseURL:n||`https://api.perplexity.ai`,...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}async generateObject(e){return super.generateObject({...e,mode:`json`})}},Le=class extends q{constructor(){super(),this.name=`Google`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ae({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Re=class extends q{constructor(){super(),this.name=`OpenAI`}getRequiredApiKeyName(){return`OPENAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return oe({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},ze=class extends q{constructor(){super(),this.name=`xAI`}getRequiredApiKeyName(){return`XAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return se({apiKey:t,baseURL:n||`https://api.x.ai/v1`})}catch(e){this.handleError(`client initialization`,e)}}},Be=class extends q{constructor(){super(),this.name=`Groq`}getRequiredApiKeyName(){return`GROQ_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return ce({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},Ve=class extends q{constructor(){super(),this.name=`OpenRouter`}getRequiredApiKeyName(){return`OPENROUTER_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return le({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},He=class extends q{constructor(){super(),this.name=`Ollama`}validateAuth(e){}getClient(e){try{let{baseURL:t}=e;return ue({...t&&{baseURL:t}})}catch(e){this.handleError(`client initialization`,e)}}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`OLLAMA_API_KEY`}},Ue=class extends q{constructor(){super(),this.name=`Bedrock`}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`AWS_ACCESS_KEY_ID`}validateAuth(e){}getClient(e){try{let e=fe(),t=this.createProxyFetch();return de({credentialProvider:e,...t&&{fetch:t}})}catch(e){this.handleError(`client initialization`,e)}}},We=class extends q{constructor(){super(),this.name=`Azure OpenAI`}getRequiredApiKeyName(){return`AZURE_OPENAI_API_KEY`}validateAuth(e){if(!e.apiKey)throw Error(`Azure API key is required`);if(!e.baseURL)throw Error(`Azure endpoint URL is required. Set it in .taskmasterconfig global.azureBaseURL or models.[role].baseURL`)}normalizeBaseURL(e){if(!e)return e;try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``);return n.endsWith(`/openai`)||(n=`${n}/openai`),t.pathname=n,t.toString()}catch{let t=e.replace(/\/+$/,``);return t.endsWith(`/openai`)?t:`${t}/openai`}}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.normalizeBaseURL(n),i=this.createProxyFetch();return pe({apiKey:t,baseURL:r,...i&&{fetch:i}})}catch(e){this.handleError(`client initialization`,e)}}},J=class extends Error{constructor(e){super(e),this.name=`VertexAuthError`,this.code=`vertex_auth_error`}},Y=class extends Error{constructor(e){super(e),this.name=`VertexConfigError`,this.code=`vertex_config_error`}},Ge=class extends Error{constructor(e,t){super(e),this.name=`VertexApiError`,this.code=`vertex_api_error`,this.statusCode=t}},Ke=class extends q{constructor(){super(),this.name=`Google Vertex AI`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}isRequiredApiKey(){return!1}isAuthenticationRequired(){return!0}isValidCredential(e){return e?typeof e==`string`?e.trim().length>0:typeof e==`object`:!1}validateAuth(e){let{apiKey:t,projectId:n,location:r,credentials:i}=e,a=this.isValidCredential(t),o=this.isValidCredential(i);if(!a&&!o)throw new J(`Vertex AI requires authentication. Provide one of the following:
2
2
  • GOOGLE_API_KEY environment variable (typical for API-based auth), OR
3
3
  • GOOGLE_APPLICATION_CREDENTIALS pointing to a service account JSON file (recommended for production)`);if(!n||typeof n==`string`&&n.trim().length===0)throw new Y(`Google Cloud project ID is required for Vertex AI. Set VERTEX_PROJECT_ID environment variable.`);if(!r||typeof r==`string`&&r.trim().length===0)throw new Y(`Google Cloud location is required for Vertex AI. Set VERTEX_LOCATION environment variable (e.g., "us-central1").`)}getClient(e){try{let{apiKey:t,projectId:n,location:r,credentials:i,baseURL:a}=e,o=this.createProxyFetch(),s={};return t?s.googleAuthOptions={...i,apiKey:t}:i&&(s.googleAuthOptions=i),me({...s,project:n,location:r,...a&&{baseURL:a},...o&&{fetch:o}})}catch(e){this.handleError(`client initialization`,e)}}handleError(e,t){if(S(`error`,`Vertex AI ${e} error:`,t),t.name===`VertexAuthError`||t.name===`VertexConfigError`||t.name===`VertexApiError`)throw t;if(t.response){let e=t.response.status,n=t.response.data?.error?.message||t.message;throw e===401||e===403?new J(`Authentication failed: ${n}`):e===400?new Y(`Invalid request: ${n}`):new Ge(`API error (${e}): ${n}`,e)}throw Error(`Vertex AI ${e} failed: ${t.message}`)}};let X=!1;var qe=class extends q{constructor(){super(),this.name=`Claude Code`,this.supportedModels=l(`claude-code`),this.supportedModels.length===0&&S(`warn`,`No supported models found for claude-code provider. Check supported-models.json configuration.`),this.needsExplicitJsonSchema=!0,this.supportsTemperature=!1}getRequiredApiKeyName(){return`CLAUDE_CODE_API_KEY`}isRequiredApiKey(){return!1}validateAuth(e){if(process.env.NODE_ENV!==`test`&&!X&&!process.env.CLAUDE_CODE_OAUTH_TOKEN)try{j(`claude --version`,{stdio:`pipe`,timeout:1e3})}catch{S(`warn`,`Claude Code CLI not detected. Install it with: npm install -g @anthropic-ai/claude-code`)}finally{X=!0}}getClient(e={}){try{let t=v(e.commandName)||{},n=process.env.ANTHROPIC_API_KEY,r=process.env.CLAUDE_CODE_API_KEY;try{return r?process.env.ANTHROPIC_API_KEY=r:n&&delete process.env.ANTHROPIC_API_KEY,he({defaultSettings:{systemPrompt:{type:`preset`,preset:`claude_code`},settingSources:[`user`,`project`,`local`],...t}})}finally{n?process.env.ANTHROPIC_API_KEY=n:delete process.env.ANTHROPIC_API_KEY}}catch(e){let t=String(e?.message||``);if(e?.code===`ENOENT`||/claude/i.test(t)){let t=Error(`Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${e.message}`);t.cause=e,this.handleError(`Claude Code CLI initialization`,t)}else this.handleError(`client initialization`,e)}}getSupportedModels(){return this.supportedModels}isModelSupported(e){return e?this.supportedModels.includes(String(e).toLowerCase()):!1}},Je=class extends q{constructor(){super(),this.name=`Gemini CLI`,this.supportsTemperature=!1}validateAuth(e){}async getClient(e){try{let t={};return t=e.apiKey&&e.apiKey!==`gemini-cli-no-key-required`?{authType:`api-key`,apiKey:e.apiKey}:{authType:`oauth-personal`},e.baseURL&&(t.baseURL=e.baseURL),ge(t)}catch(e){this.handleError(`client initialization`,e)}}getRequiredApiKeyName(){return`GEMINI_API_KEY`}isRequiredApiKey(){return!1}};function Z({message:e,code:t,exitCode:n,stderr:r,stdout:i,promptExcerpt:a,isRetryable:o=!1}){return new I({message:e,isRetryable:o,url:`grok-cli://command`,requestBodyValues:a?{prompt:a}:void 0,data:{code:t,exitCode:n,stderr:r,stdout:i,promptExcerpt:a}})}function Ye({message:e}){return new _e({message:e||`Authentication failed. Please ensure Grok CLI is properly configured with API key.`})}function Xe({message:e,promptExcerpt:t,timeoutMs:n}){return new I({message:e,isRetryable:!0,url:`grok-cli://command`,requestBodyValues:t?{prompt:t}:void 0,data:{code:`TIMEOUT`,promptExcerpt:t,timeoutMs:n}})}function Ze({message:e}){return new I({message:e||`Grok CLI is not installed or not found in PATH. Please install with: npm install -g @vibe-kit/grok-cli`,isRetryable:!1,url:`grok-cli://installation`,requestBodyValues:void 0})}function Qe(e){let t=e.trim(),n=/```(?:json)?\s*([\s\S]*?)\s*```/i.exec(t);n&&(t=n[1]);let r=/^\s*(?:const|let|var)\s+\w+\s*=\s*([\s\S]*)/i.exec(t);r&&(t=r[1],t.trim().endsWith(`;`)&&(t=t.trim().slice(0,-1)));let i=t.indexOf(`{`),a=t.indexOf(`[`);if(i===-1&&a===-1)return e;let o=a===-1?i:i===-1?a:Math.min(i,a);t=t.slice(o);let s=e=>{let t=[];try{let n=ve(e,t,{allowTrailingComma:!0});if(t.length===0)return JSON.stringify(n,null,2)}catch{}},c=s(t);if(c!==void 0)return c;let l=t[0],u=l===`{`?`}`:`]`,d=[],f=0,p=!1,m=!1;for(let e=0;e<t.length;e++){let n=t[e];if(m){m=!1;continue}if(n===`\\`){m=!0;continue}if(n===`"`&&!p){p=!0;continue}if(n===`"`&&p){p=!1;continue}p||(n===l?f++:n===u&&(f--,f===0&&d.push(e+1)))}for(let e=d.length-1;e>=0;e--){let n=s(t.slice(0,d[e]));if(n!==void 0)return n}let h=Math.max(0,t.length-1e3);for(let e=t.length-1;e>h;e--){let n=s(t.slice(0,e));if(n!==void 0)return n}return e}function $e(e){return e.map(e=>{let t=``;return typeof e.content==`string`?t=e.content:Array.isArray(e.content)?t=e.content.filter(e=>e.type===`text`).map(e=>e.text||``).join(`
4
4
  `):e.content&&typeof e.content==`object`&&(t=e.content.text||JSON.stringify(e.content)),{role:e.role,content:t.trim()}})}function et(e){try{let t=e.trim().split(`
@@ -1,4 +1,4 @@
1
- import"./ai-services-unified-DZEwiMzn.js";import{An as e,B as t,Bt as n,E as r,Ht as i,Kt as a,Lt as o,Nt as s,Q as c,R as l,Rt as u,Tt as d,U as f,Ut as p,Vt as m,dt as h,f as g,hn as _,ln as ee,m as v,mn as te,p as y,t as b,ut as ne,yt as x}from"./config-manager-CynteFcs.js";import"./git-utils-DllbRE35.js";import"./sentry-DMIPmMuT.js";import{$ as S,C,D as w,F as T,I as E,J as re,L as ie,M as ae,N as oe,O as se,P as ce,Q as le,S as ue,St as de,X as D,Y as fe,Z as pe,_ as me,_t as he,a as ge,at as O,b as _e,bt as ve,c as ye,ct as be,d as k,dt as xe,et as A,f as Se,g as Ce,h as we,ht as Te,i as Ee,it as De,j as Oe,k as j,l as ke,m as Ae,n as je,nt as Me,o as Ne,ot as Pe,p as M,r as Fe,rt as Ie,s as Le,st as Re,t as ze,tt as Be,u as Ve,ut as He,v as N,vt as Ue,w as We,wt as Ge,xt as Ke,y as qe,yt as Je}from"./dependency-manager-B3ejwqo-.js";import{t as Ye}from"./response-language-Bvp5hrxw.js";import{_ as Xe,a as Ze,c as Qe,d as $e,f as et,g as tt,h as nt,i as rt,l as P,m as it,n as at,o as F,p as ot,r as st,s as I,t as L,u as R,v as z}from"./profiles-ByYa1H74.js";import B from"chalk";import V from"fs";import H from"path";import U from"boxen";import{Command as ct}from"commander";import W from"inquirer";const G={AUTHENTICATION:`authentication`,VALIDATION:`validation`,NETWORK:`network`,API:`api`,FILE_SYSTEM:`file_system`,TASK:`task`,PERMISSION:`permission`,TIMEOUT:`timeout`,GENERIC:`generic`},lt=[/\b[A-Za-z0-9_-]{20,}\b/g,/sk-[A-Za-z0-9]{32,}/g,/api[_-]?key[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/\/Users\/[^/]+/g,/C:\\Users\\[^\\]+/g,/\/home\/[^/]+/g,/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,/https?:\/\/[^:]+:[^@]+@/g];function K(e){if(!e||typeof e!=`string`)return e;let t=e;for(let e of lt)t=t.replace(e,`***REDACTED***`);return t}function ut(e){if(!e)return G.GENERIC;let t=(e.message||``).toLowerCase(),n=(e.code||``).toLowerCase();return t.includes(`auth`)||t.includes(`unauthorized`)||t.includes(`forbidden`)||t.includes(`api key`)||t.includes(`token`)||n.includes(`auth`)?G.AUTHENTICATION:t.includes(`invalid`)||t.includes(`validation`)||t.includes(`required`)||t.includes(`must be`)||n.includes(`validation`)?G.VALIDATION:t.includes(`network`)||t.includes(`connection`)||t.includes(`econnrefused`)||t.includes(`enotfound`)||n.includes(`network`)||n.includes(`econnrefused`)||n.includes(`enotfound`)?G.NETWORK:t.includes(`timeout`)||t.includes(`timed out`)||n.includes(`timeout`)?G.TIMEOUT:t.includes(`api`)||t.includes(`rate limit`)||t.includes(`quota`)||n.includes(`api`)?G.API:t.includes(`enoent`)||t.includes(`eacces`)||t.includes(`file`)||t.includes(`directory`)||n.includes(`enoent`)||n.includes(`eacces`)?G.FILE_SYSTEM:t.includes(`permission`)||t.includes(`access denied`)||n.includes(`eperm`)?G.PERMISSION:t.includes(`task`)||t.includes(`subtask`)?G.TASK:G.GENERIC}function dt(e,t,n){let r=[],i=(t.message||``).toLowerCase();switch(e){case G.AUTHENTICATION:i.includes(`api key`)?(r.push(`Check that your API key is correctly set in the .env file`),r.push(`Verify the API key has not expired or been revoked`)):i.includes(`token`)?(r.push(`Your authentication token may have expired`),r.push(`Try running: tm auth refresh`)):(r.push(`Verify your credentials are correctly configured`),r.push(`Check the authentication status with: tm auth status`));break;case G.VALIDATION:i.includes(`brief id`)?(r.push(`Brief IDs are case-insensitive (e.g., "ham32" = "HAM-32")`),r.push(`Check the brief ID format: usually LETTERS-NUMBERS`)):i.includes(`task id`)||i.includes(`invalid id`)?(r.push(`Task IDs should be numbers (e.g., 1, 2, 3)`),r.push(`Subtask IDs use dot notation (e.g., 1.1, 2.3)`)):(r.push(`Check that all required parameters are provided`),r.push(`Verify parameter values match expected formats`));break;case G.NETWORK:i.includes(`econnrefused`)?(r.push(`Could not connect to the server`),r.push(`Check your internet connection`),r.push(`Verify the API endpoint URL is correct`)):i.includes(`enotfound`)?(r.push(`Could not resolve the server hostname`),r.push(`Check your internet connection`)):(r.push(`Check your network connection`),r.push(`Verify firewall settings are not blocking the request`));break;case G.TIMEOUT:r.push(`The operation took too long to complete`),r.push(`Try again with a simpler request`),r.push(`Check your network speed and stability`);break;case G.API:i.includes(`rate limit`)?(r.push(`You have exceeded the API rate limit`),r.push(`Wait a few minutes before trying again`)):i.includes(`quota`)?(r.push(`You have reached your API quota`),r.push(`Check your account usage and limits`)):(r.push(`The API returned an error`),r.push(`Try again in a few moments`));break;case G.FILE_SYSTEM:i.includes(`enoent`)?(r.push(`The specified file or directory does not exist`),r.push(`Check the file path and ensure it is correct`),n.includes(`tasks.json`)&&r.push(`Initialize the project with: tm init`)):i.includes(`eacces`)?(r.push(`Permission denied to access the file`),r.push(`Check file permissions or run with appropriate privileges`)):r.push(`Check that the file or directory exists and is accessible`);break;case G.PERMISSION:r.push(`You do not have permission to perform this operation`),r.push(`Check file/directory permissions`),r.push(`You may need elevated privileges (sudo)`);break;case G.TASK:i.includes(`not found`)?(r.push(`The specified task does not exist`),r.push(`Use: tm list to see all available tasks`)):i.includes(`dependency`)||i.includes(`circular`)?(r.push(`Task dependencies form a circular reference`),r.push(`Use: tm validate-dependencies to identify issues`)):(r.push(`Check that the task ID is correct`),r.push(`Use: tm show <id> to view task details`));break;default:r.push(`Check the error message for specific details`),n&&r.push(`Operation failed while: ${n}`)}return r.slice(0,2)}function ft(e,t={}){let{context:n=``,debug:r=!1,command:i=``}=t;typeof e==`string`&&(e=Error(e)),(!e||typeof e!=`object`)&&(e=Error(`An unknown error occurred`));let a=K(e.message||`Unknown error`),o=ut(e),s=dt(o,e,n);return{type:o,message:a,context:n||`Unknown operation`,hints:s,command:i||null,code:e.code||null,stack:r?K(e.stack):null}}function q(e,t={}){let n=ft(e,t),r=B.red.bold(`✗ Error
1
+ import"./ai-services-unified-CEISDqFA.js";import{B as e,Bt as t,E as n,Ht as r,Kt as i,Lt as a,Nt as o,On as s,Q as c,R as l,Rt as u,Tt as d,U as f,Ut as p,Vt as m,dt as h,f as g,hn as _,ln as ee,m as v,mn as te,p as y,t as b,ut as ne,yt as x}from"./config-manager-3pTgfD7M.js";import"./git-utils-DllbRE35.js";import"./sentry-BU9KKY_b.js";import{$ as S,C,D as w,F as T,I as E,J as re,L as ie,M as ae,N as oe,O as se,P as ce,Q as le,S as ue,St as de,X as D,Y as fe,Z as pe,_ as me,_t as he,a as ge,at as O,b as _e,bt as ve,c as ye,ct as be,d as k,dt as xe,et as A,f as Se,g as Ce,h as we,ht as Te,i as Ee,it as De,j as Oe,k as j,l as ke,m as Ae,n as je,nt as Me,o as Ne,ot as Pe,p as M,r as Fe,rt as Ie,s as Le,st as Re,t as ze,tt as Be,u as Ve,ut as He,v as N,vt as Ue,w as We,wt as Ge,xt as Ke,y as qe,yt as Je}from"./dependency-manager-C-vZzEg8.js";import{t as Ye}from"./response-language-CoZ1-GFh.js";import{_ as Xe,a as Ze,c as Qe,d as $e,f as et,g as tt,h as nt,i as rt,l as P,m as it,n as at,o as F,p as ot,r as st,s as I,t as L,u as R,v as z}from"./profiles-Bcr6LYd4.js";import B from"chalk";import V from"fs";import H from"path";import U from"boxen";import{Command as ct}from"commander";import W from"inquirer";const G={AUTHENTICATION:`authentication`,VALIDATION:`validation`,NETWORK:`network`,API:`api`,FILE_SYSTEM:`file_system`,TASK:`task`,PERMISSION:`permission`,TIMEOUT:`timeout`,GENERIC:`generic`},lt=[/\b[A-Za-z0-9_-]{20,}\b/g,/sk-[A-Za-z0-9]{32,}/g,/api[_-]?key[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/\/Users\/[^/]+/g,/C:\\Users\\[^\\]+/g,/\/home\/[^/]+/g,/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,/https?:\/\/[^:]+:[^@]+@/g];function K(e){if(!e||typeof e!=`string`)return e;let t=e;for(let e of lt)t=t.replace(e,`***REDACTED***`);return t}function ut(e){if(!e)return G.GENERIC;let t=(e.message||``).toLowerCase(),n=(e.code||``).toLowerCase();return t.includes(`auth`)||t.includes(`unauthorized`)||t.includes(`forbidden`)||t.includes(`api key`)||t.includes(`token`)||n.includes(`auth`)?G.AUTHENTICATION:t.includes(`invalid`)||t.includes(`validation`)||t.includes(`required`)||t.includes(`must be`)||n.includes(`validation`)?G.VALIDATION:t.includes(`network`)||t.includes(`connection`)||t.includes(`econnrefused`)||t.includes(`enotfound`)||n.includes(`network`)||n.includes(`econnrefused`)||n.includes(`enotfound`)?G.NETWORK:t.includes(`timeout`)||t.includes(`timed out`)||n.includes(`timeout`)?G.TIMEOUT:t.includes(`api`)||t.includes(`rate limit`)||t.includes(`quota`)||n.includes(`api`)?G.API:t.includes(`enoent`)||t.includes(`eacces`)||t.includes(`file`)||t.includes(`directory`)||n.includes(`enoent`)||n.includes(`eacces`)?G.FILE_SYSTEM:t.includes(`permission`)||t.includes(`access denied`)||n.includes(`eperm`)?G.PERMISSION:t.includes(`task`)||t.includes(`subtask`)?G.TASK:G.GENERIC}function dt(e,t,n){let r=[],i=(t.message||``).toLowerCase();switch(e){case G.AUTHENTICATION:i.includes(`api key`)?(r.push(`Check that your API key is correctly set in the .env file`),r.push(`Verify the API key has not expired or been revoked`)):i.includes(`token`)?(r.push(`Your authentication token may have expired`),r.push(`Try running: tm auth refresh`)):(r.push(`Verify your credentials are correctly configured`),r.push(`Check the authentication status with: tm auth status`));break;case G.VALIDATION:i.includes(`brief id`)?(r.push(`Brief IDs are case-insensitive (e.g., "ham32" = "HAM-32")`),r.push(`Check the brief ID format: usually LETTERS-NUMBERS`)):i.includes(`task id`)||i.includes(`invalid id`)?(r.push(`Task IDs should be numbers (e.g., 1, 2, 3)`),r.push(`Subtask IDs use dot notation (e.g., 1.1, 2.3)`)):(r.push(`Check that all required parameters are provided`),r.push(`Verify parameter values match expected formats`));break;case G.NETWORK:i.includes(`econnrefused`)?(r.push(`Could not connect to the server`),r.push(`Check your internet connection`),r.push(`Verify the API endpoint URL is correct`)):i.includes(`enotfound`)?(r.push(`Could not resolve the server hostname`),r.push(`Check your internet connection`)):(r.push(`Check your network connection`),r.push(`Verify firewall settings are not blocking the request`));break;case G.TIMEOUT:r.push(`The operation took too long to complete`),r.push(`Try again with a simpler request`),r.push(`Check your network speed and stability`);break;case G.API:i.includes(`rate limit`)?(r.push(`You have exceeded the API rate limit`),r.push(`Wait a few minutes before trying again`)):i.includes(`quota`)?(r.push(`You have reached your API quota`),r.push(`Check your account usage and limits`)):(r.push(`The API returned an error`),r.push(`Try again in a few moments`));break;case G.FILE_SYSTEM:i.includes(`enoent`)?(r.push(`The specified file or directory does not exist`),r.push(`Check the file path and ensure it is correct`),n.includes(`tasks.json`)&&r.push(`Initialize the project with: tm init`)):i.includes(`eacces`)?(r.push(`Permission denied to access the file`),r.push(`Check file permissions or run with appropriate privileges`)):r.push(`Check that the file or directory exists and is accessible`);break;case G.PERMISSION:r.push(`You do not have permission to perform this operation`),r.push(`Check file/directory permissions`),r.push(`You may need elevated privileges (sudo)`);break;case G.TASK:i.includes(`not found`)?(r.push(`The specified task does not exist`),r.push(`Use: tm list to see all available tasks`)):i.includes(`dependency`)||i.includes(`circular`)?(r.push(`Task dependencies form a circular reference`),r.push(`Use: tm validate-dependencies to identify issues`)):(r.push(`Check that the task ID is correct`),r.push(`Use: tm show <id> to view task details`));break;default:r.push(`Check the error message for specific details`),n&&r.push(`Operation failed while: ${n}`)}return r.slice(0,2)}function ft(e,t={}){let{context:n=``,debug:r=!1,command:i=``}=t;typeof e==`string`&&(e=Error(e)),(!e||typeof e!=`object`)&&(e=Error(`An unknown error occurred`));let a=K(e.message||`Unknown error`),o=ut(e),s=dt(o,e,n);return{type:o,message:a,context:n||`Unknown operation`,hints:s,command:i||null,code:e.code||null,stack:r?K(e.stack):null}}function q(e,t={}){let n=ft(e,t),r=B.red.bold(`✗ Error
2
2
 
3
3
  `);r+=B.white(n.message)+`
4
4
 
@@ -12,7 +12,7 @@ import"./ai-services-unified-DZEwiMzn.js";import{An as e,B as t,Bt as n,E as r,H
12
12
  `+U(r.trim(),{padding:{top:1,bottom:1,left:2,right:2},borderStyle:`round`,borderColor:`red`})+`
13
13
  `),t.debug&&n.stack&&(console.log(B.gray(`Stack Trace:`)),console.log(B.dim(n.stack)),console.log())}function pt(e,t=`Info`){let n=B.blue.bold(`ℹ ${t}\n\n`);n+=B.white(e),console.log(`
14
14
  `+U(n.trim(),{padding:{top:1,bottom:1,left:2,right:2},borderStyle:`round`,borderColor:`blue`})+`
15
- `)}var mt=class{#e;#t;constructor(e,t){this.#e=Object.freeze({...e}),this.#t=t}getProjectRoot(){return this.#e.projectRoot}getTaskMasterDir(){return this.#e.taskMasterDir}getTasksPath(){return this.#e.tasksPath}getPrdPath(){return this.#e.prdPath}getComplexityReportPath(){if(this.#e.complexityReportPath)return this.#e.complexityReportPath;let e=this.getCurrentTag()===`master`?s:s.replace(`.json`,`_${this.getCurrentTag()}.json`);return H.join(this.#e.projectRoot,e)}getConfigPath(){return this.#e.configPath}getStatePath(){return this.#e.statePath}getAllPaths(){return this.#e}getCurrentTag(){if(this.#t)return this.#t;try{if(V.existsSync(this.#e.statePath)){let e=V.readFileSync(this.#e.statePath,`utf8`),t=JSON.parse(e);if(t&&t.currentTag)return t.currentTag}}catch{}try{if(V.existsSync(this.#e.configPath)){let e=V.readFileSync(this.#e.configPath,`utf8`),t=JSON.parse(e);if(t&&t.global&&t.global.defaultTag)return t.global.defaultTag}}catch{}return`master`}};function J(e={}){let t=(e,t,n=[],r=null,i=!1)=>{if(typeof t==`string`){let n=H.isAbsolute(t)?t:H.resolve(r||process.cwd(),t);if(i){let t=H.dirname(n);if(!V.existsSync(t))try{V.mkdirSync(t,{recursive:!0})}catch(n){throw Error(`Could not create directory for ${e}: ${t}. Error: ${n.message}`)}}else if(!V.existsSync(n))throw Error(`${e} override path does not exist: ${n}`);return n}if(t===!0){for(let e of n){let t=H.isAbsolute(e)?e:H.join(r||process.cwd(),e);if(V.existsSync(t))return t}throw Error(`Required ${e} not found. Searched: ${n.join(`, `)}`)}for(let e of n){let t=H.isAbsolute(e)?e:H.join(r||process.cwd(),e);if(V.existsSync(t))return t}return null},r={};if(e.projectRoot){let t=H.resolve(e.projectRoot);if(!V.existsSync(t))throw Error(`Project root override path does not exist: ${t}`);let n=V.existsSync(H.join(t,m)),i=V.existsSync(H.join(t,o));if(!n&&!i)throw Error(`Project root override is not a valid taskmaster project: ${t}`);r.projectRoot=t}else r.projectRoot=c();return`taskMasterDir`in e?r.taskMasterDir=t(`taskmaster directory`,e.taskMasterDir,[m],r.projectRoot):r.taskMasterDir=t(`taskmaster directory`,!1,[m],r.projectRoot),r.configPath=H.join(r.projectRoot,n),r.statePath=H.join(r.taskMasterDir||H.join(r.projectRoot,m),`state.json`),r.tasksPath=H.join(r.projectRoot,a),`configPath`in e&&(r.configPath=t(`config file`,e.configPath,[n,o],r.projectRoot)),`statePath`in e&&(r.statePath=t(`state file`,e.statePath,[`state.json`],r.taskMasterDir)),`tasksPath`in e&&(r.tasksPath=t(`tasks file`,e.tasksPath,[a,u],r.projectRoot)),`prdPath`in e&&(r.prdPath=t(`PRD file`,e.prdPath,[H.join(i,`PRD.md`),H.join(i,`prd.md`),H.join(i,`PRD.txt`),H.join(i,`prd.txt`),H.join(`scripts`,`PRD.md`),H.join(`scripts`,`prd.md`),H.join(`scripts`,`PRD.txt`),H.join(`scripts`,`prd.txt`),`PRD.md`,`prd.md`,`PRD.txt`,`prd.txt`],r.projectRoot)),`complexityReportPath`in e&&(r.complexityReportPath=t(`complexity report`,e.complexityReportPath,[H.join(p,`task-complexity-report.json`),H.join(p,`complexity-report.json`),H.join(`scripts`,`task-complexity-report.json`),H.join(`scripts`,`complexity-report.json`),`task-complexity-report.json`,`complexity-report.json`],r.projectRoot,!0)),new mt(r,e.tag)}async function ht(e){let t=e.map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(`, `);console.log(U(B.yellow(`WARNING: This will selectively remove Task Master components for: ${t}.
15
+ `)}var mt=class{#e;#t;constructor(e,t){this.#e=Object.freeze({...e}),this.#t=t}getProjectRoot(){return this.#e.projectRoot}getTaskMasterDir(){return this.#e.taskMasterDir}getTasksPath(){return this.#e.tasksPath}getPrdPath(){return this.#e.prdPath}getComplexityReportPath(){if(this.#e.complexityReportPath)return this.#e.complexityReportPath;let e=this.getCurrentTag()===`master`?o:o.replace(`.json`,`_${this.getCurrentTag()}.json`);return H.join(this.#e.projectRoot,e)}getConfigPath(){return this.#e.configPath}getStatePath(){return this.#e.statePath}getAllPaths(){return this.#e}getCurrentTag(){if(this.#t)return this.#t;try{if(V.existsSync(this.#e.statePath)){let e=V.readFileSync(this.#e.statePath,`utf8`),t=JSON.parse(e);if(t&&t.currentTag)return t.currentTag}}catch{}try{if(V.existsSync(this.#e.configPath)){let e=V.readFileSync(this.#e.configPath,`utf8`),t=JSON.parse(e);if(t&&t.global&&t.global.defaultTag)return t.global.defaultTag}}catch{}return`master`}};function J(e={}){let n=(e,t,n=[],r=null,i=!1)=>{if(typeof t==`string`){let n=H.isAbsolute(t)?t:H.resolve(r||process.cwd(),t);if(i){let t=H.dirname(n);if(!V.existsSync(t))try{V.mkdirSync(t,{recursive:!0})}catch(n){throw Error(`Could not create directory for ${e}: ${t}. Error: ${n.message}`)}}else if(!V.existsSync(n))throw Error(`${e} override path does not exist: ${n}`);return n}if(t===!0){for(let e of n){let t=H.isAbsolute(e)?e:H.join(r||process.cwd(),e);if(V.existsSync(t))return t}throw Error(`Required ${e} not found. Searched: ${n.join(`, `)}`)}for(let e of n){let t=H.isAbsolute(e)?e:H.join(r||process.cwd(),e);if(V.existsSync(t))return t}return null},o={};if(e.projectRoot){let t=H.resolve(e.projectRoot);if(!V.existsSync(t))throw Error(`Project root override path does not exist: ${t}`);let n=V.existsSync(H.join(t,m)),r=V.existsSync(H.join(t,a));if(!n&&!r)throw Error(`Project root override is not a valid taskmaster project: ${t}`);o.projectRoot=t}else o.projectRoot=c();return`taskMasterDir`in e?o.taskMasterDir=n(`taskmaster directory`,e.taskMasterDir,[m],o.projectRoot):o.taskMasterDir=n(`taskmaster directory`,!1,[m],o.projectRoot),o.configPath=H.join(o.projectRoot,t),o.statePath=H.join(o.taskMasterDir||H.join(o.projectRoot,m),`state.json`),o.tasksPath=H.join(o.projectRoot,i),`configPath`in e&&(o.configPath=n(`config file`,e.configPath,[t,a],o.projectRoot)),`statePath`in e&&(o.statePath=n(`state file`,e.statePath,[`state.json`],o.taskMasterDir)),`tasksPath`in e&&(o.tasksPath=n(`tasks file`,e.tasksPath,[i,u],o.projectRoot)),`prdPath`in e&&(o.prdPath=n(`PRD file`,e.prdPath,[H.join(r,`PRD.md`),H.join(r,`prd.md`),H.join(r,`PRD.txt`),H.join(r,`prd.txt`),H.join(`scripts`,`PRD.md`),H.join(`scripts`,`prd.md`),H.join(`scripts`,`PRD.txt`),H.join(`scripts`,`prd.txt`),`PRD.md`,`prd.md`,`PRD.txt`,`prd.txt`],o.projectRoot)),`complexityReportPath`in e&&(o.complexityReportPath=n(`complexity report`,e.complexityReportPath,[H.join(p,`task-complexity-report.json`),H.join(p,`complexity-report.json`),H.join(`scripts`,`task-complexity-report.json`),H.join(`scripts`,`complexity-report.json`),`task-complexity-report.json`,`complexity-report.json`],o.projectRoot,!0)),new mt(o,e.tag)}async function ht(e){let t=e.map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(`, `);console.log(U(B.yellow(`WARNING: This will selectively remove Task Master components for: ${t}.
16
16
 
17
17
  What will be removed:
18
18
  • Task Master specific rule files (e.g., cursor_rules.mdc, taskmaster.mdc, etc.)
@@ -86,24 +86,24 @@ Now your entire team can go as fast as you can with Taskmaster.`)+`
86
86
  `,` `).replace(B.cyan(` tm`),B.dim(` tm`))+X(`tm briefs`,`View briefs and select one
87
87
 
88
88
  `,` `).replace(B.cyan(` tm`),B.dim(` tm`))+B.white.bold(`» Need more commands?
89
- `)+B.gray(`Advanced features (models, tags, PRD parsing) are managed in Hamster Studio.`),{padding:1,margin:{top:1},borderStyle:`round`,borderColor:`cyan`,width:t}))}function Q(n){n.on(`option:unknown`,function(e){let t=this._name||`unknown`;q(Error(`Unknown option '${e}'`),{context:`Running command: ${t}`,command:`task-master ${t}`,debug:y()}),process.exit(1)}),n.command(`help`).description(`Show help information (Hamster-aware)`).action(()=>{Y()?Z():n.help()}),n.configureHelp({helpWidth:120,sortSubcommands:!1});let i=n.help.bind(n);n.help=function(){Y()?Z():i()},n.hook(`preAction`,async(t,n)=>{let r=n.name();e.includes(r)&&await Ke(r,J(n.opts()).getProjectRoot())&&process.exit(1)}),n.command(`parse-prd`).description(`Parse a PRD file and generate tasks`).argument(`[file]`,`Path to the PRD file`).option(`-i, --input <file>`,`Path to the PRD file (alternative to positional argument)`).option(`-o, --output <file>`,`Output file path`).option(`-n, --num-tasks <number>`,`Number of tasks to generate`,v()).option(`-f, --force`,`Skip confirmation when overwriting existing tasks`).option(`--append`,`Append new tasks to existing tasks.json instead of overwriting`).option(`-r, --research`,`Use Perplexity AI for research-backed task generation, providing more comprehensive and accurate task breakdown`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=t.input||e,r;try{let e={prdPath:n||!0,tag:t.tag};t.output&&(e.tasksPath=t.output),r=J(e)}catch(e){q(e,{context:`Initializing Task Master for PRD parsing`,command:`task-master parse-prd`,debug:y()}),pt(`${B.cyan(`Usage:`)}\n task-master parse-prd <prd-file.txt> [options]\n\n${B.cyan(`Options:`)}\n -i, --input <file> Path to the PRD file\n -o, --output <file> Output file path\n -n, --num-tasks <number> Number of tasks to generate\n -f, --force Skip confirmation\n --append Append to existing tasks\n -r, --research Use Perplexity AI\n\n${B.cyan(`Examples:`)}\n task-master parse-prd requirements.txt --num-tasks 15\n task-master parse-prd --input=requirements.txt\n task-master parse-prd requirements.txt --research`,`Parse PRD Help`),process.exit(1)}let i=parseInt(t.numTasks,10),o=t.force||!1,s=t.append||!1,c=t.research||!1,l=o,u=s,d=r.getCurrentTag();if(await k(d),await _t()===`hamster`){await vt(r.getPrdPath());return}async function f(){let e=!1,t=r.getTasksPath();if(V.existsSync(t))try{let n=V.readFileSync(t,`utf8`),r=JSON.parse(n);r[d]&&Array.isArray(r[d].tasks)&&r[d].tasks.length>0&&(e=!0)}catch{e=!1}if(e&&!l&&!u){if(!await ge(t))return x(`info`,`Operation cancelled.`),!1;l=!0}return!0}try{if(!await f())return;console.log(B.blue(`Parsing PRD file: ${r.getPrdPath()}`)),console.log(B.blue(`Generating ${i} tasks...`)),s&&console.log(B.blue(`Appending to existing tasks...`)),c&&console.log(B.blue(`Using Perplexity AI for research-backed task generation`));let e=r.getTasksPath()||H.join(r.getProjectRoot(),a);await ce(r.getPrdPath(),e,i,{append:u,force:l,research:c,projectRoot:r.getProjectRoot(),tag:d})}catch(e){console.error(B.red(`Error parsing PRD: ${e.message}`)),process.exit(1)}}),n.command(`update`).description(`Update multiple tasks with ID >= "from" based on new information or implementation changes`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--from <id>`,`Task ID to start updating from (tasks with ID >= this value will be updated)`,`1`).option(`-p, --prompt <text>`,`Prompt explaining the changes or new context (required)`).option(`-r, --research`,`Use Perplexity AI for research-backed task updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=parseInt(e.from,10),r=e.prompt,i=e.research||!1,a=t.getTasksPath(),o=t.getCurrentTag();await k(o),(process.argv.includes(`--id`)||process.argv.some(e=>e.startsWith(`--id=`)))&&(console.error(B.red(`Error: The update command uses --from=<id>, not --id=<id>`)),console.log(B.yellow(`
89
+ `)+B.gray(`Advanced features (models, tags, PRD parsing) are managed in Hamster Studio.`),{padding:1,margin:{top:1},borderStyle:`round`,borderColor:`cyan`,width:t}))}function Q(t){t.on(`option:unknown`,function(e){let t=this._name||`unknown`;q(Error(`Unknown option '${e}'`),{context:`Running command: ${t}`,command:`task-master ${t}`,debug:y()}),process.exit(1)}),t.command(`help`).description(`Show help information (Hamster-aware)`).action(()=>{Y()?Z():t.help()}),t.configureHelp({helpWidth:120,sortSubcommands:!1});let r=t.help.bind(t);t.help=function(){Y()?Z():r()},t.hook(`preAction`,async(e,t)=>{let n=t.name();s.includes(n)&&await Ke(n,J(t.opts()).getProjectRoot())&&process.exit(1)}),t.command(`parse-prd`).description(`Parse a PRD file and generate tasks`).argument(`[file]`,`Path to the PRD file`).option(`-i, --input <file>`,`Path to the PRD file (alternative to positional argument)`).option(`-o, --output <file>`,`Output file path`).option(`-n, --num-tasks <number>`,`Number of tasks to generate`,v()).option(`-f, --force`,`Skip confirmation when overwriting existing tasks`).option(`--append`,`Append new tasks to existing tasks.json instead of overwriting`).option(`-r, --research`,`Use Perplexity AI for research-backed task generation, providing more comprehensive and accurate task breakdown`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=t.input||e,r;try{let e={prdPath:n||!0,tag:t.tag};t.output&&(e.tasksPath=t.output),r=J(e)}catch(e){q(e,{context:`Initializing Task Master for PRD parsing`,command:`task-master parse-prd`,debug:y()}),pt(`${B.cyan(`Usage:`)}\n task-master parse-prd <prd-file.txt> [options]\n\n${B.cyan(`Options:`)}\n -i, --input <file> Path to the PRD file\n -o, --output <file> Output file path\n -n, --num-tasks <number> Number of tasks to generate\n -f, --force Skip confirmation\n --append Append to existing tasks\n -r, --research Use Perplexity AI\n\n${B.cyan(`Examples:`)}\n task-master parse-prd requirements.txt --num-tasks 15\n task-master parse-prd --input=requirements.txt\n task-master parse-prd requirements.txt --research`,`Parse PRD Help`),process.exit(1)}let a=parseInt(t.numTasks,10),o=t.force||!1,s=t.append||!1,c=t.research||!1,l=o,u=s,d=r.getCurrentTag();if(await k(d),await _t()===`hamster`){await vt(r.getPrdPath());return}async function f(){let e=!1,t=r.getTasksPath();if(V.existsSync(t))try{let n=V.readFileSync(t,`utf8`),r=JSON.parse(n);r[d]&&Array.isArray(r[d].tasks)&&r[d].tasks.length>0&&(e=!0)}catch{e=!1}if(e&&!l&&!u){if(!await ge(t))return x(`info`,`Operation cancelled.`),!1;l=!0}return!0}try{if(!await f())return;console.log(B.blue(`Parsing PRD file: ${r.getPrdPath()}`)),console.log(B.blue(`Generating ${a} tasks...`)),s&&console.log(B.blue(`Appending to existing tasks...`)),c&&console.log(B.blue(`Using Perplexity AI for research-backed task generation`));let e=r.getTasksPath()||H.join(r.getProjectRoot(),i);await ce(r.getPrdPath(),e,a,{append:u,force:l,research:c,projectRoot:r.getProjectRoot(),tag:d})}catch(e){console.error(B.red(`Error parsing PRD: ${e.message}`)),process.exit(1)}}),t.command(`update`).description(`Update multiple tasks with ID >= "from" based on new information or implementation changes`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--from <id>`,`Task ID to start updating from (tasks with ID >= this value will be updated)`,`1`).option(`-p, --prompt <text>`,`Prompt explaining the changes or new context (required)`).option(`-r, --research`,`Use Perplexity AI for research-backed task updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=parseInt(e.from,10),r=e.prompt,i=e.research||!1,a=t.getTasksPath(),o=t.getCurrentTag();await k(o),(process.argv.includes(`--id`)||process.argv.some(e=>e.startsWith(`--id=`)))&&(console.error(B.red(`Error: The update command uses --from=<id>, not --id=<id>`)),console.log(B.yellow(`
90
90
  To update multiple tasks:`)),console.log(` task-master update --from=${n} --prompt="Your prompt here"`),console.log(B.yellow(`
91
- To update a single specific task, use the update-task command instead:`)),console.log(` task-master update-task --id=<id> --prompt="Your prompt here"`),process.exit(1)),r||(console.error(B.red(`Error: --prompt parameter is required. Please provide information about the changes.`)),process.exit(1)),console.log(B.blue(`Updating tasks from ID >= ${n} with prompt: "${r}"`)),Y()||console.log(B.blue(`Tasks file: ${a}`)),i&&console.log(B.blue(`Using Perplexity AI for research-backed task updates`)),await ue(t.getTasksPath(),n,r,i,{projectRoot:t.getProjectRoot(),tag:o})}),n.command(`update-task`).description(`Update a single specific task by ID with new information`).argument(`[id]`,`Task ID to update (e.g., 1, 1.1, TAS-123)`).argument(`[prompt...]`,`Update prompt - multiple words, no quotes needed`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <id>`,`Task ID to update (fallback if not using positional)`).option(`-p, --prompt <text>`,`Prompt (fallback if not using positional)`).option(`-r, --research`,`Use Perplexity AI for research-backed task updates`).option(`--append`,`Append timestamped information to task details instead of full update`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t,n)=>{try{let r=J({tasksPath:n.file||!0,tag:n.tag}),i=r.getTasksPath(),o=r.getCurrentTag();await k(o);let s=e||n.id,c=t.length>0?t.join(` `):n.prompt;s||(console.error(B.red(`Error: Task ID is required`)),console.log(B.yellow(`Usage examples:
91
+ To update a single specific task, use the update-task command instead:`)),console.log(` task-master update-task --id=<id> --prompt="Your prompt here"`),process.exit(1)),r||(console.error(B.red(`Error: --prompt parameter is required. Please provide information about the changes.`)),process.exit(1)),console.log(B.blue(`Updating tasks from ID >= ${n} with prompt: "${r}"`)),Y()||console.log(B.blue(`Tasks file: ${a}`)),i&&console.log(B.blue(`Using Perplexity AI for research-backed task updates`)),await ue(t.getTasksPath(),n,r,i,{projectRoot:t.getProjectRoot(),tag:o})}),t.command(`update-task`).description(`Update a single specific task by ID with new information`).argument(`[id]`,`Task ID to update (e.g., 1, 1.1, TAS-123)`).argument(`[prompt...]`,`Update prompt - multiple words, no quotes needed`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <id>`,`Task ID to update (fallback if not using positional)`).option(`-p, --prompt <text>`,`Prompt (fallback if not using positional)`).option(`-r, --research`,`Use Perplexity AI for research-backed task updates`).option(`--append`,`Append timestamped information to task details instead of full update`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t,n)=>{try{let r=J({tasksPath:n.file||!0,tag:n.tag}),a=r.getTasksPath(),o=r.getCurrentTag();await k(o);let s=e||n.id,c=t.length>0?t.join(` `):n.prompt;s||(console.error(B.red(`Error: Task ID is required`)),console.log(B.yellow(`Usage examples:
92
92
  tm update-task 1 Added implementation details
93
93
  tm update-task TAS-123 Fixed the auth bug
94
94
  tm update-task --id=23 --prompt="Update with new information"`)),process.exit(1)),/^\d+$/.test(s)||/^[a-z]+-\d+$/i.test(s)||(console.error(B.red(`Error: Invalid task ID: ${s}. Task ID must be a positive integer or in the form "ham-123".`)),console.log(B.yellow(`Usage examples:
95
95
  tm update-task 1 Added implementation details
96
96
  tm update-task TAS-123 Fixed the auth bug`)),process.exit(1)),c||(console.error(B.red(`Error: Prompt is required. Please provide information about the changes.`)),console.log(B.yellow(`Usage examples:
97
97
  tm update-task 1 Added implementation details
98
- tm update-task 23 "Update with new information"`)),process.exit(1));let u=n.research||!1;V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),i===a?console.log(B.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${i}`)),process.exit(1)),console.log(B.blue(`Updating task ${s} with prompt: "${c}"`)),Y()||console.log(B.blue(`Tasks file: ${i}`)),u&&(l(`perplexity`)?console.log(B.blue(`Using Perplexity AI for research-backed task update`)):(console.log(B.yellow(`Warning: PERPLEXITY_API_KEY environment variable is missing. Research-backed updates will not be available.`)),console.log(B.yellow(`Falling back to Claude AI for task update.`))));let d=Y()?!0:n.append||!1;await C(r.getTasksPath(),s,c,u,{projectRoot:r.getProjectRoot(),tag:o},`text`,d)||console.log(B.yellow(`
98
+ tm update-task 23 "Update with new information"`)),process.exit(1));let u=n.research||!1;V.existsSync(a)||(console.error(B.red(`Error: Tasks file not found at path: ${a}`)),a===i?console.log(B.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${a}`)),process.exit(1)),console.log(B.blue(`Updating task ${s} with prompt: "${c}"`)),Y()||console.log(B.blue(`Tasks file: ${a}`)),u&&(l(`perplexity`)?console.log(B.blue(`Using Perplexity AI for research-backed task update`)):(console.log(B.yellow(`Warning: PERPLEXITY_API_KEY environment variable is missing. Research-backed updates will not be available.`)),console.log(B.yellow(`Falling back to Claude AI for task update.`))));let d=Y()?!0:n.append||!1;await C(r.getTasksPath(),s,c,u,{projectRoot:r.getProjectRoot(),tag:o},`text`,d)||console.log(B.yellow(`
99
99
  Task update was not completed. Review the messages above for details.`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`task`)&&e.message.includes(`not found`)?(console.log(B.yellow(`
100
100
  To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use a valid task ID with the --id parameter`)):e.message.includes(`API key`)&&console.log(B.yellow(`
101
- This error is related to API keys. Check your environment variables.`)),y()&&console.error(e),process.exit(1)}}),n.command(`update-subtask`).description(`Update a subtask by appending additional timestamped information`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <id>`,`Subtask ID to update (required)`).option(`-p, --prompt <text>`,`Prompt explaining what information to add (required)`).option(`-r, --research`,`Use Perplexity AI for research-backed updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: task-master update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let i=e.id;e.prompt||(console.error(B.red(`Error: --prompt parameter is required. Please provide information to add to the subtask.`)),console.log(B.yellow(`Usage example: task-master update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let o=e.prompt,s=e.research||!1;V.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),n===a?console.log(B.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${n}`)),process.exit(1)),console.log(B.blue(`Updating subtask ${i} with prompt: "${o}"`)),Y()||console.log(B.blue(`Tasks file: ${n}`)),s&&(l(`perplexity`)?console.log(B.blue(`Using Perplexity AI for research-backed subtask update`)):(console.log(B.yellow(`Warning: PERPLEXITY_API_KEY environment variable is missing. Research-backed updates will not be available.`)),console.log(B.yellow(`Falling back to Claude AI for subtask update.`)))),await We(t.getTasksPath(),i,o,s,{projectRoot:t.getProjectRoot(),tag:r})||console.log(B.yellow(`
101
+ This error is related to API keys. Check your environment variables.`)),y()&&console.error(e),process.exit(1)}}),t.command(`update-subtask`).description(`Update a subtask by appending additional timestamped information`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <id>`,`Subtask ID to update (required)`).option(`-p, --prompt <text>`,`Prompt explaining what information to add (required)`).option(`-r, --research`,`Use Perplexity AI for research-backed updates`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: task-master update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let a=e.id;e.prompt||(console.error(B.red(`Error: --prompt parameter is required. Please provide information to add to the subtask.`)),console.log(B.yellow(`Usage example: task-master update-subtask --id=5.2 --prompt="Add more details about the API endpoint"`)),process.exit(1));let o=e.prompt,s=e.research||!1;V.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),n===i?console.log(B.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)):console.log(B.yellow(`Hint: Check if the file path is correct: ${n}`)),process.exit(1)),console.log(B.blue(`Updating subtask ${a} with prompt: "${o}"`)),Y()||console.log(B.blue(`Tasks file: ${n}`)),s&&(l(`perplexity`)?console.log(B.blue(`Using Perplexity AI for research-backed subtask update`)):(console.log(B.yellow(`Warning: PERPLEXITY_API_KEY environment variable is missing. Research-backed updates will not be available.`)),console.log(B.yellow(`Falling back to Claude AI for subtask update.`)))),await We(t.getTasksPath(),a,o,s,{projectRoot:t.getProjectRoot(),tag:r})||console.log(B.yellow(`
102
102
  Subtask update was not completed. Review the messages above for details.`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`subtask`)&&e.message.includes(`not found`)?(console.log(B.yellow(`
103
103
  To fix this issue:`)),console.log(` 1. Run task-master list --with-subtasks to see all available subtask IDs`),console.log(` 2. Use a valid subtask ID with the --id parameter in format "parentId.subtaskId"`)):e.message.includes(`API key`)&&console.log(B.yellow(`
104
- This error is related to API keys. Check your environment variables.`)),y()&&console.error(e),process.exit(1)}}),n.command(`scope-up`).description(`Increase task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope up (required)`).option(`-s, --strength <level>`,`Complexity increase strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: task-master scope-up --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});j(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),V.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(B.blue(`Scoping up ${i.length} task(s): ${i.join(`, `)}`)),console.log(B.blue(`Strength level: ${e.strength}`)),e.prompt&&console.log(B.blue(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-up`,outputType:`cli`,research:e.research||!1},o=await se(n,i,e.strength,e.prompt||null,a,`text`);console.log(B.green(`✅ Successfully scoped up ${o.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
105
- To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),y()&&console.error(e),process.exit(1)}}),n.command(`scope-down`).description(`Decrease task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope down (required)`).option(`-s, --strength <level>`,`Complexity decrease strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: task-master scope-down --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});j(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),V.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(B.blue(`Scoping down ${i.length} task(s): ${i.join(`, `)}`)),console.log(B.blue(`Strength level: ${e.strength}`)),e.prompt&&console.log(B.blue(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-down`,outputType:`cli`,research:e.research||!1},o=await w(n,i,e.strength,e.prompt||null,a,`text`);console.log(B.green(`✅ Successfully scoped down ${o.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
106
- To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),y()&&console.error(e),process.exit(1)}}),Pe(n),n.command(`expand`).description(`Expand a task into subtasks using AI`).option(`-i, --id <id>`,`ID of the task to expand`).option(`-a, --all`,`Expand all pending tasks based on complexity analysis`).option(`-n, --num <number>`,`Number of subtasks to generate (uses complexity analysis by default if available)`).option(`-r, --research`,`Enable research-backed generation (e.g., using Perplexity)`,!1).option(`-p, --prompt <text>`,`Additional context for subtask generation`).option(`-f, --force`,`Force expansion even if subtasks exist`,!1).option(`--file <file>`,`Path to the tasks file (relative to project root)`,a).option(`-cr, --complexity-report <file>`,`Path to the complexity report file (use this to specify the complexity report, not --file)`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.complexityReport&&(t.complexityReportPath=e.complexityReport);let r=J(t),i=r.getCurrentTag();if(await k(i),e.all){console.log(B.blue(`Expanding all pending tasks...`));try{await re(r.getTasksPath(),e.num,e.research,e.prompt,e.force,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()})}catch(e){console.error(B.red(`Error expanding all tasks: ${e.message}`)),process.exit(1)}}else if(e.id){e.id||(console.error(B.red(`Error: Task ID is required unless using --all.`)),process.exit(1)),console.log(B.blue(`Expanding task ${e.id}...`));try{await fe(r.getTasksPath(),e.id,e.num,e.research,e.prompt,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()},e.force)}catch(t){console.error(B.red(`Error expanding task ${e.id}: ${t.message}`)),process.exit(1)}}else console.error(B.red(`Error: You must specify either a task ID (--id) or --all.`)),n.help()}),n.command(`analyze-complexity`).description(`Analyze tasks and generate expansion recommendations${B.reset(``)}`).option(`-o, --output <file>`,`Output file path for the report`).option(`-m, --model <model>`,`LLM model to use for analysis (defaults to configured model)`).option(`-t, --threshold <number>`,`Minimum complexity score to recommend expansion (1-10)`,`5`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-r, --research`,`Use configured research model for research-backed complexity analysis`).option(`-i, --id <ids>`,`Comma-separated list of specific task IDs to analyze (e.g., "1,3,5")`).option(`--from <id>`,`Starting task ID in a range to analyze`).option(`--to <id>`,`Ending task ID in a range to analyze`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.output&&(t.complexityReportPath=e.output);let n=J(t);e.model,parseFloat(e.threshold);let r=e.research||!1,i=n.getCurrentTag();await k(i);let a=n.getComplexityReportPath();if(console.log(B.blue(`Analyzing task complexity from: ${n.getTasksPath()}`)),console.log(B.blue(`Output report will be saved to: ${a}`)),e.id)console.log(B.blue(`Analyzing specific task IDs: ${e.id}`));else if(e.from||e.to){let t=e.from?e.from:`first`,n=e.to?e.to:`last`;console.log(B.blue(`Analyzing tasks in range: ${t} to ${n}`))}r&&console.log(B.blue(`Using Perplexity AI for research-backed complexity analysis`)),await pe({...e,output:a,tag:i,projectRoot:n.getProjectRoot(),file:n.getTasksPath()})}),n.command(`research`).description(`Perform AI-powered research queries with project context`).argument(`[prompt]`,`Research prompt to investigate`).option(`--file <file>`,`Path to the tasks file`).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to include as context (e.g., "15,16.2")`).option(`-f, --files <paths>`,`Comma-separated file paths to include as context`).option(`-c, --context <text>`,`Additional custom context to include in the research prompt`).option(`-t, --tree`,`Include project file tree structure in the research context`).option(`-s, --save <file>`,`Save research results to the specified task/subtask(s)`).option(`-d, --detail <level>`,`Output detail level: low, medium, high`,`medium`).option(`--save-to <id>`,`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`).option(`--save-file`,`Save research results to .taskmaster/docs/research/ directory`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=J({tasksPath:t.file||!0,tag:t.tag});(!e||typeof e!=`string`||e.trim().length===0)&&(console.error(B.red(`Error: Research prompt is required and cannot be empty`)),m(),process.exit(1));let r=[`low`,`medium`,`high`];t.detail&&!r.includes(t.detail.toLowerCase())&&(console.error(B.red(`Error: Detail level must be one of: ${r.join(`, `)}`)),process.exit(1));let i=[];if(t.id)try{i=t.id.split(`,`).map(e=>{let t=e.trim();if(!/^\d+(\.\d+)?$/.test(t))throw Error(`Invalid task ID format: "${t}". Expected format: "15" or "15.2"`);return t})}catch(e){console.error(B.red(`Error parsing task IDs: ${e.message}`)),process.exit(1)}let a=[];if(t.files)try{a=t.files.split(`,`).map(e=>{let t=e.trim();if(t.length===0)throw Error(`Empty file path provided`);return t})}catch(e){console.error(B.red(`Error parsing file paths: ${e.message}`)),process.exit(1)}if(t.saveTo){let e=t.saveTo.trim();e.length===0&&(console.error(B.red(`Error: Save-to ID cannot be empty`)),process.exit(1)),/^\d+(\.\d+)?$/.test(e)||(console.error(B.red(`Error: Save-to ID must be in format "15" for task or "15.2" for subtask`)),process.exit(1))}if(t.save){let e=t.save.trim();e.length===0&&(console.error(B.red(`Error: Save target cannot be empty`)),process.exit(1)),(e.includes(`..`)||e.startsWith(`/`))&&(console.error(B.red(`Error: Save path must be relative and cannot contain ".."`)),process.exit(1))}let o=n.getCurrentTag();if(await k(o),i.length>0)try{let e=d(n.getTasksPath(),n.getProjectRoot(),o);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${n.getTasksPath()} for tag '${o}'`)),process.exit(1))}catch(e){console.error(B.red(`Error reading tasks file: ${e.message}`)),process.exit(1)}if(a.length>0)for(let e of a){let t=H.isAbsolute(e)?e:H.join(n.getProjectRoot(),e);V.existsSync(t)||(console.error(B.red(`Error: File not found: ${e}`)),process.exit(1))}let s={prompt:e.trim(),taskIds:i,filePaths:a,customContext:t.context?t.context.trim():null,includeProjectTree:!!t.tree,saveTarget:t.save?t.save.trim():null,saveToId:t.saveTo?t.saveTo.trim():null,allowFollowUp:!0,detailLevel:t.detail?t.detail.toLowerCase():`medium`,tasksPath:n.getTasksPath(),projectRoot:n.getProjectRoot()};console.log(B.blue(`Researching: "${s.prompt}"`)),s.taskIds.length>0&&console.log(B.gray(`Task context: ${s.taskIds.join(`, `)}`)),s.filePaths.length>0&&console.log(B.gray(`File context: ${s.filePaths.join(`, `)}`)),s.customContext&&console.log(B.gray(`Custom context: ${s.customContext.substring(0,50)}${s.customContext.length>50?`...`:``}`)),s.includeProjectTree&&console.log(B.gray(`Including project file tree`)),console.log(B.gray(`Detail level: ${s.detailLevel}`));try{let{performResearch:e}=await import(`./research-aocf1qGI.js`),n={taskIds:s.taskIds,filePaths:s.filePaths,customContext:s.customContext||``,includeProjectTree:s.includeProjectTree,detailLevel:s.detailLevel,projectRoot:s.projectRoot,saveToFile:!!t.saveFile,tag:o},r=await e(s.prompt,n,{commandName:`research`,outputType:`cli`,tag:o},`text`,s.allowFollowUp);if(s.saveToId&&!r.interactiveSaveOccurred)try{let e=s.saveToId.includes(`.`),t=`## Research Query: ${s.prompt}
104
+ This error is related to API keys. Check your environment variables.`)),y()&&console.error(e),process.exit(1)}}),t.command(`scope-up`).description(`Increase task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope up (required)`).option(`-s, --strength <level>`,`Complexity increase strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: task-master scope-up --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});j(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),V.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(B.blue(`Scoping up ${i.length} task(s): ${i.join(`, `)}`)),console.log(B.blue(`Strength level: ${e.strength}`)),e.prompt&&console.log(B.blue(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-up`,outputType:`cli`,research:e.research||!1},o=await se(n,i,e.strength,e.prompt||null,a,`text`);console.log(B.green(`✅ Successfully scoped up ${o.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
105
+ To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),y()&&console.error(e),process.exit(1)}}),t.command(`scope-down`).description(`Decrease task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope down (required)`).option(`-s, --strength <level>`,`Complexity decrease strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(B.red(`Error: --id parameter is required`)),console.log(B.yellow(`Usage example: task-master scope-down --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(B.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});j(e.strength)||(console.error(B.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),V.existsSync(n)||(console.error(B.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(B.blue(`Scoping down ${i.length} task(s): ${i.join(`, `)}`)),console.log(B.blue(`Strength level: ${e.strength}`)),e.prompt&&console.log(B.blue(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-down`,outputType:`cli`,research:e.research||!1},o=await w(n,i,e.strength,e.prompt||null,a,`text`);console.log(B.green(`✅ Successfully scoped down ${o.updatedTasks.length} task(s)`))}catch(e){console.error(B.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(B.yellow(`
106
+ To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),y()&&console.error(e),process.exit(1)}}),Pe(t),t.command(`expand`).description(`Expand a task into subtasks using AI`).option(`-i, --id <id>`,`ID of the task to expand`).option(`-a, --all`,`Expand all pending tasks based on complexity analysis`).option(`-n, --num <number>`,`Number of subtasks to generate (uses complexity analysis by default if available)`).option(`-r, --research`,`Enable research-backed generation (e.g., using Perplexity)`,!1).option(`-p, --prompt <text>`,`Additional context for subtask generation`).option(`-f, --force`,`Force expansion even if subtasks exist`,!1).option(`--file <file>`,`Path to the tasks file (relative to project root)`,i).option(`-cr, --complexity-report <file>`,`Path to the complexity report file (use this to specify the complexity report, not --file)`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let n={tasksPath:e.file||!0,tag:e.tag};e.complexityReport&&(n.complexityReportPath=e.complexityReport);let r=J(n),i=r.getCurrentTag();if(await k(i),e.all){console.log(B.blue(`Expanding all pending tasks...`));try{await re(r.getTasksPath(),e.num,e.research,e.prompt,e.force,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()})}catch(e){console.error(B.red(`Error expanding all tasks: ${e.message}`)),process.exit(1)}}else if(e.id){e.id||(console.error(B.red(`Error: Task ID is required unless using --all.`)),process.exit(1)),console.log(B.blue(`Expanding task ${e.id}...`));try{await fe(r.getTasksPath(),e.id,e.num,e.research,e.prompt,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()},e.force)}catch(t){console.error(B.red(`Error expanding task ${e.id}: ${t.message}`)),process.exit(1)}}else console.error(B.red(`Error: You must specify either a task ID (--id) or --all.`)),t.help()}),t.command(`analyze-complexity`).description(`Analyze tasks and generate expansion recommendations${B.reset(``)}`).option(`-o, --output <file>`,`Output file path for the report`).option(`-m, --model <model>`,`LLM model to use for analysis (defaults to configured model)`).option(`-t, --threshold <number>`,`Minimum complexity score to recommend expansion (1-10)`,`5`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-r, --research`,`Use configured research model for research-backed complexity analysis`).option(`-i, --id <ids>`,`Comma-separated list of specific task IDs to analyze (e.g., "1,3,5")`).option(`--from <id>`,`Starting task ID in a range to analyze`).option(`--to <id>`,`Ending task ID in a range to analyze`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.output&&(t.complexityReportPath=e.output);let n=J(t);e.model,parseFloat(e.threshold);let r=e.research||!1,i=n.getCurrentTag();await k(i);let a=n.getComplexityReportPath();if(console.log(B.blue(`Analyzing task complexity from: ${n.getTasksPath()}`)),console.log(B.blue(`Output report will be saved to: ${a}`)),e.id)console.log(B.blue(`Analyzing specific task IDs: ${e.id}`));else if(e.from||e.to){let t=e.from?e.from:`first`,n=e.to?e.to:`last`;console.log(B.blue(`Analyzing tasks in range: ${t} to ${n}`))}r&&console.log(B.blue(`Using Perplexity AI for research-backed complexity analysis`)),await pe({...e,output:a,tag:i,projectRoot:n.getProjectRoot(),file:n.getTasksPath()})}),t.command(`research`).description(`Perform AI-powered research queries with project context`).argument(`[prompt]`,`Research prompt to investigate`).option(`--file <file>`,`Path to the tasks file`).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to include as context (e.g., "15,16.2")`).option(`-f, --files <paths>`,`Comma-separated file paths to include as context`).option(`-c, --context <text>`,`Additional custom context to include in the research prompt`).option(`-t, --tree`,`Include project file tree structure in the research context`).option(`-s, --save <file>`,`Save research results to the specified task/subtask(s)`).option(`-d, --detail <level>`,`Output detail level: low, medium, high`,`medium`).option(`--save-to <id>`,`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`).option(`--save-file`,`Save research results to .taskmaster/docs/research/ directory`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=J({tasksPath:t.file||!0,tag:t.tag});(!e||typeof e!=`string`||e.trim().length===0)&&(console.error(B.red(`Error: Research prompt is required and cannot be empty`)),m(),process.exit(1));let r=[`low`,`medium`,`high`];t.detail&&!r.includes(t.detail.toLowerCase())&&(console.error(B.red(`Error: Detail level must be one of: ${r.join(`, `)}`)),process.exit(1));let i=[];if(t.id)try{i=t.id.split(`,`).map(e=>{let t=e.trim();if(!/^\d+(\.\d+)?$/.test(t))throw Error(`Invalid task ID format: "${t}". Expected format: "15" or "15.2"`);return t})}catch(e){console.error(B.red(`Error parsing task IDs: ${e.message}`)),process.exit(1)}let a=[];if(t.files)try{a=t.files.split(`,`).map(e=>{let t=e.trim();if(t.length===0)throw Error(`Empty file path provided`);return t})}catch(e){console.error(B.red(`Error parsing file paths: ${e.message}`)),process.exit(1)}if(t.saveTo){let e=t.saveTo.trim();e.length===0&&(console.error(B.red(`Error: Save-to ID cannot be empty`)),process.exit(1)),/^\d+(\.\d+)?$/.test(e)||(console.error(B.red(`Error: Save-to ID must be in format "15" for task or "15.2" for subtask`)),process.exit(1))}if(t.save){let e=t.save.trim();e.length===0&&(console.error(B.red(`Error: Save target cannot be empty`)),process.exit(1)),(e.includes(`..`)||e.startsWith(`/`))&&(console.error(B.red(`Error: Save path must be relative and cannot contain ".."`)),process.exit(1))}let o=n.getCurrentTag();if(await k(o),i.length>0)try{let e=d(n.getTasksPath(),n.getProjectRoot(),o);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${n.getTasksPath()} for tag '${o}'`)),process.exit(1))}catch(e){console.error(B.red(`Error reading tasks file: ${e.message}`)),process.exit(1)}if(a.length>0)for(let e of a){let t=H.isAbsolute(e)?e:H.join(n.getProjectRoot(),e);V.existsSync(t)||(console.error(B.red(`Error: File not found: ${e}`)),process.exit(1))}let s={prompt:e.trim(),taskIds:i,filePaths:a,customContext:t.context?t.context.trim():null,includeProjectTree:!!t.tree,saveTarget:t.save?t.save.trim():null,saveToId:t.saveTo?t.saveTo.trim():null,allowFollowUp:!0,detailLevel:t.detail?t.detail.toLowerCase():`medium`,tasksPath:n.getTasksPath(),projectRoot:n.getProjectRoot()};console.log(B.blue(`Researching: "${s.prompt}"`)),s.taskIds.length>0&&console.log(B.gray(`Task context: ${s.taskIds.join(`, `)}`)),s.filePaths.length>0&&console.log(B.gray(`File context: ${s.filePaths.join(`, `)}`)),s.customContext&&console.log(B.gray(`Custom context: ${s.customContext.substring(0,50)}${s.customContext.length>50?`...`:``}`)),s.includeProjectTree&&console.log(B.gray(`Including project file tree`)),console.log(B.gray(`Detail level: ${s.detailLevel}`));try{let{performResearch:e}=await import(`./research-LCg5MHnP.js`),n={taskIds:s.taskIds,filePaths:s.filePaths,customContext:s.customContext||``,includeProjectTree:s.includeProjectTree,detailLevel:s.detailLevel,projectRoot:s.projectRoot,saveToFile:!!t.saveFile,tag:o},r=await e(s.prompt,n,{commandName:`research`,outputType:`cli`,tag:o},`text`,s.allowFollowUp);if(s.saveToId&&!r.interactiveSaveOccurred)try{let e=s.saveToId.includes(`.`),t=`## Research Query: ${s.prompt}
107
107
 
108
108
  **Detail Level:** ${r.detailLevel}
109
109
  **Context Size:** ${r.contextSize} characters
@@ -111,7 +111,7 @@ To fix this issue:`)),console.log(` 1. Run task-master list to see all availabl
111
111
 
112
112
  ### Results
113
113
 
114
- ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-BWC9_KFA.js`);await e(s.tasksPath,s.saveToId,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`),console.log(B.green(`✅ Research saved to subtask ${s.saveToId}`))}else{let e=(await import(`./update-task-by-id-BHYw3Axm.js`)).default,n=parseInt(s.saveToId,10);await e(s.tasksPath,n,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`,!0),console.log(B.green(`✅ Research saved to task ${s.saveToId}`))}}catch(e){console.log(B.red(`❌ Error saving to task/subtask: ${e.message}`))}if(s.saveTarget){let e=`# Research Query: ${s.prompt}
114
+ ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-B5uMpDq6.js`);await e(s.tasksPath,s.saveToId,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`),console.log(B.green(`✅ Research saved to subtask ${s.saveToId}`))}else{let e=(await import(`./update-task-by-id-D_HOOs3f.js`)).default,n=parseInt(s.saveToId,10);await e(s.tasksPath,n,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`,!0),console.log(B.green(`✅ Research saved to task ${s.saveToId}`))}}catch(e){console.log(B.red(`❌ Error saving to task/subtask: ${e.message}`))}if(s.saveTarget){let e=`# Research Query: ${s.prompt}
115
115
 
116
116
  **Detail Level:** ${r.detailLevel}
117
117
  **Context Size:** ${r.contextSize} characters
@@ -120,15 +120,15 @@ ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id
120
120
  ## Results
121
121
 
122
122
  ${r.result}
123
- `;V.writeFileSync(s.saveTarget,e,`utf-8`),console.log(B.green(`\n💾 Results saved to: ${s.saveTarget}`))}}catch(e){console.error(B.red(`\n❌ Research failed: ${e.message}`)),process.exit(1)}}),n.command(`clear-subtasks`).description(`Clear subtasks from specified tasks`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <ids>`,`Task IDs (comma-separated) to clear subtasks from`).option(`--all`,`Clear subtasks from all tasks`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=e.id,n=e.all,r=J({tasksPath:e.file||!0,tag:e.tag}),i=r.getCurrentTag();if(await k(i),!t&&!n&&(console.error(B.red(`Error: Please specify task IDs with --id=<ids> or use --all to clear all tasks`)),process.exit(1)),n){let e=d(r.getTasksPath(),r.getProjectRoot(),i);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found`)),process.exit(1));let t=e.tasks.map(e=>e.id).join(`,`);D(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}else D(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}),n.command(`add-task`).description(`Add a new task using AI, optionally providing manual details`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-p, --prompt <prompt>`,`Description of the task to add (required if not using manual fields)`).option(`-t, --title <title>`,`Task title (for manual task creation)`).option(`-d, --description <description>`,`Task description (for manual task creation)`).option(`--details <details>`,`Implementation details (for manual task creation)`).option(`--dependencies <dependencies>`,`Comma-separated list of task IDs this task depends on`).option(`--priority <priority>`,`Task priority (high, medium, low)`,`medium`).option(`-r, --research`,`Whether to use research capabilities for task creation`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=e.title&&e.description;!e.prompt&&!t&&(console.error(B.red(`Error: Either --prompt or both --title and --description must be provided`)),process.exit(1));let n=e.file||a;V.existsSync(n)||(console.error(`❌ No tasks.json file found. Please run "task-master init" or create a tasks.json file at ${a}`),process.exit(1));let r=J({tasksPath:e.file||!0,tag:e.tag}),i=r.getProjectRoot(),o=r.getCurrentTag();await k(o);let s=null;t?(s={title:e.title,description:e.description,details:e.details||``,testStrategy:e.testStrategy||``},console.log(B.blue(`Creating task manually with title: "${e.title}"`))):console.log(B.blue(`Creating task with AI using prompt: "${e.prompt}"`));let c=e.dependencies?e.dependencies.split(`,`).map(e=>e.trim()):[];c.length>0&&console.log(B.blue(`Dependencies: [${c.join(`, `)}]`)),e.priority&&console.log(B.blue(`Priority: ${e.priority}`));let l={projectRoot:i,tag:o,commandName:`add-task`,outputType:`cli`};try{let{newTaskId:t,telemetryData:n}=await le(r.getTasksPath(),e.prompt,c,e.priority,l,`text`,s,e.research)}catch(e){console.error(B.red(`Error adding task: ${e.message}`)),e.details&&console.error(B.red(e.details)),process.exit(1)}}),n.command(`add-dependency`).description(`Add a dependency to a task`).option(`-i, --id <id>`,`Task ID to add dependency to`).option(`-d, --depends-on <id>`,`Task ID that will become a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await k(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await ze(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),n.command(`remove-dependency`).description(`Remove a dependency from a task`).option(`-i, --id <id>`,`Task ID to remove dependency from`).option(`-d, --depends-on <id>`,`Task ID to remove as a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await k(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await Fe(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),n.command(`validate-dependencies`).description(`Identify invalid dependencies without fixing them${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await k(n),await Ee(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),n.command(`fix-dependencies`).description(`Fix invalid dependencies automatically${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await k(n),await je(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),n.command(`complexity-report`).description(`Display the complexity analysis report${B.reset(``)}`).option(`-f, --file <file>`,`Path to the report file`,s).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tag:e.tag};e.file&&e.file!==s&&(t.complexityReportPath=e.file);let n=J(t);await k(n.getCurrentTag()),await ke(n.getComplexityReportPath())}),n.command(`add-subtask`).description(`Add a subtask to an existing task`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-p, --parent <id>`,`Parent task ID (required)`).option(`-i, --task-id <id>`,`Existing task ID to convert to subtask`).option(`-t, --title <title>`,`Title for the new subtask (when creating a new subtask)`).option(`-d, --description <text>`,`Description for the new subtask`).option(`--details <text>`,`Implementation details for the new subtask`).option(`--dependencies <ids>`,`Comma-separated list of dependency IDs for the new subtask`).option(`-s, --status <status>`,`Status for the new subtask`,`pending`).option(`--generate`,`Regenerate task files after adding subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.parent,r=e.taskId,i=e.generate||!1,a=t.getCurrentTag();await k(a),n||(console.error(B.red(`Error: --parent parameter is required. Please provide a parent task ID.`)),o(),process.exit(1));let s=[];e.dependencies&&(s=e.dependencies.split(`,`).map(e=>e.includes(`.`)?e.trim():parseInt(e.trim(),10)));try{if(r)console.log(B.blue(`Converting task ${r} to a subtask of ${n}...`)),await S(t.getTasksPath(),n,r,null,i,{projectRoot:t.getProjectRoot(),tag:a}),console.log(B.green(`✓ Task ${r} successfully converted to a subtask of task ${n}`));else if(e.title){console.log(B.blue(`Creating new subtask for parent task ${n}...`));let r={title:e.title,description:e.description||``,details:e.details||``,status:e.status||`pending`,dependencies:s},o=await S(t.getTasksPath(),n,null,r,i,{projectRoot:t.getProjectRoot(),tag:a});console.log(B.green(`✓ New subtask ${n}.${o.id} successfully created`)),console.log(U(B.white.bold(`Subtask ${n}.${o.id} Added Successfully`)+`
123
+ `;V.writeFileSync(s.saveTarget,e,`utf-8`),console.log(B.green(`\n💾 Results saved to: ${s.saveTarget}`))}}catch(e){console.error(B.red(`\n❌ Research failed: ${e.message}`)),process.exit(1)}}),t.command(`clear-subtasks`).description(`Clear subtasks from specified tasks`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <ids>`,`Task IDs (comma-separated) to clear subtasks from`).option(`--all`,`Clear subtasks from all tasks`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=e.id,n=e.all,r=J({tasksPath:e.file||!0,tag:e.tag}),i=r.getCurrentTag();if(await k(i),!t&&!n&&(console.error(B.red(`Error: Please specify task IDs with --id=<ids> or use --all to clear all tasks`)),process.exit(1)),n){let e=d(r.getTasksPath(),r.getProjectRoot(),i);(!e||!e.tasks)&&(console.error(B.red(`Error: No valid tasks found`)),process.exit(1));let t=e.tasks.map(e=>e.id).join(`,`);D(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}else D(r.getTasksPath(),t,{projectRoot:r.getProjectRoot(),tag:i})}),t.command(`add-task`).description(`Add a new task using AI, optionally providing manual details`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-p, --prompt <prompt>`,`Description of the task to add (required if not using manual fields)`).option(`-t, --title <title>`,`Task title (for manual task creation)`).option(`-d, --description <description>`,`Task description (for manual task creation)`).option(`--details <details>`,`Implementation details (for manual task creation)`).option(`--dependencies <dependencies>`,`Comma-separated list of task IDs this task depends on`).option(`--priority <priority>`,`Task priority (high, medium, low)`,`medium`).option(`-r, --research`,`Whether to use research capabilities for task creation`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=e.title&&e.description;!e.prompt&&!t&&(console.error(B.red(`Error: Either --prompt or both --title and --description must be provided`)),process.exit(1));let n=e.file||i;V.existsSync(n)||(console.error(`❌ No tasks.json file found. Please run "task-master init" or create a tasks.json file at ${i}`),process.exit(1));let r=J({tasksPath:e.file||!0,tag:e.tag}),a=r.getProjectRoot(),o=r.getCurrentTag();await k(o);let s=null;t?(s={title:e.title,description:e.description,details:e.details||``,testStrategy:e.testStrategy||``},console.log(B.blue(`Creating task manually with title: "${e.title}"`))):console.log(B.blue(`Creating task with AI using prompt: "${e.prompt}"`));let c=e.dependencies?e.dependencies.split(`,`).map(e=>e.trim()):[];c.length>0&&console.log(B.blue(`Dependencies: [${c.join(`, `)}]`)),e.priority&&console.log(B.blue(`Priority: ${e.priority}`));let l={projectRoot:a,tag:o,commandName:`add-task`,outputType:`cli`};try{let{newTaskId:t,telemetryData:n}=await le(r.getTasksPath(),e.prompt,c,e.priority,l,`text`,s,e.research)}catch(e){console.error(B.red(`Error adding task: ${e.message}`)),e.details&&console.error(B.red(e.details)),process.exit(1)}}),t.command(`add-dependency`).description(`Add a dependency to a task`).option(`-i, --id <id>`,`Task ID to add dependency to`).option(`-d, --depends-on <id>`,`Task ID that will become a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await k(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await ze(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),t.command(`remove-dependency`).description(`Remove a dependency from a task`).option(`-i, --id <id>`,`Task ID to remove dependency from`).option(`-d, --depends-on <id>`,`Task ID to remove as a dependency`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.dependsOn,i=t.getCurrentTag();await k(i),(!n||!r)&&(console.error(B.red(`Error: Both --id and --depends-on are required`)),process.exit(1));let a=n.includes(`.`)?n:parseInt(n,10),o=r.includes(`.`)?r:parseInt(r,10);await Fe(t.getTasksPath(),a,o,{projectRoot:t.getProjectRoot(),tag:i})}),t.command(`validate-dependencies`).description(`Identify invalid dependencies without fixing them${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await k(n),await Ee(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),t.command(`fix-dependencies`).description(`Fix invalid dependencies automatically${B.reset(``)}`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=t.getCurrentTag();await k(n),await je(t.getTasksPath(),{context:{projectRoot:t.getProjectRoot(),tag:n}})}),t.command(`complexity-report`).description(`Display the complexity analysis report${B.reset(``)}`).option(`-f, --file <file>`,`Path to the report file`,o).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tag:e.tag};e.file&&e.file!==o&&(t.complexityReportPath=e.file);let n=J(t);await k(n.getCurrentTag()),await ke(n.getComplexityReportPath())}),t.command(`add-subtask`).description(`Add a subtask to an existing task`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-p, --parent <id>`,`Parent task ID (required)`).option(`-i, --task-id <id>`,`Existing task ID to convert to subtask`).option(`-t, --title <title>`,`Title for the new subtask (when creating a new subtask)`).option(`-d, --description <text>`,`Description for the new subtask`).option(`--details <text>`,`Implementation details for the new subtask`).option(`--dependencies <ids>`,`Comma-separated list of dependency IDs for the new subtask`).option(`-s, --status <status>`,`Status for the new subtask`,`pending`).option(`--generate`,`Regenerate task files after adding subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.parent,r=e.taskId,i=e.generate||!1,o=t.getCurrentTag();await k(o),n||(console.error(B.red(`Error: --parent parameter is required. Please provide a parent task ID.`)),a(),process.exit(1));let s=[];e.dependencies&&(s=e.dependencies.split(`,`).map(e=>e.includes(`.`)?e.trim():parseInt(e.trim(),10)));try{if(r)console.log(B.blue(`Converting task ${r} to a subtask of ${n}...`)),await S(t.getTasksPath(),n,r,null,i,{projectRoot:t.getProjectRoot(),tag:o}),console.log(B.green(`✓ Task ${r} successfully converted to a subtask of task ${n}`));else if(e.title){console.log(B.blue(`Creating new subtask for parent task ${n}...`));let r={title:e.title,description:e.description||``,details:e.details||``,status:e.status||`pending`,dependencies:s},a=await S(t.getTasksPath(),n,null,r,i,{projectRoot:t.getProjectRoot(),tag:o});console.log(B.green(`✓ New subtask ${n}.${a.id} successfully created`)),console.log(U(B.white.bold(`Subtask ${n}.${a.id} Added Successfully`)+`
124
124
 
125
- `+B.white(`Title: ${o.title}`)+`
126
- `+B.white(`Status: ${N(o.status)}`)+`
125
+ `+B.white(`Title: ${a.title}`)+`
126
+ `+B.white(`Status: ${N(a.status)}`)+`
127
127
  `+(s.length>0?B.white(`Dependencies: ${s.join(`, `)}`)+`
128
128
  `:``)+`
129
129
  `+B.white.bold(`Next Steps:`)+`
130
130
  `+B.cyan(`1. Run ${B.yellow(`task-master show ${n}`)} to see the parent task with all subtasks`)+`
131
- `+B.cyan(`2. Run ${B.yellow(`tm set-status ${n}.${o.id} in-progress`)} to start working on it`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}}))}else console.error(B.red(`Error: Either --task-id or --title must be provided.`)),console.log(U(B.white.bold(`Usage Examples:`)+`
131
+ `+B.cyan(`2. Run ${B.yellow(`tm set-status ${n}.${a.id} in-progress`)} to start working on it`),{padding:1,borderColor:`green`,borderStyle:`round`,margin:{top:1}}))}else console.error(B.red(`Error: Either --task-id or --title must be provided.`)),console.log(U(B.white.bold(`Usage Examples:`)+`
132
132
 
133
133
  `+B.white(`Convert existing task to subtask:`)+`
134
134
  `+B.yellow(` task-master add-subtask --parent=5 --task-id=8`)+`
@@ -136,7 +136,7 @@ ${r.result}
136
136
  `+B.white(`Create new subtask:`)+`
137
137
  `+B.yellow(` task-master add-subtask --parent=5 --title="Implement login UI" --description="Create the login form"`)+`
138
138
 
139
- `,{padding:1,borderColor:`blue`,borderStyle:`round`})),process.exit(1)}catch(e){console.error(B.red(`Error: ${e.message}`)),o(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),o(),process.exit(1)});function o(){console.log(U(`${B.white.bold(`Add Subtask Command Help`)}\n\n${B.cyan(`Usage:`)}\n task-master add-subtask --parent=<id> [options]\n\n${B.cyan(`Options:`)}\n -p, --parent <id> Parent task ID (required)\n -i, --task-id <id> Existing task ID to convert to subtask\n -t, --title <title> Title for the new subtask\n -d, --description <text> Description for the new subtask\n --details <text> Implementation details for the new subtask\n --dependencies <ids> Comma-separated list of dependency IDs\n -s, --status <status> Status for the new subtask (default: "pending")\n -f, --file <file> Path to the tasks file (default: "${a}")\n --generate Regenerate task files after adding subtask\n\n${B.cyan(`Examples:`)}\n task-master add-subtask --parent=5 --task-id=8\n task-master add-subtask -p 5 -t "Implement login UI" -d "Create the login form" --generate`,{padding:1,borderColor:`blue`,borderStyle:`round`}))}n.command(`remove-subtask`).description(`Remove a subtask from its parent task`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <id>`,`Subtask ID(s) to remove in format "parentId.subtaskId" (can be comma-separated for multiple subtasks)`).option(`-c, --convert`,`Convert the subtask to a standalone task instead of deleting it`).option(`--generate`,`Regenerate task files after removing subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.convert||!1,i=e.generate||!1,a=t.getCurrentTag();n||(console.error(B.red(`Error: --id parameter is required. Please provide subtask ID(s) in format "parentId.subtaskId".`)),c(),process.exit(1));try{let e=n.split(`,`).map(e=>e.trim());for(let n of e){n.includes(`.`)||(console.error(B.red(`Error: Subtask ID "${n}" must be in format "parentId.subtaskId"`)),c(),process.exit(1)),console.log(B.blue(`Removing subtask ${n}...`)),r&&console.log(B.blue(`The subtask will be converted to a standalone task`));let e=await oe(t.getTasksPath(),n,r,i,{projectRoot:t.getProjectRoot(),tag:a});r&&e?console.log(U(B.white.bold(`Subtask ${n} Converted to Task #${e.id}`)+`
139
+ `,{padding:1,borderColor:`blue`,borderStyle:`round`})),process.exit(1)}catch(e){console.error(B.red(`Error: ${e.message}`)),a(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),a(),process.exit(1)});function a(){console.log(U(`${B.white.bold(`Add Subtask Command Help`)}\n\n${B.cyan(`Usage:`)}\n task-master add-subtask --parent=<id> [options]\n\n${B.cyan(`Options:`)}\n -p, --parent <id> Parent task ID (required)\n -i, --task-id <id> Existing task ID to convert to subtask\n -t, --title <title> Title for the new subtask\n -d, --description <text> Description for the new subtask\n --details <text> Implementation details for the new subtask\n --dependencies <ids> Comma-separated list of dependency IDs\n -s, --status <status> Status for the new subtask (default: "pending")\n -f, --file <file> Path to the tasks file (default: "${i}")\n --generate Regenerate task files after adding subtask\n\n${B.cyan(`Examples:`)}\n task-master add-subtask --parent=5 --task-id=8\n task-master add-subtask -p 5 -t "Implement login UI" -d "Create the login form" --generate`,{padding:1,borderColor:`blue`,borderStyle:`round`}))}t.command(`remove-subtask`).description(`Remove a subtask from its parent task`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-i, --id <id>`,`Subtask ID(s) to remove in format "parentId.subtaskId" (can be comma-separated for multiple subtasks)`).option(`-c, --convert`,`Convert the subtask to a standalone task instead of deleting it`).option(`--generate`,`Regenerate task files after removing subtask`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=e.convert||!1,i=e.generate||!1,a=t.getCurrentTag();n||(console.error(B.red(`Error: --id parameter is required. Please provide subtask ID(s) in format "parentId.subtaskId".`)),c(),process.exit(1));try{let e=n.split(`,`).map(e=>e.trim());for(let n of e){n.includes(`.`)||(console.error(B.red(`Error: Subtask ID "${n}" must be in format "parentId.subtaskId"`)),c(),process.exit(1)),console.log(B.blue(`Removing subtask ${n}...`)),r&&console.log(B.blue(`The subtask will be converted to a standalone task`));let e=await oe(t.getTasksPath(),n,r,i,{projectRoot:t.getProjectRoot(),tag:a});r&&e?console.log(U(B.white.bold(`Subtask ${n} Converted to Task #${e.id}`)+`
140
140
 
141
141
  `+B.white(`Title: ${e.title}`)+`
142
142
  `+B.white(`Status: ${N(e.status)}`)+`
@@ -154,7 +154,7 @@ ${r.result}
154
154
  `+B.cyan(`Options:`)+`
155
155
  -i, --id <id> Subtask ID(s) to remove in format "parentId.subtaskId" (can be comma-separated, required)
156
156
  -c, --convert Convert the subtask to a standalone task instead of deleting it
157
- -f, --file <file> Path to the tasks file (default: "`+a+`")
157
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
158
158
  --skip-generate Skip regenerating task files
159
159
 
160
160
  `+B.cyan(`Examples:`)+`
@@ -166,7 +166,7 @@ ${r.result}
166
166
  task-master add-tag <tagName> [options]
167
167
 
168
168
  `+B.cyan(`Options:`)+`
169
- -f, --file <file> Path to the tasks file (default: "`+a+`")
169
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
170
170
  --copy-from-current Copy tasks from the current tag to the new tag
171
171
  --copy-from <tag> Copy tasks from the specified tag to the new tag
172
172
  -d, --description <text> Optional description for the tag
@@ -181,7 +181,7 @@ ${r.result}
181
181
  task-master delete-tag <tagName> [options]
182
182
 
183
183
  `+B.cyan(`Options:`)+`
184
- -f, --file <file> Path to the tasks file (default: "`+a+`")
184
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
185
185
  -y, --yes Skip confirmation prompts
186
186
 
187
187
  `+B.cyan(`Examples:`)+`
@@ -195,7 +195,7 @@ ${r.result}
195
195
  task-master use-tag <tagName> [options]
196
196
 
197
197
  `+B.cyan(`Options:`)+`
198
- -f, --file <file> Path to the tasks file (default: "`+a+`")
198
+ -f, --file <file> Path to the tasks file (default: "`+i+`")
199
199
 
200
200
  `+B.cyan(`Examples:`)+`
201
201
  task-master use-tag feature-xyz
@@ -226,7 +226,7 @@ ${r.result}
226
226
  task-master research "How should I implement user authentication?"
227
227
  task-master research "What's the best approach?" --id=15,23.2
228
228
  task-master research "How does auth work?" --files=src/auth.js --tree
229
- task-master research "Implementation steps?" --save-to=15.2 --detail=high`,{padding:1,borderColor:`blue`,borderStyle:`round`}))}return n.command(`remove-task`).description(`Remove one or more tasks or subtasks permanently`).option(`-i, --id <ids>`,`ID(s) of the task(s) or subtask(s) to remove (e.g., "5", "5.2", or "5,6.1,7")`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-y, --yes`,`Skip confirmation prompt`,!1).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=t.getCurrentTag();await k(r),n||(console.error(B.red(`Error: Task ID(s) are required`)),console.error(B.yellow(`Usage: task-master remove-task --id=<taskId1,taskId2...>`)),process.exit(1));let i=n.split(`,`).map(e=>e.trim()).filter(Boolean);i.length===0&&(console.error(B.red(`Error: No valid task IDs provided.`)),process.exit(1));try{let n=t.getTasksPath(),a=d(n,t.getProjectRoot(),r);(!a||!a.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${n}`)),process.exit(1));let o=[],s=[],c=0,l=[];for(let e of i)if(!ae(a.tasks,e))s.push(e);else{let t=h(a.tasks,e).task;if(t){if(o.push({id:e,task:t}),!t.isSubtask){t.subtasks&&t.subtasks.length>0&&(c+=t.subtasks.length);let n=a.tasks.filter(t=>t.dependencies&&t.dependencies.includes(parseInt(e,10)));n.length>0&&l.push(` - Task ${e}: ${n.length} dependent tasks (${n.map(e=>e.id).join(`, `)})`)}}else s.push(`${e} (error finding details)`)}if(s.length>0&&console.warn(B.yellow(`Warning: The following task IDs were not found: ${s.join(`, `)}`)),o.length===0&&(console.log(B.blue(`No existing tasks found to remove.`)),process.exit(0)),!e.yes){console.log(),console.log(B.red.bold(`⚠️ WARNING: This will permanently delete the following ${o.length} item(s):`)),console.log(),o.forEach(({id:e,task:t})=>{t&&(t.isSubtask?(console.log(B.white(` Subtask ${e}: ${t.title||`(no title)`}`)),t.parentTask&&console.log(B.gray(` (Parent: ${t.parentTask.id} - ${t.parentTask.title||`(no title)`})`))):console.log(B.white.bold(` Task ${e}: ${t.title||`(no title)`}`)))}),c>0&&console.log(B.yellow(`⚠️ This will also delete ${c} subtasks associated with the selected main tasks!`)),l.length>0&&(console.log(B.yellow(`⚠️ Warning: Dependencies on the following tasks will be removed:`)),l.forEach(e=>console.log(B.yellow(e)))),console.log();let{confirm:e}=await W.prompt([{type:`confirm`,name:`confirm`,message:B.red.bold(`Are you sure you want to permanently delete these ${o.length} item(s)?`),default:!1}]);e||(console.log(B.blue(`Task deletion cancelled.`)),process.exit(0))}let u=qe(`Removing ${o.length} task(s)/subtask(s)...`),f=o.map(({id:e})=>e).join(`,`),p=await Oe(t.getTasksPath(),f,{projectRoot:t.getProjectRoot(),tag:r});_e(u),p.success?console.log(U(B.green(`Successfully removed ${p.removedTasks.length} task(s)/subtask(s).`)+(p.message?`\n\nDetails:\n${p.message}`:``)+(p.error?`\n\nWarnings:\n${B.yellow(p.error)}`:``),{padding:1,borderColor:`green`,borderStyle:`round`})):(console.error(U(B.red(`Operation completed with errors. Removed ${p.removedTasks.length} task(s)/subtask(s).`)+(p.message?`\n\nDetails:\n${p.message}`:``)+(p.error?`\n\nErrors:\n${B.red(p.error)}`:``),{padding:1,borderColor:`red`,borderStyle:`round`})),process.exit(1)),s.length>0&&(console.warn(B.yellow(`Note: The following IDs were not found initially and were skipped: ${s.join(`, `)}`)),p.removedTasks.length===0&&process.exit(1))}catch(e){console.error(B.red(`Error: ${e.message||`An unknown error occurred`}`)),process.exit(1)}}),n.command(`init`).description(`Initialize a new project with Task Master structure`).option(`-y, --yes`,`Skip prompts and use default values`).option(`-n, --name <name>`,`Project name`).option(`-d, --description <description>`,`Project description`).option(`-v, --version <version>`,`Project version`,`0.1.0`).option(`-a, --author <author>`,`Author name`).option(`-r, --rules <rules...>`,`List of rules to add (roo, windsurf, cursor, ...). Accepts comma or space separated values.`).option(`--skip-install`,`Skip installing dependencies`).option(`--dry-run`,`Show what would be done without making changes`).option(`--aliases`,`Add shell aliases (tm, taskmaster, hamster, ham)`).option(`--no-aliases`,`Skip shell aliases (tm, taskmaster, hamster, ham)`).option(`--git`,`Initialize Git repository`).option(`--no-git`,`Skip Git repository initialization`).option(`--git-tasks`,`Store tasks in Git`).option(`--no-git-tasks`,`No Git storage of tasks`).action(async e=>{let t=z,n=!1;if(e.rules&&Array.isArray(e.rules)){let r=e.rules.flatMap(e=>e.split(`,`)).map(e=>e.trim()).filter(Boolean);r.length>0&&(t=r,n=!0)}e.rules=t,e.rulesExplicitlyProvided=n;try{await et(e)}catch(e){console.error(B.red(`Error during initialization: ${e.message}`)),process.exit(1)}}),n.command(`models`).description(`Manage AI model configurations`).option(`--set-main <model_id>`,`Set the primary model for task generation/updates`).option(`--set-research <model_id>`,`Set the model for research-backed operations`).option(`--set-fallback <model_id>`,`Set the model to use if the primary fails`).option(`--setup`,`Run interactive setup to configure models`).option(`--openrouter`,`Allow setting a custom OpenRouter model ID (use with --set-*) `).option(`--ollama`,`Allow setting a custom Ollama model ID (use with --set-*) `).option(`--bedrock`,`Allow setting a custom Bedrock model ID (use with --set-*) `).option(`--claude-code`,`Allow setting a Claude Code model ID (use with --set-*)`).option(`--azure`,`Allow setting a custom Azure OpenAI model ID (use with --set-*) `).option(`--vertex`,`Allow setting a custom Vertex AI model ID (use with --set-*) `).option(`--gemini-cli`,`Allow setting a Gemini CLI model ID (use with --set-*)`).option(`--codex-cli`,`Allow setting a Codex CLI model ID (use with --set-*)`).option(`--lmstudio`,`Allow setting a custom LM Studio model ID (use with --set-*)`).option(`--openai-compatible`,`Allow setting a custom OpenAI-compatible model ID (use with --set-*)`).option(`--baseURL <url>`,`Custom base URL for openai-compatible, lmstudio, or ollama providers (e.g., http://localhost:8000/v1)`).addHelpText(`after`,`
229
+ task-master research "Implementation steps?" --save-to=15.2 --detail=high`,{padding:1,borderColor:`blue`,borderStyle:`round`}))}return t.command(`remove-task`).description(`Remove one or more tasks or subtasks permanently`).option(`-i, --id <ids>`,`ID(s) of the task(s) or subtask(s) to remove (e.g., "5", "5.2", or "5,6.1,7")`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-y, --yes`,`Skip confirmation prompt`,!1).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.id,r=t.getCurrentTag();await k(r),n||(console.error(B.red(`Error: Task ID(s) are required`)),console.error(B.yellow(`Usage: task-master remove-task --id=<taskId1,taskId2...>`)),process.exit(1));let i=n.split(`,`).map(e=>e.trim()).filter(Boolean);i.length===0&&(console.error(B.red(`Error: No valid task IDs provided.`)),process.exit(1));try{let n=t.getTasksPath(),a=d(n,t.getProjectRoot(),r);(!a||!a.tasks)&&(console.error(B.red(`Error: No valid tasks found in ${n}`)),process.exit(1));let o=[],s=[],c=0,l=[];for(let e of i)if(!ae(a.tasks,e))s.push(e);else{let t=h(a.tasks,e).task;if(t){if(o.push({id:e,task:t}),!t.isSubtask){t.subtasks&&t.subtasks.length>0&&(c+=t.subtasks.length);let n=a.tasks.filter(t=>t.dependencies&&t.dependencies.includes(parseInt(e,10)));n.length>0&&l.push(` - Task ${e}: ${n.length} dependent tasks (${n.map(e=>e.id).join(`, `)})`)}}else s.push(`${e} (error finding details)`)}if(s.length>0&&console.warn(B.yellow(`Warning: The following task IDs were not found: ${s.join(`, `)}`)),o.length===0&&(console.log(B.blue(`No existing tasks found to remove.`)),process.exit(0)),!e.yes){console.log(),console.log(B.red.bold(`⚠️ WARNING: This will permanently delete the following ${o.length} item(s):`)),console.log(),o.forEach(({id:e,task:t})=>{t&&(t.isSubtask?(console.log(B.white(` Subtask ${e}: ${t.title||`(no title)`}`)),t.parentTask&&console.log(B.gray(` (Parent: ${t.parentTask.id} - ${t.parentTask.title||`(no title)`})`))):console.log(B.white.bold(` Task ${e}: ${t.title||`(no title)`}`)))}),c>0&&console.log(B.yellow(`⚠️ This will also delete ${c} subtasks associated with the selected main tasks!`)),l.length>0&&(console.log(B.yellow(`⚠️ Warning: Dependencies on the following tasks will be removed:`)),l.forEach(e=>console.log(B.yellow(e)))),console.log();let{confirm:e}=await W.prompt([{type:`confirm`,name:`confirm`,message:B.red.bold(`Are you sure you want to permanently delete these ${o.length} item(s)?`),default:!1}]);e||(console.log(B.blue(`Task deletion cancelled.`)),process.exit(0))}let u=qe(`Removing ${o.length} task(s)/subtask(s)...`),f=o.map(({id:e})=>e).join(`,`),p=await Oe(t.getTasksPath(),f,{projectRoot:t.getProjectRoot(),tag:r});_e(u),p.success?console.log(U(B.green(`Successfully removed ${p.removedTasks.length} task(s)/subtask(s).`)+(p.message?`\n\nDetails:\n${p.message}`:``)+(p.error?`\n\nWarnings:\n${B.yellow(p.error)}`:``),{padding:1,borderColor:`green`,borderStyle:`round`})):(console.error(U(B.red(`Operation completed with errors. Removed ${p.removedTasks.length} task(s)/subtask(s).`)+(p.message?`\n\nDetails:\n${p.message}`:``)+(p.error?`\n\nErrors:\n${B.red(p.error)}`:``),{padding:1,borderColor:`red`,borderStyle:`round`})),process.exit(1)),s.length>0&&(console.warn(B.yellow(`Note: The following IDs were not found initially and were skipped: ${s.join(`, `)}`)),p.removedTasks.length===0&&process.exit(1))}catch(e){console.error(B.red(`Error: ${e.message||`An unknown error occurred`}`)),process.exit(1)}}),t.command(`init`).description(`Initialize a new project with Task Master structure`).option(`-y, --yes`,`Skip prompts and use default values`).option(`-n, --name <name>`,`Project name`).option(`-d, --description <description>`,`Project description`).option(`-v, --version <version>`,`Project version`,`0.1.0`).option(`-a, --author <author>`,`Author name`).option(`-r, --rules <rules...>`,`List of rules to add (roo, windsurf, cursor, ...). Accepts comma or space separated values.`).option(`--skip-install`,`Skip installing dependencies`).option(`--dry-run`,`Show what would be done without making changes`).option(`--aliases`,`Add shell aliases (tm, taskmaster, hamster, ham)`).option(`--no-aliases`,`Skip shell aliases (tm, taskmaster, hamster, ham)`).option(`--git`,`Initialize Git repository`).option(`--no-git`,`Skip Git repository initialization`).option(`--git-tasks`,`Store tasks in Git`).option(`--no-git-tasks`,`No Git storage of tasks`).action(async e=>{let t=z,n=!1;if(e.rules&&Array.isArray(e.rules)){let r=e.rules.flatMap(e=>e.split(`,`)).map(e=>e.trim()).filter(Boolean);r.length>0&&(t=r,n=!0)}e.rules=t,e.rulesExplicitlyProvided=n;try{await et(e)}catch(e){console.error(B.red(`Error during initialization: ${e.message}`)),process.exit(1)}}),t.command(`models`).description(`Manage AI model configurations`).option(`--set-main <model_id>`,`Set the primary model for task generation/updates`).option(`--set-research <model_id>`,`Set the model for research-backed operations`).option(`--set-fallback <model_id>`,`Set the model to use if the primary fails`).option(`--setup`,`Run interactive setup to configure models`).option(`--openrouter`,`Allow setting a custom OpenRouter model ID (use with --set-*) `).option(`--ollama`,`Allow setting a custom Ollama model ID (use with --set-*) `).option(`--bedrock`,`Allow setting a custom Bedrock model ID (use with --set-*) `).option(`--claude-code`,`Allow setting a Claude Code model ID (use with --set-*)`).option(`--azure`,`Allow setting a custom Azure OpenAI model ID (use with --set-*) `).option(`--vertex`,`Allow setting a custom Vertex AI model ID (use with --set-*) `).option(`--gemini-cli`,`Allow setting a Gemini CLI model ID (use with --set-*)`).option(`--codex-cli`,`Allow setting a Codex CLI model ID (use with --set-*)`).option(`--lmstudio`,`Allow setting a custom LM Studio model ID (use with --set-*)`).option(`--openai-compatible`,`Allow setting a custom OpenAI-compatible model ID (use with --set-*)`).option(`--baseURL <url>`,`Custom base URL for openai-compatible, lmstudio, or ollama providers (e.g., http://localhost:8000/v1)`).addHelpText(`after`,`
230
230
  Examples:
231
231
  $ task-master models # View current configuration
232
232
  $ task-master models --set-main gpt-4o # Set main model (provider inferred)
@@ -243,9 +243,9 @@ Examples:
243
243
  $ task-master models --set-main qwen3-vl-4b --lmstudio # Set LM Studio model for main role (defaults to http://localhost:1234/v1)
244
244
  $ task-master models --set-main qwen3-vl-4b --lmstudio --baseURL http://localhost:8000/v1 # Set LM Studio model with custom base URL
245
245
  $ task-master models --set-main my-model --openai-compatible --baseURL http://localhost:8000/v1 # Set custom OpenAI-compatible model with custom endpoint
246
- $ task-master models --setup # Run interactive setup`).action(async e=>{let n=J({tasksPath:e.file||!1}),r=n.getProjectRoot();[e.openrouter,e.ollama,e.bedrock,e.claudeCode,e.geminiCli,e.codexCli,e.lmstudio,e.openaiCompatible].filter(Boolean).length>1&&(console.error(B.red(`Error: Cannot use multiple provider flags (--openrouter, --ollama, --bedrock, --claude-code, --gemini-cli, --codex-cli, --lmstudio, --openai-compatible) simultaneously.`)),process.exit(1));let i=e.setup,a=e.setMain||e.setResearch||e.setFallback;if(i){console.log(B.blue(`Starting interactive model setup...`));try{await Be(n.getProjectRoot())}catch(e){console.error(B.red(`\\nInteractive setup failed unexpectedly:`),e.message)}return}if(a){let t=!1;if(e.setMain){let n=await O(`main`,e.setMain,{projectRoot:r,providerHint:e.openrouter?`openrouter`:e.ollama?`ollama`:e.bedrock?`bedrock`:e.claudeCode?`claude-code`:e.geminiCli?`gemini-cli`:e.codexCli?`codex-cli`:e.lmstudio?`lmstudio`:e.openaiCompatible?`openai-compatible`:void 0,baseURL:e.baseURL});n.success?(console.log(B.green(`✅ ${n.data.message}`)),n.data.warning&&console.log(B.yellow(n.data.warning)),t=!0):console.error(B.red(`❌ Error setting main model: ${n.error.message}`))}if(e.setResearch){let n=await O(`research`,e.setResearch,{projectRoot:r,providerHint:e.openrouter?`openrouter`:e.ollama?`ollama`:e.bedrock?`bedrock`:e.claudeCode?`claude-code`:e.geminiCli?`gemini-cli`:e.codexCli?`codex-cli`:e.lmstudio?`lmstudio`:e.openaiCompatible?`openai-compatible`:void 0,baseURL:e.baseURL});n.success?(console.log(B.green(`✅ ${n.data.message}`)),n.data.warning&&console.log(B.yellow(n.data.warning)),t=!0):console.error(B.red(`❌ Error setting research model: ${n.error.message}`))}if(e.setFallback){let n=await O(`fallback`,e.setFallback,{projectRoot:r,providerHint:e.openrouter?`openrouter`:e.ollama?`ollama`:e.bedrock?`bedrock`:e.claudeCode?`claude-code`:e.geminiCli?`gemini-cli`:e.codexCli?`codex-cli`:e.lmstudio?`lmstudio`:e.openaiCompatible?`openai-compatible`:void 0,baseURL:e.baseURL});n.success?(console.log(B.green(`✅ ${n.data.message}`)),n.data.warning&&console.log(B.yellow(n.data.warning)),t=!0):console.error(B.red(`❌ Error setting fallback model: ${n.error.message}`))}t?console.log(B.blue(`
246
+ $ task-master models --setup # Run interactive setup`).action(async t=>{let n=J({tasksPath:t.file||!1}),r=n.getProjectRoot();[t.openrouter,t.ollama,t.bedrock,t.claudeCode,t.geminiCli,t.codexCli,t.lmstudio,t.openaiCompatible].filter(Boolean).length>1&&(console.error(B.red(`Error: Cannot use multiple provider flags (--openrouter, --ollama, --bedrock, --claude-code, --gemini-cli, --codex-cli, --lmstudio, --openai-compatible) simultaneously.`)),process.exit(1));let i=t.setup,a=t.setMain||t.setResearch||t.setFallback;if(i){console.log(B.blue(`Starting interactive model setup...`));try{await Be(n.getProjectRoot())}catch(e){console.error(B.red(`\\nInteractive setup failed unexpectedly:`),e.message)}return}if(a){let e=!1;if(t.setMain){let n=await O(`main`,t.setMain,{projectRoot:r,providerHint:t.openrouter?`openrouter`:t.ollama?`ollama`:t.bedrock?`bedrock`:t.claudeCode?`claude-code`:t.geminiCli?`gemini-cli`:t.codexCli?`codex-cli`:t.lmstudio?`lmstudio`:t.openaiCompatible?`openai-compatible`:void 0,baseURL:t.baseURL});n.success?(console.log(B.green(`✅ ${n.data.message}`)),n.data.warning&&console.log(B.yellow(n.data.warning)),e=!0):console.error(B.red(`❌ Error setting main model: ${n.error.message}`))}if(t.setResearch){let n=await O(`research`,t.setResearch,{projectRoot:r,providerHint:t.openrouter?`openrouter`:t.ollama?`ollama`:t.bedrock?`bedrock`:t.claudeCode?`claude-code`:t.geminiCli?`gemini-cli`:t.codexCli?`codex-cli`:t.lmstudio?`lmstudio`:t.openaiCompatible?`openai-compatible`:void 0,baseURL:t.baseURL});n.success?(console.log(B.green(`✅ ${n.data.message}`)),n.data.warning&&console.log(B.yellow(n.data.warning)),e=!0):console.error(B.red(`❌ Error setting research model: ${n.error.message}`))}if(t.setFallback){let n=await O(`fallback`,t.setFallback,{projectRoot:r,providerHint:t.openrouter?`openrouter`:t.ollama?`ollama`:t.bedrock?`bedrock`:t.claudeCode?`claude-code`:t.geminiCli?`gemini-cli`:t.codexCli?`codex-cli`:t.lmstudio?`lmstudio`:t.openaiCompatible?`openai-compatible`:void 0,baseURL:t.baseURL});n.success?(console.log(B.green(`✅ ${n.data.message}`)),n.data.warning&&console.log(B.yellow(n.data.warning)),e=!0):console.error(B.red(`❌ Error setting fallback model: ${n.error.message}`))}e?console.log(B.blue(`
247
247
  Model configuration updated.`)):console.log(B.yellow(`
248
- No model configuration changes were made (or errors occurred).`));return}console.log(B.blue(`Fetching current model configuration...`));let o=await De({projectRoot:r}),s=await Ie({projectRoot:r}),c=await Me({projectRoot:r});if(o.success?we(o.data,s.data?.models||[]):console.error(B.red(`❌ Error fetching configuration: ${o.error.message}`)),c.success?Ne(c.data.report):console.error(B.yellow(`⚠️ Warning: Could not display API Key status: ${c.error.message}`)),s.success){let e=o.success?[o.data.activeModels.main.modelId,o.data.activeModels.research.modelId,o.data.activeModels.fallback?.modelId].filter(Boolean):[];ye(s.data.models.filter(t=>!e.includes(t.modelId)&&!t.modelId.startsWith(`[`)))}else console.error(B.yellow(`⚠️ Warning: Could not display available models: ${s.error.message}`));t(r)||console.log(B.yellow(`\\nHint: Run 'task-master models --setup' to create or update your configuration.`))}),n.command(`lang`).description(`Manage response language settings`).option(`--response <response_language>`,`Set the response language`).option(`--setup`,`Run interactive setup to configure response language`).action(async e=>{let t=J({}).getProjectRoot(),{response:n,setup:r}=e,i=n===void 0?`English`:n;if(r){console.log(B.blue(`Starting interactive response language setup...`));try{let e=await W.prompt([{type:`input`,name:`responseLanguage`,message:`Input your preferred response language`,default:`English`}]);console.log(B.blue(`Response language set to:`,e.responseLanguage)),i=e.responseLanguage}catch(e){console.error(B.red(`\\nInteractive setup failed unexpectedly:`),e.message)}}let a=Ye(i,{projectRoot:t});a.success?console.log(B.green(`✅ ${a.data.message}`)):(console.error(B.red(`❌ Error setting response language: ${a.error.message}`)),process.exit(1))}),n.command(`move`).description(`Move tasks between tags or reorder within tags. Supports cross-tag moves with dependency resolution options.`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--from <id>`,`ID of the task/subtask to move (e.g., "5" or "5.2"). Can be comma-separated to move multiple tasks (e.g., "5,6,7")`).option(`--to <id>`,`ID of the destination (e.g., "7" or "7.3"). Must match the number of source IDs if comma-separated`).option(`--tag <tag>`,`Specify tag context for task operations`).option(`--from-tag <tag>`,`Source tag for cross-tag moves`).option(`--to-tag <tag>`,`Target tag for cross-tag moves`).option(`--with-dependencies`,`Move dependent tasks along with main task`).option(`--ignore-dependencies`,`Break cross-tag dependencies during move`).action(async e=>{function t(){console.log(B.white.bold(`Move Command Help`)+`
248
+ No model configuration changes were made (or errors occurred).`));return}console.log(B.blue(`Fetching current model configuration...`));let o=await De({projectRoot:r}),s=await Ie({projectRoot:r}),c=await Me({projectRoot:r});if(o.success?we(o.data,s.data?.models||[]):console.error(B.red(`❌ Error fetching configuration: ${o.error.message}`)),c.success?Ne(c.data.report):console.error(B.yellow(`⚠️ Warning: Could not display API Key status: ${c.error.message}`)),s.success){let e=o.success?[o.data.activeModels.main.modelId,o.data.activeModels.research.modelId,o.data.activeModels.fallback?.modelId].filter(Boolean):[];ye(s.data.models.filter(t=>!e.includes(t.modelId)&&!t.modelId.startsWith(`[`)))}else console.error(B.yellow(`⚠️ Warning: Could not display available models: ${s.error.message}`));e(r)||console.log(B.yellow(`\\nHint: Run 'task-master models --setup' to create or update your configuration.`))}),t.command(`lang`).description(`Manage response language settings`).option(`--response <response_language>`,`Set the response language`).option(`--setup`,`Run interactive setup to configure response language`).action(async e=>{let t=J({}).getProjectRoot(),{response:n,setup:r}=e,i=n===void 0?`English`:n;if(r){console.log(B.blue(`Starting interactive response language setup...`));try{let e=await W.prompt([{type:`input`,name:`responseLanguage`,message:`Input your preferred response language`,default:`English`}]);console.log(B.blue(`Response language set to:`,e.responseLanguage)),i=e.responseLanguage}catch(e){console.error(B.red(`\\nInteractive setup failed unexpectedly:`),e.message)}}let a=Ye(i,{projectRoot:t});a.success?console.log(B.green(`✅ ${a.data.message}`)):(console.error(B.red(`❌ Error setting response language: ${a.error.message}`)),process.exit(1))}),t.command(`move`).description(`Move tasks between tags or reorder within tags. Supports cross-tag moves with dependency resolution options.`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--from <id>`,`ID of the task/subtask to move (e.g., "5" or "5.2"). Can be comma-separated to move multiple tasks (e.g., "5,6,7")`).option(`--to <id>`,`ID of the destination (e.g., "7" or "7.3"). Must match the number of source IDs if comma-separated`).option(`--tag <tag>`,`Specify tag context for task operations`).option(`--from-tag <tag>`,`Source tag for cross-tag moves`).option(`--to-tag <tag>`,`Target tag for cross-tag moves`).option(`--with-dependencies`,`Move dependent tasks along with main task`).option(`--ignore-dependencies`,`Break cross-tag dependencies during move`).action(async e=>{function t(){console.log(B.white.bold(`Move Command Help`)+`
249
249
 
250
250
  `+B.cyan(`Move tasks between tags or reorder within tags.`)+`
251
251
 
@@ -287,13 +287,13 @@ Note: Some tasks were moved successfully. Check the errors above for failed move
287
287
  `+B.yellow.bold(`Conflict: ID already exists in target tag`)+`
288
288
  `+B.white(` • Choose a different target tag without conflicting IDs`)+`
289
289
  `+B.white(` • Move a different set of IDs (avoid existing ones)`)+`
290
- `+B.white(` • If needed, move within-tag to a new ID first, then cross-tag move`)),process.exit(1)),i(e,m)}}),n.command(`rules [action] [profiles...]`).description(`Add or remove rules for one or more profiles. Valid actions: ${Object.values(P).join(`, `)} (e.g., task-master rules ${P.ADD} windsurf roo)`).option(`-f, --force`,`Skip confirmation prompt when removing rules (dangerous)`).option(`--${R}`,`Run interactive setup to select rule profiles to add`).option(`-m, --mode <mode>`,`Operating mode for filtering rules/commands (solo or team). Auto-detected from config if not specified.`).option(`-y, --yes`,`Non-interactive mode: auto-detect IDEs and install rules without prompting`).addHelpText(`after`,`
290
+ `+B.white(` • If needed, move within-tag to a new ID first, then cross-tag move`)),process.exit(1)),i(e,m)}}),t.command(`rules [action] [profiles...]`).description(`Add or remove rules for one or more profiles. Valid actions: ${Object.values(P).join(`, `)} (e.g., task-master rules ${P.ADD} windsurf roo)`).option(`-f, --force`,`Skip confirmation prompt when removing rules (dangerous)`).option(`--${R}`,`Run interactive setup to select rule profiles to add`).option(`-m, --mode <mode>`,`Operating mode for filtering rules/commands (solo or team). Auto-detected from config if not specified.`).option(`-y, --yes`,`Non-interactive mode: auto-detect IDEs and install rules without prompting`).addHelpText(`after`,`
291
291
  Examples:
292
292
  $ task-master rules ${P.ADD} # Interactive setup with auto-detected IDEs pre-selected
293
293
  $ task-master rules ${P.ADD} -y # Auto-detect and install without prompting
294
294
  $ task-master rules ${P.ADD} windsurf roo # Add specific profiles
295
295
  $ task-master rules ${P.ADD} cursor --mode=team # Add Cursor rules for team mode only
296
- $ task-master rules ${P.REMOVE} windsurf # Remove Windsurf rule set`).action(async(e,t,n)=>{let i=J({}).getProjectRoot();if(i||(console.error(B.red(`Error: Could not find project root.`)),process.exit(1)),n[R]){let e=await I(i);if(!e||e.length===0){console.log(B.yellow(`No profiles selected. Exiting.`));return}console.log(B.blue(`Installing ${e.length} selected profile(s)...`)),await F(e,i,n.mode),console.log(B.green(`\nCompleted installation of all ${e.length} profile(s).`));return}if((!e||!$e(e))&&(console.error(B.red(`Error: Invalid or missing action '${e||`none`}'. Valid actions are: ${Object.values(P).join(`, `)}`)),console.error(B.yellow(`For interactive setup, use: task-master rules --${R}`)),process.exit(1)),e===P.ADD&&(!t||t.length===0)){let e;if(n.yes){console.log(B.blue(`
296
+ $ task-master rules ${P.REMOVE} windsurf # Remove Windsurf rule set`).action(async(e,t,r)=>{let i=J({}).getProjectRoot();if(i||(console.error(B.red(`Error: Could not find project root.`)),process.exit(1)),r[R]){let e=await I(i);if(!e||e.length===0){console.log(B.yellow(`No profiles selected. Exiting.`));return}console.log(B.blue(`Installing ${e.length} selected profile(s)...`)),await F(e,i,r.mode),console.log(B.green(`\nCompleted installation of all ${e.length} profile(s).`));return}if((!e||!$e(e))&&(console.error(B.red(`Error: Invalid or missing action '${e||`none`}'. Valid actions are: ${Object.values(P).join(`, `)}`)),console.error(B.yellow(`For interactive setup, use: task-master rules --${R}`)),process.exit(1)),e===P.ADD&&(!t||t.length===0)){let e;if(r.yes){console.log(B.blue(`
297
297
  🔍 Auto-detecting installed IDEs...
298
298
  `));let t=Xe({projectRoot:i});if(t.length===0){console.log(B.yellow(`No IDE markers detected in this project.
299
299
  `+B.gray(`Searched for: .cursor, .claude, .windsurf, .roo, .vscode, etc.
@@ -303,14 +303,14 @@ Note: Some tasks were moved successfully. Check the errors above for failed move
303
303
  Or specify profiles directly:
304
304
  task-master rules add cursor windsurf
305
305
  `));return}console.log(B.green(`✓ Detected the following IDEs:
306
- `));for(let e of t)console.log(` • ${e.displayName} ${B.gray(`(${e.markerPath})`)}`);console.log(``),e=t.map(e=>e.profileName)}else e=await I(i);if(!e||e.length===0){console.log(B.yellow(`No profiles selected. Exiting.`));return}console.log(B.blue(`Installing ${e.length} selected profile(s)...`));let{allSuccessfulProfiles:t,totalSuccess:r,totalFailed:a}=L(await F(e,i,n.mode));console.log(B.green(`\n✓ Successfully installed ${t.length} profile(s)`)),r>0&&console.log(B.gray(` ${r} files processed, ${a} failed`));return}(!t||t.length===0)&&(console.error(`Please specify at least one rule profile (e.g., windsurf, roo).`),process.exit(1));let a=t.flatMap(e=>e.split(`,`).map(e=>e.trim())).filter(Boolean);if(e===P.REMOVE){let e=!0;if(n.force||(e=Qe(i,a)?await gt(a,Ze(i)):await ht(a)),!e){console.log(B.yellow(`Aborted: No rules were removed.`));return}}let o=[],s=[];for(let t of a){if(!nt(t)){console.warn(`Rule profile for "${t}" not found. Valid profiles: ${z.join(`, `)}. Skipping.`);continue}let a=it(t);if(e===P.ADD){console.log(B.blue(`Adding rules for profile: ${t}...`));let e=ot(i,a,{mode:await r(n.mode)});console.log(B.blue(`Completed adding rules for profile: ${t}`)),s.push({profileName:t,success:e.success,failed:e.failed}),console.log(B.green(rt(t,e)))}else if(e===P.REMOVE){console.log(B.blue(`Removing rules for profile: ${t}...`));let e=tt(i,a);o.push(e),console.log(B.green(st(t,e)))}else console.error(`Unknown action. Use "${P.ADD}" or "${P.REMOVE}".`),process.exit(1)}if(e===P.ADD&&s.length>0){let{allSuccessfulProfiles:e,totalSuccess:t,totalFailed:n}=L(s);e.length>0&&(console.log(B.green(`\nSuccessfully processed profiles: ${e.join(`, `)}`)),t>0?console.log(B.green(`Total: ${t} files processed, ${n} failed.`)):console.log(B.green(`Total: ${e.length} profile(s) set up successfully.`)))}if(e===P.REMOVE&&o.length>0){let{successfulRemovals:e,skippedRemovals:t,failedRemovals:n,removalsWithNotices:r}=at(o);e.length>0&&console.log(B.green(`\nSuccessfully removed profiles for: ${e.join(`, `)}`)),t.length>0&&console.log(B.yellow(`Skipped (default or protected): ${t.join(`, `)}`)),n.length>0&&(console.log(B.red(`
306
+ `));for(let e of t)console.log(` • ${e.displayName} ${B.gray(`(${e.markerPath})`)}`);console.log(``),e=t.map(e=>e.profileName)}else e=await I(i);if(!e||e.length===0){console.log(B.yellow(`No profiles selected. Exiting.`));return}console.log(B.blue(`Installing ${e.length} selected profile(s)...`));let{allSuccessfulProfiles:t,totalSuccess:n,totalFailed:a}=L(await F(e,i,r.mode));console.log(B.green(`\n✓ Successfully installed ${t.length} profile(s)`)),n>0&&console.log(B.gray(` ${n} files processed, ${a} failed`));return}(!t||t.length===0)&&(console.error(`Please specify at least one rule profile (e.g., windsurf, roo).`),process.exit(1));let a=t.flatMap(e=>e.split(`,`).map(e=>e.trim())).filter(Boolean);if(e===P.REMOVE){let e=!0;if(r.force||(e=Qe(i,a)?await gt(a,Ze(i)):await ht(a)),!e){console.log(B.yellow(`Aborted: No rules were removed.`));return}}let o=[],s=[];for(let t of a){if(!nt(t)){console.warn(`Rule profile for "${t}" not found. Valid profiles: ${z.join(`, `)}. Skipping.`);continue}let a=it(t);if(e===P.ADD){console.log(B.blue(`Adding rules for profile: ${t}...`));let e=ot(i,a,{mode:await n(r.mode)});console.log(B.blue(`Completed adding rules for profile: ${t}`)),s.push({profileName:t,success:e.success,failed:e.failed}),console.log(B.green(rt(t,e)))}else if(e===P.REMOVE){console.log(B.blue(`Removing rules for profile: ${t}...`));let e=tt(i,a);o.push(e),console.log(B.green(st(t,e)))}else console.error(`Unknown action. Use "${P.ADD}" or "${P.REMOVE}".`),process.exit(1)}if(e===P.ADD&&s.length>0){let{allSuccessfulProfiles:e,totalSuccess:t,totalFailed:n}=L(s);e.length>0&&(console.log(B.green(`\nSuccessfully processed profiles: ${e.join(`, `)}`)),t>0?console.log(B.green(`Total: ${t} files processed, ${n} failed.`)):console.log(B.green(`Total: ${e.length} profile(s) set up successfully.`)))}if(e===P.REMOVE&&o.length>0){let{successfulRemovals:e,skippedRemovals:t,failedRemovals:n,removalsWithNotices:r}=at(o);e.length>0&&console.log(B.green(`\nSuccessfully removed profiles for: ${e.join(`, `)}`)),t.length>0&&console.log(B.yellow(`Skipped (default or protected): ${t.join(`, `)}`)),n.length>0&&(console.log(B.red(`
307
307
  Errors occurred:`)),n.forEach(e=>{console.log(B.red(` ${e.profileName}: ${e.error}`))})),r.length>0&&(console.log(B.cyan(`
308
- Notices:`)),r.forEach(e=>{console.log(B.cyan(` ${e.profileName}: ${e.notice}`))}));let i=o.length,a=e.length,s=t.length,c=n.length;console.log(B.blue(`\nTotal: ${i} profile(s) processed - ${a} removed, ${s} skipped, ${c} failed.`))}}),n.command(`migrate`).description(`Migrate existing project to use the new .taskmaster directory structure`).option(`-f, --force`,`Force migration even if .taskmaster directory already exists`).option(`--backup`,`Create backup of old files before migration (default: false)`,!1).option(`--cleanup`,`Remove old files after successful migration (default: true)`,!0).option(`-y, --yes`,`Skip confirmation prompts`).option(`--dry-run`,`Show what would be migrated without actually moving files`).action(async e=>{try{await ie(e)}catch(e){console.error(B.red(`Error during migration:`),e.message),process.exit(1)}}),n.command(`sync-readme`).description(`Sync the current task list to README.md in the project root`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--with-subtasks`,`Include subtasks in the README output`).option(`-s, --status <status>`,`Show only tasks matching this status (e.g., pending, done)`).option(`-t, --tag <tag>`,`Tag to use for the task list (default: master)`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.withSubtasks||!1,r=e.status||null,i=t.getCurrentTag();console.log(B.blue(`📝 Syncing tasks to README.md${n?` (with subtasks)`:``}${r?` (status: ${r})`:``}...`)),await syncTasksToReadme(t.getProjectRoot(),{withSubtasks:n,status:r,tasksPath:t.getTasksPath(),tag:i})||(console.error(B.red(`❌ Failed to sync tasks to README.md`)),process.exit(1))}),n.command(`add-tag`).description(`[DEPRECATED] Create a new tag context for organizing tasks (use "tm tags add" instead)`).argument(`[tagName]`,`Name of the new tag to create (optional when using --from-branch)`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--copy-from-current`,`Copy tasks from the current tag to the new tag`).option(`--copy-from <tag>`,`Copy tasks from the specified tag to the new tag`).option(`--from-branch`,`Create tag name from current git branch (ignores tagName argument)`).option(`-d, --description <text>`,`Optional description for the tag`).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm add-tag" is deprecated. Use "tm tags add" instead.`)),console.log(B.gray(` This command will be removed in a future version.
309
- `));try{let n=J({tasksPath:t.file||!0}),r=n.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),console.log(B.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)),process.exit(1)),!e&&!t.fromBranch&&(console.error(B.red(`Error: Either tagName argument or --from-branch option is required.`)),console.log(B.yellow(`Usage examples:`)),console.log(B.cyan(` task-master add-tag my-tag`)),console.log(B.cyan(` task-master add-tag --from-branch`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`add-tag`,outputType:`cli`};if(t.fromBranch){let{createTagFromBranch:e}=await import(`./tag-management-CGTs8N6O.js`),r=await import(`./git-utils-PBP1PRVP.js`);await r.isGitRepository(i.projectRoot)||(console.error(B.red(`Error: Not in a git repository. Cannot use --from-branch option.`)),process.exit(1));let a=await r.getCurrentBranch(i.projectRoot);a||(console.error(B.red(`Error: Could not determine current git branch.`)),process.exit(1));let o={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description||`Tag created from git branch "${a}"`};await e(n.getTasksPath(),a,o,i,`text`)}else{let r={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description};await be(n.getTasksPath(),e,r,i,`text`)}if(t.autoSwitch){let{useTag:r}=await import(`./tag-management-CGTs8N6O.js`),a=t.fromBranch?(await import(`./git-utils-PBP1PRVP.js`)).sanitizeBranchNameForTag(await(await import(`./git-utils-PBP1PRVP.js`)).getCurrentBranch(projectRoot)):e;await r(n.getTasksPath(),a,{},i,`text`)}}catch(e){console.error(B.red(`Error creating tag: ${e.message}`)),u(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),u(),process.exit(1)}),n.command(`delete-tag`).description(`[DEPRECATED] Delete an existing tag and all its tasks (use "tm tags remove" instead)`).argument(`<tagName>`,`Name of the tag to delete`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-y, --yes`,`Skip confirmation prompts`).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm delete-tag" is deprecated. Use "tm tags remove" instead.`)),console.log(B.gray(` This command will be removed in a future version.
310
- `));try{let n=J({tasksPath:t.file||!0}),r=n.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={yes:t.yes||!1},a={projectRoot:n.getProjectRoot(),commandName:`delete-tag`,outputType:`cli`};await He(n.getTasksPath(),e,i,a,`text`)}catch(e){console.error(B.red(`Error deleting tag: ${e.message}`)),f(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),f(),process.exit(1)}),n.command(`use-tag`).description(`[DEPRECATED] Switch to a different tag context (use "tm tags use" instead)`).argument(`<tagName>`,`Name of the tag to switch to`).option(`-f, --file <file>`,`Path to the tasks file`,a).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm use-tag" is deprecated. Use "tm tags use" instead.`)),console.log(B.gray(` This command will be removed in a future version.
311
- `));try{let n=J({tasksPath:t.file||!0}),r=n.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`use-tag`,outputType:`cli`};await Te(n.getTasksPath(),e,{},i,`text`)}catch(e){console.error(B.red(`Error switching tag: ${e.message}`)),p(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),p(),process.exit(1)}),n.command(`rename-tag`).description(`[DEPRECATED] Rename an existing tag (use "tm tags rename" instead)`).argument(`<oldName>`,`Current name of the tag`).argument(`<newName>`,`New name for the tag`).option(`-f, --file <file>`,`Path to the tasks file`,a).action(async(e,t,n)=>{console.warn(B.yellow(`⚠ Warning: "tm rename-tag" is deprecated. Use "tm tags rename" instead.`)),console.log(B.gray(` This command will be removed in a future version.
312
- `));try{let r=J({tasksPath:n.file||!0}),i=r.getTasksPath();V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1));let a={projectRoot:r.getProjectRoot(),commandName:`rename-tag`,outputType:`cli`};await xe(r.getTasksPath(),e,t,{},a,`text`)}catch(e){console.error(B.red(`Error renaming tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),n.command(`copy-tag`).description(`[DEPRECATED] Copy an existing tag to create a new tag with the same tasks (use "tm tags copy" instead)`).argument(`<sourceName>`,`Name of the source tag to copy from`).argument(`<targetName>`,`Name of the new tag to create`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-d, --description <text>`,`Optional description for the new tag`).action(async(e,t,n)=>{console.warn(B.yellow(`⚠ Warning: "tm copy-tag" is deprecated. Use "tm tags copy" instead.`)),console.log(B.gray(` This command will be removed in a future version.
313
- `));try{let r=J({tasksPath:n.file||!0}),i=r.getTasksPath();V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1)),await Re(i,e,t,{description:n.description},{projectRoot:r.getProjectRoot(),commandName:`copy-tag`,outputType:`cli`},`text`)}catch(e){console.error(B.red(`Error copying tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),n.command(`tui`).alias(`repl`).description(`Launch the interactive TUI/REPL mode`).action(async()=>{await $()}),n}async function yt(){return null}async function $(){let e=await import(`react`),t=await yt();if(!t){console.log(B.yellow(`TUI mode coming soon!`)),console.log(B.dim(`Showing help instead...
308
+ Notices:`)),r.forEach(e=>{console.log(B.cyan(` ${e.profileName}: ${e.notice}`))}));let i=o.length,a=e.length,s=t.length,c=n.length;console.log(B.blue(`\nTotal: ${i} profile(s) processed - ${a} removed, ${s} skipped, ${c} failed.`))}}),t.command(`migrate`).description(`Migrate existing project to use the new .taskmaster directory structure`).option(`-f, --force`,`Force migration even if .taskmaster directory already exists`).option(`--backup`,`Create backup of old files before migration (default: false)`,!1).option(`--cleanup`,`Remove old files after successful migration (default: true)`,!0).option(`-y, --yes`,`Skip confirmation prompts`).option(`--dry-run`,`Show what would be migrated without actually moving files`).action(async e=>{try{await ie(e)}catch(e){console.error(B.red(`Error during migration:`),e.message),process.exit(1)}}),t.command(`sync-readme`).description(`Sync the current task list to README.md in the project root`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--with-subtasks`,`Include subtasks in the README output`).option(`-s, --status <status>`,`Show only tasks matching this status (e.g., pending, done)`).option(`-t, --tag <tag>`,`Tag to use for the task list (default: master)`).action(async e=>{let t=J({tasksPath:e.file||!0,tag:e.tag}),n=e.withSubtasks||!1,r=e.status||null,i=t.getCurrentTag();console.log(B.blue(`📝 Syncing tasks to README.md${n?` (with subtasks)`:``}${r?` (status: ${r})`:``}...`)),await syncTasksToReadme(t.getProjectRoot(),{withSubtasks:n,status:r,tasksPath:t.getTasksPath(),tag:i})||(console.error(B.red(`❌ Failed to sync tasks to README.md`)),process.exit(1))}),t.command(`add-tag`).description(`[DEPRECATED] Create a new tag context for organizing tasks (use "tm tags add" instead)`).argument(`[tagName]`,`Name of the new tag to create (optional when using --from-branch)`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`--copy-from-current`,`Copy tasks from the current tag to the new tag`).option(`--copy-from <tag>`,`Copy tasks from the specified tag to the new tag`).option(`--from-branch`,`Create tag name from current git branch (ignores tagName argument)`).option(`-d, --description <text>`,`Optional description for the tag`).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm add-tag" is deprecated. Use "tm tags add" instead.`)),console.log(B.gray(` This command will be removed in a future version.
309
+ `));try{let n=J({tasksPath:t.file||!0}),r=n.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),console.log(B.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)),process.exit(1)),!e&&!t.fromBranch&&(console.error(B.red(`Error: Either tagName argument or --from-branch option is required.`)),console.log(B.yellow(`Usage examples:`)),console.log(B.cyan(` task-master add-tag my-tag`)),console.log(B.cyan(` task-master add-tag --from-branch`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`add-tag`,outputType:`cli`};if(t.fromBranch){let{createTagFromBranch:e}=await import(`./tag-management-DvcGPdM_.js`),r=await import(`./git-utils-PBP1PRVP.js`);await r.isGitRepository(i.projectRoot)||(console.error(B.red(`Error: Not in a git repository. Cannot use --from-branch option.`)),process.exit(1));let a=await r.getCurrentBranch(i.projectRoot);a||(console.error(B.red(`Error: Could not determine current git branch.`)),process.exit(1));let o={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description||`Tag created from git branch "${a}"`};await e(n.getTasksPath(),a,o,i,`text`)}else{let r={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description};await be(n.getTasksPath(),e,r,i,`text`)}if(t.autoSwitch){let{useTag:r}=await import(`./tag-management-DvcGPdM_.js`),a=t.fromBranch?(await import(`./git-utils-PBP1PRVP.js`)).sanitizeBranchNameForTag(await(await import(`./git-utils-PBP1PRVP.js`)).getCurrentBranch(projectRoot)):e;await r(n.getTasksPath(),a,{},i,`text`)}}catch(e){console.error(B.red(`Error creating tag: ${e.message}`)),u(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),u(),process.exit(1)}),t.command(`delete-tag`).description(`[DEPRECATED] Delete an existing tag and all its tasks (use "tm tags remove" instead)`).argument(`<tagName>`,`Name of the tag to delete`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-y, --yes`,`Skip confirmation prompts`).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm delete-tag" is deprecated. Use "tm tags remove" instead.`)),console.log(B.gray(` This command will be removed in a future version.
310
+ `));try{let n=J({tasksPath:t.file||!0}),r=n.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={yes:t.yes||!1},a={projectRoot:n.getProjectRoot(),commandName:`delete-tag`,outputType:`cli`};await He(n.getTasksPath(),e,i,a,`text`)}catch(e){console.error(B.red(`Error deleting tag: ${e.message}`)),f(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),f(),process.exit(1)}),t.command(`use-tag`).description(`[DEPRECATED] Switch to a different tag context (use "tm tags use" instead)`).argument(`<tagName>`,`Name of the tag to switch to`).option(`-f, --file <file>`,`Path to the tasks file`,i).action(async(e,t)=>{console.warn(B.yellow(`⚠ Warning: "tm use-tag" is deprecated. Use "tm tags use" instead.`)),console.log(B.gray(` This command will be removed in a future version.
311
+ `));try{let n=J({tasksPath:t.file||!0}),r=n.getTasksPath();V.existsSync(r)||(console.error(B.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`use-tag`,outputType:`cli`};await Te(n.getTasksPath(),e,{},i,`text`)}catch(e){console.error(B.red(`Error switching tag: ${e.message}`)),p(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),p(),process.exit(1)}),t.command(`rename-tag`).description(`[DEPRECATED] Rename an existing tag (use "tm tags rename" instead)`).argument(`<oldName>`,`Current name of the tag`).argument(`<newName>`,`New name for the tag`).option(`-f, --file <file>`,`Path to the tasks file`,i).action(async(e,t,n)=>{console.warn(B.yellow(`⚠ Warning: "tm rename-tag" is deprecated. Use "tm tags rename" instead.`)),console.log(B.gray(` This command will be removed in a future version.
312
+ `));try{let r=J({tasksPath:n.file||!0}),i=r.getTasksPath();V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1));let a={projectRoot:r.getProjectRoot(),commandName:`rename-tag`,outputType:`cli`};await xe(r.getTasksPath(),e,t,{},a,`text`)}catch(e){console.error(B.red(`Error renaming tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),t.command(`copy-tag`).description(`[DEPRECATED] Copy an existing tag to create a new tag with the same tasks (use "tm tags copy" instead)`).argument(`<sourceName>`,`Name of the source tag to copy from`).argument(`<targetName>`,`Name of the new tag to create`).option(`-f, --file <file>`,`Path to the tasks file`,i).option(`-d, --description <text>`,`Optional description for the new tag`).action(async(e,t,n)=>{console.warn(B.yellow(`⚠ Warning: "tm copy-tag" is deprecated. Use "tm tags copy" instead.`)),console.log(B.gray(` This command will be removed in a future version.
313
+ `));try{let r=J({tasksPath:n.file||!0}),i=r.getTasksPath();V.existsSync(i)||(console.error(B.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1)),await Re(i,e,t,{description:n.description},{projectRoot:r.getProjectRoot(),commandName:`copy-tag`,outputType:`cli`},`text`)}catch(e){console.error(B.red(`Error copying tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),process.exit(1)}),t.command(`tui`).alias(`repl`).description(`Launch the interactive TUI/REPL mode`).action(async()=>{await $()}),t}async function yt(){return null}async function $(){let e=await import(`react`),t=await yt();if(!t){console.log(B.yellow(`TUI mode coming soon!`)),console.log(B.dim(`Showing help instead...
314
314
  `)),Y()?Z():M();return}let{render:n,Shell:r}=t,i=`master`,a=`local`,o,s={isAuthenticated:!1},c=process.cwd();try{let e=J({});i=e.getCurrentTag(),c=e.getProjectRoot()||process.cwd();let t=_.getInstance(),n=t.getContext(),r=t.getStoredContext();r&&r.email&&(s={isAuthenticated:!0,email:r.email,userId:r.userId}),n&&n.briefId&&(a=`api`,o={id:n.briefId,name:n.briefName||i})}catch{}let l=process.stdin.isTTY&&typeof process.stdin.setRawMode==`function`;console.clear();let u={showBanner:!0,showSplash:l,initialTag:i,storageType:a,brief:o,authState:s,isInteractive:l,projectRoot:c,onExit:()=>{console.log(B.dim(`
315
315
  Goodbye! 👋`)),process.exit(0)}},d=n(e.createElement(r,u));l||setTimeout(()=>{d.unmount(),console.log(B.dim(`
316
316
  💡 Run in an interactive terminal for full REPL mode.`)),process.exit(0)},200)}function bt(){let e=new ct().name(`task-master`).description(`AI-driven development task management`).version(A()).helpOption(`-h, --help`,`Display help`).addHelpCommand(!1),t=e.helpInformation.bind(e);return e.helpInformation=function(){return this.parent&&this.parent!==e?t():(Y()?Z():M(),``)},Q(e),e}async function xt(e=process.argv){try{if(e.length<=2){await $();return}let t=e.includes(`init`),n=e.includes(`tui`)||e.includes(`repl`),r=e.includes(`--no-banner`);process.stdout.isTTY&&!t&&!n&&!r&&Le();let i=process.env.TASKMASTER_SKIP_AUTO_UPDATE===`1`||process.env.CI||process.env.NODE_ENV===`test`,a=A(),o=i?{currentVersion:a,latestVersion:a,needsUpdate:!1}:await ve(a);if(o.needsUpdate&&(Je(o.currentVersion,o.latestVersion,o.highlights),await Ue(o.latestVersion))){he(e);return}let s=bt(),c=e.filter(e=>e!==`--no-banner`);await s.parseAsync(c);try{let e=J({}),t=e.getTasksPath(),n=e.getStatePath();if(t&&V.existsSync(t)){let e=V.readFileSync(t,`utf8`),r=JSON.parse(e);if(r&&r.master){let e={migrationNoticeShown:!1};if(n&&V.existsSync(n)){let t=V.readFileSync(n,`utf8`);e=JSON.parse(t)||e}e.migrationNoticeShown||(me({_migrationHappened:!0}),e.migrationNoticeShown=!0,n&&V.writeFileSync(n,JSON.stringify(e,null,2)))}}}catch{}}catch(e){e instanceof b?console.error(U(B.red.bold(`Configuration Update Required!`)+`