@hhsw2015/task-master-ai 0.43.19 → 0.43.20

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-DWAPupZV.js";import"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import"./sentry-DsxpJLVM.js";export{i as generateObjectService,n as generateTextService,r as logAiUsage,t as streamObjectService,e as streamTextService};
@@ -1,4 +1,4 @@
1
- import{C as e,E as t,Et as n,F as r,H as i,I as a,J as o,L as s,M as c,N as l,O as u,P as d,a as f,f as p,ht as m,j as h,l as g,m as _,o as ee,s as te,ut as v,v as y,w as b,x,y as S,yt as C}from"./config-manager-Cm3z1HZv.js";import{n as w,t as T}from"./sentry-hPhwSfRH.js";import{createRequire as E}from"node:module";import D,{promises as O}from"fs";import k,{join as A}from"path";import{homedir as j}from"os";import{execSync as M,spawn as N}from"child_process";import*as P from"ai";import{jsonrepair as F}from"jsonrepair";import{EnvHttpProxyAgent as I}from"undici";import{createAnthropic as ne}from"@ai-sdk/anthropic";import{createPerplexity as re}from"@ai-sdk/perplexity";import{createGoogleGenerativeAI as ie}from"@ai-sdk/google";import{createOpenAI as ae}from"@ai-sdk/openai";import{createXai as oe}from"@ai-sdk/xai";import{createGroq as se}from"@ai-sdk/groq";import{createOpenRouter as ce}from"@openrouter/ai-sdk-provider";import{createOllama as le}from"ollama-ai-provider-v2";import{createAmazonBedrock as ue}from"@ai-sdk/amazon-bedrock";import{fromNodeProviderChain as de}from"@aws-sdk/credential-providers";import{createAzure as fe}from"@ai-sdk/azure";import{createVertex as pe}from"@ai-sdk/google-vertex";import{createClaudeCode as me}from"ai-sdk-provider-claude-code";import{createGeminiProvider as he}from"ai-sdk-provider-gemini-cli";import{APICallError as L,LoadAPIKeyError as ge,NoSuchModelError as R}from"@ai-sdk/provider";import{generateId as z}from"@ai-sdk/provider-utils";import{parse as _e}from"jsonc-parser";import{createCodexCli as ve}from"ai-sdk-provider-codex-cli";import{createOpenAICompatible as ye}from"@ai-sdk/openai-compatible";var be=Object.defineProperty,xe=e=>{let t={};for(var n in e)be(t,n,{get:e[n],enumerable:!0});return t},B=E(import.meta.url);let V=null;var H=class e{constructor(){this._providers=new Map,this._initialized=!1}static getInstance(){return V||=new e,V}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}};H.getInstance().initialize();var U=H;const{JSONParseError:Se,NoObjectGeneratedError:Ce,generateObject:we,generateText:Te,streamObject:Ee,streamText:De,zodSchema:Oe}=P,W=P.jsonSchema,ke=new Set([`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`]),Ae=[`additionalProperties`,`contains`,`if`,`then`,`else`,`not`,`propertyNames`],je=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],Me=[`definitions`,`$defs`,`dependentSchemas`,`patternProperties`,`properties`],Ne=e=>e?Array.isArray(e)?e.includes(`integer`):e===`integer`:!1,G=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(G);let t={...e};if(Ne(t.type))for(let e of ke)e in t&&delete t[e];for(let e of Ae)t[e]&&(t[e]=G(t[e]));for(let e of je)Array.isArray(t[e])&&(t[e]=t[e].map(G));for(let e of Me)if(t[e]&&typeof t[e]==`object`){let n={};for(let[r,i]of Object.entries(t[e]))n[r]=G(i);t[e]=n}return t.items&&=G(t.items),t},K=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(K);let t={};for(let[n,r]of Object.entries(e))t[n]=K(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},q=e=>{let t=Oe(e);if(!t||typeof t!=`object`||!t.jsonSchema)return t;let n=K(G(t.jsonSchema));return typeof W==`function`?W(n,{validate:t.validate}):{...t,jsonSchema:n}};var J=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||=v();let e=this._projectRoot;if(i(null,e))return this._proxyAgent||=new I,(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 C(`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),C(`debug`,`Generating ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.generateText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await Te({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}});C(`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),C(`debug`,`Streaming ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.streamText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await De({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 C(`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`);C(`debug`,`Streaming ${this.name} object with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.streamObject`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=q(e.schema),a=await Ee({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 C(`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`);C(`debug`,`Generating ${this.name} object ('${e.objectName}') with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.generateObject.${e.objectName}`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=q(e.schema),a=await we({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}});C(`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(Ce.isInstance(e)&&e.cause instanceof Se&&e.cause.text){C(`warn`,`${this.name} generated malformed JSON, attempting to repair...`);try{let t=F(e.cause.text),n=JSON.parse(t);return C(`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){C(`error`,`Failed to repair ${this.name} JSON: ${e.message}`)}}this.handleError(`object generation`,e)}}},Pe=class extends J{constructor(){super(),this.name=`Anthropic`}getRequiredApiKeyName(){return`ANTHROPIC_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ne({apiKey:t,...n&&{baseURL:n},headers:{"anthropic-beta":`output-128k-2025-02-19`},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Fe=class extends J{constructor(){super(),this.name=`Perplexity`}getRequiredApiKeyName(){return`PERPLEXITY_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return re({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`})}},Ie=class extends J{constructor(){super(),this.name=`Google`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ie({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Le=class extends J{constructor(){super(),this.name=`OpenAI`}getRequiredApiKeyName(){return`OPENAI_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 J{constructor(){super(),this.name=`xAI`}getRequiredApiKeyName(){return`XAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return oe({apiKey:t,baseURL:n||`https://api.x.ai/v1`})}catch(e){this.handleError(`client initialization`,e)}}},ze=class extends J{constructor(){super(),this.name=`Groq`}getRequiredApiKeyName(){return`GROQ_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return se({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},Be=class extends J{constructor(){super(),this.name=`OpenRouter`}getRequiredApiKeyName(){return`OPENROUTER_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 J{constructor(){super(),this.name=`Ollama`}validateAuth(e){}getClient(e){try{let{baseURL:t}=e;return le({...t&&{baseURL:t}})}catch(e){this.handleError(`client initialization`,e)}}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`OLLAMA_API_KEY`}},He=class extends J{constructor(){super(),this.name=`Bedrock`}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`AWS_ACCESS_KEY_ID`}validateAuth(e){}getClient(e){try{let e=de(),t=this.createProxyFetch();return ue({credentialProvider:e,...t&&{fetch:t}})}catch(e){this.handleError(`client initialization`,e)}}},Ue=class extends J{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 fe({apiKey:t,baseURL:r,...i&&{fetch:i}})}catch(e){this.handleError(`client initialization`,e)}}},Y=class extends Error{constructor(e){super(e),this.name=`VertexAuthError`,this.code=`vertex_auth_error`}},X=class extends Error{constructor(e){super(e),this.name=`VertexConfigError`,this.code=`vertex_config_error`}},We=class extends Error{constructor(e,t){super(e),this.name=`VertexApiError`,this.code=`vertex_api_error`,this.statusCode=t}},Ge=class extends J{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 Y(`Vertex AI requires authentication. Provide one of the following:
1
+ import{C as e,E as t,Et as n,F as r,H as i,I as a,J as o,L as s,M as c,N as l,O as u,P as d,a as f,f as p,ht as m,j as h,l as g,m as _,o as ee,s as te,ut as v,v as y,w as b,x,y as S,yt as C}from"./config-manager-cNtpB94F.js";import{n as w,t as T}from"./sentry-DsxpJLVM.js";import{createRequire as E}from"node:module";import D,{promises as O}from"fs";import k,{join as A}from"path";import{homedir as j}from"os";import{execSync as M,spawn as N}from"child_process";import*as P from"ai";import{jsonrepair as F}from"jsonrepair";import{EnvHttpProxyAgent as I}from"undici";import{createAnthropic as ne}from"@ai-sdk/anthropic";import{createPerplexity as re}from"@ai-sdk/perplexity";import{createGoogleGenerativeAI as ie}from"@ai-sdk/google";import{createOpenAI as ae}from"@ai-sdk/openai";import{createXai as oe}from"@ai-sdk/xai";import{createGroq as se}from"@ai-sdk/groq";import{createOpenRouter as ce}from"@openrouter/ai-sdk-provider";import{createOllama as le}from"ollama-ai-provider-v2";import{createAmazonBedrock as ue}from"@ai-sdk/amazon-bedrock";import{fromNodeProviderChain as de}from"@aws-sdk/credential-providers";import{createAzure as fe}from"@ai-sdk/azure";import{createVertex as pe}from"@ai-sdk/google-vertex";import{createClaudeCode as me}from"ai-sdk-provider-claude-code";import{createGeminiProvider as he}from"ai-sdk-provider-gemini-cli";import{APICallError as L,LoadAPIKeyError as ge,NoSuchModelError as R}from"@ai-sdk/provider";import{generateId as z}from"@ai-sdk/provider-utils";import{parse as _e}from"jsonc-parser";import{createCodexCli as ve}from"ai-sdk-provider-codex-cli";import{createOpenAICompatible as ye}from"@ai-sdk/openai-compatible";var be=Object.defineProperty,xe=e=>{let t={};for(var n in e)be(t,n,{get:e[n],enumerable:!0});return t},B=E(import.meta.url);let V=null;var H=class e{constructor(){this._providers=new Map,this._initialized=!1}static getInstance(){return V||=new e,V}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}};H.getInstance().initialize();var U=H;const{JSONParseError:Se,NoObjectGeneratedError:Ce,generateObject:we,generateText:Te,streamObject:Ee,streamText:De,zodSchema:Oe}=P,W=P.jsonSchema,ke=new Set([`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`]),Ae=[`additionalProperties`,`contains`,`if`,`then`,`else`,`not`,`propertyNames`],je=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],Me=[`definitions`,`$defs`,`dependentSchemas`,`patternProperties`,`properties`],Ne=e=>e?Array.isArray(e)?e.includes(`integer`):e===`integer`:!1,G=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(G);let t={...e};if(Ne(t.type))for(let e of ke)e in t&&delete t[e];for(let e of Ae)t[e]&&(t[e]=G(t[e]));for(let e of je)Array.isArray(t[e])&&(t[e]=t[e].map(G));for(let e of Me)if(t[e]&&typeof t[e]==`object`){let n={};for(let[r,i]of Object.entries(t[e]))n[r]=G(i);t[e]=n}return t.items&&=G(t.items),t},K=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(K);let t={};for(let[n,r]of Object.entries(e))t[n]=K(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},q=e=>{let t=Oe(e);if(!t||typeof t!=`object`||!t.jsonSchema)return t;let n=K(G(t.jsonSchema));return typeof W==`function`?W(n,{validate:t.validate}):{...t,jsonSchema:n}};var J=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||=v();let e=this._projectRoot;if(i(null,e))return this._proxyAgent||=new I,(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 C(`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),C(`debug`,`Generating ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.generateText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await Te({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}});C(`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),C(`debug`,`Streaming ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.streamText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await De({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 C(`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`);C(`debug`,`Streaming ${this.name} object with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.streamObject`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=q(e.schema),a=await Ee({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 C(`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`);C(`debug`,`Generating ${this.name} object ('${e.objectName}') with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=T(`${this.name}.${e.modelId}.${n}.generateObject.${e.objectName}`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:w(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=q(e.schema),a=await we({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}});C(`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(Ce.isInstance(e)&&e.cause instanceof Se&&e.cause.text){C(`warn`,`${this.name} generated malformed JSON, attempting to repair...`);try{let t=F(e.cause.text),n=JSON.parse(t);return C(`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){C(`error`,`Failed to repair ${this.name} JSON: ${e.message}`)}}this.handleError(`object generation`,e)}}},Pe=class extends J{constructor(){super(),this.name=`Anthropic`}getRequiredApiKeyName(){return`ANTHROPIC_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ne({apiKey:t,...n&&{baseURL:n},headers:{"anthropic-beta":`output-128k-2025-02-19`},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Fe=class extends J{constructor(){super(),this.name=`Perplexity`}getRequiredApiKeyName(){return`PERPLEXITY_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return re({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`})}},Ie=class extends J{constructor(){super(),this.name=`Google`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ie({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Le=class extends J{constructor(){super(),this.name=`OpenAI`}getRequiredApiKeyName(){return`OPENAI_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 J{constructor(){super(),this.name=`xAI`}getRequiredApiKeyName(){return`XAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return oe({apiKey:t,baseURL:n||`https://api.x.ai/v1`})}catch(e){this.handleError(`client initialization`,e)}}},ze=class extends J{constructor(){super(),this.name=`Groq`}getRequiredApiKeyName(){return`GROQ_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return se({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},Be=class extends J{constructor(){super(),this.name=`OpenRouter`}getRequiredApiKeyName(){return`OPENROUTER_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 J{constructor(){super(),this.name=`Ollama`}validateAuth(e){}getClient(e){try{let{baseURL:t}=e;return le({...t&&{baseURL:t}})}catch(e){this.handleError(`client initialization`,e)}}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`OLLAMA_API_KEY`}},He=class extends J{constructor(){super(),this.name=`Bedrock`}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`AWS_ACCESS_KEY_ID`}validateAuth(e){}getClient(e){try{let e=de(),t=this.createProxyFetch();return ue({credentialProvider:e,...t&&{fetch:t}})}catch(e){this.handleError(`client initialization`,e)}}},Ue=class extends J{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 fe({apiKey:t,baseURL:r,...i&&{fetch:i}})}catch(e){this.handleError(`client initialization`,e)}}},Y=class extends Error{constructor(e){super(e),this.name=`VertexAuthError`,this.code=`vertex_auth_error`}},X=class extends Error{constructor(e){super(e),this.name=`VertexConfigError`,this.code=`vertex_config_error`}},We=class extends Error{constructor(e,t){super(e),this.name=`VertexApiError`,this.code=`vertex_api_error`,this.statusCode=t}},Ge=class extends J{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 Y(`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 X(`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 X(`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),pe({...s,project:n,location:r,...a&&{baseURL:a},...o&&{fetch:o}})}catch(e){this.handleError(`client initialization`,e)}}handleError(e,t){if(C(`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 Y(`Authentication failed: ${n}`):e===400?new X(`Invalid request: ${n}`):new We(`API error (${e}): ${n}`,e)}throw Error(`Vertex AI ${e} failed: ${t.message}`)}};let Ke=!1;var qe=class extends J{constructor(){super(),this.name=`Claude Code`,this.supportedModels=d(`claude-code`),this.supportedModels.length===0&&C(`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`&&!Ke&&!process.env.CLAUDE_CODE_OAUTH_TOKEN)try{M(`claude --version`,{stdio:`pipe`,timeout:1e3})}catch{C(`warn`,`Claude Code CLI not detected. Install it with: npm install -g @anthropic-ai/claude-code`)}finally{Ke=!0}}getClient(e={}){try{let t=g(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,me({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 J{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),he(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 L({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 ge({message:e||`Authentication failed. Please ensure Grok CLI is properly configured with API key.`})}function Xe({message:e,promptExcerpt:t,timeoutMs:n}){return new L({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 L({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=_e(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-tvfkaOTr.js";import{B as e,Bt as t,D as n,Ht as r,Kt as i,Lt as a,Nt as o,On as s,Q as c,Rt as l,Tt as u,U as d,Ut as f,Vt as p,dt as m,h,hn as g,ln as ee,m as _,mn as te,p as v,t as y,ut as ne,yt as b,z as x}from"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import"./sentry-hPhwSfRH.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-CaRCB7TO.js";import{t as Ye}from"./response-language-BnJvZzdq.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-DQcCVbeo.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-DWAPupZV.js";import{B as e,Bt as t,D as n,Ht as r,Kt as i,Lt as a,Nt as o,On as s,Q as c,Rt as l,Tt as u,U as d,Ut as f,Vt as p,dt as m,h,hn as g,ln as ee,m as _,mn as te,p as v,t as y,ut as ne,yt as b,z as x}from"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import"./sentry-DsxpJLVM.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-mDsYzQ71.js";import{t as Ye}from"./response-language-BmOan_mF.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-CVELZrKz.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
 
@@ -106,7 +106,7 @@ Subtask update was not completed. Review the messages above for details.`))}catc
106
106
  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(`
107
107
  This error is related to API keys. Check your environment variables.`)),_()&&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(`
108
108
  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`)),_()&&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(`
109
- 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`)),_()&&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`)),p(),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=u(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-C7BFO_sx.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}
109
+ 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`)),_()&&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`)),p(),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=u(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-BK3rN6lz.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}
110
110
 
111
111
  **Detail Level:** ${r.detailLevel}
112
112
  **Context Size:** ${r.contextSize} characters
@@ -114,7 +114,7 @@ To fix this issue:`)),console.log(` 1. Run task-master list to see all availabl
114
114
 
115
115
  ### Results
116
116
 
117
- ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-z0WhVh4e.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-D6r8NE3N.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}
117
+ ${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-ntk5CuRW.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-DP498AAF.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}
118
118
 
119
119
  **Detail Level:** ${r.detailLevel}
120
120
  **Context Size:** ${r.contextSize} characters
@@ -309,7 +309,7 @@ Or specify profiles directly:
309
309
  `));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(`
310
310
  Errors occurred:`)),n.forEach(e=>{console.log(B.red(` ${e.profileName}: ${e.error}`))})),r.length>0&&(console.log(B.cyan(`
311
311
  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.
312
- `));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-D7V7ewib.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-D7V7ewib.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}`)),l(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),l(),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.
312
+ `));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-B8NsLhr8.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-B8NsLhr8.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}`)),l(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),l(),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.
313
313
  `));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}`)),d(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),d(),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.
314
314
  `));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}`)),f(),process.exit(1)}}).on(`error`,function(e){console.error(B.red(`Error: ${e.message}`)),f(),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.
315
315
  `));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.
@@ -1 +1 @@
1
- import{A as e,B as t,C as n,Cn as r,D as i,E as a,F as o,G as s,H as c,I as l,J as u,K as d,L as f,M as p,N as m,O as h,P as g,R as _,S as v,T as y,U as b,V as x,W as S,_ as C,a as w,b as T,bn as E,c as D,d as O,f as k,g as A,h as j,i as M,j as N,k as P,l as F,m as I,n as L,o as R,p as z,q as B,r as V,s as H,t as U,u as W,v as G,w as K,x as q,xn as J,y as Y,z as X}from"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";export{E as ALL_PROVIDERS,J as CUSTOM_PROVIDERS,U as ConfigurationError,u as MODEL_MAP,r as VALIDATED_PROVIDERS,L as getAllProviders,V as getAnonymousTelemetryEnabled,M as getAvailableModels,w as getAzureBaseURL,R as getBaseUrlForRole,H as getBedrockBaseURL,D as getClaudeCodeSettings,F as getClaudeCodeSettingsForCommand,W as getCodebaseAnalysisMode,O as getCodexCliSettings,k as getCodexCliSettingsForCommand,z as getConfig,I as getDebugFlag,j as getDefaultNumTasks,A as getDefaultPriority,C as getDefaultSubtasks,G as getFallbackModelId,Y as getFallbackProvider,T as getGrokCliSettings,q as getGrokCliSettingsForCommand,v as getLogLevel,n as getMainModelId,K as getMainProvider,y as getMcpApiKeyStatus,a as getOllamaBaseURL,i as getOperatingMode,h as getParametersForRole,P as getProjectName,e as getProxyEnabled,N as getResearchModelId,p as getResearchProvider,m as getResponseLanguage,g as getSupportedModelsForProvider,o as getUserId,l as getVertexLocation,f as getVertexProjectId,_ as hasCodebaseAnalysis,X as isApiKeySet,t as isConfigFilePresent,x as isConfigWarningSuppressed,c as isProxyEnabled,b as setSuppressConfigWarnings,S as validateClaudeCodeSettings,s as validateCodexCliSettings,d as validateProvider,B as writeConfig};
1
+ import{A as e,B as t,C as n,Cn as r,D as i,E as a,F as o,G as s,H as c,I as l,J as u,K as d,L as f,M as p,N as m,O as h,P as g,R as _,S as v,T as y,U as b,V as x,W as S,_ as C,a as w,b as T,bn as E,c as D,d as O,f as k,g as A,h as j,i as M,j as N,k as P,l as F,m as I,n as L,o as R,p as z,q as B,r as V,s as H,t as U,u as W,v as G,w as K,x as q,xn as J,y as Y,z as X}from"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";export{E as ALL_PROVIDERS,J as CUSTOM_PROVIDERS,U as ConfigurationError,u as MODEL_MAP,r as VALIDATED_PROVIDERS,L as getAllProviders,V as getAnonymousTelemetryEnabled,M as getAvailableModels,w as getAzureBaseURL,R as getBaseUrlForRole,H as getBedrockBaseURL,D as getClaudeCodeSettings,F as getClaudeCodeSettingsForCommand,W as getCodebaseAnalysisMode,O as getCodexCliSettings,k as getCodexCliSettingsForCommand,z as getConfig,I as getDebugFlag,j as getDefaultNumTasks,A as getDefaultPriority,C as getDefaultSubtasks,G as getFallbackModelId,Y as getFallbackProvider,T as getGrokCliSettings,q as getGrokCliSettingsForCommand,v as getLogLevel,n as getMainModelId,K as getMainProvider,y as getMcpApiKeyStatus,a as getOllamaBaseURL,i as getOperatingMode,h as getParametersForRole,P as getProjectName,e as getProxyEnabled,N as getResearchModelId,p as getResearchProvider,m as getResponseLanguage,g as getSupportedModelsForProvider,o as getUserId,l as getVertexLocation,f as getVertexProjectId,_ as hasCodebaseAnalysis,X as isApiKeySet,t as isConfigFilePresent,x as isConfigWarningSuppressed,c as isProxyEnabled,b as setSuppressConfigWarnings,S as validateClaudeCodeSettings,s as validateCodexCliSettings,d as validateProvider,B as writeConfig};
@@ -50,13 +50,13 @@ Phase: {{phase}}{{/phase}}{{#testsPassing}}
50
50
  Tests: {{testsPassing}} passing{{#testsFailing}}, {{testsFailing}} failing{{/testsFailing}}{{/testsPassing}}`};var St=class{templates;preservePlaceholders;constructor(e={}){let t=`customTemplates`in e||`preservePlaceholders`in e?e:{customTemplates:e};this.templates={...xt,...t.customTemplates||{}},this.preservePlaceholders=t.preservePlaceholders??!1}render(e,t,n){let r=n===void 0?this.templates[e]:n;if(r===void 0)throw Error(`Template "${e}" not found`);return this.substituteVariables(r,t)}setTemplate(e,t){this.templates[e]=t}getTemplate(e){return this.templates[e]}hasTemplate(e){return e in this.templates}validateTemplate(e,t){let n=this.extractVariables(e),r=t.filter(e=>!n.includes(e));return{isValid:r.length===0,missingVars:r}}extractVariables(e){let t=e.matchAll(/\{\{\s*([^}#/\s]+)\s*\}\}/g),n=new Set;for(let e of t)n.add(e[1]);return Array.from(n)}substituteVariables(e,t){let n=e;return n=this.processConditionalBlocks(n,t),n=n.replace(/\{\{\s*([^}#/\s]+)\s*\}\}/g,(e,n)=>{let r=t[n];return r==null?this.preservePlaceholders?`{{${n}}}`:``:String(r)}),n}processConditionalBlocks(e,t){let n=e,r=!0;for(;r;){let e=n;n=n.replace(/\{\{#([^}]+)\}\}((?:(?!\{\{#).)*?)\{\{\/\1\}\}/gs,(e,n,r)=>{let i=t[n.trim()];return i!=null&&i!==!1&&i!==``?r:``}),r=n!==e}return n}};const Ct=[`feat`,`fix`,`docs`,`style`,`refactor`,`perf`,`test`,`build`,`ci`,`chore`,`revert`];var wt=class{templateEngine;scopeDetector;constructor(e,t,n){this.templateEngine=new St(e),this.scopeDetector=new bt(t,n)}generateMessage(e){let{type:t,description:n,changedFiles:r,scope:i,body:a,breaking:o=!1,taskId:s,phase:c,tag:l,testsPassing:u,testsFailing:d,coveragePercent:f}=e,p={type:t,scope:i??this.scopeDetector.detectScope(r),breaking:o?`!`:``,description:n,body:a,taskId:s,phase:c,tag:l,testsPassing:u,testsFailing:d,coveragePercent:f};return this.templateEngine.render(`commitMessage`,p)}validateConventionalCommit(e){let t=[],n=e.split(`
51
51
  `)[0];if(!n)return t.push(`Missing commit message`),{isValid:!1,errors:t};let r=n.match(/^(\w+)(?:\(([^)]+)\))?(!)?:\s*(.+)$/);if(!r)return t.push(`Invalid conventional commit format. Expected: type(scope): description`),{isValid:!1,errors:t};let[,i,,,a]=r;return Ct.includes(i)||t.push(`Invalid commit type "${i}". Must be one of: ${Ct.join(`, `)}`),(!a||a.trim().length===0)&&t.push(`Missing description`),{isValid:t.length===0,errors:t}}parseCommitMessage(e){let t=e.split(`
52
52
  `),n=t[0].match(/^(\w+)(?:\(([^)]+)\))?(!)?:\s*(.+)$/);if(!n)throw Error(`Invalid conventional commit format`);let[,r,i,a,o]=n,s=t.findIndex((e,t)=>t>0&&e===``),c=s===-1?void 0:t.slice(s+1).join(`
53
- `).trim();return{type:r,scope:i,breaking:a===`!`,description:o,body:c}}getScopeDetector(){return this.scopeDetector}getTemplateEngine(){return this.templateEngine}},Tt=class{gitAdapter;commitGenerator;constructor(e){this.gitAdapter=new _t(e),this.commitGenerator=new wt}async isGitRepository(){return this.gitAdapter.isGitRepository()}async ensureGitRepository(){return this.gitAdapter.ensureGitRepository()}async getRepositoryRoot(){return this.gitAdapter.getRepositoryRoot()}async isWorkingTreeClean(){return this.gitAdapter.isWorkingTreeClean()}async getStatus(){return this.gitAdapter.getStatus()}async getStatusSummary(){return this.gitAdapter.getStatusSummary()}async hasUncommittedChanges(){return this.gitAdapter.hasUncommittedChanges()}async hasStagedChanges(){return this.gitAdapter.hasStagedChanges()}async getCurrentBranch(){return this.gitAdapter.getCurrentBranch()}async listBranches(){return this.gitAdapter.listBranches()}async branchExists(e){return this.gitAdapter.branchExists(e)}async createBranch(e,t){return this.gitAdapter.createBranch(e,t)}async checkoutBranch(e,t){return this.gitAdapter.checkoutBranch(e,t)}async createAndCheckoutBranch(e){return this.gitAdapter.createAndCheckoutBranch(e)}async deleteBranch(e,t){return this.gitAdapter.deleteBranch(e,t)}async getDefaultBranch(){return this.gitAdapter.getDefaultBranch()}async isOnDefaultBranch(){return this.gitAdapter.isOnDefaultBranch()}async stageFiles(e){return this.gitAdapter.stageFiles(e)}async unstageFiles(e){return this.gitAdapter.unstageFiles(e)}async createCommit(e,t){return this.gitAdapter.createCommit(e,t)}async getCommitLog(e){return this.gitAdapter.getCommitLog(e)}async getLastCommit(){return this.gitAdapter.getLastCommit()}async hasRemote(){return this.gitAdapter.hasRemote()}async getRemotes(){return this.gitAdapter.getRemotes()}generateCommitMessage(e){return this.commitGenerator.generateMessage(e)}validateCommitMessage(e){return this.commitGenerator.validateConventionalCommit(e)}parseCommitMessage(e){return this.commitGenerator.parseCommitMessage(e)}},Et=class{detectFormat(e){return!e||typeof e!=`object`?`standard`:Object.keys(e).some(e=>e!==`tasks`&&e!==`metadata`)?`legacy`:`standard`}extractTasks(e,t){return e?this.detectFormat(e)===`legacy`?this.extractTasksFromLegacy(e,t):this.extractTasksFromStandard(e):[]}extractTasksFromLegacy(e,t){if(t in e)return e[t]?.tasks||[];let n=Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`);return t===`master`&&n.length>0&&e[n[0]]?.tasks||[]}extractTasksFromStandard(e){return e?.tasks||[]}extractMetadata(e,t){return e?this.detectFormat(e)===`legacy`?this.extractMetadataFromLegacy(e,t):this.extractMetadataFromStandard(e):null}extractMetadataFromLegacy(e,t){if(t in e){let n=e[t];return!n?.metadata&&n?.tasks?this.generateMetadataFromTasks(n.tasks,t):n?.metadata||null}let n=Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`);if(t===`master`&&n.length>0){let t=n[0],r=e[t];return!r?.metadata&&r?.tasks?this.generateMetadataFromTasks(r.tasks,t):r?.metadata||null}return null}extractMetadataFromStandard(e){return e?.metadata||null}extractTags(e){return e?this.detectFormat(e)===`legacy`?Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`):[`master`]:[]}convertToSaveFormat(e,t,n,r){let i=r||`master`,a=this.normalizeTasks(e);return n&&this.detectFormat(n)===`legacy`?this.convertToLegacyFormat(a,t,i):this.convertToStandardFormat(a,t,r)}convertToLegacyFormat(e,t,n){return{[n]:{tasks:e,metadata:{...t,tags:[n]}}}}convertToStandardFormat(e,t,n){return{tasks:e,metadata:{...t,tags:n?[n]:[]}}}normalizeTasks(e){return e.map(e=>({...e,id:String(e.id),dependencies:e.dependencies?.map(e=>String(e))||[],subtasks:e.subtasks?.map(e=>({...e,id:Number(e.id),parentId:String(e.parentId)}))||[]}))}generateMetadataFromTasks(e,t){return{version:`1.0.0`,lastModified:new Date().toISOString(),taskCount:e.length,completedCount:e.filter(e=>e.status===`done`).length,tags:[t]}}};const Dt={stale:1e4,retries:{retries:5,factor:2,minTimeout:100,maxTimeout:1e3},realpath:!1};var Ot=class{writers=new Map;getWriter(e){let t=this.writers.get(e);return t||(t=new d(e),this.writers.set(e,t)),t}async readJson(e){try{let t=await _.readFile(e,`utf-8`);return JSON.parse(t)}catch(t){throw t.code===`ENOENT`?t:t instanceof SyntaxError?Error(`Invalid JSON in file ${e}: ${t.message}`):Error(`Failed to read file ${e}: ${t.message}`)}}async writeJson(e,t){await this.ensureFileExists(e);let n=null;try{n=await le.lock(e,Dt);let r=JSON.stringify(t,null,2);await this.getWriter(e).write(r)}finally{if(n)try{await n()}catch(t){(process.env.DEBUG||process.env.TASKMASTER_DEBUG===`true`)&&console.warn(`[WARN] Lock release warning for ${e}: ${t.message}`)}}}async modifyJson(e,t){await this.ensureFileExists(e);let n=null;try{n=await le.lock(e,Dt);let r;try{let t=await _.readFile(e,`utf-8`);r=JSON.parse(t)}catch(t){if(t.code===`ENOENT`)r={};else if(t instanceof SyntaxError){let n=await _.readFile(e,`utf-8`).catch(()=>``);if(n.trim()===``||n.trim()===`{}`)r={};else throw Error(`Corrupted JSON in ${e}: ${t.message}. File contains: ${n.substring(0,100)}...`)}else throw Error(`Failed to read ${e} for modification: ${t.message}`)}let i=await t(r),a=JSON.stringify(i,null,2);await this.getWriter(e).write(a)}finally{if(n)try{await n()}catch(t){(process.env.DEBUG||process.env.TASKMASTER_DEBUG===`true`)&&console.warn(`[WARN] Lock release warning for ${e}: ${t.message}`)}}}async ensureFileExists(e){let n=t.dirname(e);await _.mkdir(n,{recursive:!0});try{await _.writeFile(e,`{}`,{flag:`wx`})}catch(e){if(e.code!==`EEXIST`)throw e}}async exists(e){try{return await _.access(e,h.F_OK),!0}catch{return!1}}async getStats(e){return _.stat(e)}async readDir(e){return _.readdir(e)}async ensureDir(e){try{await _.mkdir(e,{recursive:!0})}catch(t){throw Error(`Failed to create directory ${e}: ${t.message}`)}}async deleteFile(e){try{await _.unlink(e)}catch(t){if(t.code!==`ENOENT`)throw Error(`Failed to delete file ${e}: ${t.message}`)}}async moveFile(e,t){try{await _.rename(e,t)}catch(n){throw Error(`Failed to move file from ${e} to ${t}: ${n.message}`)}}async copyFile(e,t){try{await _.copyFile(e,t)}catch(n){throw Error(`Failed to copy file from ${e} to ${t}: ${n.message}`)}}async cleanup(){this.writers.clear()}},kt=class{basePath;tasksDir;tasksFilePath;constructor(e){this.basePath=t.join(e,`.taskmaster`),this.tasksDir=t.join(this.basePath,`tasks`),this.tasksFilePath=t.join(this.tasksDir,`tasks.json`)}getBasePath(){return this.basePath}getTasksDir(){return this.tasksDir}getTasksPath(){return this.tasksFilePath}};const At=S(`ComplexityReportManager`);var jt=class{projectRoot;reportCache=new Map;constructor(e){this.projectRoot=e}getReportPath(e){let t=c.join(this.projectRoot,`.taskmaster`,`reports`),n=e&&e!==`master`?`_${e}`:``;return c.join(t,`task-complexity-report${n}.json`)}async loadReport(e){let t=e||`master`,n=t;if(this.reportCache.has(n))return this.reportCache.get(n);let r=this.getReportPath(e);try{await _.access(r);let e=await _.readFile(r,`utf-8`),i=JSON.parse(e);return!i.meta||!Array.isArray(i.complexityAnalysis)?(At.warn(`Invalid complexity report structure at ${r}, ignoring`),null):(this.reportCache.set(n,i),At.debug(`Loaded complexity report for tag '${t}' with ${i.complexityAnalysis.length} analyses`),i)}catch(e){return e.code===`ENOENT`?(At.debug(`No complexity report found for tag '${t}'`),null):(At.warn(`Failed to load complexity report for tag '${t}': ${e.message}`),null)}}async getComplexityForTask(e,t){let n=await this.loadReport(t);if(!n)return null;let r=n.complexityAnalysis.find(t=>String(t.taskId)===String(e));return r?{complexityScore:r.complexityScore,recommendedSubtasks:r.recommendedSubtasks,expansionPrompt:r.expansionPrompt,complexityReasoning:r.complexityReasoning}:null}async getComplexityForTasks(e,t){let n=new Map,r=await this.loadReport(t);if(!r)return n;let i=new Map;return r.complexityAnalysis.forEach(e=>{i.set(String(e.taskId),e)}),e.forEach(e=>{let t=i.get(String(e));t&&n.set(String(e),{complexityScore:t.complexityScore,recommendedSubtasks:t.recommendedSubtasks,expansionPrompt:t.expansionPrompt,complexityReasoning:t.complexityReasoning})}),n}clearCache(e){e?this.reportCache.delete(e):this.reportCache.clear()}async hasReport(e){let t=this.getReportPath(e);try{return await _.access(t),!0}catch{return!1}}},Mt=class{formatHandler;fileOps;pathResolver;complexityManager;constructor(e){this.formatHandler=new Et,this.fileOps=new Ot,this.pathResolver=new kt(e),this.complexityManager=new jt(e)}async initialize(){await this.fileOps.ensureDir(this.pathResolver.getTasksDir())}async close(){await this.fileOps.cleanup()}getStorageType(){return`file`}getCurrentBriefName(){return null}async getStats(){let e=this.pathResolver.getTasksPath();try{let t=await this.fileOps.getStats(e),n=await this.fileOps.readJson(e),r=this.formatHandler.extractTags(n),i=0,a=r.map(e=>{let r=this.formatHandler.extractTasks(n,e).length;return i+=r,{tag:e,taskCount:r,lastModified:t.mtime.toISOString()}});return{totalTasks:i,totalTags:r.length,lastModified:t.mtime.toISOString(),storageSize:0,tagStats:a}}catch(e){if(e.code===`ENOENT`)return{totalTasks:0,totalTags:0,lastModified:new Date().toISOString(),storageSize:0,tagStats:[]};throw Error(`Failed to get storage stats: ${e.message}`)}}async loadTasks(e,t){let n=this.pathResolver.getTasksPath(),r=e||`master`;try{let e=await this.fileOps.readJson(n),i=this.formatHandler.extractTasks(e,r);return t&&(t.status&&(i=i.filter(e=>e.status===t.status)),t.excludeSubtasks&&(i=i.map(e=>({...e,subtasks:[]})))),await this.enrichTasksWithComplexity(i,r)}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to load tasks: ${e.message}`)}}async loadTask(e,t){let n=await this.loadTasks(t);if(e.includes(`.`)){let[t,r]=e.split(`.`),i=n.find(e=>String(e.id)===t);if(!i||!i.subtasks)return null;let a=i.subtasks.find(e=>String(e.id)===r);if(!a)return null;let o=e=>{let t=String(e);return t.includes(`.`)?t:`${i.id}.${t}`},s=a.dependencies?.map(e=>o(e))??[];return{...a,id:e,title:a.title||`Subtask ${r}`,description:a.description||``,status:a.status||`pending`,priority:a.priority||i.priority||`medium`,dependencies:s,details:a.details||``,testStrategy:a.testStrategy||``,subtasks:[],tags:i.tags||[],assignee:a.assignee||i.assignee,complexity:a.complexity||i.complexity,createdAt:a.createdAt||i.createdAt,updatedAt:a.updatedAt||i.updatedAt,parentTask:{id:i.id,title:i.title,status:i.status},isSubtask:!0}}return n.find(t=>String(t.id)===String(e))||null}async saveTasks(e,t){let n=this.pathResolver.getTasksPath(),r=t||`master`;await this.fileOps.ensureDir(this.pathResolver.getTasksDir());let i={version:`1.0.0`,lastModified:new Date().toISOString(),taskCount:e.length,completedCount:e.filter(e=>e.status===`done`).length,tags:[r]},a=this.normalizeTaskIds(e);await this.fileOps.modifyJson(n,e=>this.formatHandler.detectFormat(e)===`legacy`||Object.keys(e).some(e=>e!==`tasks`&&e!==`metadata`)?(e[r]={tasks:a,metadata:i},e):r===`master`?{tasks:a,metadata:i}:{master:{tasks:e.tasks||[],metadata:e.metadata||i},[r]:{tasks:a,metadata:i}})}normalizeTaskIds(e){return e.map(e=>({...e,id:String(e.id),dependencies:e.dependencies?.map(e=>String(e))||[],subtasks:e.subtasks?.map(e=>({...e,id:Number(e.id),parentId:String(e.parentId)}))||[]}))}async exists(e){let t=this.pathResolver.getTasksPath();return this.fileOps.exists(t)}async getAllTags(){try{let e=this.pathResolver.getTasksPath(),t=await this.fileOps.readJson(e);return this.formatHandler.extractTags(t)}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to get tags: ${e.message}`)}}async loadMetadata(e){let t=this.pathResolver.getTasksPath(),n=e||`master`;try{let e=await this.fileOps.readJson(t);return this.formatHandler.extractMetadata(e,n)}catch(e){if(e.code===`ENOENT`)return null;throw Error(`Failed to load metadata: ${e.message}`)}}async saveMetadata(e,t){let n=await this.loadTasks(t);await this.saveTasks(n,t)}async appendTasks(e,t){let n=[...await this.loadTasks(t),...e];await this.saveTasks(n,t)}async updateTask(e,t,n){let r=await this.loadTasks(n),i=r.findIndex(t=>String(t.id)===String(e));if(i===-1)throw Error(`Task ${e} not found`);let a=r[i],o=t.subtasks;t.subtasks&&a.subtasks&&(o=t.subtasks.map(e=>{let t=a.subtasks?.find(t=>String(t.id)===String(e.id)||e.title&&t.title===e.title);return t?.metadata||e.metadata?{...e,metadata:{...t?.metadata||{},...e.metadata||{}}}:e})),r[i]={...a,...t,...o&&{subtasks:o},id:String(e)},await this.saveTasks(r,n)}async updateTaskWithPrompt(e,t,n,r){throw Error(`File storage does not support updateTaskWithPrompt. Client-side AI logic must process the prompt before calling updateTask().`)}async expandTaskWithPrompt(e,t,n){throw Error(`File storage does not support expandTaskWithPrompt. Client-side AI logic must process the expansion before calling updateTask().`)}async updateTaskStatus(e,t,n){let r=await this.loadTasks(n);if(e.includes(`.`))return this.updateSubtaskStatusInFile(r,e,t,n);let i=r.findIndex(t=>String(t.id)===String(e));if(i===-1)throw Error(`Task ${e} not found`);let a=r[i].status;return a===t?{success:!0,oldStatus:a,newStatus:t,taskId:String(e)}:(r[i]={...r[i],status:t,updatedAt:new Date().toISOString()},await this.saveTasks(r,n),{success:!0,oldStatus:a,newStatus:t,taskId:String(e)})}async updateSubtaskStatusInFile(e,t,n,r){let i=t.split(`.`);if(i.length!==2)throw Error(`Invalid subtask ID format: ${t}. Expected format: parentId.subtaskId`);let[a,o]=i,s=o.trim();if(!/^\d+$/.test(s))throw Error(`Invalid subtask ID: ${s}. Subtask ID must be a positive integer.`);let c=Number(s),l=e.findIndex(e=>String(e.id)===String(a));if(l===-1)throw Error(`Parent task ${a} not found`);let u=e[l],d=u.subtasks.findIndex(e=>e.id===c||String(e.id)===s);if(d===-1)throw Error(`Subtask ${t} not found in parent task ${a}`);let f=u.subtasks[d].status||`pending`;if(f===n)return{success:!0,oldStatus:f,newStatus:n,taskId:t};let p=new Date().toISOString();u.subtasks[d]={...u.subtasks[d],status:n,updatedAt:p};let m=u.subtasks,h=u.status;if(m.length>0){let e=e=>e.status||`pending`,t=t=>{let n=e(t);return n===`done`||n===`completed`},n=m.every(t),r=m.some(t=>e(t)===`in-progress`),i=m.some(t),a=m.every(t=>e(t)===`pending`);n?h=`done`:r||i?h=`in-progress`:a&&(h=`pending`)}return e[l]={...u,...h===u.status?{}:{status:h},updatedAt:p},await this.saveTasks(e,r),{success:!0,oldStatus:f,newStatus:n,taskId:t}}async deleteTask(e,t){let n=await this.loadTasks(t),r=n.filter(t=>String(t.id)!==String(e));if(r.length===n.length)throw Error(`Task ${e} not found`);await this.saveTasks(r,t)}async createTag(e,t){let n=this.pathResolver.getTasksPath();try{await this.fileOps.modifyJson(n,n=>{if(this.formatHandler.detectFormat(n)===`legacy`){if(e in n)throw new b(`Tag ${e} already exists`,y.VALIDATION_ERROR);let r=[];return t?.copyFrom&&t.copyFrom in n&&n[t.copyFrom].tasks&&(r=JSON.parse(JSON.stringify(n[t.copyFrom].tasks))),n[e]={tasks:r,metadata:{created:new Date().toISOString(),updatedAt:new Date().toISOString(),description:t?.description||`Tag created on ${new Date().toLocaleDateString()}`,tags:[e]}},n}else{let r=n.tasks||[],i=n.metadata||{},a=[];return(t?.copyFrom===`master`||!t?.copyFrom)&&(a=JSON.parse(JSON.stringify(r))),{master:{tasks:r,metadata:{...i,tags:[`master`]}},[e]:{tasks:a,metadata:{created:new Date().toISOString(),updatedAt:new Date().toISOString(),description:t?.description||`Tag created on ${new Date().toLocaleDateString()}`,tags:[e]}}}}})}catch(e){throw e.code===`ENOENT`?Error(`Tasks file not found - initialize project first`):e}}async deleteTag(e){let t=this.pathResolver.getTasksPath();try{let n=!1;await this.fileOps.modifyJson(t,t=>{if(this.formatHandler.detectFormat(t)!==`legacy`&&e===`master`)return n=!0,t;if(this.formatHandler.detectFormat(t)===`legacy`){if(e in t)return delete t[e],t;throw Error(`Tag ${e} not found`)}else throw Error(`Tag ${e} not found in standard format`)}),n&&await this.fileOps.deleteFile(t)}catch(t){throw t.code===`ENOENT`?Error(`Tag ${e} not found - file doesn't exist`):t}}async renameTag(e,t){let n=this.pathResolver.getTasksPath();try{await this.fileOps.modifyJson(n,n=>{if(this.formatHandler.detectFormat(n)===`legacy`){if(e in n)return n[t]=n[e],delete n[e],n[t].metadata&&(n[t].metadata.tags=[t]),n;throw Error(`Tag ${e} not found`)}else if(e===`master`){let e=n.tasks||[],r=n.metadata||{};return{[t]:{tasks:e,metadata:{...r,tags:[t]}}}}else throw Error(`Tag ${e} not found in standard format`)})}catch(t){throw t.code===`ENOENT`?Error(`Tag ${e} not found - file doesn't exist`):t}}async copyTag(e,t){let n=await this.loadTasks(e);if(n.length===0)throw Error(`Source tag ${e} not found or has no tasks`);await this.saveTasks(n,t)}async getTagsWithStats(){let e=await this.getAllTags(),t=await this.getActiveTagFromState(),n=await Promise.all(e.map(async e=>{try{let n=await this.loadTasks(e),r={},i=0,a={totalSubtasks:0,subtasksByStatus:{}};n.forEach(e=>{let t=e.status||`pending`;r[t]=(r[t]||0)+1,t===`done`&&i++,e.subtasks&&e.subtasks.length>0&&(a.totalSubtasks+=e.subtasks.length,e.subtasks.forEach(e=>{let t=e.status||`pending`;a.subtasksByStatus[t]=(a.subtasksByStatus[t]||0)+1}))});let o=await this.loadMetadata(e);return{name:e,isCurrent:e===t,taskCount:n.length,completedTasks:i,statusBreakdown:r,subtaskCounts:a.totalSubtasks>0?a:void 0,created:o?.created,description:o?.description}}catch{return{name:e,isCurrent:e===t,taskCount:0,completedTasks:0,statusBreakdown:{}}}}));return{tags:n,currentTag:t,totalTags:n.length}}async getActiveTagFromState(){try{let e=t.join(this.pathResolver.getBasePath(),`state.json`);return(await this.fileOps.readJson(e))?.currentTag||`master`}catch{return`master`}}async watch(e,t){let n=this.pathResolver.getTasksPath(),r=t?.debounceMs??100;if(!await this.fileOps.exists(n))throw new b(`Tasks file not found. Initialize the project first.`,y.NOT_FOUND,{path:n});let i,a=!1,o=m.watch(n,(t,n)=>{a||n&&t===`change`&&(i&&clearTimeout(i),i=setTimeout(()=>{a||e({type:`change`,timestamp:new Date})},r))});return o.on(`error`,t=>{a||e({type:`error`,timestamp:new Date,error:t})}),{unsubscribe:()=>{a=!0,i&&clearTimeout(i),o.close()}}}async enrichTasksWithComplexity(e,t){let n=e.map(e=>e.id),r=await this.complexityManager.getComplexityForTasks(n,t);return r.size===0?e:e.map(e=>{let t=r.get(String(e.id));return t?{...e,complexity:t.complexityScore,recommendedSubtasks:t.recommendedSubtasks,expansionPrompt:t.expansionPrompt,complexityReasoning:t.complexityReasoning}:e})}},Nt=class{configManager;authManager;constructor(e,t){this.configManager=e,this.authManager=t}async exportTasks(e){if(!await this.authManager.hasValidSession())throw new b(`Authentication required for export`,y.AUTHENTICATION_ERROR);let t=await this.authManager.getContext(),n=e.orgId||t?.orgId,r=e.briefId||t?.briefId;if(!n)throw new b(`Organization ID is required for export. Use "tm context org" to select one.`,y.MISSING_CONFIGURATION);if(!r)throw new b(`Brief ID is required for export. Use "tm context brief" or provide --brief flag.`,y.MISSING_CONFIGURATION);let i=this.configManager.getActiveTag(),a=e.tag||i,o=new Mt(this.configManager.getProjectRoot());await o.initialize();let s=await o.loadTasks(a,{status:e.status,excludeSubtasks:e.excludeSubtasks}),c={tasks:s,total:(await o.loadTasks(a)).length,filtered:s.length,tag:a,storageType:`file`};if(c.tasks.length===0)return{success:!1,taskCount:0,briefId:r,orgId:n,message:`No tasks found to export`,error:{code:`NO_TASKS`,message:`No tasks match the specified criteria`}};try{return await this.performExport(n,r,c.tasks),{success:!0,taskCount:c.tasks.length,briefId:r,orgId:n,message:`Successfully exported ${c.tasks.length} task(s) to brief`}}catch(e){return{success:!1,taskCount:0,briefId:r,orgId:n,error:{code:`EXPORT_FAILED`,message:e instanceof Error?e.message:String(e)}}}}async exportFromBriefInput(e){let t=this.extractBriefId(e);if(!t)throw new b(`Invalid brief ID or URL provided`,y.VALIDATION_ERROR);let n=await this.authManager.getBrief(t);if(!n)throw new b(`Brief not found or you do not have access`,y.NOT_FOUND);return this.exportTasks({orgId:n.accountId,briefId:n.id})}async validateContext(){let e=await this.authManager.getContext();return{hasOrg:!!e?.orgId,hasBrief:!!e?.briefId,context:e}}transformTasksForBulkImport(e){let t=[],n=this.configManager.getResponseLanguage(),r=new Set;for(let t of e)if(r.add(String(t.id)),t.subtasks)for(let e of t.subtasks)r.add(`${t.id}.${e.id}`);return e.forEach(e=>{let i=(e.dependencies||[]).map(String).filter(e=>r.has(e));t.push({externalId:String(e.id),title:e.title,description:this.enrichDescription(e,n),status:this.mapStatusForAPI(e.status),priority:e.priority||`medium`,dependencies:i,details:e.details,testStrategy:e.testStrategy,complexity:e.complexity,metadata:{complexity:e.complexity,originalId:e.id,originalDescription:e.description,originalDetails:e.details,originalTestStrategy:e.testStrategy}}),e.subtasks&&e.subtasks.length>0&&e.subtasks.forEach(i=>{let a=(i.dependencies||[]).map(t=>String(t).includes(`.`)?String(t):`${e.id}.${t}`).filter(e=>r.has(e));t.push({externalId:`${e.id}.${i.id}`,parentExternalId:String(e.id),title:i.title,description:this.enrichDescription(i,n),status:this.mapStatusForAPI(i.status),priority:i.priority||`medium`,dependencies:a,details:i.details,testStrategy:i.testStrategy,complexity:i.complexity,metadata:{complexity:i.complexity,originalId:i.id,originalDescription:i.description,originalDetails:i.details,originalTestStrategy:i.testStrategy}})})}),t}enrichDescription(e,t){let n=[],r=this.isEnglishLanguage(t),i=r?`## Implementation Details
53
+ `).trim();return{type:r,scope:i,breaking:a===`!`,description:o,body:c}}getScopeDetector(){return this.scopeDetector}getTemplateEngine(){return this.templateEngine}},Tt=class{gitAdapter;commitGenerator;constructor(e){this.gitAdapter=new _t(e),this.commitGenerator=new wt}async isGitRepository(){return this.gitAdapter.isGitRepository()}async ensureGitRepository(){return this.gitAdapter.ensureGitRepository()}async getRepositoryRoot(){return this.gitAdapter.getRepositoryRoot()}async isWorkingTreeClean(){return this.gitAdapter.isWorkingTreeClean()}async getStatus(){return this.gitAdapter.getStatus()}async getStatusSummary(){return this.gitAdapter.getStatusSummary()}async hasUncommittedChanges(){return this.gitAdapter.hasUncommittedChanges()}async hasStagedChanges(){return this.gitAdapter.hasStagedChanges()}async getCurrentBranch(){return this.gitAdapter.getCurrentBranch()}async listBranches(){return this.gitAdapter.listBranches()}async branchExists(e){return this.gitAdapter.branchExists(e)}async createBranch(e,t){return this.gitAdapter.createBranch(e,t)}async checkoutBranch(e,t){return this.gitAdapter.checkoutBranch(e,t)}async createAndCheckoutBranch(e){return this.gitAdapter.createAndCheckoutBranch(e)}async deleteBranch(e,t){return this.gitAdapter.deleteBranch(e,t)}async getDefaultBranch(){return this.gitAdapter.getDefaultBranch()}async isOnDefaultBranch(){return this.gitAdapter.isOnDefaultBranch()}async stageFiles(e){return this.gitAdapter.stageFiles(e)}async unstageFiles(e){return this.gitAdapter.unstageFiles(e)}async createCommit(e,t){return this.gitAdapter.createCommit(e,t)}async getCommitLog(e){return this.gitAdapter.getCommitLog(e)}async getLastCommit(){return this.gitAdapter.getLastCommit()}async hasRemote(){return this.gitAdapter.hasRemote()}async getRemotes(){return this.gitAdapter.getRemotes()}generateCommitMessage(e){return this.commitGenerator.generateMessage(e)}validateCommitMessage(e){return this.commitGenerator.validateConventionalCommit(e)}parseCommitMessage(e){return this.commitGenerator.parseCommitMessage(e)}},Et=class{detectFormat(e){return!e||typeof e!=`object`?`standard`:Object.keys(e).some(e=>e!==`tasks`&&e!==`metadata`)?`legacy`:`standard`}extractTasks(e,t){return e?this.detectFormat(e)===`legacy`?this.extractTasksFromLegacy(e,t):this.extractTasksFromStandard(e):[]}extractTasksFromLegacy(e,t){if(t in e)return e[t]?.tasks||[];let n=Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`);return t===`master`&&n.length>0&&e[n[0]]?.tasks||[]}extractTasksFromStandard(e){return e?.tasks||[]}extractMetadata(e,t){return e?this.detectFormat(e)===`legacy`?this.extractMetadataFromLegacy(e,t):this.extractMetadataFromStandard(e):null}extractMetadataFromLegacy(e,t){if(t in e){let n=e[t];return!n?.metadata&&n?.tasks?this.generateMetadataFromTasks(n.tasks,t):n?.metadata||null}let n=Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`);if(t===`master`&&n.length>0){let t=n[0],r=e[t];return!r?.metadata&&r?.tasks?this.generateMetadataFromTasks(r.tasks,t):r?.metadata||null}return null}extractMetadataFromStandard(e){return e?.metadata||null}extractTags(e){return e?this.detectFormat(e)===`legacy`?Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`):[`master`]:[]}convertToSaveFormat(e,t,n,r){let i=r||`master`,a=this.normalizeTasks(e);return n&&this.detectFormat(n)===`legacy`?this.convertToLegacyFormat(a,t,i):this.convertToStandardFormat(a,t,r)}convertToLegacyFormat(e,t,n){return{[n]:{tasks:e,metadata:{...t,tags:[n]}}}}convertToStandardFormat(e,t,n){return{tasks:e,metadata:{...t,tags:n?[n]:[]}}}normalizeTasks(e){return e.map(e=>({...e,id:String(e.id),dependencies:e.dependencies?.map(e=>String(e))||[],subtasks:e.subtasks?.map(e=>({...e,id:Number(e.id),parentId:String(e.parentId)}))||[]}))}generateMetadataFromTasks(e,t){return{version:`1.0.0`,lastModified:new Date().toISOString(),taskCount:e.length,completedCount:e.filter(e=>e.status===`done`).length,tags:[t]}}};const Dt={stale:1e4,retries:{retries:5,factor:2,minTimeout:100,maxTimeout:1e3},realpath:!1};var Ot=class{writers=new Map;getWriter(e){let t=this.writers.get(e);return t||(t=new d(e),this.writers.set(e,t)),t}async readJson(e){try{let t=await _.readFile(e,`utf-8`);return JSON.parse(t)}catch(t){throw t.code===`ENOENT`?t:t instanceof SyntaxError?Error(`Invalid JSON in file ${e}: ${t.message}`):Error(`Failed to read file ${e}: ${t.message}`)}}async writeJson(e,t){await this.ensureFileExists(e);let n=null;try{n=await le.lock(e,Dt);let r=JSON.stringify(t,null,2);await this.getWriter(e).write(r)}finally{if(n)try{await n()}catch(t){(process.env.DEBUG||process.env.TASKMASTER_DEBUG===`true`)&&console.warn(`[WARN] Lock release warning for ${e}: ${t.message}`)}}}async modifyJson(e,t){await this.ensureFileExists(e);let n=null;try{n=await le.lock(e,Dt);let r;try{let t=await _.readFile(e,`utf-8`);r=JSON.parse(t)}catch(t){if(t.code===`ENOENT`)r={};else if(t instanceof SyntaxError){let n=await _.readFile(e,`utf-8`).catch(()=>``);if(n.trim()===``||n.trim()===`{}`)r={};else throw Error(`Corrupted JSON in ${e}: ${t.message}. File contains: ${n.substring(0,100)}...`)}else throw Error(`Failed to read ${e} for modification: ${t.message}`)}let i=await t(r),a=JSON.stringify(i,null,2);await this.getWriter(e).write(a)}finally{if(n)try{await n()}catch(t){(process.env.DEBUG||process.env.TASKMASTER_DEBUG===`true`)&&console.warn(`[WARN] Lock release warning for ${e}: ${t.message}`)}}}async ensureFileExists(e){let n=t.dirname(e);await _.mkdir(n,{recursive:!0});try{await _.writeFile(e,`{}`,{flag:`wx`})}catch(e){if(e.code!==`EEXIST`)throw e}}async exists(e){try{return await _.access(e,h.F_OK),!0}catch{return!1}}async getStats(e){return _.stat(e)}async readDir(e){return _.readdir(e)}async ensureDir(e){try{await _.mkdir(e,{recursive:!0})}catch(t){throw Error(`Failed to create directory ${e}: ${t.message}`)}}async deleteFile(e){try{await _.unlink(e)}catch(t){if(t.code!==`ENOENT`)throw Error(`Failed to delete file ${e}: ${t.message}`)}}async moveFile(e,t){try{await _.rename(e,t)}catch(n){throw Error(`Failed to move file from ${e} to ${t}: ${n.message}`)}}async copyFile(e,t){try{await _.copyFile(e,t)}catch(n){throw Error(`Failed to copy file from ${e} to ${t}: ${n.message}`)}}async cleanup(){this.writers.clear()}},kt=class{basePath;tasksDir;tasksFilePath;constructor(e){this.basePath=t.join(e,`.taskmaster`),this.tasksDir=t.join(this.basePath,`tasks`),this.tasksFilePath=t.join(this.tasksDir,`tasks.json`)}getBasePath(){return this.basePath}getTasksDir(){return this.tasksDir}getTasksPath(){return this.tasksFilePath}};const At=S(`ComplexityReportManager`);var jt=class{projectRoot;reportCache=new Map;constructor(e){this.projectRoot=e}getReportPath(e){let t=c.join(this.projectRoot,`.taskmaster`,`reports`),n=e&&e!==`master`?`_${e}`:``;return c.join(t,`task-complexity-report${n}.json`)}async loadReport(e){let t=e||`master`,n=t;if(this.reportCache.has(n))return this.reportCache.get(n);let r=this.getReportPath(e);try{await _.access(r);let e=await _.readFile(r,`utf-8`),i=JSON.parse(e);return!i.meta||!Array.isArray(i.complexityAnalysis)?(At.warn(`Invalid complexity report structure at ${r}, ignoring`),null):(this.reportCache.set(n,i),At.debug(`Loaded complexity report for tag '${t}' with ${i.complexityAnalysis.length} analyses`),i)}catch(e){return e.code===`ENOENT`?(At.debug(`No complexity report found for tag '${t}'`),null):(At.warn(`Failed to load complexity report for tag '${t}': ${e.message}`),null)}}async getComplexityForTask(e,t){let n=await this.loadReport(t);if(!n)return null;let r=n.complexityAnalysis.find(t=>String(t.taskId)===String(e));return r?{complexityScore:r.complexityScore,recommendedSubtasks:r.recommendedSubtasks,expansionPrompt:r.expansionPrompt,complexityReasoning:r.complexityReasoning}:null}async getComplexityForTasks(e,t){let n=new Map,r=await this.loadReport(t);if(!r)return n;let i=new Map;return r.complexityAnalysis.forEach(e=>{i.set(String(e.taskId),e)}),e.forEach(e=>{let t=i.get(String(e));t&&n.set(String(e),{complexityScore:t.complexityScore,recommendedSubtasks:t.recommendedSubtasks,expansionPrompt:t.expansionPrompt,complexityReasoning:t.complexityReasoning})}),n}clearCache(e){e?this.reportCache.delete(e):this.reportCache.clear()}async hasReport(e){let t=this.getReportPath(e);try{return await _.access(t),!0}catch{return!1}}},Mt=class{formatHandler;fileOps;pathResolver;complexityManager;constructor(e){this.formatHandler=new Et,this.fileOps=new Ot,this.pathResolver=new kt(e),this.complexityManager=new jt(e)}async initialize(){await this.fileOps.ensureDir(this.pathResolver.getTasksDir())}async close(){await this.fileOps.cleanup()}getStorageType(){return`file`}getCurrentBriefName(){return null}async getStats(){let e=this.pathResolver.getTasksPath();try{let t=await this.fileOps.getStats(e),n=await this.fileOps.readJson(e),r=this.formatHandler.extractTags(n),i=0,a=r.map(e=>{let r=this.formatHandler.extractTasks(n,e).length;return i+=r,{tag:e,taskCount:r,lastModified:t.mtime.toISOString()}});return{totalTasks:i,totalTags:r.length,lastModified:t.mtime.toISOString(),storageSize:0,tagStats:a}}catch(e){if(e.code===`ENOENT`)return{totalTasks:0,totalTags:0,lastModified:new Date().toISOString(),storageSize:0,tagStats:[]};throw Error(`Failed to get storage stats: ${e.message}`)}}async loadTasks(e,t){let n=this.pathResolver.getTasksPath(),r=e||`master`;try{let e=await this.fileOps.readJson(n),i=this.formatHandler.extractTasks(e,r);return t&&(t.status&&(i=i.filter(e=>e.status===t.status)),t.excludeSubtasks&&(i=i.map(e=>({...e,subtasks:[]})))),await this.enrichTasksWithComplexity(i,r)}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to load tasks: ${e.message}`)}}async loadTask(e,t){let n=await this.loadTasks(t);if(e.includes(`.`)){let[t,r]=e.split(`.`),i=n.find(e=>String(e.id)===t);if(!i||!i.subtasks)return null;let a=i.subtasks.find(e=>String(e.id)===r);if(!a)return null;let o=e=>{let t=String(e);return t.includes(`.`)?t:`${i.id}.${t}`},s=a.dependencies?.map(e=>o(e))??[];return{...a,id:e,title:a.title||`Subtask ${r}`,description:a.description||``,status:a.status||`pending`,priority:a.priority||i.priority||`medium`,dependencies:s,details:a.details||``,testStrategy:a.testStrategy||``,subtasks:[],tags:i.tags||[],assignee:a.assignee||i.assignee,complexity:a.complexity||i.complexity,createdAt:a.createdAt||i.createdAt,updatedAt:a.updatedAt||i.updatedAt,parentTask:{id:i.id,title:i.title,status:i.status},isSubtask:!0}}return n.find(t=>String(t.id)===String(e))||null}async saveTasks(e,t){let n=this.pathResolver.getTasksPath(),r=t||`master`;await this.fileOps.ensureDir(this.pathResolver.getTasksDir());let i={version:`1.0.0`,lastModified:new Date().toISOString(),taskCount:e.length,completedCount:e.filter(e=>e.status===`done`).length,tags:[r]},a=this.normalizeTaskIds(e);await this.fileOps.modifyJson(n,e=>this.formatHandler.detectFormat(e)===`legacy`||Object.keys(e).some(e=>e!==`tasks`&&e!==`metadata`)?(e[r]={tasks:a,metadata:i},e):r===`master`?{tasks:a,metadata:i}:{master:{tasks:e.tasks||[],metadata:e.metadata||i},[r]:{tasks:a,metadata:i}})}normalizeTaskIds(e){return e.map(e=>({...e,id:String(e.id),dependencies:e.dependencies?.map(e=>String(e))||[],subtasks:e.subtasks?.map(e=>({...e,id:Number(e.id),parentId:String(e.parentId)}))||[]}))}async exists(e){let t=this.pathResolver.getTasksPath();return this.fileOps.exists(t)}async getAllTags(){try{let e=this.pathResolver.getTasksPath(),t=await this.fileOps.readJson(e);return this.formatHandler.extractTags(t)}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to get tags: ${e.message}`)}}async loadMetadata(e){let t=this.pathResolver.getTasksPath(),n=e||`master`;try{let e=await this.fileOps.readJson(t);return this.formatHandler.extractMetadata(e,n)}catch(e){if(e.code===`ENOENT`)return null;throw Error(`Failed to load metadata: ${e.message}`)}}async saveMetadata(e,t){let n=await this.loadTasks(t);await this.saveTasks(n,t)}async appendTasks(e,t){let n=[...await this.loadTasks(t),...e];await this.saveTasks(n,t)}async updateTask(e,t,n){let r=await this.loadTasks(n),i=r.findIndex(t=>String(t.id)===String(e));if(i===-1)throw Error(`Task ${e} not found`);let a=r[i],o=t.subtasks;t.subtasks&&a.subtasks&&(o=t.subtasks.map(e=>{let t=a.subtasks?.find(t=>String(t.id)===String(e.id)||e.title&&t.title===e.title);return t?.metadata||e.metadata?{...e,metadata:{...t?.metadata||{},...e.metadata||{}}}:e})),r[i]={...a,...t,...o&&{subtasks:o},id:String(e)},await this.saveTasks(r,n)}async updateTaskWithPrompt(e,t,n,r){throw Error(`File storage does not support updateTaskWithPrompt. Client-side AI logic must process the prompt before calling updateTask().`)}async expandTaskWithPrompt(e,t,n){throw Error(`File storage does not support expandTaskWithPrompt. Client-side AI logic must process the expansion before calling updateTask().`)}async updateTaskStatus(e,t,n){let r=await this.loadTasks(n);if(e.includes(`.`))return this.updateSubtaskStatusInFile(r,e,t,n);let i=r.findIndex(t=>String(t.id)===String(e));if(i===-1)throw Error(`Task ${e} not found`);let a=r[i].status;return a===t?{success:!0,oldStatus:a,newStatus:t,taskId:String(e)}:(r[i]={...r[i],status:t,updatedAt:new Date().toISOString()},await this.saveTasks(r,n),{success:!0,oldStatus:a,newStatus:t,taskId:String(e)})}async updateSubtaskStatusInFile(e,t,n,r){let i=t.split(`.`);if(i.length!==2)throw Error(`Invalid subtask ID format: ${t}. Expected format: parentId.subtaskId`);let[a,o]=i,s=o.trim();if(!/^\d+$/.test(s))throw Error(`Invalid subtask ID: ${s}. Subtask ID must be a positive integer.`);let c=Number(s),l=e.findIndex(e=>String(e.id)===String(a));if(l===-1)throw Error(`Parent task ${a} not found`);let u=e[l],d=u.subtasks.findIndex(e=>e.id===c||String(e.id)===s);if(d===-1)throw Error(`Subtask ${t} not found in parent task ${a}`);let f=u.subtasks[d].status||`pending`;if(f===n)return{success:!0,oldStatus:f,newStatus:n,taskId:t};let p=new Date().toISOString();u.subtasks[d]={...u.subtasks[d],status:n,updatedAt:p};let m=u.subtasks,h=u.status;if(m.length>0){let e=e=>e.status||`pending`,t=t=>{let n=e(t);return n===`done`||n===`completed`},n=m.every(t),r=m.some(t=>e(t)===`in-progress`),i=m.some(t),a=m.every(t=>e(t)===`pending`);n?h=`done`:r||i?h=`in-progress`:a&&(h=`pending`)}return e[l]={...u,...h===u.status?{}:{status:h},updatedAt:p},await this.saveTasks(e,r),{success:!0,oldStatus:f,newStatus:n,taskId:t}}async deleteTask(e,t){let n=await this.loadTasks(t),r=n.filter(t=>String(t.id)!==String(e));if(r.length===n.length)throw Error(`Task ${e} not found`);await this.saveTasks(r,t)}async createTag(e,t){let n=this.pathResolver.getTasksPath();try{await this.fileOps.modifyJson(n,n=>{if(this.formatHandler.detectFormat(n)===`legacy`){if(e in n)throw new b(`Tag ${e} already exists`,y.VALIDATION_ERROR);let r=[];return t?.copyFrom&&t.copyFrom in n&&n[t.copyFrom].tasks&&(r=JSON.parse(JSON.stringify(n[t.copyFrom].tasks))),n[e]={tasks:r,metadata:{created:new Date().toISOString(),updatedAt:new Date().toISOString(),description:t?.description||`Tag created on ${new Date().toLocaleDateString()}`,tags:[e]}},n}else{let r=n.tasks||[],i=n.metadata||{},a=[];return(t?.copyFrom===`master`||!t?.copyFrom)&&(a=JSON.parse(JSON.stringify(r))),{master:{tasks:r,metadata:{...i,tags:[`master`]}},[e]:{tasks:a,metadata:{created:new Date().toISOString(),updatedAt:new Date().toISOString(),description:t?.description||`Tag created on ${new Date().toLocaleDateString()}`,tags:[e]}}}}})}catch(e){throw e.code===`ENOENT`?Error(`Tasks file not found - initialize project first`):e}}async deleteTag(e){let t=this.pathResolver.getTasksPath();try{let n=!1;await this.fileOps.modifyJson(t,t=>{if(this.formatHandler.detectFormat(t)!==`legacy`&&e===`master`)return n=!0,t;if(this.formatHandler.detectFormat(t)===`legacy`){if(e in t)return delete t[e],t;throw Error(`Tag ${e} not found`)}else throw Error(`Tag ${e} not found in standard format`)}),n&&await this.fileOps.deleteFile(t)}catch(t){throw t.code===`ENOENT`?Error(`Tag ${e} not found - file doesn't exist`):t}}async renameTag(e,t){let n=this.pathResolver.getTasksPath();try{await this.fileOps.modifyJson(n,n=>{if(this.formatHandler.detectFormat(n)===`legacy`){if(e in n)return n[t]=n[e],delete n[e],n[t].metadata&&(n[t].metadata.tags=[t]),n;throw Error(`Tag ${e} not found`)}else if(e===`master`){let e=n.tasks||[],r=n.metadata||{};return{[t]:{tasks:e,metadata:{...r,tags:[t]}}}}else throw Error(`Tag ${e} not found in standard format`)})}catch(t){throw t.code===`ENOENT`?Error(`Tag ${e} not found - file doesn't exist`):t}}async copyTag(e,t){let n=await this.loadTasks(e);if(n.length===0)throw Error(`Source tag ${e} not found or has no tasks`);await this.saveTasks(n,t)}async getTagsWithStats(){let e=await this.getAllTags(),t=await this.getActiveTagFromState(),n=await Promise.all(e.map(async e=>{try{let n=await this.loadTasks(e),r={},i=0,a={totalSubtasks:0,subtasksByStatus:{}};n.forEach(e=>{let t=e.status||`pending`;r[t]=(r[t]||0)+1,t===`done`&&i++,e.subtasks&&e.subtasks.length>0&&(a.totalSubtasks+=e.subtasks.length,e.subtasks.forEach(e=>{let t=e.status||`pending`;a.subtasksByStatus[t]=(a.subtasksByStatus[t]||0)+1}))});let o=await this.loadMetadata(e);return{name:e,isCurrent:e===t,taskCount:n.length,completedTasks:i,statusBreakdown:r,subtaskCounts:a.totalSubtasks>0?a:void 0,created:o?.created,description:o?.description}}catch{return{name:e,isCurrent:e===t,taskCount:0,completedTasks:0,statusBreakdown:{}}}}));return{tags:n,currentTag:t,totalTags:n.length}}async getActiveTagFromState(){try{let e=t.join(this.pathResolver.getBasePath(),`state.json`);return(await this.fileOps.readJson(e))?.currentTag||`master`}catch{return`master`}}async watch(e,t){let n=this.pathResolver.getTasksPath(),r=t?.debounceMs??100;if(!await this.fileOps.exists(n))throw new b(`Tasks file not found. Initialize the project first.`,y.NOT_FOUND,{path:n});let i,a=!1,o=m.watch(n,(t,n)=>{a||n&&t===`change`&&(i&&clearTimeout(i),i=setTimeout(()=>{a||e({type:`change`,timestamp:new Date})},r))});return o.on(`error`,t=>{a||e({type:`error`,timestamp:new Date,error:t})}),{unsubscribe:()=>{a=!0,i&&clearTimeout(i),o.close()}}}async enrichTasksWithComplexity(e,t){let n=e.map(e=>e.id),r=await this.complexityManager.getComplexityForTasks(n,t);return r.size===0?e:e.map(e=>{let t=r.get(String(e.id));return t?{...e,complexity:t.complexityScore,recommendedSubtasks:t.recommendedSubtasks,expansionPrompt:t.expansionPrompt,complexityReasoning:t.complexityReasoning}:e})}},Nt=class e{static MAX_TASKS_PER_IMPORT_REQUEST=100;configManager;authManager;constructor(e,t){this.configManager=e,this.authManager=t}async exportTasks(e){if(!await this.authManager.hasValidSession())throw new b(`Authentication required for export`,y.AUTHENTICATION_ERROR);let t=await this.authManager.getContext(),n=e.orgId||t?.orgId,r=e.briefId||t?.briefId;if(!n)throw new b(`Organization ID is required for export. Use "tm context org" to select one.`,y.MISSING_CONFIGURATION);if(!r)throw new b(`Brief ID is required for export. Use "tm context brief" or provide --brief flag.`,y.MISSING_CONFIGURATION);let i=this.configManager.getActiveTag(),a=e.tag||i,o=new Mt(this.configManager.getProjectRoot());await o.initialize();let s=await o.loadTasks(a,{status:e.status,excludeSubtasks:e.excludeSubtasks}),c={tasks:s,total:(await o.loadTasks(a)).length,filtered:s.length,tag:a,storageType:`file`};if(c.tasks.length===0)return{success:!1,taskCount:0,briefId:r,orgId:n,message:`No tasks found to export`,error:{code:`NO_TASKS`,message:`No tasks match the specified criteria`}};try{return await this.performExport(n,r,c.tasks),{success:!0,taskCount:c.tasks.length,briefId:r,orgId:n,message:`Successfully exported ${c.tasks.length} task(s) to brief`}}catch(e){return{success:!1,taskCount:0,briefId:r,orgId:n,error:{code:`EXPORT_FAILED`,message:e instanceof Error?e.message:String(e)}}}}async exportFromBriefInput(e){let t=this.extractBriefId(e);if(!t)throw new b(`Invalid brief ID or URL provided`,y.VALIDATION_ERROR);let n=await this.authManager.getBrief(t);if(!n)throw new b(`Brief not found or you do not have access`,y.NOT_FOUND);return this.exportTasks({orgId:n.accountId,briefId:n.id})}async validateContext(){let e=await this.authManager.getContext();return{hasOrg:!!e?.orgId,hasBrief:!!e?.briefId,context:e}}transformTasksForBulkImport(e){let t=[],n=this.configManager.getResponseLanguage(),r=new Set;for(let t of e)if(r.add(String(t.id)),t.subtasks)for(let e of t.subtasks)r.add(`${t.id}.${e.id}`);return e.forEach(e=>{let i=(e.dependencies||[]).map(String).filter(e=>r.has(e));t.push({externalId:String(e.id),title:e.title,description:this.enrichDescription(e,n),status:this.mapStatusForAPI(e.status),priority:e.priority||`medium`,dependencies:i,details:e.details,testStrategy:e.testStrategy,complexity:e.complexity,metadata:{complexity:e.complexity,originalId:e.id,originalDescription:e.description,originalDetails:e.details,originalTestStrategy:e.testStrategy}}),e.subtasks&&e.subtasks.length>0&&e.subtasks.forEach(i=>{let a=(i.dependencies||[]).map(t=>String(t).includes(`.`)?String(t):`${e.id}.${t}`).filter(e=>r.has(e));t.push({externalId:`${e.id}.${i.id}`,parentExternalId:String(e.id),title:i.title,description:this.enrichDescription(i,n),status:this.mapStatusForAPI(i.status),priority:i.priority||`medium`,dependencies:a,details:i.details,testStrategy:i.testStrategy,complexity:i.complexity,metadata:{complexity:i.complexity,originalId:i.id,originalDescription:i.description,originalDetails:i.details,originalTestStrategy:i.testStrategy}})})}),t}enrichDescription(e,t){let n=[],r=this.isEnglishLanguage(t),i=r?`## Implementation Details
54
54
  `:`## 实现细节
55
55
  `,a=r?`## Test Strategy
56
56
  `:`## 测试策略
57
57
  `,o=r?`No description provided`:`未提供描述`;return e.description&&n.push(e.description),e.details&&(n.push(i),n.push(e.details)),e.testStrategy&&(n.push(a),n.push(e.testStrategy)),n.join(`
58
58
 
59
- `).trim()||o}isEnglishLanguage(e){let t=(e||this.configManager.getResponseLanguage()||``).trim().toLowerCase();return t===`english`||t===`en`||t.startsWith(`english-`)||t.startsWith(`en-`)}mapStatusForAPI(e){switch(e){case`pending`:return`todo`;case`in-progress`:return`in_progress`;case`done`:return`done`;default:return`todo`}}async performExport(e,t,n){let r=new k().getApiBaseUrl();if(r){let i=`${r}/ai/api/v1/briefs/${t}/tasks`,a={source:`task-master-cli`,options:{dryRun:!1,stopOnError:!1},accountId:e,tasks:this.transformTasksForBulkImport(n)},o=await this.authManager.getAccessToken();if(!o)throw Error(`Not authenticated`);let s=await fetch(i,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${o}`},body:JSON.stringify(a)});if(!s.ok){let e=await s.text();throw Error(`API request failed: ${s.status} - ${e}`)}let c=await s.json();if(c.failedCount>0){let e=c.results.filter(e=>!e.success).map(e=>`${e.externalId}: ${e.error}`).join(`, `);console.warn(`Warning: ${c.failedCount} tasks failed to import: ${e}`)}console.log(`Successfully exported ${c.successCount} of ${c.totalTasks} tasks to brief ${t}`)}else throw Error(`Export API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable to enable task export.`)}extractBriefId(e){let t=e?.trim()??``;if(!t)return null;let n=e=>{try{return new URL(e)}catch{}try{return new URL(`https://${e}`)}catch{}return null},r=e=>{let t=e.split(`/`).filter(Boolean),n=t.lastIndexOf(`briefs`);return(n>=0&&t.length>n+1?t[n+1]:t[t.length-1])?.trim()||null},i=n(t);if(i){let e=(i.searchParams.get(`id`)||i.searchParams.get(`briefId`)||r(i.pathname))??null;if(e&&(this.isLikelyId(e)||e.length>=8))return e}if(t.includes(`/`)){let e=r(t);if(e&&(this.isLikelyId(e)||e.length>=8))return e}return this.isLikelyId(t)||t.length>=8?t:null}isLikelyId(e){return/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(e)||/^[0-9A-HJKMNP-TV-Z]{26}$/i.test(e)||/^[A-Za-z0-9_-]{16,}$/.test(e)}async generateBriefFromTasks(e={}){if(!await this.authManager.hasValidSession())throw new b(`Authentication required for export`,y.AUTHENTICATION_ERROR);let t=await this.authManager.getContext(),n=e.orgId||t?.orgId;if(!n){let e=await this.authManager.getOrganizations();if(e.length===0)return{success:!1,error:{code:`NO_ORGANIZATIONS`,message:`No organizations available. Please create an organization in Hamster first.`}};n=e[0].id}let r=this.configManager.getActiveTag(),i=e.tag||r,a=new Mt(this.configManager.getProjectRoot());await a.initialize();let o=await a.loadTasks(i,{status:e.status,excludeSubtasks:e.excludeSubtasks});if(o.length===0)return{success:!1,error:{code:`NO_TASKS`,message:`No tasks found to export`}};let s=this.transformTasksForImport(o),c=this.getProjectName();return this.callGenerateBriefEndpoint({tasks:s,source:{tool:`task-master`,version:this.getVersion(),tag:i,projectName:c},orgId:n,responseLanguage:e.options?.language||this.configManager.getResponseLanguage(),options:e.options})}transformTasksForImport(e){let t=[],n=this.configManager.getResponseLanguage(),r=new Set;for(let t of e)if(r.add(String(t.id)),t.subtasks)for(let e of t.subtasks)r.add(`${t.id}.${e.id}`);for(let i of e){let e=(i.dependencies||[]).map(String).filter(e=>r.has(e));if(t.push({externalId:String(i.id),title:i.title,description:this.enrichDescription(i,n),details:i.details,status:this.mapStatusForImport(i.status),priority:this.mapPriorityForImport(i.priority),dependencies:e,metadata:{originalStatus:i.status,originalPriority:i.priority,testStrategy:i.testStrategy,complexity:i.complexity}}),i.subtasks&&i.subtasks.length>0)for(let e of i.subtasks){let a=(e.dependencies||[]).map(e=>String(e).includes(`.`)?String(e):`${i.id}.${e}`).filter(e=>r.has(e));t.push({externalId:`${i.id}.${e.id}`,parentId:String(i.id),title:e.title,description:this.enrichDescription(e,n),details:e.details,status:this.mapStatusForImport(e.status),priority:this.mapPriorityForImport(e.priority),dependencies:a,metadata:{originalStatus:e.status,originalPriority:e.priority,testStrategy:e.testStrategy,complexity:e.complexity}})}}return t}mapStatusForImport(e){switch(e){case`pending`:return`todo`;case`in-progress`:case`in_progress`:return`in_progress`;case`done`:case`completed`:return`done`;case`blocked`:return`blocked`;default:return`todo`}}mapPriorityForImport(e){switch(e?.toLowerCase()){case`low`:return`low`;case`medium`:return`medium`;case`high`:return`high`;case`critical`:case`urgent`:return`urgent`;default:return`medium`}}getVersion(){try{return process.env.npm_package_version||`1.0.0`}catch{return`1.0.0`}}getProjectName(){try{return this.configManager.getProjectRoot().split(/[/\\]/).pop()||void 0}catch{return}}async callGenerateBriefEndpoint(e){let t=new k().getApiBaseUrl();if(!t)throw new b(`Export API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable.`,y.MISSING_CONFIGURATION,{operation:`generateBriefFromTasks`});let n=`${t}/ai/api/v1/briefs/generate-from-tasks`,r=await this.authManager.getAccessToken();if(!r)throw new b(`Not authenticated`,y.AUTHENTICATION_ERROR);let i=e.orgId;if(!i)return{success:!1,error:{code:`MISSING_ACCOUNT`,message:`No organization selected. Please run "tm auth" and select an organization first.`}};let a={tasks:e.tasks,source:e.source,accountId:i,options:{generateTitle:e.options?.generateTitle??!0,generateDescription:e.options?.generateDescription??!0,preserveHierarchy:e.options?.preserveHierarchy??!0,preserveDependencies:e.options?.preserveDependencies??!0,title:e.options?.title,description:e.options?.description,language:this.isEnglishLanguage(e.responseLanguage)?`English`:`Chinese`}};try{let e={"Content-Type":`application/json`,Authorization:`Bearer ${r}`,"x-account-id":i},t=await fetch(n,{method:`POST`,headers:e,body:JSON.stringify(a)}),o;if(!t.ok&&t.status===400){let r=await t.text();o=r;let i=r.toLowerCase();if(i.includes(`language`)&&(i.includes(`additional`)||i.includes(`schema`)||i.includes(`unknown`))){let r={...a,options:{...a.options}};delete r.options.language,t=await fetch(n,{method:`POST`,headers:e,body:JSON.stringify(r)}),o=void 0}}if(!(t.headers.get(`content-type`)||``).includes(`application/json`)){let e=o||await t.text();return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${t.status}): ${e.substring(0,100)}...`}}}let s=o?JSON.parse(o):await t.json(),c=s;if(!t.ok||!c.success){let e=c.error?.message||s?.message||s?.error||`API request failed: ${t.status} - ${t.statusText}`,n=c.error?.code||s?.code||s?.statusCode||`API_ERROR`;return{success:!1,warnings:c.warnings,error:{code:String(n),message:String(e)}}}return{success:!0,brief:c.brief,taskMapping:c.taskMapping,invitations:c.invitations,warnings:c.warnings}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to connect to API: ${e instanceof Error?e.message:String(e)}`}}}}async generateBriefFromPrd(e){if(!e.prdContent||e.prdContent.trim().length===0)return{success:!1,error:{code:`INVALID_INPUT`,message:`PRD content is required`}};if(!await this.authManager.hasValidSession())throw new b(`Authentication required for PRD import`,y.AUTHENTICATION_ERROR);let t=await this.authManager.getContext(),n=e.orgId||t?.orgId;if(!n){let e=await this.authManager.getOrganizations();if(e.length===0)return{success:!1,error:{code:`NO_ORGANIZATIONS`,message:`No organizations available. Please create an organization in Hamster first.`}};n=e[0].id}return this.callGenerateBriefFromPrdEndpoint({prdContent:e.prdContent,orgId:n,options:e.options})}async callGenerateBriefFromPrdEndpoint(e){let t=new k().getApiBaseUrl();if(!t)throw new b(`API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable.`,y.MISSING_CONFIGURATION,{operation:`generateBriefFromPrd`});let n=`${t}/ai/api/v1/briefs/generate-from-prd`,r=await this.authManager.getAccessToken();if(!r)throw new b(`Not authenticated`,y.AUTHENTICATION_ERROR);let i=e.orgId;if(!i)return{success:!1,error:{code:`MISSING_ACCOUNT`,message:`No organization selected. Please run "tm auth" and select an organization first.`}};let a={prdContent:e.prdContent,accountId:i,options:{generateTitle:e.options?.generateTitle??!0,generateDescription:e.options?.generateDescription??!0,title:e.options?.title,description:e.options?.description}};try{let e=await fetch(n,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${r}`,"x-account-id":i},body:JSON.stringify(a)});if(!(e.headers.get(`content-type`)||``).includes(`application/json`)){let t=await e.text();return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${e.status}): ${t.substring(0,100)}...`}}}let t=await e.json(),o=t;if(!e.ok||!o.success){let n=o.error?.message||t?.message||t?.error||`API request failed: ${e.status} - ${e.statusText}`,r=o.error?.code||t?.code||t?.statusCode||`API_ERROR`;return{success:!1,error:{code:String(r),message:String(n)}}}return{success:!0,brief:o.brief,orgId:i,jobId:o.jobId,invitations:o.invitations}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to connect to API: ${e instanceof Error?e.message:String(e)}`}}}}async getBriefStatus(e){if(!await this.authManager.hasValidSession())return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Authentication required`}};let t=new k().getApiBaseUrl();if(!t)return{success:!1,error:{code:`MISSING_CONFIGURATION`,message:`API endpoint not configured`}};let n=`${t}/ai/api/v1/briefs/${e}/status`,r=await this.authManager.getAccessToken();if(!r)return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Not authenticated`}};let i=(await this.authManager.getContext())?.orgId;if(!i){let e=await this.authManager.getOrganizations();e.length>0&&(i=e[0].id)}if(!i)return{success:!1,error:{code:`MISSING_ACCOUNT`,message:`No organization available`}};try{let e=await fetch(n,{method:`GET`,headers:{Authorization:`Bearer ${r}`,"x-account-id":i}});if(!(e.headers.get(`content-type`)||``).includes(`application/json`))return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${e.status})`}};let t=await e.json();return e.ok?{success:!0,status:t}:{success:!1,error:{code:`API_ERROR`,message:t?.message||`Failed to get status: ${e.status}`}}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to get brief status: ${e instanceof Error?e.message:String(e)}`}}}}async sendTeamInvitations(e,t,n=`member`){if(!await this.authManager.hasValidSession())return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Authentication required`}};let r=new k().getApiBaseUrl();if(!r)return{success:!1,error:{code:`MISSING_CONFIGURATION`,message:`API endpoint not configured`}};let i=`${r}/api/teams/${e}/invitations`,a=await this.authManager.getAccessToken();if(!a)return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Not authenticated`}};try{let e=await fetch(i,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${a}`},body:JSON.stringify({emails:t.slice(0,10),role:n})});if(!(e.headers.get(`content-type`)||``).includes(`application/json`))return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${e.status})`}};let r=await e.json(),o=r.data,s=r.invitations||o?.invitations||o||(Array.isArray(r)?r:null),c=r.error;if(e.ok&&s&&Array.isArray(s))return{success:!0,invitations:s.map(e=>({email:e.email||``,status:e.status||`sent`}))};if(!e.ok||c){let n=typeof c==`object`&&c?c:null;return s&&Array.isArray(s)&&s.length>0&&s.every(e=>e.status===`already_member`)||n?.code===`invitation_failed`&&n?.message?.toLowerCase().includes(`already member`)?{success:!0,invitations:Array.isArray(s)?s:t.map(e=>({email:e,status:`already_member`}))}:{success:!1,error:{code:`API_ERROR`,message:r.message||(typeof c==`string`?c:n?.message||JSON.stringify(c))||`Failed to send invitations: ${e.status}`}}}return{success:!1,error:{code:`INVALID_RESPONSE`,message:`No invitations in response`}}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to send invitations: ${e instanceof Error?e.message:String(e)}`}}}}},Pt=class{exportService;constructor(e){this.exportService=new Nt(e,O.getInstance())}async generateBriefFromTasks(e){return this.exportService.generateBriefFromTasks(e)}async exportTasks(e){return this.exportService.exportTasks(e)}async generateBriefFromPrd(e){return this.exportService.generateBriefFromPrd(e)}async getBriefStatus(e){return this.exportService.getBriefStatus(e)}async sendTeamInvitations(e,t,n=`member`){return this.exportService.sendTeamInvitations(e,t,n)}};const Ft={default:`SETUP: If task-master command not found, run: npm i -g task-master-ai
59
+ `).trim()||o}isEnglishLanguage(e){let t=(e||this.configManager.getResponseLanguage()||``).trim().toLowerCase();return t===`english`||t===`en`||t.startsWith(`english-`)||t.startsWith(`en-`)}mapStatusForAPI(e){switch(e){case`pending`:return`todo`;case`in-progress`:return`in_progress`;case`done`:return`done`;default:return`todo`}}async performExport(t,n,r){let i=new k().getApiBaseUrl();if(i){let a=`${i}/ai/api/v1/briefs/${n}/tasks`,o=this.transformTasksForBulkImport(r),s=this.chunkImportTasks(o,e.MAX_TASKS_PER_IMPORT_REQUEST);if(o.length===0){console.log(`No tasks to export for brief ${n} after transformation.`);return}let c=await this.authManager.getAccessToken();if(!c)throw Error(`Not authenticated`);let l=0,u=0,d=[];for(let e=0;e<s.length;e++){let n={source:`task-master-cli`,options:{dryRun:!1,stopOnError:!1},accountId:t,tasks:s[e]},r=await fetch(a,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${c}`},body:JSON.stringify(n)});if(!r.ok){let t=await r.text();throw Error(`API request failed (batch ${e+1}/${s.length}): ${r.status} - ${t}`)}let i=await r.json();l+=i.successCount,u+=i.failedCount,i.failedCount>0&&d.push(...i.results.filter(e=>!e.success).map(e=>`${e.externalId}: ${e.error}`))}if(u>0){let e=d.slice(0,10).join(`, `),t=d.length>10;console.warn(`Warning: ${u} tasks failed to import${e?`: ${e}${t?`, ...`:``}`:``}`)}let f=s.length>1?` in ${s.length} batches`:``;console.log(`Successfully exported ${l} of ${o.length} tasks to brief ${n}${f}`)}else throw Error(`Export API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable to enable task export.`)}chunkImportTasks(e,t){if(e.length===0)return[];let n=Math.max(1,t),r=[];for(let t=0;t<e.length;t+=n)r.push(e.slice(t,t+n));return r}extractBriefId(e){let t=e?.trim()??``;if(!t)return null;let n=e=>{try{return new URL(e)}catch{}try{return new URL(`https://${e}`)}catch{}return null},r=e=>{let t=e.split(`/`).filter(Boolean),n=t.lastIndexOf(`briefs`);return(n>=0&&t.length>n+1?t[n+1]:t[t.length-1])?.trim()||null},i=n(t);if(i){let e=(i.searchParams.get(`id`)||i.searchParams.get(`briefId`)||r(i.pathname))??null;if(e&&(this.isLikelyId(e)||e.length>=8))return e}if(t.includes(`/`)){let e=r(t);if(e&&(this.isLikelyId(e)||e.length>=8))return e}return this.isLikelyId(t)||t.length>=8?t:null}isLikelyId(e){return/^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/.test(e)||/^[0-9A-HJKMNP-TV-Z]{26}$/i.test(e)||/^[A-Za-z0-9_-]{16,}$/.test(e)}async generateBriefFromTasks(e={}){if(!await this.authManager.hasValidSession())throw new b(`Authentication required for export`,y.AUTHENTICATION_ERROR);let t=await this.authManager.getContext(),n=e.orgId||t?.orgId;if(!n){let e=await this.authManager.getOrganizations();if(e.length===0)return{success:!1,error:{code:`NO_ORGANIZATIONS`,message:`No organizations available. Please create an organization in Hamster first.`}};n=e[0].id}let r=this.configManager.getActiveTag(),i=e.tag||r,a=new Mt(this.configManager.getProjectRoot());await a.initialize();let o=await a.loadTasks(i,{status:e.status,excludeSubtasks:e.excludeSubtasks});if(o.length===0)return{success:!1,error:{code:`NO_TASKS`,message:`No tasks found to export`}};let s=this.transformTasksForImport(o),c=this.getProjectName();return this.callGenerateBriefEndpoint({tasks:s,source:{tool:`task-master`,version:this.getVersion(),tag:i,projectName:c},orgId:n,responseLanguage:e.options?.language||this.configManager.getResponseLanguage(),options:e.options})}transformTasksForImport(e){let t=[],n=this.configManager.getResponseLanguage(),r=new Set;for(let t of e)if(r.add(String(t.id)),t.subtasks)for(let e of t.subtasks)r.add(`${t.id}.${e.id}`);for(let i of e){let e=(i.dependencies||[]).map(String).filter(e=>r.has(e));if(t.push({externalId:String(i.id),title:i.title,description:this.enrichDescription(i,n),details:i.details,status:this.mapStatusForImport(i.status),priority:this.mapPriorityForImport(i.priority),dependencies:e,metadata:{originalStatus:i.status,originalPriority:i.priority,testStrategy:i.testStrategy,complexity:i.complexity}}),i.subtasks&&i.subtasks.length>0)for(let e of i.subtasks){let a=(e.dependencies||[]).map(e=>String(e).includes(`.`)?String(e):`${i.id}.${e}`).filter(e=>r.has(e));t.push({externalId:`${i.id}.${e.id}`,parentId:String(i.id),title:e.title,description:this.enrichDescription(e,n),details:e.details,status:this.mapStatusForImport(e.status),priority:this.mapPriorityForImport(e.priority),dependencies:a,metadata:{originalStatus:e.status,originalPriority:e.priority,testStrategy:e.testStrategy,complexity:e.complexity}})}}return t}mapStatusForImport(e){switch(e){case`pending`:return`todo`;case`in-progress`:case`in_progress`:return`in_progress`;case`done`:case`completed`:return`done`;case`blocked`:return`blocked`;default:return`todo`}}mapPriorityForImport(e){switch(e?.toLowerCase()){case`low`:return`low`;case`medium`:return`medium`;case`high`:return`high`;case`critical`:case`urgent`:return`urgent`;default:return`medium`}}getVersion(){try{return process.env.npm_package_version||`1.0.0`}catch{return`1.0.0`}}getProjectName(){try{return this.configManager.getProjectRoot().split(/[/\\]/).pop()||void 0}catch{return}}async callGenerateBriefEndpoint(e){let t=new k().getApiBaseUrl();if(!t)throw new b(`Export API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable.`,y.MISSING_CONFIGURATION,{operation:`generateBriefFromTasks`});let n=`${t}/ai/api/v1/briefs/generate-from-tasks`,r=await this.authManager.getAccessToken();if(!r)throw new b(`Not authenticated`,y.AUTHENTICATION_ERROR);let i=e.orgId;if(!i)return{success:!1,error:{code:`MISSING_ACCOUNT`,message:`No organization selected. Please run "tm auth" and select an organization first.`}};let a={tasks:e.tasks,source:e.source,accountId:i,options:{generateTitle:e.options?.generateTitle??!0,generateDescription:e.options?.generateDescription??!0,preserveHierarchy:e.options?.preserveHierarchy??!0,preserveDependencies:e.options?.preserveDependencies??!0,title:e.options?.title,description:e.options?.description,language:this.isEnglishLanguage(e.responseLanguage)?`English`:`Chinese`}};try{let e={"Content-Type":`application/json`,Authorization:`Bearer ${r}`,"x-account-id":i},t=await fetch(n,{method:`POST`,headers:e,body:JSON.stringify(a)}),o;if(!t.ok&&t.status===400){let r=await t.text();o=r;let i=r.toLowerCase();if(i.includes(`language`)&&(i.includes(`additional`)||i.includes(`schema`)||i.includes(`unknown`))){let r={...a,options:{...a.options}};delete r.options.language,t=await fetch(n,{method:`POST`,headers:e,body:JSON.stringify(r)}),o=void 0}}if(!(t.headers.get(`content-type`)||``).includes(`application/json`)){let e=o||await t.text();return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${t.status}): ${e.substring(0,100)}...`}}}let s=o?JSON.parse(o):await t.json(),c=s;if(!t.ok||!c.success){let e=c.error?.message||s?.message||s?.error||`API request failed: ${t.status} - ${t.statusText}`,n=c.error?.code||s?.code||s?.statusCode||`API_ERROR`;return{success:!1,warnings:c.warnings,error:{code:String(n),message:String(e)}}}return{success:!0,brief:c.brief,taskMapping:c.taskMapping,invitations:c.invitations,warnings:c.warnings}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to connect to API: ${e instanceof Error?e.message:String(e)}`}}}}async generateBriefFromPrd(e){if(!e.prdContent||e.prdContent.trim().length===0)return{success:!1,error:{code:`INVALID_INPUT`,message:`PRD content is required`}};if(!await this.authManager.hasValidSession())throw new b(`Authentication required for PRD import`,y.AUTHENTICATION_ERROR);let t=await this.authManager.getContext(),n=e.orgId||t?.orgId;if(!n){let e=await this.authManager.getOrganizations();if(e.length===0)return{success:!1,error:{code:`NO_ORGANIZATIONS`,message:`No organizations available. Please create an organization in Hamster first.`}};n=e[0].id}return this.callGenerateBriefFromPrdEndpoint({prdContent:e.prdContent,orgId:n,options:e.options})}async callGenerateBriefFromPrdEndpoint(e){let t=new k().getApiBaseUrl();if(!t)throw new b(`API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable.`,y.MISSING_CONFIGURATION,{operation:`generateBriefFromPrd`});let n=`${t}/ai/api/v1/briefs/generate-from-prd`,r=await this.authManager.getAccessToken();if(!r)throw new b(`Not authenticated`,y.AUTHENTICATION_ERROR);let i=e.orgId;if(!i)return{success:!1,error:{code:`MISSING_ACCOUNT`,message:`No organization selected. Please run "tm auth" and select an organization first.`}};let a={prdContent:e.prdContent,accountId:i,options:{generateTitle:e.options?.generateTitle??!0,generateDescription:e.options?.generateDescription??!0,title:e.options?.title,description:e.options?.description}};try{let e=await fetch(n,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${r}`,"x-account-id":i},body:JSON.stringify(a)});if(!(e.headers.get(`content-type`)||``).includes(`application/json`)){let t=await e.text();return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${e.status}): ${t.substring(0,100)}...`}}}let t=await e.json(),o=t;if(!e.ok||!o.success){let n=o.error?.message||t?.message||t?.error||`API request failed: ${e.status} - ${e.statusText}`,r=o.error?.code||t?.code||t?.statusCode||`API_ERROR`;return{success:!1,error:{code:String(r),message:String(n)}}}return{success:!0,brief:o.brief,orgId:i,jobId:o.jobId,invitations:o.invitations}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to connect to API: ${e instanceof Error?e.message:String(e)}`}}}}async getBriefStatus(e){if(!await this.authManager.hasValidSession())return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Authentication required`}};let t=new k().getApiBaseUrl();if(!t)return{success:!1,error:{code:`MISSING_CONFIGURATION`,message:`API endpoint not configured`}};let n=`${t}/ai/api/v1/briefs/${e}/status`,r=await this.authManager.getAccessToken();if(!r)return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Not authenticated`}};let i=(await this.authManager.getContext())?.orgId;if(!i){let e=await this.authManager.getOrganizations();e.length>0&&(i=e[0].id)}if(!i)return{success:!1,error:{code:`MISSING_ACCOUNT`,message:`No organization available`}};try{let e=await fetch(n,{method:`GET`,headers:{Authorization:`Bearer ${r}`,"x-account-id":i}});if(!(e.headers.get(`content-type`)||``).includes(`application/json`))return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${e.status})`}};let t=await e.json();return e.ok?{success:!0,status:t}:{success:!1,error:{code:`API_ERROR`,message:t?.message||`Failed to get status: ${e.status}`}}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to get brief status: ${e instanceof Error?e.message:String(e)}`}}}}async sendTeamInvitations(e,t,n=`member`){if(!await this.authManager.hasValidSession())return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Authentication required`}};let r=new k().getApiBaseUrl();if(!r)return{success:!1,error:{code:`MISSING_CONFIGURATION`,message:`API endpoint not configured`}};let i=`${r}/api/teams/${e}/invitations`,a=await this.authManager.getAccessToken();if(!a)return{success:!1,error:{code:`AUTH_REQUIRED`,message:`Not authenticated`}};try{let e=await fetch(i,{method:`POST`,headers:{"Content-Type":`application/json`,Authorization:`Bearer ${a}`},body:JSON.stringify({emails:t.slice(0,10),role:n})});if(!(e.headers.get(`content-type`)||``).includes(`application/json`))return{success:!1,error:{code:`API_ERROR`,message:`API returned non-JSON response (${e.status})`}};let r=await e.json(),o=r.data,s=r.invitations||o?.invitations||o||(Array.isArray(r)?r:null),c=r.error;if(e.ok&&s&&Array.isArray(s))return{success:!0,invitations:s.map(e=>({email:e.email||``,status:e.status||`sent`}))};if(!e.ok||c){let n=typeof c==`object`&&c?c:null;return s&&Array.isArray(s)&&s.length>0&&s.every(e=>e.status===`already_member`)||n?.code===`invitation_failed`&&n?.message?.toLowerCase().includes(`already member`)?{success:!0,invitations:Array.isArray(s)?s:t.map(e=>({email:e,status:`already_member`}))}:{success:!1,error:{code:`API_ERROR`,message:r.message||(typeof c==`string`?c:n?.message||JSON.stringify(c))||`Failed to send invitations: ${e.status}`}}}return{success:!1,error:{code:`INVALID_RESPONSE`,message:`No invitations in response`}}}catch(e){return{success:!1,error:{code:`NETWORK_ERROR`,message:`Failed to send invitations: ${e instanceof Error?e.message:String(e)}`}}}}},Pt=class{exportService;constructor(e){this.exportService=new Nt(e,O.getInstance())}async generateBriefFromTasks(e){return this.exportService.generateBriefFromTasks(e)}async exportTasks(e){return this.exportService.exportTasks(e)}async generateBriefFromPrd(e){return this.exportService.generateBriefFromPrd(e)}async getBriefStatus(e){return this.exportService.getBriefStatus(e)}async sendTeamInvitations(e,t,n=`member`){return this.exportService.sendTeamInvitations(e,t,n)}};const Ft={default:`SETUP: If task-master command not found, run: npm i -g task-master-ai
60
60
 
61
61
  TASK: Implement ONE task/subtask from the Taskmaster backlog.
62
62
 
@@ -1,4 +1,4 @@
1
- import{a as e,i as t,l as n,n as r,t as i}from"./ai-services-unified-tvfkaOTr.js";import{$ as a,At as o,B as s,Bt as c,C as l,Ct as u,Dn as d,En as f,Jt as p,Kt as m,Lt as h,M as g,Mt as _,O as v,Ot as y,R as b,Rt as x,T as S,Tn as C,Tt as w,X as T,Xt as E,Y as D,Yt as O,Z as k,Zt as A,_ as j,_n as M,a as N,an as P,bt as ee,cn as te,ct as ne,dn as re,dt as ie,en as ae,et as F,fn as oe,ft as se,g as ce,gn as le,gt as ue,hn as de,ht as fe,i as pe,it as me,j as he,k as ge,kn as _e,kt as ve,ln as I,lt as ye,m as be,mn as xe,mt as Se,n as Ce,nn as we,o as Te,on as Ee,p as De,pn as Oe,pt as ke,q as Ae,rt as je,sn as Me,tt as Ne,un as Pe,ut as Fe,v as Ie,vn as Le,vt as L,w as Re,wn as ze,wt as Be,xn as R,y as Ve,yn as He,yt as z,z as Ue}from"./config-manager-Cm3z1HZv.js";import We,{resolve as Ge}from"node:path";import B from"chalk";import*as Ke from"fs";import V from"fs";import H from"path";import qe from"os";import Je from"node:fs";import{fileURLToPath as Ye}from"node:url";import Xe from"node:fs/promises";import Ze from"node:os";import{z as U}from"zod";import{spawn as Qe}from"child_process";import{fileURLToPath as $e}from"url";import{FastMCP as et}from"fastmcp";import{smoothStream as tt}from"ai";import W from"boxen";import nt from"readline";import{Command as G}from"commander";import rt from"figlet";import it from"gradient-string";import at from"terminal-link";import{marked as ot}from"marked";import{markedTerminal as st}from"marked-terminal";import ct from"turndown";import K from"cli-table3";import q from"inquirer";import J from"ora";import lt from"open";import ut,{Separator as dt}from"@inquirer/search";import ft from"process";import pt from"https";import mt from"cli-progress";import ht from"http";import gt from"fuse.js";import _t from"ajv";import vt from"ajv-formats";import yt from"gpt-tokens";import{LRUCache as bt}from"lru-cache";import"@streamparser/json";var xt=`@hhsw2015/task-master-ai`,St=`0.43.19`;function Ct(e,t,n){return(n?.color?B[n.color]:B.cyan)(at(e,t,{fallback:(e,t)=>`${e} (${t})`}))}function wt(e,t){return Ct(e,e,t)}const Tt=it([`#00b4d8`,`#0077b6`,`#03045e`]);function Et(){return process.env.TM_HIDE_BANNER===`true`}function Dt(){return process.stdout.columns||80}function Ot(e={}){if(Et())return;let{version:t}=e;try{let e=rt.textSync(`Task Master`,{font:`Standard`,horizontalLayout:`default`,verticalLayout:`default`});console.log(Tt(e))}catch{console.log(Tt(`=== Task Master ===`))}let n=Ct(`x.com/eyaltoledano`,`https://x.com/eyaltoledano`),r=B.dim(`by `)+B.cyan(n),i=t?t.replace(/^v/,``):``,a=`https://github.com/eyaltoledano/claude-task-master/releases/tag/task-master-ai%40${i}`,o=t?Ct(`v${i}`,a,{color:`gray`}):``;if(o){let e=i.length+1,t=Dt(),n=Math.max(2,t-22-e-2);console.log(r+` `.repeat(n)+o)}else console.log(r);let s=Ct(`tryhamster.com`,`https://tryhamster.com`);console.log(B.dim(`Taskmaster for teams: `)+B.magenta(s)),console.log(``)}function kt(){if(Et())return;try{let e=rt.textSync(`Task Master`,{font:`Standard`,horizontalLayout:`default`,verticalLayout:`default`});console.log(Tt(e))}catch{console.log(Tt(`=== Task Master ===`))}let e=Ct(`x.com/eyaltoledano`,`https://x.com/eyaltoledano`);console.log(B.dim(`by `)+B.cyan(e));let t=Ct(`tryhamster.com`,`https://tryhamster.com`);console.log(B.dim(`Taskmaster for teams: `)+B.magenta(t)),console.log(``)}function At(e){let{header:t,body:n,callToAction:r,footer:i,level:a=`warn`}=e,o=a===`info`?B.blue.bold:B.yellow.bold,s=a===`info`?`blue`:`yellow`,c=[o(t),...n.map(e=>B.white(e))];return r&&r.label&&r.action&&c.push(B.cyan(r.label)+`
1
+ import{a as e,i as t,l as n,n as r,t as i}from"./ai-services-unified-DWAPupZV.js";import{$ as a,At as o,B as s,Bt as c,C as l,Ct as u,Dn as d,En as f,Jt as p,Kt as m,Lt as h,M as g,Mt as _,O as v,Ot as y,R as b,Rt as x,T as S,Tn as C,Tt as w,X as T,Xt as E,Y as D,Yt as O,Z as k,Zt as A,_ as j,_n as M,a as N,an as P,bt as ee,cn as te,ct as ne,dn as re,dt as ie,en as ae,et as F,fn as oe,ft as se,g as ce,gn as le,gt as ue,hn as de,ht as fe,i as pe,it as me,j as he,k as ge,kn as _e,kt as ve,ln as I,lt as ye,m as be,mn as xe,mt as Se,n as Ce,nn as we,o as Te,on as Ee,p as De,pn as Oe,pt as ke,q as Ae,rt as je,sn as Me,tt as Ne,un as Pe,ut as Fe,v as Ie,vn as Le,vt as L,w as Re,wn as ze,wt as Be,xn as R,y as Ve,yn as He,yt as z,z as Ue}from"./config-manager-cNtpB94F.js";import We,{resolve as Ge}from"node:path";import B from"chalk";import*as Ke from"fs";import V from"fs";import H from"path";import qe from"os";import Je from"node:fs";import{fileURLToPath as Ye}from"node:url";import Xe from"node:fs/promises";import Ze from"node:os";import{z as U}from"zod";import{spawn as Qe}from"child_process";import{fileURLToPath as $e}from"url";import{FastMCP as et}from"fastmcp";import{smoothStream as tt}from"ai";import W from"boxen";import nt from"readline";import{Command as G}from"commander";import rt from"figlet";import it from"gradient-string";import at from"terminal-link";import{marked as ot}from"marked";import{markedTerminal as st}from"marked-terminal";import ct from"turndown";import K from"cli-table3";import q from"inquirer";import J from"ora";import lt from"open";import ut,{Separator as dt}from"@inquirer/search";import ft from"process";import pt from"https";import mt from"cli-progress";import ht from"http";import gt from"fuse.js";import _t from"ajv";import vt from"ajv-formats";import yt from"gpt-tokens";import{LRUCache as bt}from"lru-cache";import"@streamparser/json";var xt=`@hhsw2015/task-master-ai`,St=`0.43.20`;function Ct(e,t,n){return(n?.color?B[n.color]:B.cyan)(at(e,t,{fallback:(e,t)=>`${e} (${t})`}))}function wt(e,t){return Ct(e,e,t)}const Tt=it([`#00b4d8`,`#0077b6`,`#03045e`]);function Et(){return process.env.TM_HIDE_BANNER===`true`}function Dt(){return process.stdout.columns||80}function Ot(e={}){if(Et())return;let{version:t}=e;try{let e=rt.textSync(`Task Master`,{font:`Standard`,horizontalLayout:`default`,verticalLayout:`default`});console.log(Tt(e))}catch{console.log(Tt(`=== Task Master ===`))}let n=Ct(`x.com/eyaltoledano`,`https://x.com/eyaltoledano`),r=B.dim(`by `)+B.cyan(n),i=t?t.replace(/^v/,``):``,a=`https://github.com/eyaltoledano/claude-task-master/releases/tag/task-master-ai%40${i}`,o=t?Ct(`v${i}`,a,{color:`gray`}):``;if(o){let e=i.length+1,t=Dt(),n=Math.max(2,t-22-e-2);console.log(r+` `.repeat(n)+o)}else console.log(r);let s=Ct(`tryhamster.com`,`https://tryhamster.com`);console.log(B.dim(`Taskmaster for teams: `)+B.magenta(s)),console.log(``)}function kt(){if(Et())return;try{let e=rt.textSync(`Task Master`,{font:`Standard`,horizontalLayout:`default`,verticalLayout:`default`});console.log(Tt(e))}catch{console.log(Tt(`=== Task Master ===`))}let e=Ct(`x.com/eyaltoledano`,`https://x.com/eyaltoledano`);console.log(B.dim(`by `)+B.cyan(e));let t=Ct(`tryhamster.com`,`https://tryhamster.com`);console.log(B.dim(`Taskmaster for teams: `)+B.magenta(t)),console.log(``)}function At(e){let{header:t,body:n,callToAction:r,footer:i,level:a=`warn`}=e,o=a===`info`?B.blue.bold:B.yellow.bold,s=a===`info`?`blue`:`yellow`,c=[o(t),...n.map(e=>B.white(e))];return r&&r.label&&r.action&&c.push(B.cyan(r.label)+`
2
2
  `+B.blue.underline(r.action)),i&&c.push(B.gray(i)),W(c.join(`
3
3
 
4
4
  `),{padding:1,borderColor:s,borderStyle:`round`,margin:{top:1,bottom:1}})}function jt(e,t=30,n){if(!n){let n=Math.round(e/100*t),r=t-n;return B.green(`█`).repeat(n)+B.gray(`░`).repeat(r)}let r=``,i=0;if(n.done&&n.done>0){let e=Math.round(n.done/100*t);e>0&&(r+=B.green(`█`).repeat(e),i+=e)}if(n.cancelled&&i<t){let e=Math.round(n.cancelled/100*t),a=Math.min(e,t-i);a>0&&(r+=B.gray(`█`).repeat(a),i+=a)}if(n.deferred&&i<t){let e=Math.round(n.deferred/100*t),a=Math.min(e,t-i);a>0&&(r+=B.gray(`█`).repeat(a),i+=a)}if(n[`in-progress`]&&i<t){let e=Math.round(n[`in-progress`]/100*t),a=Math.min(e,t-i);a>0&&(r+=B.blue(`█`).repeat(a),i+=a)}if(n.review&&i<t){let e=Math.round(n.review/100*t),a=Math.min(e,t-i);a>0&&(r+=B.magenta(`░`).repeat(a),i+=a)}if(n.pending&&i<t){let e=Math.round(n.pending/100*t),a=Math.min(e,t-i);a>0&&(r+=B.yellow(`░`).repeat(a),i+=a)}if(n.blocked&&i<t){let e=Math.round(n.blocked/100*t),a=Math.min(e,t-i);a>0&&(r+=B.red(`░`).repeat(a),i+=a)}return i<t&&(r+=B.yellow(`░`).repeat(t-i)),r}function Mt(e){let t={total:e.length,done:0,inProgress:0,pending:0,blocked:0,deferred:0,cancelled:0,review:0,completionPercentage:0,completedCount:0};return e.forEach(e=>{switch(e.status){case`done`:t.done++;break;case`in-progress`:t.inProgress++;break;case`pending`:t.pending++;break;case`blocked`:t.blocked++;break;case`deferred`:t.deferred++;break;case`cancelled`:t.cancelled++;break;case`review`:t.review=(t.review||0)+1;break}}),t.completedCount=e.filter(e=>He(e.status)).length,t.completionPercentage=t.total>0?Math.round(t.completedCount/t.total*100):0,t}function Nt(e){let t={total:0,done:0,inProgress:0,pending:0,blocked:0,deferred:0,cancelled:0,review:0,completionPercentage:0,completedCount:0},n=[];return e.forEach(e=>{e.subtasks&&e.subtasks.length>0&&e.subtasks.forEach(e=>{switch(t.total++,n.push(e),e.status){case`done`:t.done++;break;case`in-progress`:t.inProgress++;break;case`pending`:t.pending++;break;case`blocked`:t.blocked++;break;case`deferred`:t.deferred++;break;case`cancelled`:t.cancelled++;break;case`review`:t.review=(t.review||0)+1;break}})}),t.completedCount=n.filter(e=>He(e.status)).length,t.completionPercentage=t.total>0?Math.round(t.completedCount/t.total*100):0,t}function Pt(e){let t=new Set(e.filter(e=>He(e.status)).map(e=>e.id)),n=e.filter(e=>!He(e.status)&&(!e.dependencies||e.dependencies.length===0)).length,r=e.filter(e=>!He(e.status)&&e.dependencies&&e.dependencies.length>0&&e.dependencies.every(e=>t.has(e))).length,i=e.filter(e=>!He(e.status)&&e.dependencies&&e.dependencies.length>0&&!e.dependencies.every(e=>t.has(e))).length,a={};e.forEach(e=>{e.dependencies&&e.dependencies.length>0&&e.dependencies.forEach(e=>{let t=String(e);a[t]=(a[t]||0)+1})});let o,s=0;for(let[e,t]of Object.entries(a))t>s&&(s=t,o=parseInt(e));let c=e.reduce((e,t)=>e+(t.dependencies?t.dependencies.length:0),0),l=e.length>0?c/e.length:0;return{tasksWithNoDeps:n,tasksReadyToWork:n+r,tasksBlockedByDeps:i,mostDependedOnTaskId:o,mostDependedOnCount:s,avgDependenciesPerTask:l}}function Ft(e){let t={critical:0,high:0,medium:0,low:0};return e.forEach(e=>{let n=e.priority||`medium`;t[n]++}),t}function It(e){return e.total===0?{}:{done:e.done/e.total*100,"in-progress":e.inProgress/e.total*100,pending:e.pending/e.total*100,blocked:e.blocked/e.total*100,deferred:e.deferred/e.total*100,cancelled:e.cancelled/e.total*100,review:(e.review||0)/e.total*100}}function Lt(e,t=!1){let n=[];t?n.push(`Completed: ${B.green(`${e.completedCount}/${e.total}`)}`):n.push(`Done: ${B.green(e.done)}`),n.push(`Cancelled: ${B.gray(e.cancelled)}`),n.push(`Deferred: ${B.gray(e.deferred)}`);let r=n.join(` `);n.length=0,n.push(`In Progress: ${B.blue(e.inProgress)}`),n.push(`Review: ${B.magenta(e.review||0)}`),n.push(`Pending: ${B.yellow(e.pending)}`),n.push(`Blocked: ${B.red(e.blocked)}`);let i=n.join(` `);return r+`
@@ -950,7 +950,7 @@ ${B.cyan(`1.`)} Run ${B.yellow(`task-master next`)} to see what to work on next\
950
950
  ${B.cyan(`1.`)} Run ${B.yellow(`task-master list`)} to view all tasks\n${B.cyan(`2.`)} Run ${B.yellow(`task-master expand --id=<id>`)} to break down a task into subtasks\n${B.cyan(`3.`)} Run ${B.yellow(`task-master analyze-complexity`)} to analyze task complexity`;console.log(W(e,ns.nextSteps))}function hs(e){return Math.ceil(e.length/4)}function gs(e){let t=V.readFileSync(e,`utf8`);if(!t)throw Error(`Input file ${e} is empty or could not be read.`);return t}function _s(e,t){let n=[],r=1;if(!V.existsSync(e))return{existingTasks:n,nextId:r};try{let i=V.readFileSync(e,`utf8`),a=JSON.parse(i);a[t]?.tasks&&Array.isArray(a[t].tasks)&&(n=a[t].tasks,n.length>0&&(r=Math.max(...n.map(e=>e.id||0))+1))}catch{return{existingTasks:[],nextId:1}}return{existingTasks:n,nextId:r}}function vs({existingTasks:e,targetTag:t,append:n,force:r,isMCP:i,logger:a}){if(!(e.length>0)){a.report(`Tag '${t}' is empty or doesn't exist. Creating/updating tag with new tasks.`,`info`);return}if(n){a.report(`Append mode enabled. Found ${e.length} existing tasks in tag '${t}'.`,`info`);return}if(!r){let n=`Tag '${t}' already contains ${e.length} tasks. Use --force to overwrite or --append to add to existing tasks.`;if(a.report(n,`error`),i)throw Error(n);console.error(B.red(n)),process.exit(1)}a.report(`Force flag enabled. Overwriting existing tasks in tag '${t}'.`,`debug`)}function ys(e,t,n,r){bs(e,t);let i=t,a=new Map,o=e.map(e=>{let t=i++;return a.set(e.id,t),{...e,id:t,status:e.status||`pending`,priority:e.priority||r,dependencies:Array.isArray(e.dependencies)?e.dependencies:[],subtasks:e.subtasks||[],title:e.title||``,description:e.description||``,details:e.details||``,testStrategy:e.testStrategy||``}});return o.forEach(e=>{e.dependencies=e.dependencies.map(e=>a.get(e)).filter(t=>t!=null&&t<e.id&&(ie(n,t)||o.some(e=>e.id===t)))}),o}function bs(e,t=1){if(!Array.isArray(e)||e.length===0)return;let n=e.map(e=>e.id);if(n.some(e=>!Number.isInteger(e)||e<1))throw Error(`PRD tasks must use sequential positive integer IDs starting at 1.`);let r=new Set(n);if(r.size!==n.length)throw Error(`PRD task IDs must be unique and sequential starting at 1.`);let i=[...r].sort((e,t)=>e-t),a=i[0];if(a!==1&&a!==t)throw Error(`PRD task IDs must start at 1 or ${t} and be sequential.`);for(let e=0;e<i.length;e+=1)if(i[e]!==a+e)throw Error(`PRD task IDs must be a contiguous sequence starting at ${a}.`)}function xs(e,t,n,r){let i=H.dirname(e);V.existsSync(i)||V.mkdirSync(i,{recursive:!0});let a={};if(V.existsSync(e))try{let t=V.readFileSync(e,`utf8`);a=JSON.parse(t)}catch{a={}}a[n]={tasks:t,metadata:{created:a[n]?.metadata?.created||new Date().toISOString(),updated:new Date().toISOString(),description:`Tasks for ${n} context`}},ne(a[n],{description:`Tasks for ${n} context`}),V.writeFileSync(e,JSON.stringify(a,null,2)),r.report(`Successfully saved ${t.length} tasks to ${e}`,`debug`)}async function Ss(e,t,n){let r=Pa(),i=ce(e.projectRoot)||`medium`;return r.loadPrompt(`parse-prd`,{research:e.research,numTasks:e.numTasks,nextId:n,prdContent:t,prdPath:e.prdPath,defaultTaskPriority:i,hasCodebaseAnalysis:e.hasCodebaseAnalysis({command:`parse-prd`,prdContent:t,numTasks:e.numTasks}),projectRoot:e.projectRoot||``})}async function Cs({task:e,currentCount:t,totalTasks:n,estimatedTokens:r,progressTracker:i,reportProgress:a,priorityMap:o,defaultPriority:s,estimatedInputTokens:c}){let l=e.priority||s,u=o[l]||o.medium;if(i&&(i.addTaskLine(t,e.title,l),r&&i.updateTokens(c,r)),a)try{let i=r?Math.floor(r/n):0;await a({progress:t,total:n,message:`${u} Task ${t}/${n} - ${e.title} | ~Output: ${i} tokens`})}catch{}}async function ws({processedTasks:e,nextId:t,summary:n,prdPath:r,tasksPath:i,usedFallback:a,aiServiceResponse:o}){let s=(()=>{if(!Array.isArray(e)||e.length===0)return`task_${String(t).padStart(3,`0`)}.txt`;let n=e[0].id,r=e[e.length-1].id;return e.length===1?`task_${String(n).padStart(3,`0`)}.txt`:`task_${String(n).padStart(3,`0`)}.txt -> task_${String(r).padStart(3,`0`)}.txt`})();fs({totalTasks:e.length,taskPriorities:n.taskPriorities,prdFilePath:r,outputPath:i,elapsedTime:n.elapsedTime,usedFallback:a,taskFilesGenerated:s,actionVerb:n.actionVerb}),o?.telemetryData&&(o.mainResult?.usage&&await qo.withSoftTimeout(o.mainResult.usage,1e3,void 0),kl(o.telemetryData,`cli`))}function Ts({processedTasks:e,research:t,finalTasks:n,tasksPath:r,aiServiceResponse:i}){console.log(W(B.green(`Successfully generated ${e.length} new tasks${t?` with research-backed analysis`:``}. Total tasks in ${r}: ${n.length}`),{padding:1,borderColor:`green`,borderStyle:`round`})),console.log(W(B.white.bold(`Next Steps:`)+`
951
951
 
952
952
  ${B.cyan(`1.`)} Run ${B.yellow(`task-master list`)} to view all tasks\n${B.cyan(`2.`)} Run ${B.yellow(`task-master expand --id=<id>`)} to break down a task into subtasks`,{padding:1,borderColor:`cyan`,borderStyle:`round`,margin:{top:1}})),i?.telemetryData&&kl(i.telemetryData,`cli`)}async function Es(e,t){let n=new Qo(e.mcpLog,e.reportProgress),{systemPrompt:r,userPrompt:a}=t,o=hs(r+a),s=null;e.outputFormat===`text`&&!e.isMCP&&(s=J(`Parsing PRD and generating tasks...
953
- `).start());try{n.report(`Calling AI service to generate tasks from PRD${e.research?` with research-backed analysis`:``}...`,`info`);let t=await i({role:e.research?`research`:`main`,session:e.session,projectRoot:e.projectRoot,schema:Xo,objectName:`tasks_data`,systemPrompt:r,prompt:a,commandName:`parse-prd`,outputType:e.isMCP?`mcp`:`cli`}),c=null;if(t?.mainResult&&(typeof t.mainResult==`object`&&t.mainResult!==null&&`tasks`in t.mainResult?c=t.mainResult:typeof t.mainResult.object==`object`&&t.mainResult.object!==null&&`tasks`in t.mainResult.object&&(c=t.mainResult.object)),!c||!Array.isArray(c.tasks))throw Error(`AI service returned unexpected data structure after validation.`);return s&&s.succeed(`Tasks generated successfully!`),{parsedTasks:c.tasks,aiServiceResponse:t,estimatedInputTokens:o}}catch(e){throw s&&s.fail(`Error parsing PRD: ${e.message}`),e}}const[Ds,Os,ks]=aa,As=new Map;var js=class{constructor(e,t,n,r=null){this.name=e,this.levels=t,this.colors=n,this.thresholds=r}getColor(e){return this.colors[e]||B.gray}getLevelFromScore(e){if(!this.thresholds)throw Error(`${this.name} does not support score-based levels`);return e>=7?this.levels[0]:e<=3?this.levels[2]:this.levels[1]}};const Ms={cli:{filled:`●`,empty:`○`},statusBar:{high:`⋮`,medium:`:`,low:`.`},mcp:{high:`🔴`,medium:`🟠`,low:`🟢`}},Ns=new js(`priority`,[Ds,Os,ks],{[Ds]:B.hex(`#CC0000`),[Os]:B.hex(`#FF8800`),[ks]:B.yellow});function Ps(e,t){let n=Ms.cli.filled,r=Ms.cli.empty,i=``;for(let a=0;a<3;a++)a<e?i+=t(n):i+=B.white(r);return i}function Fs(e,t){return 3-t.indexOf(e)}function Is(e,t){if(As.has(e))return As.get(e);let n=t();return As.set(e,n),n}function Ls(){return Is(`mcp-priority-all`,()=>({[Ds]:Ms.mcp.high,[Os]:Ms.mcp.medium,[ks]:Ms.mcp.low}))}function Rs(){return Is(`cli-priority-all`,()=>{let e={};return Ns.levels.forEach(t=>{e[t]=Ps(Fs(t,Ns.levels),Ns.getColor(t))}),e})}function zs(){return Is(`statusbar-priority-all`,()=>{let e={};return Ns.levels.forEach((t,n)=>{let r=n===0?Ms.statusBar.high:n===1?Ms.statusBar.medium:Ms.statusBar.low;e[t]=Ns.getColor(t)(r)}),e})}function Bs(){return{[Ds]:Ns.colors[Ds],[Os]:Ns.colors[Os],[ks]:Ns.colors[ks]}}function Vs(e=!1){return e?Ls():Rs()}function Hs(e,t=!1){let n=Vs(t);return n[e]||n[Os]}new js(`complexity`,[`high`,`medium`,`low`],{high:B.hex(`#CC0000`),medium:B.hex(`#FF8800`),low:B.green},{high:e=>e>=7,medium:e=>e>=4&&e<=6,low:e=>e<=3});const Us={clearOnComplete:!1,stopOnComplete:!0,hideCursor:!0,barsize:40},Ws={shades_classic:mt.Presets.shades_classic,shades_grey:mt.Presets.shades_grey,rect:mt.Presets.rect,legacy:mt.Presets.legacy},Gs=new class{constructor(e={},t=Ws.shades_classic){this.defaultOptions={...Us,...e},this.defaultPreset=t}createSingleBar(e={},t=null){let n=this._mergeConfig(e),r=t||this.defaultPreset;return new mt.SingleBar(n,r)}createMultiBar(e={},t=null){let n=this._mergeConfig(e),r=t||this.defaultPreset;return new mt.MultiBar(n,r)}_mergeConfig(e){return{...this.defaultOptions,...e}}setDefaultOptions(e){this.defaultOptions={...this.defaultOptions,...e}}setDefaultPreset(e){this.defaultPreset=e}};function Ks(e={}){return Gs.createMultiBar(e)}var qs=class{constructor(e={}){this.numUnits=e.numUnits||1,this.unitName=e.unitName||`unit`,this.startTime=null,this.completedUnits=0,this.tokensIn=0,this.tokensOut=0,this.isEstimate=!0,this.bestAvgTimePerUnit=null,this.lastEstimateTime=null,this.lastEstimateSeconds=0,this.multibar=null,this.timeTokensBar=null,this.progressBar=null,this._timerInterval=null,this.isStarted=!1,this.isFinished=!1,this._initializeCustomProperties(e)}_initializeCustomProperties(e){}get unitNamePlural(){return`${this.unitName}s`}start(){this.isStarted||this.isFinished||(this.isStarted=!0,this.startTime=Date.now(),this.multibar=Ks(),this.timeTokensBar=this.multibar.create(1,0,{},{format:this._getTimeTokensBarFormat(),barsize:1,hideCursor:!0,clearOnComplete:!1}),this.progressBar=this.multibar.create(this.numUnits,0,{},{format:this._getProgressBarFormat(),barCompleteChar:`█`,barIncompleteChar:`░`}),this._updateTimeTokensBar(),this.progressBar.update(0,{[this.unitNamePlural]:`0/${this.numUnits}`}),this._timerInterval=setInterval(()=>this._updateTimeTokensBar(),1e3),this._setupCustomUI())}_setupCustomUI(){}_getTimeTokensBarFormat(){return`{clock} {elapsed} | Tokens (I/O): {in}/{out} | Est: {remaining}`}_getProgressBarFormat(){return`${this.unitName.charAt(0).toUpperCase()+this.unitName.slice(1)}s {${this.unitNamePlural}} |{bar}| {percentage}%`}updateTokens(e,t,n=!1){this.tokensIn=e||0,this.tokensOut=t||0,this.isEstimate=n,this._updateTimeTokensBar()}_updateTimeTokensBar(){if(!this.timeTokensBar||this.isFinished)return;let e=this._formatElapsedTime(),t=this._estimateRemainingTime(),n=this.isEstimate?`~ Tokens (I/O)`:`Tokens (I/O)`;this.timeTokensBar.update(1,{clock:`⏱️`,elapsed:e,in:this.tokensIn,out:this.tokensOut,remaining:t,tokensLabel:n,...this._getCustomTimeTokensPayload()})}_getCustomTimeTokensPayload(){return{}}_formatElapsedTime(){if(!this.startTime)return`0m 00s`;let e=Math.floor((Date.now()-this.startTime)/1e3);return`${Math.floor(e/60)}m ${(e%60).toString().padStart(2,`0`)}s`}_estimateRemainingTime(){let e=this._getProgressFraction();if(e>=1)return`~0s`;let t=Date.now(),n=(t-this.startTime)/1e3;if(e===0)return`~calculating...`;let r=n/e;(this.bestAvgTimePerUnit===null||r<this.bestAvgTimePerUnit)&&(this.bestAvgTimePerUnit=r);let i=this.numUnits*(1-e),a=Math.ceil(i*this.bestAvgTimePerUnit);if(this.lastEstimateTime){let e=Math.floor((t-this.lastEstimateTime)/1e3),n=Math.max(0,this.lastEstimateSeconds-e);if(n===0)return`~0s`;a=Math.min(a,n)}return this.lastEstimateTime=t,this.lastEstimateSeconds=a,`~${this._formatDuration(a)}`}_getProgressFraction(){return this.completedUnits/this.numUnits}_formatDuration(e){if(e<60)return`${e}s`;let t=Math.floor(e/60),n=e%60;return t<60?n>0?`${t}m ${n}s`:`${t}m`:`${Math.floor(t/60)}h ${t%60}m`}getElapsedTime(){return this.startTime?Date.now()-this.startTime:0}stop(){this.isFinished||(this.isFinished=!0,this._timerInterval&&=(clearInterval(this._timerInterval),null),this.multibar&&(this._updateTimeTokensBar(),this.multibar.stop()),this.cleanup())}getSummary(){return{completedUnits:this.completedUnits,elapsedTime:this.getElapsedTime()}}cleanup(){if(this._timerInterval&&=(clearInterval(this._timerInterval),null),this.multibar){try{this.multibar.stop()}catch{}this.multibar=null}this.timeTokensBar=null,this.progressBar=null,this.isStarted=!1,this.isFinished=!0,this._performCustomCleanup()}_performCustomCleanup(){}},Js=class{constructor(e){if(!e)throw Error(`Multibar instance is required`);this.multibar=e}createBar(e,t={}){if(typeof e!=`string`)throw Error(`Format must be a string`);let n=this.multibar.create(1,1,{},{format:e,barsize:1,hideCursor:!0,clearOnComplete:!1});return n.update(1,t),n}createHeader(e,t){this.createBar(t),this.createBar(e),this.createBar(t)}createRow(e,t){if(!t||typeof t!=`object`)throw Error(`Payload must be an object`);return this.createBar(e,t)}createBorder(e){return this.createBar(e)}};function Ys(e,t,n){new Js(e).createHeader(t,n)}function Xs(e,t,n){new Js(e).createRow(t,n)}function Zs(e,t){new Js(e).createBorder(t)}Rs();const Qs=zs();Bs();const $s={DEBOUNCE_DELAY:100,MAX_TITLE_LENGTH:57,TRUNCATED_LENGTH:54,TASK_ID_PAD_START:3,TASK_ID_PAD_END:4,PRIORITY_PAD_END:3,VALID_PRIORITIES:[`high`,`medium`,`low`],DEFAULT_PRIORITY:`medium`};var ec=class{constructor(e=$s.DEBOUNCE_DELAY){this.delay=e,this.pendingTimeout=null}debounce(e){this.clear(),this.pendingTimeout=setTimeout(()=>{e(),this.pendingTimeout=null},this.delay)}clear(){this.pendingTimeout&&=(clearTimeout(this.pendingTimeout),null)}hasPending(){return this.pendingTimeout!==null}},tc=class{constructor(){this.priorities={high:0,medium:0,low:0}}increment(e){let t=this.normalize(e);return this.priorities[t]++,t}normalize(e){let t=e?e.toLowerCase():$s.DEFAULT_PRIORITY;return $s.VALID_PRIORITIES.includes(t)?t:$s.DEFAULT_PRIORITY}getCounts(){return{...this.priorities}}},nc=class{static formatTitle(e,t){return e?e.length>$s.MAX_TITLE_LENGTH?e.substring(0,$s.TRUNCATED_LENGTH)+`...`:e:`Task ${t}`}static formatPriority(e){return Hs(e,!1).padEnd($s.PRIORITY_PAD_END,` `)}static formatTaskId(e){return e.toString().padStart($s.TASK_ID_PAD_START,` `).padEnd($s.TASK_ID_PAD_END,` `)}},rc=class extends qs{_initializeCustomProperties(e){this.append=e.append,this.priorityManager=new tc,this.debouncer=new ec,this.headerShown=!1}_getTimeTokensBarFormat(){return`{clock} {elapsed} | ${Qs.high} {high} ${Qs.medium} {medium} ${Qs.low} {low} | Tokens (I/O): {in}/{out} | Est: {remaining}`}_getProgressBarFormat(){return`Tasks {tasks} |{bar}| {percentage}%`}_getCustomTimeTokensPayload(){return this.priorityManager.getCounts()}addTaskLine(e,t,n=`medium`){if(!this.multibar||this.isFinished)return;this._ensureHeaderShown();let r=this._updateTaskCounters(e,n);this._updateTimeTokensBar(),this.debouncer.debounce(()=>{this._updateProgressDisplay(e,t,r)})}_ensureHeaderShown(){this.headerShown||(this.headerShown=!0,Ys(this.multibar,` TASK | PRI | TITLE`,`------+-----+----------------------------------------------------------------`))}_updateTaskCounters(e,t){let n=this.priorityManager.increment(t);return this.completedUnits=e,n}_updateProgressDisplay(e,t,n){this.progressBar.update(this.completedUnits,{tasks:`${this.completedUnits}/${this.numUnits}`});let r=nc.formatTitle(t,e),i=nc.formatPriority(n),a=nc.formatTaskId(e);Xs(this.multibar,` ${a} | ${i} | {title}`,{title:r}),Zs(this.multibar,`------+-----+----------------------------------------------------------------`),this._updateTimeTokensBar()}finish(){this.debouncer.hasPending()&&(this.debouncer.clear(),this._updateTimeTokensBar()),this.cleanup(),super.finish()}_performCustomCleanup(){this.debouncer.clear()}getSummary(){return{...super.getSummary(),taskPriorities:this.priorityManager.getCounts(),actionVerb:this.append?`appended`:`generated`}}};function ic(e={}){return new rc(e)}async function ac(e,t,n){let r=oc(e,t,n);await cc(e,n,r.estimatedInputTokens);let i=await lc(e,t,e.streamingTimeout),{progressTracker:a,priorityMap:o}=await uc(e,n),s=await dc(i.mainResult,e,t,n,a,o,r.defaultPriority,r.estimatedInputTokens,r.logger);if(sc(s),s.usage&&e.projectRoot){let{logAiUsage:t}=await import(`./ai-services-unified-D56eIxmP.js`),{getUserId:n}=await import(`./config-manager-B7h71nH_.js`),a=n(e.projectRoot);if(a&&i.providerName&&i.modelId)try{let n=await t({userId:a,commandName:`parse-prd`,providerName:i.providerName,modelId:i.modelId,inputTokens:s.usage.promptTokens||0,outputTokens:s.usage.completionTokens||0,outputType:e.isMCP?`mcp`:`cli`});n&&(i.telemetryData=n)}catch(e){r.logger.report(`Failed to log telemetry: ${e.message}`,`debug`)}}return xc(s,i,r.estimatedInputTokens,a)}function oc(e,t,n){let{systemPrompt:r,userPrompt:i}=t;return{logger:new Qo(e.mcpLog,e.reportProgress),estimatedInputTokens:hs(r+i),defaultPriority:ce(e.projectRoot)||`medium`}}function sc(e){if(e.parsedTasks.length===0)throw Error(`No tasks were generated from the PRD`)}async function cc(e,t,n){e.reportProgress&&await e.reportProgress({progress:0,total:t,message:`Starting PRD analysis (Input: ${n} tokens)${e.research?` with research`:``}...`})}async function lc(e,n,r){let{systemPrompt:i,userPrompt:a}=n;return await qo.withTimeout(t({role:e.research?`research`:`main`,session:e.session,projectRoot:e.projectRoot,schema:Xo,systemPrompt:i,prompt:a,commandName:`parse-prd`,outputType:e.isMCP?`mcp`:`cli`}),r,`Streaming operation`)}async function uc(e,t){let n=Vs(e.isMCP),r=null;if(e.outputFormat===`text`&&!e.isMCP){r=ic({numUnits:t,unitName:`task`,append:e.append});let n=e.research?he():l(),i=v(e.research?`research`:`main`);ss({prdFilePath:e.prdPath,outputPath:e.tasksPath,numTasks:t,append:e.append,research:e.research,force:e.force,existingTasks:[],nextId:1,model:n||`Default`,temperature:i?.temperature||.7}),r.start()}return{progressTracker:r,priorityMap:n}}async function dc(e,t,n,r,i,a,o,s,c){let{systemPrompt:l,userPrompt:u}=n,d={config:{...t,schema:Xo},numTasks:r,progressTracker:i,priorityMap:a,defaultPriority:o,estimatedInputTokens:s,prompt:u,systemPrompt:l};try{let t={lastPartialObject:null,taskCount:0,estimatedOutputTokens:0,usage:null};if(await fc(e.partialObjectStream,t,d),e.usage)try{t.usage=await e.usage}catch(e){c.report(`Failed to get usage data: ${e.message}`,`debug`)}return gc(t,d)}catch(e){return c.report(`StreamObject processing failed: ${e.message}. Falling back to generateObject.`,`debug`),await bc(d,c)}}async function fc(e,t,n){for await(let r of e)t.lastPartialObject=r,r&&(t.estimatedOutputTokens=hs(JSON.stringify(r))),await pc(r,t,n)}async function pc(e,t,n){if(!e?.tasks||!Array.isArray(e.tasks))return;let r=e.tasks.length;r>t.taskCount?(await mc(e.tasks,t.taskCount,r,t.estimatedOutputTokens,n),t.taskCount=r):n.progressTracker&&t.estimatedOutputTokens>0&&n.progressTracker.updateTokens(n.estimatedInputTokens,t.estimatedOutputTokens,!0)}async function mc(e,t,n,r,i){for(let a=t;a<n;a++){let t=e[a]||{};t.title?await Cs({task:t,currentCount:a+1,totalTasks:i.numTasks,estimatedTokens:r,progressTracker:i.progressTracker,reportProgress:i.config.reportProgress,priorityMap:i.priorityMap,defaultPriority:i.defaultPriority,estimatedInputTokens:i.estimatedInputTokens}):await hc(a+1,r,i)}}async function hc(e,t,n){let{progressTracker:r,config:i,numTasks:a,defaultPriority:o,estimatedInputTokens:s}=n;r&&(r.addTaskLine(e,`Generating task ${e}...`,o),r.updateTokens(s,t,!0)),i.reportProgress&&!r&&await i.reportProgress({progress:e,total:a,message:`Generating task ${e}/${a}...`})}async function gc(e,t){let{lastPartialObject:n,estimatedOutputTokens:r,taskCount:i,usage:a}=e;if(!n?.tasks||!Array.isArray(n.tasks))throw Error(`No tasks generated from streamObject`);let o=a?.completionTokens||r,s=a?.promptTokens||t.estimatedInputTokens;return t.progressTracker&&await _c(n.tasks,i,a?o:r,t,a?s:null),{parsedTasks:n.tasks,estimatedOutputTokens:o,actualInputTokens:s,usage:a,usedFallback:!1}}async function _c(e,t,n,r,i=null){let{progressTracker:a,defaultPriority:o,estimatedInputTokens:s}=r;t>0?vc(e,a,o):await yc(e,n,r),a.updateTokens(i||s,n,!1),a.stop()}function vc(e,t,n){for(let r=0;r<e.length;r++){let i=e[r];i?.title&&t.addTaskLine(r+1,i.title,i.priority||n)}}async function yc(e,t,n){for(let r=0;r<e.length;r++){let i=e[r];i?.title&&await Cs({task:i,currentCount:r+1,totalTasks:n.numTasks,estimatedTokens:t,progressTracker:n.progressTracker,reportProgress:n.config.reportProgress,priorityMap:n.priorityMap,defaultPriority:n.defaultPriority,estimatedInputTokens:n.estimatedInputTokens})}}async function bc(e,t){if(t.report(`Using generateObject fallback for PRD parsing`,`info`),e.progressTracker)for(let t=0;t<e.numTasks;t++)e.progressTracker.addTaskLine(t+1,`Generating task ${t+1}...`,e.defaultPriority),e.progressTracker.updateTokens(e.estimatedInputTokens,0,!0);let n=await i({role:e.config.research?`research`:`main`,commandName:`parse-prd`,prompt:e.prompt,systemPrompt:e.systemPrompt,schema:e.config.schema,outputFormat:e.config.outputFormat||`text`,projectRoot:e.config.projectRoot,session:e.config.session}),r=n?.mainResult||n;if(r&&Array.isArray(r.tasks)&&(r.tasks=r.tasks.map(e=>({...e,dependencies:e.dependencies??[],priority:e.priority??null,details:e.details??null,testStrategy:e.testStrategy??null}))),r&&Array.isArray(r.tasks)){if(e.progressTracker){for(let t=0;t<r.tasks.length;t++){let n=r.tasks[t];n&&n.title&&e.progressTracker.addTaskLine(t+1,n.title,n.priority||e.defaultPriority)}let t=n.telemetryData?.outputTokens||hs(JSON.stringify(r)),i=n.telemetryData?.inputTokens||e.estimatedInputTokens;e.progressTracker.updateTokens(i,t,!1)}return{parsedTasks:r.tasks,estimatedOutputTokens:n.telemetryData?.outputTokens||hs(JSON.stringify(r)),actualInputTokens:n.telemetryData?.inputTokens,telemetryData:n.telemetryData,usedFallback:!0}}throw Error(`Failed to generate tasks using generateObject fallback`)}function xc(e,t,n,r){let i=null;if(r&&(i=r.getSummary(),r.cleanup()),e.usage&&t){let n=e.usage;t.usage||={promptTokens:n.promptTokens||0,completionTokens:n.completionTokens||0,totalTokens:n.totalTokens||0}}return{parsedTasks:e.parsedTasks,aiServiceResponse:t,estimatedInputTokens:e.actualInputTokens||n,estimatedOutputTokens:e.estimatedOutputTokens,usedFallback:e.usedFallback,progressTracker:r,summary:i}}async function Sc(e,t,n){let r=new Qo(e.mcpLog,e.reportProgress);r.report(`Parsing PRD file: ${e.prdPath}, Force: ${e.force}, Append: ${e.append}, Research: ${e.research}`,`debug`);try{let{existingTasks:i,nextId:a}=_s(e.tasksPath,e.targetTag);vs({existingTasks:i,targetTag:e.targetTag,append:e.append,force:e.force,isMCP:e.isMCP,logger:r});let o=await t(e,await Ss(e,gs(e.prdPath),a),e.numTasks),s=ce(e.projectRoot)||`medium`,c=ys(o.parsedTasks,a,i,s),l=e.append?[...i,...c]:c;return xs(e.tasksPath,l,e.targetTag,r),await Cc(e,o,c,l,a,n),{success:!0,tasksPath:e.tasksPath,telemetryData:o.aiServiceResponse?.telemetryData,tagInfo:o.aiServiceResponse?.tagInfo}}catch(t){throw r.report(`Error parsing PRD: ${t.message}`,`error`),e.isMCP||(console.error(B.red(`Error: ${t.message}`)),be(e.projectRoot)&&console.error(t)),t}}async function Cc(e,t,n,r,i,a){let{aiServiceResponse:o,estimatedInputTokens:s,estimatedOutputTokens:c}=t;if(e.reportProgress){let t=o?.telemetryData&&(o.telemetryData.inputTokens>0||o.telemetryData.outputTokens>0),n;if(t){let e=o.telemetryData.totalCost||0,t=o.telemetryData.currency||`USD`;n=`✅ Task Generation Completed | Tokens (I/O): ${o.telemetryData.inputTokens}/${o.telemetryData.outputTokens} | Cost: ${t===`USD`?`$`:t}${e.toFixed(4)}`}else n=`✅ Task Generation Completed | ~Tokens (I/O): ${s}/${a?c:`unknown`} | Cost: ~$0.00`;await e.reportProgress({progress:e.numTasks,total:e.numTasks,message:n})}e.outputFormat===`text`&&!e.isMCP&&(a&&t.summary?await ws({processedTasks:n,nextId:i,summary:t.summary,prdPath:e.prdPath,tasksPath:e.tasksPath,usedFallback:t.usedFallback,aiServiceResponse:o}):a||Ts({processedTasks:n,research:e.research,finalTasks:r,tasksPath:e.tasksPath,aiServiceResponse:o}))}async function wc(e,t,n,r={}){return Sc(new Zo(e,t,n,r),ac,!0)}async function Tc(e,t,n,r={}){return Sc(new Zo(e,t,n,r),Es,!1)}async function Ec(e,t,n,r={}){let i=new Zo(e,t,n,r);if(i.useStreaming)try{return await wc(e,t,n,r)}catch(a){if(a instanceof Go||a.code===Ko.NOT_ASYNC_ITERABLE||a.code===Ko.STREAM_PROCESSING_FAILED||a.code===Ko.STREAM_NOT_ITERABLE||qo.isTimeoutError(a)){let o=new Qo(i.mcpLog,i.reportProgress);return i.outputFormat===`text`&&!i.isMCP?console.log(B.yellow(`⚠️ Streaming operation ${a.message.includes(`timed out`)?`timed out`:`failed`}. Falling back to non-streaming mode...`)):o.report(`Streaming failed (${a.message}), falling back to non-streaming mode...`,`warn`),await Tc(e,t,n,r)}else throw a}else return await Tc(e,t,n,r)}var Dc=Ec;async function Oc(e,t,n=!1,r=!1,i={}){let{projectRoot:a,tag:o}=i;try{z(`info`,`Removing subtask ${t}...`);let r=w(e,a,o);if(!r||!r.tasks)throw Error(`Invalid or missing tasks file at ${e}`);if(!t.includes(`.`))throw Error(`Invalid subtask ID format: ${t}. Expected format: "parentId.subtaskId"`);let[i,s]=t.split(`.`),c=parseInt(i,10),l=parseInt(s,10),u=r.tasks.find(e=>e.id===c);if(!u)throw Error(`Parent task with ID ${c} not found`);if(!u.subtasks||u.subtasks.length===0)throw Error(`Parent task ${c} has no subtasks`);let d=u.subtasks.findIndex(e=>e.id===l);if(d===-1)throw Error(`Subtask ${t} not found`);let f={...u.subtasks[d]};u.subtasks.splice(d,1),u.subtasks.length===0&&(u.subtasks=void 0);let p=null;if(n){z(`info`,`Converting subtask ${t} to a standalone task...`);let e=Math.max(...r.tasks.map(e=>e.id))+1;p={id:e,title:f.title,description:f.description||``,details:f.details||``,status:f.status||`pending`,dependencies:f.dependencies||[],priority:u.priority||`medium`},p.dependencies.includes(c)||p.dependencies.push(c),r.tasks.push(p),z(`info`,`Created new task ${e} from subtask ${t}`)}else z(`info`,`Subtask ${t} deleted`);return _(e,r,a,o),p}catch(e){throw z(`error`,`Error removing subtask: ${e.message}`),e}}var kc=Oc;function Ac(e,t){if(typeof t==`string`&&t.includes(`.`)){let n=t.split(`.`);if(n.length!==2||!n[0]||!n[1]){let n=parseInt(t,10);return e.some(e=>e.id===n)}let[r,i]=n,a=parseInt(r,10),o=parseInt(i,10),s=e.find(e=>e.id===a);return s&&s.subtasks&&s.subtasks.some(e=>e.id===o)}let n=parseInt(t,10);return e.some(e=>e.id===n)}var jc=Ac;async function Mc(e,t,n={}){let{projectRoot:r,tag:i}=n,a={success:!0,messages:[],errors:[],removedTasks:[]},o=t.split(`,`).map(e=>e.trim()).filter(Boolean);if(o.length===0)return a.success=!1,a.errors.push(`No valid task IDs provided.`),a;try{let t=w(e,r,i);if(!t)throw Error(`Could not read tasks file at ${e}`);let n=t._rawTaggedData||t;if(!n[i]||!n[i].tasks)throw Error(`Tag '${i}' not found or has no tasks.`);let s=n[i].tasks,c=[];for(let e of o){if(!jc(s,e)){let t=`Task with ID ${e} in tag '${i}' not found or already removed.`;a.errors.push(t),a.success=!1;continue}try{if(typeof e==`string`&&e.includes(`.`)){let[t,n]=e.split(`.`).map(e=>parseInt(e,10)),r=s.find(e=>e.id===t);if(!r||!r.subtasks)throw Error(`Parent task ${t} or its subtasks not found for subtask ${e}`);let o=r.subtasks.findIndex(e=>e.id===n);if(o===-1)throw Error(`Subtask ${n} not found in parent task ${t}`);let c={...r.subtasks[o],parentTaskId:t};a.removedTasks.push(c),r.subtasks.splice(o,1),a.messages.push(`Successfully removed subtask ${e} from tag '${i}'`)}else{let t=parseInt(e,10),n=s.findIndex(e=>e.id===t);if(n===-1)throw Error(`Task with ID ${e} not found in tag '${i}'`);let r=s[n];a.removedTasks.push(r),c.push(t),s.splice(n,1),a.messages.push(`Successfully removed task ${e} from tag '${i}'`)}}catch(t){let n=`Error processing ID ${e}: ${t.message}`;a.errors.push(n),a.success=!1,z(`warn`,n)}}if(a.removedTasks.length>0){let t=new Set(o.map(e=>typeof e==`string`&&e.includes(`.`)?e:parseInt(e,10)));for(let e in n[i].tasks=s,n)Object.prototype.hasOwnProperty.call(n,e)&&n[e]&&n[e].tasks&&n[e].tasks.forEach(e=>{e.dependencies&&=e.dependencies.filter(e=>!t.has(e)),e.subtasks&&e.subtasks.forEach(n=>{n.dependencies&&=n.dependencies.filter(n=>!t.has(`${e.id}.${n}`)&&!t.has(n))})});_(e,n,r,i);for(let t of c){let n=H.join(H.dirname(e),`task_${t.toString().padStart(3,`0`)}.txt`);if(Ke.existsSync(n))try{Ke.unlinkSync(n),a.messages.push(`Deleted task file: ${n}`)}catch(e){let t=`Failed to delete task file ${n}: ${e.message}`;a.errors.push(t),a.success=!1,z(`warn`,t)}}}else a.errors.length===0&&a.messages.push(`No tasks found matching the provided IDs.`);let l=a.messages.join(`
953
+ `).start());try{n.report(`Calling AI service to generate tasks from PRD${e.research?` with research-backed analysis`:``}...`,`info`);let t=await i({role:e.research?`research`:`main`,session:e.session,projectRoot:e.projectRoot,schema:Xo,objectName:`tasks_data`,systemPrompt:r,prompt:a,commandName:`parse-prd`,outputType:e.isMCP?`mcp`:`cli`}),c=null;if(t?.mainResult&&(typeof t.mainResult==`object`&&t.mainResult!==null&&`tasks`in t.mainResult?c=t.mainResult:typeof t.mainResult.object==`object`&&t.mainResult.object!==null&&`tasks`in t.mainResult.object&&(c=t.mainResult.object)),!c||!Array.isArray(c.tasks))throw Error(`AI service returned unexpected data structure after validation.`);return s&&s.succeed(`Tasks generated successfully!`),{parsedTasks:c.tasks,aiServiceResponse:t,estimatedInputTokens:o}}catch(e){throw s&&s.fail(`Error parsing PRD: ${e.message}`),e}}const[Ds,Os,ks]=aa,As=new Map;var js=class{constructor(e,t,n,r=null){this.name=e,this.levels=t,this.colors=n,this.thresholds=r}getColor(e){return this.colors[e]||B.gray}getLevelFromScore(e){if(!this.thresholds)throw Error(`${this.name} does not support score-based levels`);return e>=7?this.levels[0]:e<=3?this.levels[2]:this.levels[1]}};const Ms={cli:{filled:`●`,empty:`○`},statusBar:{high:`⋮`,medium:`:`,low:`.`},mcp:{high:`🔴`,medium:`🟠`,low:`🟢`}},Ns=new js(`priority`,[Ds,Os,ks],{[Ds]:B.hex(`#CC0000`),[Os]:B.hex(`#FF8800`),[ks]:B.yellow});function Ps(e,t){let n=Ms.cli.filled,r=Ms.cli.empty,i=``;for(let a=0;a<3;a++)a<e?i+=t(n):i+=B.white(r);return i}function Fs(e,t){return 3-t.indexOf(e)}function Is(e,t){if(As.has(e))return As.get(e);let n=t();return As.set(e,n),n}function Ls(){return Is(`mcp-priority-all`,()=>({[Ds]:Ms.mcp.high,[Os]:Ms.mcp.medium,[ks]:Ms.mcp.low}))}function Rs(){return Is(`cli-priority-all`,()=>{let e={};return Ns.levels.forEach(t=>{e[t]=Ps(Fs(t,Ns.levels),Ns.getColor(t))}),e})}function zs(){return Is(`statusbar-priority-all`,()=>{let e={};return Ns.levels.forEach((t,n)=>{let r=n===0?Ms.statusBar.high:n===1?Ms.statusBar.medium:Ms.statusBar.low;e[t]=Ns.getColor(t)(r)}),e})}function Bs(){return{[Ds]:Ns.colors[Ds],[Os]:Ns.colors[Os],[ks]:Ns.colors[ks]}}function Vs(e=!1){return e?Ls():Rs()}function Hs(e,t=!1){let n=Vs(t);return n[e]||n[Os]}new js(`complexity`,[`high`,`medium`,`low`],{high:B.hex(`#CC0000`),medium:B.hex(`#FF8800`),low:B.green},{high:e=>e>=7,medium:e=>e>=4&&e<=6,low:e=>e<=3});const Us={clearOnComplete:!1,stopOnComplete:!0,hideCursor:!0,barsize:40},Ws={shades_classic:mt.Presets.shades_classic,shades_grey:mt.Presets.shades_grey,rect:mt.Presets.rect,legacy:mt.Presets.legacy},Gs=new class{constructor(e={},t=Ws.shades_classic){this.defaultOptions={...Us,...e},this.defaultPreset=t}createSingleBar(e={},t=null){let n=this._mergeConfig(e),r=t||this.defaultPreset;return new mt.SingleBar(n,r)}createMultiBar(e={},t=null){let n=this._mergeConfig(e),r=t||this.defaultPreset;return new mt.MultiBar(n,r)}_mergeConfig(e){return{...this.defaultOptions,...e}}setDefaultOptions(e){this.defaultOptions={...this.defaultOptions,...e}}setDefaultPreset(e){this.defaultPreset=e}};function Ks(e={}){return Gs.createMultiBar(e)}var qs=class{constructor(e={}){this.numUnits=e.numUnits||1,this.unitName=e.unitName||`unit`,this.startTime=null,this.completedUnits=0,this.tokensIn=0,this.tokensOut=0,this.isEstimate=!0,this.bestAvgTimePerUnit=null,this.lastEstimateTime=null,this.lastEstimateSeconds=0,this.multibar=null,this.timeTokensBar=null,this.progressBar=null,this._timerInterval=null,this.isStarted=!1,this.isFinished=!1,this._initializeCustomProperties(e)}_initializeCustomProperties(e){}get unitNamePlural(){return`${this.unitName}s`}start(){this.isStarted||this.isFinished||(this.isStarted=!0,this.startTime=Date.now(),this.multibar=Ks(),this.timeTokensBar=this.multibar.create(1,0,{},{format:this._getTimeTokensBarFormat(),barsize:1,hideCursor:!0,clearOnComplete:!1}),this.progressBar=this.multibar.create(this.numUnits,0,{},{format:this._getProgressBarFormat(),barCompleteChar:`█`,barIncompleteChar:`░`}),this._updateTimeTokensBar(),this.progressBar.update(0,{[this.unitNamePlural]:`0/${this.numUnits}`}),this._timerInterval=setInterval(()=>this._updateTimeTokensBar(),1e3),this._setupCustomUI())}_setupCustomUI(){}_getTimeTokensBarFormat(){return`{clock} {elapsed} | Tokens (I/O): {in}/{out} | Est: {remaining}`}_getProgressBarFormat(){return`${this.unitName.charAt(0).toUpperCase()+this.unitName.slice(1)}s {${this.unitNamePlural}} |{bar}| {percentage}%`}updateTokens(e,t,n=!1){this.tokensIn=e||0,this.tokensOut=t||0,this.isEstimate=n,this._updateTimeTokensBar()}_updateTimeTokensBar(){if(!this.timeTokensBar||this.isFinished)return;let e=this._formatElapsedTime(),t=this._estimateRemainingTime(),n=this.isEstimate?`~ Tokens (I/O)`:`Tokens (I/O)`;this.timeTokensBar.update(1,{clock:`⏱️`,elapsed:e,in:this.tokensIn,out:this.tokensOut,remaining:t,tokensLabel:n,...this._getCustomTimeTokensPayload()})}_getCustomTimeTokensPayload(){return{}}_formatElapsedTime(){if(!this.startTime)return`0m 00s`;let e=Math.floor((Date.now()-this.startTime)/1e3);return`${Math.floor(e/60)}m ${(e%60).toString().padStart(2,`0`)}s`}_estimateRemainingTime(){let e=this._getProgressFraction();if(e>=1)return`~0s`;let t=Date.now(),n=(t-this.startTime)/1e3;if(e===0)return`~calculating...`;let r=n/e;(this.bestAvgTimePerUnit===null||r<this.bestAvgTimePerUnit)&&(this.bestAvgTimePerUnit=r);let i=this.numUnits*(1-e),a=Math.ceil(i*this.bestAvgTimePerUnit);if(this.lastEstimateTime){let e=Math.floor((t-this.lastEstimateTime)/1e3),n=Math.max(0,this.lastEstimateSeconds-e);if(n===0)return`~0s`;a=Math.min(a,n)}return this.lastEstimateTime=t,this.lastEstimateSeconds=a,`~${this._formatDuration(a)}`}_getProgressFraction(){return this.completedUnits/this.numUnits}_formatDuration(e){if(e<60)return`${e}s`;let t=Math.floor(e/60),n=e%60;return t<60?n>0?`${t}m ${n}s`:`${t}m`:`${Math.floor(t/60)}h ${t%60}m`}getElapsedTime(){return this.startTime?Date.now()-this.startTime:0}stop(){this.isFinished||(this.isFinished=!0,this._timerInterval&&=(clearInterval(this._timerInterval),null),this.multibar&&(this._updateTimeTokensBar(),this.multibar.stop()),this.cleanup())}getSummary(){return{completedUnits:this.completedUnits,elapsedTime:this.getElapsedTime()}}cleanup(){if(this._timerInterval&&=(clearInterval(this._timerInterval),null),this.multibar){try{this.multibar.stop()}catch{}this.multibar=null}this.timeTokensBar=null,this.progressBar=null,this.isStarted=!1,this.isFinished=!0,this._performCustomCleanup()}_performCustomCleanup(){}},Js=class{constructor(e){if(!e)throw Error(`Multibar instance is required`);this.multibar=e}createBar(e,t={}){if(typeof e!=`string`)throw Error(`Format must be a string`);let n=this.multibar.create(1,1,{},{format:e,barsize:1,hideCursor:!0,clearOnComplete:!1});return n.update(1,t),n}createHeader(e,t){this.createBar(t),this.createBar(e),this.createBar(t)}createRow(e,t){if(!t||typeof t!=`object`)throw Error(`Payload must be an object`);return this.createBar(e,t)}createBorder(e){return this.createBar(e)}};function Ys(e,t,n){new Js(e).createHeader(t,n)}function Xs(e,t,n){new Js(e).createRow(t,n)}function Zs(e,t){new Js(e).createBorder(t)}Rs();const Qs=zs();Bs();const $s={DEBOUNCE_DELAY:100,MAX_TITLE_LENGTH:57,TRUNCATED_LENGTH:54,TASK_ID_PAD_START:3,TASK_ID_PAD_END:4,PRIORITY_PAD_END:3,VALID_PRIORITIES:[`high`,`medium`,`low`],DEFAULT_PRIORITY:`medium`};var ec=class{constructor(e=$s.DEBOUNCE_DELAY){this.delay=e,this.pendingTimeout=null}debounce(e){this.clear(),this.pendingTimeout=setTimeout(()=>{e(),this.pendingTimeout=null},this.delay)}clear(){this.pendingTimeout&&=(clearTimeout(this.pendingTimeout),null)}hasPending(){return this.pendingTimeout!==null}},tc=class{constructor(){this.priorities={high:0,medium:0,low:0}}increment(e){let t=this.normalize(e);return this.priorities[t]++,t}normalize(e){let t=e?e.toLowerCase():$s.DEFAULT_PRIORITY;return $s.VALID_PRIORITIES.includes(t)?t:$s.DEFAULT_PRIORITY}getCounts(){return{...this.priorities}}},nc=class{static formatTitle(e,t){return e?e.length>$s.MAX_TITLE_LENGTH?e.substring(0,$s.TRUNCATED_LENGTH)+`...`:e:`Task ${t}`}static formatPriority(e){return Hs(e,!1).padEnd($s.PRIORITY_PAD_END,` `)}static formatTaskId(e){return e.toString().padStart($s.TASK_ID_PAD_START,` `).padEnd($s.TASK_ID_PAD_END,` `)}},rc=class extends qs{_initializeCustomProperties(e){this.append=e.append,this.priorityManager=new tc,this.debouncer=new ec,this.headerShown=!1}_getTimeTokensBarFormat(){return`{clock} {elapsed} | ${Qs.high} {high} ${Qs.medium} {medium} ${Qs.low} {low} | Tokens (I/O): {in}/{out} | Est: {remaining}`}_getProgressBarFormat(){return`Tasks {tasks} |{bar}| {percentage}%`}_getCustomTimeTokensPayload(){return this.priorityManager.getCounts()}addTaskLine(e,t,n=`medium`){if(!this.multibar||this.isFinished)return;this._ensureHeaderShown();let r=this._updateTaskCounters(e,n);this._updateTimeTokensBar(),this.debouncer.debounce(()=>{this._updateProgressDisplay(e,t,r)})}_ensureHeaderShown(){this.headerShown||(this.headerShown=!0,Ys(this.multibar,` TASK | PRI | TITLE`,`------+-----+----------------------------------------------------------------`))}_updateTaskCounters(e,t){let n=this.priorityManager.increment(t);return this.completedUnits=e,n}_updateProgressDisplay(e,t,n){this.progressBar.update(this.completedUnits,{tasks:`${this.completedUnits}/${this.numUnits}`});let r=nc.formatTitle(t,e),i=nc.formatPriority(n),a=nc.formatTaskId(e);Xs(this.multibar,` ${a} | ${i} | {title}`,{title:r}),Zs(this.multibar,`------+-----+----------------------------------------------------------------`),this._updateTimeTokensBar()}finish(){this.debouncer.hasPending()&&(this.debouncer.clear(),this._updateTimeTokensBar()),this.cleanup(),super.finish()}_performCustomCleanup(){this.debouncer.clear()}getSummary(){return{...super.getSummary(),taskPriorities:this.priorityManager.getCounts(),actionVerb:this.append?`appended`:`generated`}}};function ic(e={}){return new rc(e)}async function ac(e,t,n){let r=oc(e,t,n);await cc(e,n,r.estimatedInputTokens);let i=await lc(e,t,e.streamingTimeout),{progressTracker:a,priorityMap:o}=await uc(e,n),s=await dc(i.mainResult,e,t,n,a,o,r.defaultPriority,r.estimatedInputTokens,r.logger);if(sc(s),s.usage&&e.projectRoot){let{logAiUsage:t}=await import(`./ai-services-unified-DPFFMTq4.js`),{getUserId:n}=await import(`./config-manager-BI29Nudz.js`),a=n(e.projectRoot);if(a&&i.providerName&&i.modelId)try{let n=await t({userId:a,commandName:`parse-prd`,providerName:i.providerName,modelId:i.modelId,inputTokens:s.usage.promptTokens||0,outputTokens:s.usage.completionTokens||0,outputType:e.isMCP?`mcp`:`cli`});n&&(i.telemetryData=n)}catch(e){r.logger.report(`Failed to log telemetry: ${e.message}`,`debug`)}}return xc(s,i,r.estimatedInputTokens,a)}function oc(e,t,n){let{systemPrompt:r,userPrompt:i}=t;return{logger:new Qo(e.mcpLog,e.reportProgress),estimatedInputTokens:hs(r+i),defaultPriority:ce(e.projectRoot)||`medium`}}function sc(e){if(e.parsedTasks.length===0)throw Error(`No tasks were generated from the PRD`)}async function cc(e,t,n){e.reportProgress&&await e.reportProgress({progress:0,total:t,message:`Starting PRD analysis (Input: ${n} tokens)${e.research?` with research`:``}...`})}async function lc(e,n,r){let{systemPrompt:i,userPrompt:a}=n;return await qo.withTimeout(t({role:e.research?`research`:`main`,session:e.session,projectRoot:e.projectRoot,schema:Xo,systemPrompt:i,prompt:a,commandName:`parse-prd`,outputType:e.isMCP?`mcp`:`cli`}),r,`Streaming operation`)}async function uc(e,t){let n=Vs(e.isMCP),r=null;if(e.outputFormat===`text`&&!e.isMCP){r=ic({numUnits:t,unitName:`task`,append:e.append});let n=e.research?he():l(),i=v(e.research?`research`:`main`);ss({prdFilePath:e.prdPath,outputPath:e.tasksPath,numTasks:t,append:e.append,research:e.research,force:e.force,existingTasks:[],nextId:1,model:n||`Default`,temperature:i?.temperature||.7}),r.start()}return{progressTracker:r,priorityMap:n}}async function dc(e,t,n,r,i,a,o,s,c){let{systemPrompt:l,userPrompt:u}=n,d={config:{...t,schema:Xo},numTasks:r,progressTracker:i,priorityMap:a,defaultPriority:o,estimatedInputTokens:s,prompt:u,systemPrompt:l};try{let t={lastPartialObject:null,taskCount:0,estimatedOutputTokens:0,usage:null};if(await fc(e.partialObjectStream,t,d),e.usage)try{t.usage=await e.usage}catch(e){c.report(`Failed to get usage data: ${e.message}`,`debug`)}return gc(t,d)}catch(e){return c.report(`StreamObject processing failed: ${e.message}. Falling back to generateObject.`,`debug`),await bc(d,c)}}async function fc(e,t,n){for await(let r of e)t.lastPartialObject=r,r&&(t.estimatedOutputTokens=hs(JSON.stringify(r))),await pc(r,t,n)}async function pc(e,t,n){if(!e?.tasks||!Array.isArray(e.tasks))return;let r=e.tasks.length;r>t.taskCount?(await mc(e.tasks,t.taskCount,r,t.estimatedOutputTokens,n),t.taskCount=r):n.progressTracker&&t.estimatedOutputTokens>0&&n.progressTracker.updateTokens(n.estimatedInputTokens,t.estimatedOutputTokens,!0)}async function mc(e,t,n,r,i){for(let a=t;a<n;a++){let t=e[a]||{};t.title?await Cs({task:t,currentCount:a+1,totalTasks:i.numTasks,estimatedTokens:r,progressTracker:i.progressTracker,reportProgress:i.config.reportProgress,priorityMap:i.priorityMap,defaultPriority:i.defaultPriority,estimatedInputTokens:i.estimatedInputTokens}):await hc(a+1,r,i)}}async function hc(e,t,n){let{progressTracker:r,config:i,numTasks:a,defaultPriority:o,estimatedInputTokens:s}=n;r&&(r.addTaskLine(e,`Generating task ${e}...`,o),r.updateTokens(s,t,!0)),i.reportProgress&&!r&&await i.reportProgress({progress:e,total:a,message:`Generating task ${e}/${a}...`})}async function gc(e,t){let{lastPartialObject:n,estimatedOutputTokens:r,taskCount:i,usage:a}=e;if(!n?.tasks||!Array.isArray(n.tasks))throw Error(`No tasks generated from streamObject`);let o=a?.completionTokens||r,s=a?.promptTokens||t.estimatedInputTokens;return t.progressTracker&&await _c(n.tasks,i,a?o:r,t,a?s:null),{parsedTasks:n.tasks,estimatedOutputTokens:o,actualInputTokens:s,usage:a,usedFallback:!1}}async function _c(e,t,n,r,i=null){let{progressTracker:a,defaultPriority:o,estimatedInputTokens:s}=r;t>0?vc(e,a,o):await yc(e,n,r),a.updateTokens(i||s,n,!1),a.stop()}function vc(e,t,n){for(let r=0;r<e.length;r++){let i=e[r];i?.title&&t.addTaskLine(r+1,i.title,i.priority||n)}}async function yc(e,t,n){for(let r=0;r<e.length;r++){let i=e[r];i?.title&&await Cs({task:i,currentCount:r+1,totalTasks:n.numTasks,estimatedTokens:t,progressTracker:n.progressTracker,reportProgress:n.config.reportProgress,priorityMap:n.priorityMap,defaultPriority:n.defaultPriority,estimatedInputTokens:n.estimatedInputTokens})}}async function bc(e,t){if(t.report(`Using generateObject fallback for PRD parsing`,`info`),e.progressTracker)for(let t=0;t<e.numTasks;t++)e.progressTracker.addTaskLine(t+1,`Generating task ${t+1}...`,e.defaultPriority),e.progressTracker.updateTokens(e.estimatedInputTokens,0,!0);let n=await i({role:e.config.research?`research`:`main`,commandName:`parse-prd`,prompt:e.prompt,systemPrompt:e.systemPrompt,schema:e.config.schema,outputFormat:e.config.outputFormat||`text`,projectRoot:e.config.projectRoot,session:e.config.session}),r=n?.mainResult||n;if(r&&Array.isArray(r.tasks)&&(r.tasks=r.tasks.map(e=>({...e,dependencies:e.dependencies??[],priority:e.priority??null,details:e.details??null,testStrategy:e.testStrategy??null}))),r&&Array.isArray(r.tasks)){if(e.progressTracker){for(let t=0;t<r.tasks.length;t++){let n=r.tasks[t];n&&n.title&&e.progressTracker.addTaskLine(t+1,n.title,n.priority||e.defaultPriority)}let t=n.telemetryData?.outputTokens||hs(JSON.stringify(r)),i=n.telemetryData?.inputTokens||e.estimatedInputTokens;e.progressTracker.updateTokens(i,t,!1)}return{parsedTasks:r.tasks,estimatedOutputTokens:n.telemetryData?.outputTokens||hs(JSON.stringify(r)),actualInputTokens:n.telemetryData?.inputTokens,telemetryData:n.telemetryData,usedFallback:!0}}throw Error(`Failed to generate tasks using generateObject fallback`)}function xc(e,t,n,r){let i=null;if(r&&(i=r.getSummary(),r.cleanup()),e.usage&&t){let n=e.usage;t.usage||={promptTokens:n.promptTokens||0,completionTokens:n.completionTokens||0,totalTokens:n.totalTokens||0}}return{parsedTasks:e.parsedTasks,aiServiceResponse:t,estimatedInputTokens:e.actualInputTokens||n,estimatedOutputTokens:e.estimatedOutputTokens,usedFallback:e.usedFallback,progressTracker:r,summary:i}}async function Sc(e,t,n){let r=new Qo(e.mcpLog,e.reportProgress);r.report(`Parsing PRD file: ${e.prdPath}, Force: ${e.force}, Append: ${e.append}, Research: ${e.research}`,`debug`);try{let{existingTasks:i,nextId:a}=_s(e.tasksPath,e.targetTag);vs({existingTasks:i,targetTag:e.targetTag,append:e.append,force:e.force,isMCP:e.isMCP,logger:r});let o=await t(e,await Ss(e,gs(e.prdPath),a),e.numTasks),s=ce(e.projectRoot)||`medium`,c=ys(o.parsedTasks,a,i,s),l=e.append?[...i,...c]:c;return xs(e.tasksPath,l,e.targetTag,r),await Cc(e,o,c,l,a,n),{success:!0,tasksPath:e.tasksPath,telemetryData:o.aiServiceResponse?.telemetryData,tagInfo:o.aiServiceResponse?.tagInfo}}catch(t){throw r.report(`Error parsing PRD: ${t.message}`,`error`),e.isMCP||(console.error(B.red(`Error: ${t.message}`)),be(e.projectRoot)&&console.error(t)),t}}async function Cc(e,t,n,r,i,a){let{aiServiceResponse:o,estimatedInputTokens:s,estimatedOutputTokens:c}=t;if(e.reportProgress){let t=o?.telemetryData&&(o.telemetryData.inputTokens>0||o.telemetryData.outputTokens>0),n;if(t){let e=o.telemetryData.totalCost||0,t=o.telemetryData.currency||`USD`;n=`✅ Task Generation Completed | Tokens (I/O): ${o.telemetryData.inputTokens}/${o.telemetryData.outputTokens} | Cost: ${t===`USD`?`$`:t}${e.toFixed(4)}`}else n=`✅ Task Generation Completed | ~Tokens (I/O): ${s}/${a?c:`unknown`} | Cost: ~$0.00`;await e.reportProgress({progress:e.numTasks,total:e.numTasks,message:n})}e.outputFormat===`text`&&!e.isMCP&&(a&&t.summary?await ws({processedTasks:n,nextId:i,summary:t.summary,prdPath:e.prdPath,tasksPath:e.tasksPath,usedFallback:t.usedFallback,aiServiceResponse:o}):a||Ts({processedTasks:n,research:e.research,finalTasks:r,tasksPath:e.tasksPath,aiServiceResponse:o}))}async function wc(e,t,n,r={}){return Sc(new Zo(e,t,n,r),ac,!0)}async function Tc(e,t,n,r={}){return Sc(new Zo(e,t,n,r),Es,!1)}async function Ec(e,t,n,r={}){let i=new Zo(e,t,n,r);if(i.useStreaming)try{return await wc(e,t,n,r)}catch(a){if(a instanceof Go||a.code===Ko.NOT_ASYNC_ITERABLE||a.code===Ko.STREAM_PROCESSING_FAILED||a.code===Ko.STREAM_NOT_ITERABLE||qo.isTimeoutError(a)){let o=new Qo(i.mcpLog,i.reportProgress);return i.outputFormat===`text`&&!i.isMCP?console.log(B.yellow(`⚠️ Streaming operation ${a.message.includes(`timed out`)?`timed out`:`failed`}. Falling back to non-streaming mode...`)):o.report(`Streaming failed (${a.message}), falling back to non-streaming mode...`,`warn`),await Tc(e,t,n,r)}else throw a}else return await Tc(e,t,n,r)}var Dc=Ec;async function Oc(e,t,n=!1,r=!1,i={}){let{projectRoot:a,tag:o}=i;try{z(`info`,`Removing subtask ${t}...`);let r=w(e,a,o);if(!r||!r.tasks)throw Error(`Invalid or missing tasks file at ${e}`);if(!t.includes(`.`))throw Error(`Invalid subtask ID format: ${t}. Expected format: "parentId.subtaskId"`);let[i,s]=t.split(`.`),c=parseInt(i,10),l=parseInt(s,10),u=r.tasks.find(e=>e.id===c);if(!u)throw Error(`Parent task with ID ${c} not found`);if(!u.subtasks||u.subtasks.length===0)throw Error(`Parent task ${c} has no subtasks`);let d=u.subtasks.findIndex(e=>e.id===l);if(d===-1)throw Error(`Subtask ${t} not found`);let f={...u.subtasks[d]};u.subtasks.splice(d,1),u.subtasks.length===0&&(u.subtasks=void 0);let p=null;if(n){z(`info`,`Converting subtask ${t} to a standalone task...`);let e=Math.max(...r.tasks.map(e=>e.id))+1;p={id:e,title:f.title,description:f.description||``,details:f.details||``,status:f.status||`pending`,dependencies:f.dependencies||[],priority:u.priority||`medium`},p.dependencies.includes(c)||p.dependencies.push(c),r.tasks.push(p),z(`info`,`Created new task ${e} from subtask ${t}`)}else z(`info`,`Subtask ${t} deleted`);return _(e,r,a,o),p}catch(e){throw z(`error`,`Error removing subtask: ${e.message}`),e}}var kc=Oc;function Ac(e,t){if(typeof t==`string`&&t.includes(`.`)){let n=t.split(`.`);if(n.length!==2||!n[0]||!n[1]){let n=parseInt(t,10);return e.some(e=>e.id===n)}let[r,i]=n,a=parseInt(r,10),o=parseInt(i,10),s=e.find(e=>e.id===a);return s&&s.subtasks&&s.subtasks.some(e=>e.id===o)}let n=parseInt(t,10);return e.some(e=>e.id===n)}var jc=Ac;async function Mc(e,t,n={}){let{projectRoot:r,tag:i}=n,a={success:!0,messages:[],errors:[],removedTasks:[]},o=t.split(`,`).map(e=>e.trim()).filter(Boolean);if(o.length===0)return a.success=!1,a.errors.push(`No valid task IDs provided.`),a;try{let t=w(e,r,i);if(!t)throw Error(`Could not read tasks file at ${e}`);let n=t._rawTaggedData||t;if(!n[i]||!n[i].tasks)throw Error(`Tag '${i}' not found or has no tasks.`);let s=n[i].tasks,c=[];for(let e of o){if(!jc(s,e)){let t=`Task with ID ${e} in tag '${i}' not found or already removed.`;a.errors.push(t),a.success=!1;continue}try{if(typeof e==`string`&&e.includes(`.`)){let[t,n]=e.split(`.`).map(e=>parseInt(e,10)),r=s.find(e=>e.id===t);if(!r||!r.subtasks)throw Error(`Parent task ${t} or its subtasks not found for subtask ${e}`);let o=r.subtasks.findIndex(e=>e.id===n);if(o===-1)throw Error(`Subtask ${n} not found in parent task ${t}`);let c={...r.subtasks[o],parentTaskId:t};a.removedTasks.push(c),r.subtasks.splice(o,1),a.messages.push(`Successfully removed subtask ${e} from tag '${i}'`)}else{let t=parseInt(e,10),n=s.findIndex(e=>e.id===t);if(n===-1)throw Error(`Task with ID ${e} not found in tag '${i}'`);let r=s[n];a.removedTasks.push(r),c.push(t),s.splice(n,1),a.messages.push(`Successfully removed task ${e} from tag '${i}'`)}}catch(t){let n=`Error processing ID ${e}: ${t.message}`;a.errors.push(n),a.success=!1,z(`warn`,n)}}if(a.removedTasks.length>0){let t=new Set(o.map(e=>typeof e==`string`&&e.includes(`.`)?e:parseInt(e,10)));for(let e in n[i].tasks=s,n)Object.prototype.hasOwnProperty.call(n,e)&&n[e]&&n[e].tasks&&n[e].tasks.forEach(e=>{e.dependencies&&=e.dependencies.filter(e=>!t.has(e)),e.subtasks&&e.subtasks.forEach(n=>{n.dependencies&&=n.dependencies.filter(n=>!t.has(`${e.id}.${n}`)&&!t.has(n))})});_(e,n,r,i);for(let t of c){let n=H.join(H.dirname(e),`task_${t.toString().padStart(3,`0`)}.txt`);if(Ke.existsSync(n))try{Ke.unlinkSync(n),a.messages.push(`Deleted task file: ${n}`)}catch(e){let t=`Failed to delete task file ${n}: ${e.message}`;a.errors.push(t),a.success=!1,z(`warn`,t)}}}else a.errors.length===0&&a.messages.push(`No tasks found matching the provided IDs.`);let l=a.messages.join(`
954
954
  `),u=a.errors.join(`
955
955
  `);return{success:a.success,message:l||`No tasks were removed.`,error:u||null,removedTasks:a.removedTasks}}catch(e){return z(`error`,`Error removing tasks: ${e.message}`),{success:!1,message:``,error:`Operation failed: ${e.message}`,removedTasks:[]}}}var Nc=Mc;ot.use(st({code:e=>e.split(`
956
956
  `).map(e=>` `+B.cyan(e)).join(`
@@ -968,9 +968,9 @@ ${B.cyan(`1.`)} Run ${B.yellow(`task-master list`)} to view all tasks\n${B.cyan(
968
968
  `);if(r.push(B.cyan(`Prompts: `)+B.yellow(i.toLocaleString())+B.gray(` (generated)`)+`
969
969
  `+a),r.length>0){let e=W(r.join(`
970
970
 
971
- `),{title:B.blue.bold(`Context Analysis`),titleAlignment:`left`,padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1},borderStyle:`single`,borderColor:`blue`});console.log(e)}}async function Ic(e,t,n,r,i,a,o){let s=!1;try{let{readJSON:c}=await import(`./utils-ClsTocu1.js`);(await import(`./update-task-by-id-D6r8NE3N.js`)).default;let{updateSubtaskById:l}=await import(`./update-subtask-by-id-z0WhVh4e.js`),u=[{question:a,answer:o,type:`initial`,timestamp:new Date().toISOString()}];for(;;){let{action:a}=await q.prompt([{type:`list`,name:`action`,message:`What would you like to do next?`,choices:[{name:`Ask a follow-up question`,value:`followup`},{name:`Save to file`,value:`savefile`},{name:`Save to task/subtask`,value:`save`},{name:`Quit`,value:`quit`}],pageSize:4}]);if(a===`quit`)break;if(a===`savefile`){await Rc(u,r,t,i);continue}if(a===`save`){await Lc(u,r,t,i)&&(s=!0);continue}if(a===`followup`){let{followUpQuery:r}=await q.prompt([{type:`input`,name:`followUpQuery`,message:`Enter your follow-up question:`,validate:e=>!e||e.trim().length===0?`Please enter a valid question.`:!0}]);if(!r||r.trim().length===0)continue;console.log(`
971
+ `),{title:B.blue.bold(`Context Analysis`),titleAlignment:`left`,padding:{top:1,bottom:1,left:2,right:2},margin:{top:0,bottom:1},borderStyle:`single`,borderColor:`blue`});console.log(e)}}async function Ic(e,t,n,r,i,a,o){let s=!1;try{let{readJSON:c}=await import(`./utils-DGz7V7Kw.js`);(await import(`./update-task-by-id-DP498AAF.js`)).default;let{updateSubtaskById:l}=await import(`./update-subtask-by-id-ntk5CuRW.js`),u=[{question:a,answer:o,type:`initial`,timestamp:new Date().toISOString()}];for(;;){let{action:a}=await q.prompt([{type:`list`,name:`action`,message:`What would you like to do next?`,choices:[{name:`Ask a follow-up question`,value:`followup`},{name:`Save to file`,value:`savefile`},{name:`Save to task/subtask`,value:`save`},{name:`Quit`,value:`quit`}],pageSize:4}]);if(a===`quit`)break;if(a===`savefile`){await Rc(u,r,t,i);continue}if(a===`save`){await Lc(u,r,t,i)&&(s=!0);continue}if(a===`followup`){let{followUpQuery:r}=await q.prompt([{type:`input`,name:`followUpQuery`,message:`Enter your follow-up question:`,validate:e=>!e||e.trim().length===0?`Please enter a valid question.`:!0}]);if(!r||r.trim().length===0)continue;console.log(`
972
972
  `+B.gray(`─`.repeat(60))+`
973
- `);let i=Vc(u),a={...e,taskIds:[],customContext:i+(e.customContext?`\n\n--- Original Context ---\n${e.customContext}`:``)},o=await Pc(r.trim(),a,t,n,!1);u.push({question:r.trim(),answer:o.result,type:`followup`,timestamp:new Date().toISOString()})}}}catch(e){i.debug(`Follow-up questions not available: ${e.message}`)}return{interactiveSaveOccurred:s}}async function Lc(e,t,n,r){try{let{readJSON:r}=await import(`./utils-ClsTocu1.js`),i=(await import(`./update-task-by-id-D6r8NE3N.js`)).default,{updateSubtaskById:a}=await import(`./update-subtask-by-id-z0WhVh4e.js`),{taskId:o}=await q.prompt([{type:`input`,name:`taskId`,message:`Enter task ID (e.g., "15" for task or "15.2" for subtask):`,validate:e=>{if(!e||e.trim().length===0)return`Please enter a task ID.`;let t=e.trim();return/^\d+(\.\d+)?$/.test(t)?!0:`Invalid format. Use "15" for task or "15.2" for subtask.`}}]),s=o.trim(),c=Bc(e),l=s.includes(`.`),u=H.join(t,`.taskmaster`,`tasks`,`tasks.json`);if(!V.existsSync(u)){console.log(B.red(`❌ Tasks file not found. Please run task-master init first.`));return}let d=r(u,t,n.tag);if(!d||!d.tasks){console.log(B.red(`❌ No valid tasks found.`));return}if(l){let[e,t]=s.split(`.`).map(e=>parseInt(e,10)),r=d.tasks.find(t=>t.id===e);if(!r){console.log(B.red(`❌ Parent task ${e} not found.`));return}if(!r.subtasks||!r.subtasks.find(e=>e.id===t)){console.log(B.red(`❌ Subtask ${s} not found.`));return}console.log(B.blue(`💾 Saving research conversation to subtask...`)),await a(u,s,c,!1,n,`text`),console.log(B.green(`✅ Research conversation saved to subtask ${s}`))}else{let e=parseInt(s,10);if(!d.tasks.find(t=>t.id===e)){console.log(B.red(`❌ Task ${s} not found.`));return}console.log(B.blue(`💾 Saving research conversation to task...`)),await i(u,e,c,!1,n,`text`,!0),console.log(B.green(`✅ Research conversation saved to task ${s}`))}return!0}catch(e){return console.log(B.red(`❌ Error saving conversation: ${e.message}`)),r.error(`Error saving conversation: ${e.message}`),!1}}async function Rc(e,t,n,r){try{let n=H.join(t,`.taskmaster`,`docs`,`research`);V.existsSync(n)||V.mkdirSync(n,{recursive:!0});let i=e[0]?.question||`research-query`,a=`${new Date().toISOString().split(`T`)[0]}_${i.toLowerCase().replace(/[^a-z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).substring(0,50).replace(/^-+|-+$/g,``)}.md`,o=H.join(n,a),s=zc(e,i);V.writeFileSync(o,s,`utf8`);let c=H.relative(t,o);return console.log(B.green(`✅ Research saved to: ${B.cyan(c)}`)),r.success(`Research conversation saved to ${c}`),o}catch(e){throw console.log(B.red(`❌ Error saving research file: ${e.message}`)),r.error(`Error saving research file: ${e.message}`),e}}function zc(e,t){let n=new Date().toISOString(),r=`---
973
+ `);let i=Vc(u),a={...e,taskIds:[],customContext:i+(e.customContext?`\n\n--- Original Context ---\n${e.customContext}`:``)},o=await Pc(r.trim(),a,t,n,!1);u.push({question:r.trim(),answer:o.result,type:`followup`,timestamp:new Date().toISOString()})}}}catch(e){i.debug(`Follow-up questions not available: ${e.message}`)}return{interactiveSaveOccurred:s}}async function Lc(e,t,n,r){try{let{readJSON:r}=await import(`./utils-DGz7V7Kw.js`),i=(await import(`./update-task-by-id-DP498AAF.js`)).default,{updateSubtaskById:a}=await import(`./update-subtask-by-id-ntk5CuRW.js`),{taskId:o}=await q.prompt([{type:`input`,name:`taskId`,message:`Enter task ID (e.g., "15" for task or "15.2" for subtask):`,validate:e=>{if(!e||e.trim().length===0)return`Please enter a task ID.`;let t=e.trim();return/^\d+(\.\d+)?$/.test(t)?!0:`Invalid format. Use "15" for task or "15.2" for subtask.`}}]),s=o.trim(),c=Bc(e),l=s.includes(`.`),u=H.join(t,`.taskmaster`,`tasks`,`tasks.json`);if(!V.existsSync(u)){console.log(B.red(`❌ Tasks file not found. Please run task-master init first.`));return}let d=r(u,t,n.tag);if(!d||!d.tasks){console.log(B.red(`❌ No valid tasks found.`));return}if(l){let[e,t]=s.split(`.`).map(e=>parseInt(e,10)),r=d.tasks.find(t=>t.id===e);if(!r){console.log(B.red(`❌ Parent task ${e} not found.`));return}if(!r.subtasks||!r.subtasks.find(e=>e.id===t)){console.log(B.red(`❌ Subtask ${s} not found.`));return}console.log(B.blue(`💾 Saving research conversation to subtask...`)),await a(u,s,c,!1,n,`text`),console.log(B.green(`✅ Research conversation saved to subtask ${s}`))}else{let e=parseInt(s,10);if(!d.tasks.find(t=>t.id===e)){console.log(B.red(`❌ Task ${s} not found.`));return}console.log(B.blue(`💾 Saving research conversation to task...`)),await i(u,e,c,!1,n,`text`,!0),console.log(B.green(`✅ Research conversation saved to task ${s}`))}return!0}catch(e){return console.log(B.red(`❌ Error saving conversation: ${e.message}`)),r.error(`Error saving conversation: ${e.message}`),!1}}async function Rc(e,t,n,r){try{let n=H.join(t,`.taskmaster`,`docs`,`research`);V.existsSync(n)||V.mkdirSync(n,{recursive:!0});let i=e[0]?.question||`research-query`,a=`${new Date().toISOString().split(`T`)[0]}_${i.toLowerCase().replace(/[^a-z0-9\s-]/g,``).replace(/\s+/g,`-`).replace(/-+/g,`-`).substring(0,50).replace(/^-+|-+$/g,``)}.md`,o=H.join(n,a),s=zc(e,i);V.writeFileSync(o,s,`utf8`);let c=H.relative(t,o);return console.log(B.green(`✅ Research saved to: ${B.cyan(c)}`)),r.success(`Research conversation saved to ${c}`),o}catch(e){throw console.log(B.red(`❌ Error saving research file: ${e.message}`)),r.error(`Error saving research file: ${e.message}`),e}}function zc(e,t){let n=new Date().toISOString(),r=`---
974
974
  title: Research Session
975
975
  query: "${t}"
976
976
  date: ${new Date().toLocaleDateString()}
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import{o as e,s as t}from"./ai-services-unified-tvfkaOTr.js";import{$t as n,Dt as r,Ht as i,Kt as a,Mt as o,Nt as s,On as c,Qt as l,S as u,Sn as d,Tt as f,fn as p,h as m,ht as h,in as g,ln as _,ot as v,pn as y,rn as b,st as x,tn as S,tt as C,vn as ee,vt as w,wt as te,zt as ne}from"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import{r as re}from"./sentry-hPhwSfRH.js";import{$ as T,A as ie,B as E,C as ae,D as oe,Dt as se,Et as ce,F as le,G as ue,H as de,I as fe,J as pe,M as me,N as he,O as ge,P as _e,Q as ve,R as D,S as ye,U as be,V as xe,W as Se,X as Ce,Y as we,Z as Te,at as Ee,ct as De,dt as Oe,gt as ke,ht as Ae,i as je,it as Me,j as Ne,lt as Pe,n as Fe,pt as Ie,r as Le,rt as Re,st as ze,t as Be,ut as Ve,w as He,z as Ue}from"./dependency-manager-CaRCB7TO.js";import{t as We}from"./response-language-BnJvZzdq.js";import{a as Ge,c as Ke,f as qe,g as Je,h as Ye,l as O,m as k,p as Xe,v as A}from"./profiles-DQcCVbeo.js";import j from"node:path";import M from"chalk";import N from"fs";import P from"path";import Ze from"os";import F from"node:fs";import{z as I}from"zod";import{fileURLToPath as Qe}from"url";import L from"dotenv";import*as R from"@sentry/node";import{FastMCP as $e}from"fastmcp";const z={debug:0,info:1,warn:2,error:3,success:4},et=z[u().toLowerCase()]??z.info;function B(e,...t){if(w())return;let n={debug:M.gray(`[DEBUG]`),info:M.blue(`[INFO]`),warn:M.yellow(`[WARN]`),error:M.red(`[ERROR]`),success:M.green(`[SUCCESS]`)};if(z[e]!==void 0&&z[e]>=et){let r=n[e]||``,i=t;try{switch(e){case`error`:i=t.map(e=>typeof e==`string`?M.red(e):e);break;case`warn`:i=t.map(e=>typeof e==`string`?M.yellow(e):e);break;case`success`:i=t.map(e=>typeof e==`string`?M.green(e):e);break;case`info`:i=t.map(e=>typeof e==`string`?M.blue(e):e);break;case`debug`:i=t.map(e=>typeof e==`string`?M.gray(e):e);break}}catch(e){console.error(`Internal Logger Error applying chalk color:`,e),i=t}console.error(r,...i)}}function tt(){let e=e=>(...t)=>B(e,...t);return{debug:e(`debug`),info:e(`info`),warn:e(`warn`),error:e(`error`),success:e(`success`),log:B}}var V=tt(),H=class extends Error{constructor(e,t={}){super(e),this.name=`MCPError`,this.code=t.code,this.cause=t.cause,this.mcpResponse=t.mcpResponse}},U=class extends H{constructor(e,t={}){super(e,t),this.name=`MCPSessionError`}},nt=class extends H{constructor(e,t={}){super(e,t),this.name=`MCPSamplingError`}};function W(e){if(e instanceof H)return e;let t=e.message||`Unknown MCP error`,n=e;return t.includes(`session`)||t.includes(`connection`)?new U(t,{cause:n,code:`SESSION_ERROR`}):t.includes(`sampling`)||t.includes(`timeout`)?new nt(t,{cause:n,code:`SAMPLING_ERROR`}):t.includes(`capabilities`)||t.includes(`not supported`)?new U(t,{cause:n,code:`CAPABILITY_ERROR`}):new H(t,{cause:n,code:`UNKNOWN_ERROR`})}function rt(e){let t=e.trim();t=t.replace(/^```json\s*/gm,``),t=t.replace(/^```\s*/gm,``),t=t.replace(/```\s*$/gm,``),t=t.replace(/^const\s+\w+\s*=\s*/,``),t=t.replace(/^let\s+\w+\s*=\s*/,``),t=t.replace(/^var\s+\w+\s*=\s*/,``),t=t.replace(/;?\s*$/,``),t=t.replace(/^.*?(?=\{|\[)/s,``),t.split(`
2
+ import{o as e,s as t}from"./ai-services-unified-DWAPupZV.js";import{$t as n,Dt as r,Ht as i,Kt as a,Mt as o,Nt as s,On as c,Qt as l,S as u,Sn as d,Tt as f,fn as p,h as m,ht as h,in as g,ln as _,ot as v,pn as y,rn as b,st as x,tn as S,tt as C,vn as ee,vt as w,wt as te,zt as ne}from"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import{r as re}from"./sentry-DsxpJLVM.js";import{$ as T,A as ie,B as E,C as ae,D as oe,Dt as se,Et as ce,F as le,G as ue,H as de,I as fe,J as pe,M as me,N as he,O as ge,P as _e,Q as ve,R as D,S as ye,U as be,V as xe,W as Se,X as Ce,Y as we,Z as Te,at as Ee,ct as De,dt as Oe,gt as ke,ht as Ae,i as je,it as Me,j as Ne,lt as Pe,n as Fe,pt as Ie,r as Le,rt as Re,st as ze,t as Be,ut as Ve,w as He,z as Ue}from"./dependency-manager-mDsYzQ71.js";import{t as We}from"./response-language-BmOan_mF.js";import{a as Ge,c as Ke,f as qe,g as Je,h as Ye,l as O,m as k,p as Xe,v as A}from"./profiles-CVELZrKz.js";import j from"node:path";import M from"chalk";import N from"fs";import P from"path";import Ze from"os";import F from"node:fs";import{z as I}from"zod";import{fileURLToPath as Qe}from"url";import L from"dotenv";import*as R from"@sentry/node";import{FastMCP as $e}from"fastmcp";const z={debug:0,info:1,warn:2,error:3,success:4},et=z[u().toLowerCase()]??z.info;function B(e,...t){if(w())return;let n={debug:M.gray(`[DEBUG]`),info:M.blue(`[INFO]`),warn:M.yellow(`[WARN]`),error:M.red(`[ERROR]`),success:M.green(`[SUCCESS]`)};if(z[e]!==void 0&&z[e]>=et){let r=n[e]||``,i=t;try{switch(e){case`error`:i=t.map(e=>typeof e==`string`?M.red(e):e);break;case`warn`:i=t.map(e=>typeof e==`string`?M.yellow(e):e);break;case`success`:i=t.map(e=>typeof e==`string`?M.green(e):e);break;case`info`:i=t.map(e=>typeof e==`string`?M.blue(e):e);break;case`debug`:i=t.map(e=>typeof e==`string`?M.gray(e):e);break}}catch(e){console.error(`Internal Logger Error applying chalk color:`,e),i=t}console.error(r,...i)}}function tt(){let e=e=>(...t)=>B(e,...t);return{debug:e(`debug`),info:e(`info`),warn:e(`warn`),error:e(`error`),success:e(`success`),log:B}}var V=tt(),H=class extends Error{constructor(e,t={}){super(e),this.name=`MCPError`,this.code=t.code,this.cause=t.cause,this.mcpResponse=t.mcpResponse}},U=class extends H{constructor(e,t={}){super(e,t),this.name=`MCPSessionError`}},nt=class extends H{constructor(e,t={}){super(e,t),this.name=`MCPSamplingError`}};function W(e){if(e instanceof H)return e;let t=e.message||`Unknown MCP error`,n=e;return t.includes(`session`)||t.includes(`connection`)?new U(t,{cause:n,code:`SESSION_ERROR`}):t.includes(`sampling`)||t.includes(`timeout`)?new nt(t,{cause:n,code:`SAMPLING_ERROR`}):t.includes(`capabilities`)||t.includes(`not supported`)?new U(t,{cause:n,code:`CAPABILITY_ERROR`}):new H(t,{cause:n,code:`UNKNOWN_ERROR`})}function rt(e){let t=e.trim();t=t.replace(/^```json\s*/gm,``),t=t.replace(/^```\s*/gm,``),t=t.replace(/```\s*$/gm,``),t=t.replace(/^const\s+\w+\s*=\s*/,``),t=t.replace(/^let\s+\w+\s*=\s*/,``),t=t.replace(/^var\s+\w+\s*=\s*/,``),t=t.replace(/;?\s*$/,``),t=t.replace(/^.*?(?=\{|\[)/s,``),t.split(`
3
3
  `);let n=-1,r=0,i=!1,a=!1;for(let e=0;e<t.length;e++){let o=t[e];if(a){a=!1;continue}if(o===`\\`){a=!0;continue}if(o===`"`&&!a){i=!i;continue}if(!i){if(o===`{`||o===`[`)r++;else if((o===`}`||o===`]`)&&(r--,r===0)){n=e;break}}}if(n>-1&&(t=t.substring(0,n+1)),n===-1){let e=t.match(/{[\s\S]*}/),n=t.match(/\[[\s\S]*\]/);e?t=e[0]:n&&(t=n[0])}try{return JSON.parse(t),t}catch{try{let e=t.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g,`$1"$2":`).replace(/'/g,`"`).replace(/,\s*([}\]])/g,`$1`);return JSON.parse(e),e}catch{return e}}}function G(e){let t=[],n=``;for(let r of e)r.role===`system`?n=K(r.content):(r.role===`user`||r.role===`assistant`)&&t.push({role:r.role,content:{type:`text`,text:K(r.content)}});return{messages:t,systemPrompt:n}}function it(e){let t=``,n=null,r=`stop`,i=[];return typeof e==`string`?t=e:e.content?(t=K(e.content),n=e.usage,r=e.finishReason||`stop`):e.text?(t=e.text,n=e.usage,r=e.finishReason||`stop`):(t=JSON.stringify(e),i.push(`Unexpected MCP response format, used JSON fallback`)),{text:t,usage:n,finishReason:r,warnings:i}}function K(e){return typeof e==`string`?e:Array.isArray(e)?e.map(e=>typeof e==`string`?e:e.type===`text`&&e.text||e.text?e.text:``).filter(e=>e.length>0).join(` `):e&&typeof e==`object`&&(e.type===`text`&&e.text||e.text)?e.text:String(e||``)}function at(e,t=`result`){try{let n=q(e);return`
4
4
  CRITICAL JSON GENERATION INSTRUCTIONS:
5
5
 
@@ -41,4 +41,4 @@ Current Tag: ${n.currentTag}`),{content:[{type:`text`,text:r}],isError:!0}}funct
41
41
 
42
42
  ### Results
43
43
 
44
- ${y.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-z0WhVh4e.js`);await e(P.join(d,`.taskmaster`,`tasks`,`tasks.json`),l,n,!1,{session:p,mcpLog:m,commandName:`research-save`,outputType:`mcp`,projectRoot:d,tag:f},`json`),t.info(`Research saved to subtask ${l}`)}else{let e=(await import(`./update-task-by-id-D6r8NE3N.js`)).default,r=parseInt(l,10);await e(P.join(d,`.taskmaster`,`tasks`,`tasks.json`),r,n,!1,{session:p,mcpLog:m,commandName:`research-save`,outputType:`mcp`,projectRoot:d,tag:f},`json`,!0),t.info(`Research saved to task ${l}`)}}catch(e){t.warn(`Error saving research to task/subtask: ${e.message}`)}return v(),{success:!0,data:{query:y.query,result:y.result,contextSize:y.contextSize,contextTokens:y.contextTokens,tokenBreakdown:y.tokenBreakdown,systemPromptTokens:y.systemPromptTokens,userPromptTokens:y.userPromptTokens,totalInputTokens:y.totalInputTokens,detailLevel:y.detailLevel,telemetryData:y.telemetryData,tagInfo:y.tagInfo,savedFilePath:y.savedFilePath}}}catch(e){return v(),t.error(`Error in researchDirect: ${e.message}`),{success:!1,error:{code:e.code||`RESEARCH_ERROR`,message:e.message}}}}async function mn(e,t,n={}){let{tasksJsonPath:r,id:i,strength:a=`regular`,prompt:o,research:s=!1,projectRoot:c,tag:l}=e,{session:u}=n;x();let d=D(t);try{if(!r)return t.error(`scopeDownDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i)return t.error(`Missing required parameter: id`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The id parameter is required for scoping down tasks`}};let e=i.split(`,`).map(e=>parseInt(e.trim(),10));t.info(`Scoping down tasks: ${e.join(`, `)}, strength: ${a}, research: ${s}`);let n=await oe(r,e,a,o,{session:u,mcpLog:d,projectRoot:c,commandName:`scope-down`,outputType:`mcp`,tag:l,research:s},`json`);return v(),{success:!0,data:{updatedTasks:n.updatedTasks,tasksUpdated:n.updatedTasks.length,message:`Successfully scoped down ${n.updatedTasks.length} task(s)`,telemetryData:n.telemetryData}}}catch(e){return v(),t.error(`Error in scopeDownDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_DOWN_ERROR`,message:e.message}}}}async function hn(e,t,n={}){let{tasksJsonPath:r,id:i,strength:a=`regular`,prompt:o,research:s=!1,projectRoot:c,tag:l}=e,{session:u}=n;x();let d=D(t);try{if(!r)return t.error(`scopeUpDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i)return t.error(`Missing required parameter: id`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The id parameter is required for scoping up tasks`}};let e=i.split(`,`).map(e=>parseInt(e.trim(),10));t.info(`Scoping up tasks: ${e.join(`, `)}, strength: ${a}, research: ${s}`);let n=await ge(r,e,a,o,{session:u,mcpLog:d,projectRoot:c,commandName:`scope-up`,outputType:`mcp`,tag:l,research:s},`json`);return v(),{success:!0,data:{updatedTasks:n.updatedTasks,tasksUpdated:n.updatedTasks.length,message:`Successfully scoped up ${n.updatedTasks.length} task(s)`,telemetryData:n.telemetryData}}}catch(e){return v(),t.error(`Error in scopeUpDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_UP_ERROR`,message:e.message}}}}async function gn(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,id:a,prompt:o,research:s,metadata:c,projectRoot:l,tag:u}=e,d=D(t);try{if(d.info(`Updating subtask by ID via direct function. ID: ${a}, ProjectRoot: ${l}`),!i){let e=`tasksJsonPath is required but was not provided.`;return d.error(e),{success:!1,error:{code:`MISSING_ARGUMENT`,message:e}}}if(!a||typeof a!=`string`||!a.trim()){let e=`Subtask ID cannot be empty.`;return d.error(e),{success:!1,error:{code:`INVALID_SUBTASK_ID`,message:e}}}if(!o&&!c){let e=`No prompt or metadata specified. Please provide information to append or metadata to update.`;return d.error(e),{success:!1,error:{code:`MISSING_PROMPT`,message:e}}}let e=String(a).trim(),n=i,f=s===!0;t.info(`Updating subtask with ID ${e} with prompt "${o||`(metadata-only)`}" and research: ${f}`);let p=w();p||x();try{let t=await He(n,e,o,f,{mcpLog:d,session:r,projectRoot:l,tag:u,commandName:`update-subtask`,outputType:`mcp`,metadata:c},`json`);if(!t||t.updatedSubtask===null){let e=`Subtask ${a} or its parent task not found.`;return d.error(e),{success:!1,error:{code:`SUBTASK_NOT_FOUND`,message:e}}}let i=e.split(`.`)[0],s=`Successfully updated subtask with ID ${e}`;return d.success(s),{success:!0,data:{message:`Successfully updated subtask with ID ${e}`,subtaskId:e,parentId:i,subtask:t.updatedSubtask,tasksPath:n,useResearch:f,telemetryData:t.telemetryData,tagInfo:t.tagInfo}}}catch(e){return d.error(`Error updating subtask by ID: ${e.message}`),{success:!1,error:{code:`UPDATE_SUBTASK_CORE_ERROR`,message:e.message||`Unknown error updating subtask`}}}finally{!p&&w()&&v()}}catch(e){return d.error(`Setup error in updateSubtaskByIdDirect: ${e.message}`),w()&&v(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function _n(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,id:a,prompt:o,research:s,append:c,metadata:l,projectRoot:u,tag:d}=e,f=D(t);try{if(f.info(`Updating task by ID via direct function. ID: ${a}, ProjectRoot: ${u}`),!a){let e=`No task ID specified. Please provide a task ID to update.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}if(!o&&!l){let e=`No prompt or metadata specified. Please provide a prompt with new information or metadata for the task update.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let t;if(typeof a==`string`)t=a;else if(typeof a==`number`)t=String(a);else{let e=`Invalid task ID type: ${typeof a}. Task ID must be a string or number.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let n=i||E({projectRoot:u,file:e.file},f);if(!n){let e=`tasks.json path could not be resolved.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let p=s===!0;f.info(`Updating task with ID ${t} with prompt "${o||`(metadata-only)`}" and research: ${p}`);let m=w();m||x();try{let e=await ae(n,t,o,p,{mcpLog:f,session:r,projectRoot:u,tag:d,commandName:`update-task`,outputType:`mcp`,metadata:l},`json`,c||!1);if(!e||e.updatedTask===null){let n=`Task ${t} was not updated (likely already completed).`;return f.info(n),{success:!0,data:{message:n,taskId:t,updated:!1,telemetryData:e?.telemetryData,tagInfo:e?.tagInfo}}}let i=`Successfully updated task with ID ${t} based on the prompt`;return f.info(i),{success:!0,data:{message:i,taskId:t,tasksPath:n,useResearch:p,updated:!0,updatedTask:e.updatedTask,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}}catch(e){return f.error(`Error updating task by ID: ${e.message}`),{success:!1,error:{code:`UPDATE_TASK_CORE_ERROR`,message:e.message||`Unknown error updating task`}}}finally{!m&&w()&&v()}}catch(e){return f.error(`Setup error in updateTaskByIdDirect: ${e.message}`),w()&&v(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function vn(e,t,n={}){let{session:r}=n,{from:i,prompt:a,research:o,tasksJsonPath:s,projectRoot:c,tag:l}=e,u=D(t);if(!c)return u.error(`updateTasksDirect requires a projectRoot argument.`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`projectRoot is required.`}};if(!i)return u.error(`updateTasksDirect called without from ID`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Starting task ID (from) is required`}};if(!a)return u.error(`updateTasksDirect called without prompt`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Update prompt is required`}};u.info(`Updating tasks via direct function. From: ${i}, Research: ${o}, File: ${s}, ProjectRoot: ${c}`),x();try{let e=await ye(s,i,a,o,{session:r,mcpLog:u,projectRoot:c,tag:l},`json`);return e&&e.success&&Array.isArray(e.updatedTasks)?(u.success(`Successfully updated ${e.updatedTasks.length} tasks.`),{success:!0,data:{message:`Successfully updated ${e.updatedTasks.length} tasks.`,tasksPath:s,updatedCount:e.updatedTasks.length,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}):(u.error(`Core updateTasks function did not return a successful structure.`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e?.message||`Core function failed to update tasks or returned unexpected result.`}})}catch(e){return u.error(`Error executing core updateTasks: ${e.message}`),{success:!1,error:{code:`UPDATE_TASKS_CORE_ERROR`,message:e.message||`Unknown error updating tasks`}}}finally{v()}}async function yn(e,t,n={}){let{tasksJsonPath:r,name:i,projectRoot:a}=e,{session:o}=n;x();let s=D(t);try{if(!r)return t.error(`useTagDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i||typeof i!=`string`)return t.error(`Missing required parameter: name`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Tag name is required and must be a string`}};t.info(`Switching to tag: ${i}`);let e=await Ae(r,i,{},{session:o,mcpLog:s,projectRoot:a},`json`);return v(),{success:!0,data:{tagName:e.currentTag,switched:e.switched,previousTag:e.previousTag,taskCount:e.taskCount,message:`Successfully switched to tag "${e.currentTag}"`}}}catch(e){return v(),t.error(`Error in useTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`USE_TAG_ERROR`,message:e.message}}}}async function bn(e,t){let{tasksJsonPath:n,projectRoot:r,tag:i}=e;if(!n)return t.error(`validateDependenciesDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};try{t.info(`Validating dependencies in tasks: ${n}`);let e=n;return N.existsSync(e)?(x(),await je(e,{projectRoot:r,tag:i}),v(),{success:!0,data:{message:`Dependencies validated successfully`,tasksPath:e}}):{success:!1,error:{code:`FILE_NOT_FOUND`,message:`Tasks file not found at ${e}`}}}catch(e){return v(),t.error(`Error validating dependencies: ${e.message}`),{success:!1,error:{code:`VALIDATION_ERROR`,message:e.message}}}}function xn(e){e.addTool({name:`add_dependency`,description:`Add a dependency relationship between two tasks`,parameters:I.object({id:I.string().describe(`ID of task that will depend on another task`),dependsOn:I.string().describe(`ID of task that will become a dependency`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Add Dependency`,destructiveHint:!0},execute:Q(`add-dependency`,async(e,{log:t,session:n})=>{try{t.info(`Adding dependency for task ${e.id} to depend on ${e.dependsOn}`);let n=r({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await zt({tasksJsonPath:i,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t);return a.success?t.info(`Successfully added dependency: ${a.data.message}`):t.error(`Failed to add dependency: ${a.error.message}`),Y({result:a,log:t,errorPrefix:`Error adding dependency`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in addDependency tool: ${e.message}`),J(e.message)}})})}function Sn(e){e.addTool({name:`add_subtask`,description:`Add a subtask to an existing task`,parameters:I.object({id:I.string().describe(`Parent task ID (required)`),taskId:I.string().optional().describe(`Existing task ID to convert to subtask`),title:I.string().optional().describe(`Title for the new subtask (when creating a new subtask)`),description:I.string().optional().describe(`Description for the new subtask`),details:I.string().optional().describe(`Implementation details for the new subtask`),status:I.string().optional().describe(`Status for the new subtask (default: 'pending')`),dependencies:I.string().optional().describe(`Comma-separated list of dependency IDs for the new subtask`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:I.boolean().optional().describe(`Skip regenerating task files`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Add Subtask`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{let i=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Adding subtask with args: ${JSON.stringify(e)}`);let a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=await Bt({tasksJsonPath:a,id:e.id,taskId:e.taskId,title:e.title,description:e.description,details:e.details,status:e.status,dependencies:e.dependencies,skipGenerate:e.skipGenerate,projectRoot:e.projectRoot,tag:i},t,{session:n});return o.success?t.info(`Subtask added successfully: ${o.data.message}`):t.error(`Failed to add subtask: ${o.error.message}`),Y({result:o,log:t,errorPrefix:`Error adding subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in addSubtask tool: ${e.message}`),J(e.message)}})})}function Cn(e){e.addTool({name:`add_tag`,description:`Create a new tag for organizing tasks in different contexts`,parameters:I.object({name:I.string().describe(`Name of the new tag to create`),copyFromCurrent:I.boolean().optional().describe(`Whether to copy tasks from the current tag (default: false)`),copyFromTag:I.string().optional().describe(`Specific tag to copy tasks from`),fromBranch:I.boolean().optional().describe(`Create tag name from current git branch (ignores name parameter)`),description:I.string().optional().describe(`Optional description for the tag`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Add Tag`,destructiveHint:!1},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting add-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Vt({tasksJsonPath:r,name:e.name,copyFromCurrent:e.copyFromCurrent,copyFromTag:e.copyFromTag,fromBranch:e.fromBranch,description:e.description,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error creating tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in add-tag tool: ${e.message}`),J(e.message)}})})}function wn(e){e.addTool({name:`add_task`,description:`Add a new task using AI`,parameters:I.object({prompt:I.string().optional().describe(`Description of the task to add (required if not using manual fields)`),title:I.string().optional().describe(`Task title (for manual task creation)`),description:I.string().optional().describe(`Task description (for manual task creation)`),details:I.string().optional().describe(`Implementation details (for manual task creation)`),testStrategy:I.string().optional().describe(`Test strategy (for manual task creation)`),dependencies:I.string().optional().describe(`Comma-separated list of task IDs this task depends on`),priority:I.string().optional().describe(`Task priority (high, medium, low)`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),research:I.boolean().optional().describe(`Whether to use research capabilities for task creation`)}),annotations:{title:`Add Task`,destructiveHint:!1},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting add-task with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Ht({tasksJsonPath:a,prompt:e.prompt,title:e.title,description:e.description,details:e.details,testStrategy:e.testStrategy,dependencies:e.dependencies,priority:e.priority,research:e.research,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error adding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in add-task tool: ${e.message}`),J(e.message)}})})}function Tn(e){e.addTool({name:`analyze_project_complexity`,description:`Analyze task complexity and generate expansion recommendations.`,parameters:I.object({threshold:I.coerce.number().int().min(1).max(10).optional().default(5).describe(`Complexity score threshold (1-10) to recommend expansion.`),research:I.boolean().optional().default(!1).describe(`Use Perplexity AI for research-backed analysis.`),output:I.string().optional().describe(`Output file path relative to project root (default: ${s}).`),file:I.string().optional().describe(`Path to the tasks file relative to project root (default: tasks/tasks.json).`),ids:I.string().optional().describe(`Comma-separated list of task IDs to analyze specifically (e.g., "1,3,5").`),from:I.coerce.number().int().positive().optional().describe(`Starting task ID in a range to analyze.`),to:I.coerce.number().int().positive().optional().describe(`Ending task ID in a range to analyze.`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Analyze Project Complexity`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`analyze_project_complexity`;try{t.info(`Executing ${i} tool with args: ${JSON.stringify(e)}`);let a=r({projectRoot:e.projectRoot,tag:e.tag}),o;try{o=E({projectRoot:e.projectRoot,file:e.file},t),t.info(`${i}: Resolved tasks path: ${o}`)}catch(n){return t.error(`${i}: Error finding tasks.json: ${n.message}`),J(`Failed to find tasks.json within project root '${e.projectRoot}': ${n.message}`)}let s=C(e.output,{projectRoot:e.projectRoot,tag:a},t);t.info(`${i}: Report output path: ${s}`);let c=P.dirname(s);try{N.existsSync(c)||(N.mkdirSync(c,{recursive:!0}),t.info(`${i}: Created output directory: ${c}`))}catch(e){return t.error(`${i}: Failed to create output directory ${c}: ${e.message}`),J(`Failed to create output directory: ${e.message}`)}let l=await Ut({tasksJsonPath:o,outputPath:s,threshold:e.threshold,research:e.research,projectRoot:e.projectRoot,tag:a,ids:e.ids,from:e.from,to:e.to},t,{session:n});return t.info(`${i}: Direct function result: success=${l.success}`),Y({result:l,log:t,errorPrefix:`Error analyzing task complexity`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function En(e){e.addTool({name:`clear_subtasks`,description:`Clear subtasks from specified tasks`,parameters:I.object({id:I.string().optional().describe(`Task IDs (comma-separated) to clear subtasks from`),all:I.boolean().optional().describe(`Clear subtasks from all tasks`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}).refine(e=>e.id||e.all,{message:`Either 'id' or 'all' parameter must be provided`,path:[`id`,`all`]}),annotations:{title:`Clear Subtasks`,destructiveHint:!0},execute:Q(`clear-subtasks`,async(e,t)=>{try{t.log.info(`Clearing subtasks with args: ${JSON.stringify(e)}`);let n=r({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=E({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await Wt({tasksJsonPath:i,id:e.id,all:e.all,projectRoot:e.projectRoot,tag:n},t.log,{session:t.session});return a.success?t.log.info(`Subtasks cleared successfully: ${a.data.message}`):t.log.error(`Failed to clear subtasks: ${a.error.message}`),Y({result:a,log:t.log,errorPrefix:`Error clearing subtasks`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in clearSubtasks tool: ${e.message}`),J(e.message)}})})}function Dn(e){e.addTool({name:`complexity_report`,description:`Display the complexity analysis report in a readable format`,parameters:I.object({file:I.string().optional().describe(`Path to the report file (default: ${s})`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Complexity Report`,readOnlyHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Getting complexity report with args: ${JSON.stringify(e)}`);let n=h(e.projectRoot),r=Ue({projectRoot:e.projectRoot,complexityReport:e.file,tag:n},t);if(t.info(`Reading complexity report from path: `,r),!r)return J(`No complexity report found. Run task-master analyze-complexity first.`);let i=await Gt({reportPath:r},t);return i.success?t.info(`Successfully retrieved complexity report`):t.error(`Failed to retrieve complexity report: ${i.error.message}`),Y({result:i,log:t,errorPrefix:`Error retrieving complexity report`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in complexity-report tool: ${e.message}`),J(`Failed to retrieve complexity report: ${e.message}`)}})})}function On(e){e.addTool({name:`copy_tag`,description:`Copy an existing tag to create a new tag with all tasks and metadata`,parameters:I.object({sourceName:I.string().describe(`Name of the source tag to copy from`),targetName:I.string().describe(`Name of the new tag to create`),description:I.string().optional().describe(`Optional description for the new tag`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Copy Tag`,destructiveHint:!1},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting copy-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Kt({tasksJsonPath:r,sourceName:e.sourceName,targetName:e.targetName,description:e.description,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error copying tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in copy-tag tool: ${e.message}`),J(e.message)}})})}function kn(e){e.addTool({name:`delete_tag`,description:`Delete an existing tag and all its tasks`,parameters:I.object({name:I.string().describe(`Name of the tag to delete`),yes:I.boolean().optional().describe(`Skip confirmation prompts (default: true for MCP)`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Delete Tag`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting delete-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await qt({tasksJsonPath:r,name:e.name,yes:e.yes===void 0?!0:e.yes,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error deleting tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in delete-tag tool: ${e.message}`),J(e.message)}})})}function An(e){e.addTool({name:`expand_all`,description:`Expand all pending tasks into subtasks based on complexity or defaults`,parameters:I.object({num:I.string().optional().describe(`Target number of subtasks per task (uses complexity/defaults otherwise)`),research:I.boolean().optional().describe(`Enable research-backed subtask generation (e.g., using Perplexity)`),prompt:I.string().optional().describe(`Additional context to guide subtask generation for all tasks`),force:I.boolean().optional().describe(`Force regeneration of subtasks for tasks that already have them`),file:I.string().optional().describe(`Absolute path to the tasks file in the /tasks folder inside the project root (default: tasks/tasks.json)`),projectRoot:I.string().optional().describe(`Absolute path to the project root directory (derived from session if possible)`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand All Tasks`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Tool expand_all execution started with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t),t.info(`Resolved tasks.json path: ${a}`)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=xe(null,{projectRoot:e.projectRoot,tag:i},t);return t.info(`Using complexity report path: ${o}`),Y({result:await Jt({tasksJsonPath:a,num:e.num,research:e.research,prompt:e.prompt,force:e.force,projectRoot:e.projectRoot,tag:i,complexityReportPath:o},t,{session:n}),log:t,errorPrefix:`Error expanding all tasks`,projectRoot:e.projectRoot})}catch(e){return t.error(`Unexpected error in expand_all tool execute: ${e.message}`),e.stack&&t.error(e.stack),J(`An unexpected error occurred: ${e.message}`)}})})}function jn(e){e.addTool({name:`expand_task`,description:`Expand a task into subtasks for detailed implementation`,parameters:I.object({id:I.string().describe(`ID of task to expand`),num:I.string().optional().describe(`Number of subtasks to generate`),research:I.boolean().optional().default(!1).describe(`Use research role for generation`),prompt:I.string().optional().describe(`Additional context for subtask generation`),file:I.string().optional().describe(`Path to the tasks file relative to project root (e.g., tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),force:I.boolean().optional().default(!1).describe(`Force expansion even if subtasks exist`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting expand-task with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=Ue({...e,tag:i},t);return Y({result:await Yt({tasksJsonPath:a,id:e.id,num:e.num,research:e.research,prompt:e.prompt,force:e.force,complexityReportPath:o,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error expanding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in expand-task tool: ${e.message}`),J(e.message)}})})}function Mn(e){e.addTool({name:`fix_dependencies`,description:`Fix invalid dependencies in tasks automatically`,parameters:I.object({file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Fix Dependencies`,destructiveHint:!0},execute:Q(`fix-dependencies`,async(e,t)=>{try{t.log.info(`Fixing dependencies with args: ${JSON.stringify(e)}`);let n=r({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=E({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await Xt({tasksJsonPath:i,projectRoot:e.projectRoot,tag:n},t.log);return a.success?t.log.info(`Successfully fixed dependencies: ${a.data.message}`):t.log.error(`Failed to fix dependencies: ${a.error.message}`),Y({result:a,log:t.log,errorPrefix:`Error fixing dependencies`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in fixDependencies tool: ${e.message}`),J(e.message)}})})}function Nn(e){e.addTool({name:`initialize_project`,description:`Initializes a new Task Master project structure by calling the core initialization logic. Creates necessary folders and configuration files for Task Master in the current directory.`,parameters:I.object({skipInstall:I.boolean().optional().default(!1).describe(`Skip installing dependencies automatically. Never do this unless you are sure the project is already installed.`),addAliases:I.boolean().optional().default(!0).describe(`Add shell aliases (tm, taskmaster, hamster, ham) to shell config file.`),initGit:I.boolean().optional().default(!0).describe(`Initialize Git repository in project root.`),storeTasksInGit:I.boolean().optional().default(!0).describe(`Store tasks in Git (tasks.json and tasks/ directory).`),yes:I.boolean().optional().default(!0).describe(`Skip prompts and use default values. Always set to true for MCP tools.`),projectRoot:I.string().describe(`The root directory for the project. ALWAYS SET THIS TO THE PROJECT ROOT DIRECTORY. IF NOT SET, THE TOOL WILL NOT WORK.`),rules:I.array(I.enum(A)).optional().describe(`List of rule profiles to include at initialization. If omitted, defaults to Cursor profile only. Available options: ${A.join(`, `)}`)}),annotations:{title:`Initialize Project`,destructiveHint:!0},execute:Z(async(e,t)=>{let{log:n}=t,r=t.session;try{return n.info(`Executing initialize_project tool with args: ${JSON.stringify(e)}`),Y({result:await Zt(e,n,{session:r}),log:n,errorPrefix:`Initialization failed`,projectRoot:e.projectRoot})}catch(e){let t=`Project initialization tool failed: ${e.message||`Unknown error`}`;return n.error(t,e),J(t,{details:e.stack})}})})}function Pn(e){e.addTool({name:`list_tags`,description:`List all available tags with task counts and metadata`,parameters:I.object({showMetadata:I.boolean().optional().describe(`Whether to include metadata in the output (default: false)`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`List Tags`,readOnlyHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting list-tags with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Qt({tasksJsonPath:r,showMetadata:e.showMetadata,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error listing tags`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in list-tags tool: ${e.message}`),J(e.message)}})})}function Fn(e){e.addTool({name:`models`,description:`Get information about available AI models or set model configurations. Run without arguments to get the current model configuration and API key status for the selected model providers.`,parameters:I.object({setMain:I.string().optional().describe(`Set the primary model for task generation/updates. Model provider API key is required in the MCP config ENV.`),setResearch:I.string().optional().describe(`Set the model for research-backed operations. Model provider API key is required in the MCP config ENV.`),setFallback:I.string().optional().describe(`Set the model to use if the primary fails. Model provider API key is required in the MCP config ENV.`),listAvailableModels:I.boolean().optional().describe(`List all available models not currently in use. Input/output costs values are in dollars (3 is $3.00).`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),openrouter:I.boolean().optional().describe(`Indicates the set model ID is a custom OpenRouter model.`),ollama:I.boolean().optional().describe(`Indicates the set model ID is a custom Ollama model.`),bedrock:I.boolean().optional().describe(`Indicates the set model ID is a custom AWS Bedrock model.`),azure:I.boolean().optional().describe(`Indicates the set model ID is a custom Azure OpenAI model.`),vertex:I.boolean().optional().describe(`Indicates the set model ID is a custom Google Vertex AI model.`),"openai-compatible":I.boolean().optional().describe(`Indicates the set model ID is a custom OpenAI-compatible model. Requires baseURL parameter.`),baseURL:I.string().optional().describe(`Custom base URL for providers that support it (e.g., https://api.example.com/v1).`)}),annotations:{title:`Models`,destructiveHint:!0},execute:Q(`models`,async(e,t)=>{try{return t.log.info(`Starting models tool with args: ${JSON.stringify(e)}`),Y({result:await nn({...e,projectRoot:e.projectRoot},t.log,{session:t.session}),log:t.log,errorPrefix:`Error managing models`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in models tool: ${e.message}`),J(e.message)}})})}function In(e){e.addTool({name:`move_task`,description:`Move a task or subtask to a new position`,parameters:I.object({from:I.string().describe(`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")`),to:I.string().optional().describe(`ID of the destination (e.g., "7" or "7.3"). Required for within-tag moves. For cross-tag moves, if omitted, task will be moved to the target tag maintaining its ID`),file:I.string().optional().describe(`Custom path to tasks.json file`),projectRoot:I.string().describe(`Root directory of the project (typically derived from session)`),tag:I.string().optional().describe(`Tag context to operate on`),fromTag:I.string().optional().describe(`Source tag for cross-tag moves`),toTag:I.string().optional().describe(`Target tag for cross-tag moves`),withDependencies:I.boolean().optional().describe(`Move dependent tasks along with main task`),ignoreDependencies:I.boolean().optional().describe(`Break cross-tag dependencies during move`)}),annotations:{title:`Move Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{if(e.fromTag&&e.toTag&&e.fromTag!==e.toTag){if(!e.from)return J(`Source IDs are required for cross-tag moves`,`MISSING_SOURCE_IDS`);e.to&&t.warn(`The "to" parameter is not used for cross-tag moves and will be ignored. Tasks retain their original IDs in the target tag.`);let r=e.file;return r||=E(e,t),Y({result:await rn({sourceIds:e.from,sourceTag:e.fromTag,targetTag:e.toTag,withDependencies:e.withDependencies||!1,ignoreDependencies:e.ignoreDependencies||!1,tasksJsonPath:r,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error moving tasks between tags`,projectRoot:e.projectRoot})}else{if(!e.to)return J(`Destination ID is required for within-tag moves`,`MISSING_DESTINATION_ID`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a=e.file;a||=E(e,t);let o=e.from.split(`,`).map(e=>e.trim()),s=e.to.split(`,`).map(e=>e.trim());if(o.length!==s.length){if(o.length>1){let r=[],c=[];for(let l=0;l<o.length;l++){let u=o[l],d=s[l];if(u===d){t.info(`Skipping ${u} -> ${d} (same ID)`),c.push({fromId:u,toId:d,reason:`same ID`});continue}let f=l===o.length-1,p=await an({sourceId:u,destinationId:d,tasksJsonPath:a,projectRoot:e.projectRoot,tag:i,generateFiles:f},t,{session:n});p.success?r.push(p.data):t.error(`Failed to move ${u} to ${d}: ${p.error.message}`)}return Y({result:{success:!0,data:{moves:r,skipped:c.length>0?c:void 0,message:`Successfully moved ${r.length} tasks${c.length>0?`, skipped ${c.length}`:``}`}},log:t,errorPrefix:`Error moving multiple tasks`,projectRoot:e.projectRoot})}return Y({result:{success:!0,data:{moves:results,skippedMoves,message:`Successfully moved ${results.length} tasks${skippedMoves.length>0?`, skipped ${skippedMoves.length} moves`:``}`}},log:t,errorPrefix:`Error moving multiple tasks`,projectRoot:e.projectRoot})}else return Y({result:await an({sourceId:e.from,destinationId:e.to,tasksJsonPath:a,projectRoot:e.projectRoot,tag:i,generateFiles:!0},t,{session:n}),log:t,errorPrefix:`Error moving task`,projectRoot:e.projectRoot})}}catch(e){return J(`Failed to move task: ${e.message}`,`MOVE_TASK_ERROR`)}})})}function Ln(e){e.addTool({name:`next_task`,description:`Find the next task to work on based on dependencies and status`,parameters:I.object({file:I.string().optional().describe(`Absolute path to the tasks file`),complexityReport:I.string().optional().describe(`Path to the complexity report file (relative to project root or absolute)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Next Task`,readOnlyHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Finding next task with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=ue(e,n)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o;try{o=de({...e,tag:i},n)}catch(e){t.error(`Error finding complexity report: ${e.message}`),o=null}let s=await on({tasksJsonPath:a,reportPath:o,projectRoot:e.projectRoot,tag:i},t,{session:n});return t.info(`Next task result: ${s.success?`found`:`none`}`),Y({result:s,log:t,errorPrefix:`Error finding next task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error finding next task: ${e.message}`),J(e.message)}})})}function Rn(e){e.addTool({name:`parse_prd`,description:`Parse a Product Requirements Document (PRD) text file to automatically generate initial tasks. Reinitializing the project is not necessary to run this tool. It is recommended to run parse-prd after initializing the project and creating/importing a prd.txt file in the project root's ${i} directory.`,parameters:I.object({input:I.string().optional().default(ne).describe(`Absolute path to the PRD document file (.txt, .md, etc.)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),destination:I.enum([`local`,`hamster`]).optional().default(`local`).describe(`Where to parse the PRD: "local" writes tasks.json, "hamster" creates a cloud brief and tasks`),output:I.string().optional().describe(`Output path for tasks.json file (default: ${a})`),numTasks:I.string().optional().describe(`Approximate number of top-level tasks to generate (default: 10). As the agent, if you have enough information, ensure to enter a number of tasks that would logically scale with project complexity. Setting to 0 will allow Taskmaster to determine the appropriate number of tasks based on the complexity of the PRD. Avoid entering numbers above 50 due to context window limitations.`),force:I.boolean().optional().default(!1).describe(`Overwrite existing output file without prompting.`),research:I.boolean().optional().describe(`Enable Taskmaster to use the research role for potentially more informed task generation. Requires appropriate API key.`),append:I.boolean().optional().describe(`Append generated tasks to existing file.`)}),annotations:{title:`Parse PRD`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n,reportProgress:i})=>{try{let a=r({projectRoot:e.projectRoot,tag:e.tag}),o=dt(i,t);return Y({result:await sn({...e,tag:a},t,{session:n,reportProgress:o}),log:t,errorPrefix:`Error parsing PRD`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in parse_prd: ${e.message}`),J(`Failed to parse PRD: ${e.message}`)}})})}function zn(e){e.addTool({name:`remove_dependency`,description:`Remove a dependency from a task`,parameters:I.object({id:I.string().describe(`Task ID to remove dependency from`),dependsOn:I.string().describe(`Task ID to remove as a dependency`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Dependency`,destructiveHint:!0},execute:Q(`remove-dependency`,async(e,t)=>{try{let n=r({projectRoot:e.projectRoot,tag:e.tag});t.log.info(`Removing dependency for task ${e.id} from ${e.dependsOn} with args: ${JSON.stringify(e)}`);let i;try{i=E({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await ln({tasksJsonPath:i,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t.log);return a.success?t.log.info(`Successfully removed dependency: ${a.data.message}`):t.log.error(`Failed to remove dependency: ${a.error.message}`),Y({result:a,log:t.log,errorPrefix:`Error removing dependency`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in removeDependency tool: ${e.message}`),J(e.message)}})})}function Bn(e){e.addTool({name:`remove_subtask`,description:`Remove a subtask from its parent task`,parameters:I.object({id:I.string().describe(`Subtask ID to remove in format 'parentId.subtaskId' (required)`),convert:I.boolean().optional().describe(`Convert the subtask to a standalone task instead of deleting it`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:I.boolean().optional().describe(`Skip regenerating task files`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Subtask`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{let i=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Removing subtask with args: ${JSON.stringify(e)}`);let a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=await un({tasksJsonPath:a,id:e.id,convert:e.convert,skipGenerate:e.skipGenerate,projectRoot:e.projectRoot,tag:i},t,{session:n});return o.success?t.info(`Subtask removed successfully: ${o.data.message}`):t.error(`Failed to remove subtask: ${o.error.message}`),Y({result:o,log:t,errorPrefix:`Error removing subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in removeSubtask tool: ${e.message}`),J(e.message)}})})}function Vn(e){e.addTool({name:`remove_task`,description:`Remove a task or subtask permanently from the tasks list`,parameters:I.object({id:I.string().describe(`ID of the task or subtask to remove (e.g., '5' or '5.2'). Can be comma-separated to update multiple tasks/subtasks at once.`),file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),confirm:I.boolean().optional().describe(`Whether to skip confirmation prompt (default: false)`),tag:I.string().optional().describe(`Specify which tag context to operate on. Defaults to the current active tag.`)}),annotations:{title:`Remove Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Removing task(s) with ID(s): ${e.id}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}t.info(`Using tasks file path: ${a}`);let o=await dn({tasksJsonPath:a,id:e.id,projectRoot:e.projectRoot,tag:i},t,{session:n});return o.success?t.info(`Successfully removed task: ${e.id}`):t.error(`Failed to remove task: ${o.error.message}`),Y({result:o,log:t,errorPrefix:`Error removing task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in remove-task tool: ${e.message}`),J(`Failed to remove task: ${e.message}`)}})})}function Hn(e){e.addTool({name:`rename_tag`,description:`Rename an existing tag`,parameters:I.object({oldName:I.string().describe(`Current name of the tag to rename`),newName:I.string().describe(`New name for the tag`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Rename Tag`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting rename-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await fn({tasksJsonPath:r,oldName:e.oldName,newName:e.newName,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error renaming tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in rename-tag tool: ${e.message}`),J(e.message)}})})}function Un(e){e.addTool({name:`research`,description:`Perform AI-powered research queries with project context`,parameters:I.object({query:I.string().describe(`Research query/prompt (required)`),taskIds:I.string().optional().describe(`Comma-separated list of task/subtask IDs for context (e.g., "15,16.2,17")`),filePaths:I.string().optional().describe(`Comma-separated list of file paths for context (e.g., "src/api.js,docs/readme.md")`),customContext:I.string().optional().describe(`Additional custom context text to include in the research`),includeProjectTree:I.boolean().optional().describe(`Include project file tree structure in context (default: false)`),detailLevel:I.enum([`low`,`medium`,`high`]).optional().describe(`Detail level for the research response (default: medium)`),saveTo:I.string().optional().describe(`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`),saveToFile:I.boolean().optional().describe(`Save research results to .taskmaster/docs/research/ directory (default: false)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Research`,destructiveHint:!0,openWorldHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{let i=r({projectRoot:e.projectRoot,tag:e.tag});return t.info(`Starting research with query: "${e.query.substring(0,100)}${e.query.length>100?`...`:``}"`),Y({result:await pn({query:e.query,taskIds:e.taskIds,filePaths:e.filePaths,customContext:e.customContext,includeProjectTree:e.includeProjectTree||!1,detailLevel:e.detailLevel||`medium`,saveTo:e.saveTo,saveToFile:e.saveToFile||!1,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error performing research`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in research tool: ${e.message}`),J(e.message)}})})}async function Wn(e,t,n={}){let{projectRoot:r,language:i}=e,a=D(t);t.info(`Executing response-language_direct with args: ${JSON.stringify(e)}`),t.info(`Using project root: ${r}`);try{return x(),We(i,{mcpLog:a,projectRoot:r})}catch(e){return{success:!1,error:{code:`DIRECT_FUNCTION_ERROR`,message:e.message,details:e.stack}}}finally{v()}}function Gn(e){e.addTool({name:`response-language`,description:`Get or set the response language for the project`,parameters:I.object({projectRoot:I.string().describe(`The root directory for the project. ALWAYS SET THIS TO THE PROJECT ROOT DIRECTORY. IF NOT SET, THE TOOL WILL NOT WORK.`),language:I.string().describe(`The new response language to set. like "中文" "English" or "español".`)}),annotations:{title:`Response Language`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{return t.info(`Executing response-language tool with args: ${JSON.stringify(e)}`),Y({result:await Wn({...e,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error setting response language`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in response-language tool: ${e.message}`),J(e.message)}})})}async function Kn(e,t,n={}){x();try{let{action:t,profiles:n,projectRoot:r,yes:i,force:a}=e;if(!t||!Array.isArray(n)||n.length===0||!r)return{success:!1,error:{code:`MISSING_ARGUMENT`,message:`action, profiles, and projectRoot are required.`}};let o=[],s=[];if(t===O.REMOVE){if(!a&&Ke(r,n)){let e=Ge(r);return e.filter(e=>!n.includes(e)),{success:!1,error:{code:`CRITICAL_REMOVAL_BLOCKED`,message:`CRITICAL: This operation would remove ALL remaining rule profiles (${n.join(`, `)}), leaving your project with no rules configurations. This could significantly impact functionality. Currently installed profiles: ${e.join(`, `)}. If you're certain you want to proceed, set force: true or use the CLI with --force flag.`}}}for(let e of n){if(!Ye(e)){o.push({profileName:e,success:!1,error:`The requested rule profile for '${e}' is unavailable. Supported profiles are: ${A.join(`, `)}.`});continue}let t=Je(r,k(e));o.push(t)}let e=o.filter(e=>e.success).map(e=>e.profileName),t=o.filter(e=>e.skipped).map(e=>e.profileName),i=o.filter(e=>e.error&&!e.success&&!e.skipped),s=o.filter(e=>e.notice),c=``;return e.length>0&&(c+=`Successfully removed Task Master rules: ${e.join(`, `)}.`),t.length>0&&(c+=`Skipped (default or protected): ${t.join(`, `)}.`),i.length>0&&(c+=i.map(e=>`Error removing ${e.profileName}: ${e.error}`).join(` `)),s.length>0&&(c+=` Notices: ${s.map(e=>`${e.profileName} - ${e.notice}`).join(`; `)}.`),v(),{success:i.length===0,data:{summary:c,results:o}}}else if(t===O.ADD){for(let e of n){if(!Ye(e)){s.push({profileName:e,success:!1,error:`Profile not found: static import missing for '${e}'. Valid profiles: ${A.join(`, `)}`});continue}let t=k(e),{success:n,failed:i}=Xe(r,t),a=t.rulesDir,o=P.join(r,a),c=t.profileDir,l=t.mcpConfig!==!1,u=l&&t.mcpConfigPath?P.join(r,t.mcpConfigPath):null,d=l&&u?N.existsSync(u):void 0,f=N.existsSync(o),p=N.existsSync(P.join(r,c)),m=i>0?`${i} rule files failed to convert.`:null,h={profileName:e,mcpConfigCreated:d,rulesDirCreated:f,profileFolderCreated:p,skipped:!1,error:m,success:(l?d:!0)&&f&&n>0&&!m};s.push(h)}let e=s.filter(e=>e.success).map(e=>e.profileName),t=s.filter(e=>e.error&&!e.success),i=``;return e.length>0&&(i+=`Successfully added rules: ${e.join(`, `)}.`),t.length>0&&(i+=t.map(e=>` Error adding ${e.profileName}: ${e.error}`).join(` `)),v(),{success:t.length===0,data:{summary:i,results:s}}}else return v(),{success:!1,error:{code:`INVALID_ACTION`,message:`Unknown action. Use "${O.ADD}" or "${O.REMOVE}".`}}}catch(e){return v(),t.error(`[rulesDirect] Error: ${e.message}`),{success:!1,error:{code:e.code||`RULES_ERROR`,message:e.message}}}}function qn(e){e.addTool({name:`rules`,description:`Add or remove rule profiles from the project.`,parameters:I.object({action:I.enum([`add`,`remove`]).describe(`Whether to add or remove rule profiles.`),profiles:I.array(I.enum(A)).min(1).describe(`List of rule profiles to add or remove (e.g., [\"cursor\", \"roo\"]). Available options: ${A.join(`, `)}`),projectRoot:I.string().describe(`The root directory of the project. Must be an absolute path.`),force:I.boolean().optional().default(!1).describe(`DANGEROUS: Force removal even if it would leave no rule profiles. Only use if you are absolutely certain.`)}),annotations:{title:`Rules`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{return t.info(`[rules tool] Executing action: ${e.action} for profiles: ${e.profiles.join(`, `)} in ${e.projectRoot}`),Y({result:await Kn(e,t,{session:n}),log:t,projectRoot:e.projectRoot})}catch(e){return t.error(`[rules tool] Error: ${e.message}`),J(e.message,{details:e.stack})}})})}function Jn(e){e.addTool({name:`scope_down_task`,description:`Decrease the complexity of one or more tasks using AI`,parameters:I.object({id:I.string().describe(`Comma-separated list of task IDs to scope down (e.g., "1,3,5")`),strength:I.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:I.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),research:I.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Down Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-down with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await mn({tasksJsonPath:a,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error scoping down task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in scope-down tool: ${e.message}`),J(e.message)}})})}function Yn(e){e.addTool({name:`scope_up_task`,description:`Increase the complexity of one or more tasks using AI`,parameters:I.object({id:I.string().describe(`Comma-separated list of task IDs to scope up (e.g., "1,3,5")`),strength:I.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:I.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),research:I.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Up Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-up with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await hn({tasksJsonPath:a,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error scoping up task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in scope-up tool: ${e.message}`),J(e.message)}})})}function Xn(e){e.addTool({name:`update_subtask`,description:`Appends timestamped information to a specific subtask without replacing existing content. If you just want to update the subtask status, use set_task_status instead.`,parameters:I.object({id:b.describe(`ID of the subtask to update in format "parentId.subtaskId" (e.g., "5.2"). Parent ID is the ID of the task that contains the subtask.`),prompt:I.string().optional().describe(`Information to add to the subtask. Required unless only updating metadata.`),research:I.boolean().optional().describe(`Use Perplexity AI for research-backed updates`),metadata:I.string().optional().describe(`JSON string of metadata to merge into subtask metadata. Example: '{"ticketId": "JIRA-456", "reviewed": true}'. Requires TASK_MASTER_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Subtask`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`update_subtask`;try{let a=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Updating subtask with args: ${JSON.stringify(e)}`);let o;try{o=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`${i}: Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let s=mt(e.metadata,J);if(s.error)return s.error;let c=s.parsedMetadata;if(!e.prompt&&!c)return J(`Either prompt or metadata must be provided for update-subtask`);let l=await gn({tasksJsonPath:o,id:e.id,prompt:e.prompt,research:e.research,metadata:c,projectRoot:e.projectRoot,tag:a},t,{session:n});return l.success?t.info(`Successfully updated subtask with ID ${e.id}`):t.error(`Failed to update subtask: ${l.error?.message||`Unknown error`}`),Y({result:l,log:t,errorPrefix:`Error updating subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function Zn(e){e.addTool({name:`update_task`,description:`Updates a single task by ID with new information or context provided in the prompt.`,parameters:I.object({id:I.string().describe(`ID of the task (e.g., '15') to update. Subtasks are supported using the update-subtask tool.`),prompt:I.string().optional().describe(`New information or context to incorporate into the task. Required unless only updating metadata.`),research:I.boolean().optional().describe(`Use Perplexity AI for research-backed updates`),append:I.boolean().optional().describe(`Append timestamped information to task details instead of full update`),metadata:I.string().optional().describe(`JSON string of metadata to merge into task metadata. Example: '{"githubIssue": 42, "sprint": "Q1-S3"}'. Requires TASK_MASTER_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`update_task`;try{let a=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Executing ${i} tool with args: ${JSON.stringify(e)}`);let o;try{o=E({projectRoot:e.projectRoot,file:e.file},t),t.info(`${i}: Resolved tasks path: ${o}`)}catch(e){return t.error(`${i}: Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let s=mt(e.metadata,J);if(s.error)return s.error;let c=s.parsedMetadata;if(!e.prompt&&!c)return J(`Either prompt or metadata must be provided for update-task`);let l=await _n({tasksJsonPath:o,id:e.id,prompt:e.prompt,research:e.research,append:e.append,metadata:c,projectRoot:e.projectRoot,tag:a},t,{session:n});return t.info(`${i}: Direct function result: success=${l.success}`),Y({result:l,log:t,errorPrefix:`Error updating task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function Qn(e){e.addTool({name:`update`,description:`Update multiple upcoming tasks (with ID >= 'from' ID) based on new context or changes provided in the prompt. Use 'update_task' instead for a single specific task or 'update_subtask' for subtasks.`,parameters:I.object({from:I.string().describe(`Task ID from which to start updating (inclusive). IMPORTANT: This tool uses 'from', not 'id'`),prompt:I.string().describe(`Explanation of changes or new context to apply`),research:I.boolean().optional().describe(`Use Perplexity AI for research-backed updates`),file:I.string().optional().describe(`Path to the tasks file relative to project root`),projectRoot:I.string().optional().describe(`The directory of the project. (Optional, usually from session)`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Tasks`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`update`,{from:a,prompt:o,research:s,file:c,projectRoot:l,tag:u}=e,d=r({projectRoot:e.projectRoot,tag:e.tag});try{t.info(`Executing ${i} tool with normalized root: ${l}`);let r;try{r=E({projectRoot:l,file:c},t),t.info(`${i}: Resolved tasks path: ${r}`)}catch(e){return t.error(`${i}: Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json within project root '${l}': ${e.message}`)}let u=await vn({tasksJsonPath:r,from:a,prompt:o,research:s,projectRoot:l,tag:d},t,{session:n});return t.info(`${i}: Direct function result: success=${u.success}`),Y({result:u,log:t,errorPrefix:`Error updating tasks`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function $n(e){e.addTool({name:`use_tag`,description:`Switch to a different tag context for task operations`,parameters:I.object({name:I.string().describe(`Name of the tag to switch to`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Use Tag`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting use-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await yn({tasksJsonPath:r,name:e.name,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error switching tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in use-tag tool: ${e.message}`),J(e.message)}})})}function er(e){e.addTool({name:`validate_dependencies`,description:`Check tasks for dependency issues (like circular references or links to non-existent tasks) without making changes.`,parameters:I.object({file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Validate Dependencies`,readOnlyHint:!0},execute:Q(`validate-dependencies`,async(e,{log:t,session:n})=>{try{let n=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Validating dependencies with args: ${JSON.stringify(e)}`);let i;try{i=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await bn({tasksJsonPath:i,projectRoot:e.projectRoot,tag:n},t);return a.success?t.info(`Successfully validated dependencies: ${a.data.message}`):t.error(`Failed to validate dependencies: ${a.error.message}`),Y({result:a,log:t,errorPrefix:`Error validating dependencies`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in validateDependencies tool: ${e.message}`),J(e.message)}})})}const $={initialize_project:Nn,models:Fn,rules:qn,parse_prd:Rn,"response-language":Gn,analyze_project_complexity:Tn,expand_task:jn,expand_all:An,scope_up_task:Yn,scope_down_task:Jn,get_tasks:Mt,get_task:Pt,next_task:Ln,complexity_report:Dn,set_task_status:Rt,add_task:wn,add_subtask:Sn,update:Qn,update_task:Zn,update_subtask:Xn,remove_task:Vn,remove_subtask:Bn,clear_subtasks:En,move_task:In,add_dependency:xn,remove_dependency:zn,validate_dependencies:er,fix_dependencies:Mn,list_tags:Pn,add_tag:Cn,delete_tag:kn,use_tag:$n,rename_tag:Hn,copy_tag:On,research:Un,autopilot_start:gt,autopilot_resume:vt,autopilot_next:bt,autopilot_status:St,autopilot_complete:wt,autopilot_commit:Et,autopilot_finalize:Ot,autopilot_abort:At,generate:It},tr=[`get_tasks`,`next_task`,`get_task`,`set_task_status`,`update_subtask`,`parse_prd`,`expand_task`],nr=[...tr,`initialize_project`,`analyze_project_complexity`,`expand_all`,`add_subtask`,`remove_task`,`add_task`,`complexity_report`];function rr(e){return $[e]||null}function ir(){let e=process.env.TASK_MASTER_TOOLS;if(!e||e.trim()===``)return V.debug(`No TASK_MASTER_TOOLS env var found, defaulting to "core"`),`core`;let t=e.trim();return V.debug(`TASK_MASTER_TOOLS env var: "${t}"`),t}function ar(e,t=`core`){let n=[],r=[];try{let i=t.trim(),a=[],o=i.toLowerCase();switch(o){case`all`:a=Object.keys($),V.info(`Loading all available tools`);break;case`core`:case`lean`:a=tr,V.info(`Loading core tools only`);break;case`standard`:a=nr,V.info(`Loading standard tools`);break;default:let e=i.split(`,`).map(e=>e.trim()).filter(e=>e.length>0),t=new Set,n=[],r={response_language:`response-language`};for(let i of e){let e=null,a=i.toLowerCase();if(r[a]){let t=r[a];for(let n of Object.keys($))if(n.toLowerCase()===t.toLowerCase()){e=n;break}}if(!e){for(let t of Object.keys($))if(t.toLowerCase()===a){e=t;break}}if(!e){let t=a.replace(/_/g,`-`);for(let n of Object.keys($))if(n.toLowerCase()===t){e=n;break}}if(!e){let t=a.replace(/-/g,`_`);for(let n of Object.keys($))if(n.toLowerCase()===t){e=n;break}}e?(t.add(e),V.debug(`Resolved tool "${i}" to "${e}"`)):(n.push(i),V.warn(`Unknown tool specified: "${i}"`))}a=Array.from(t),n.length>0&&V.warn(`Unknown tools: ${n.join(`, `)}`),a.length===0?(V.warn(`No valid tools found in custom list. Loading all tools as fallback.`),a=Object.keys($)):V.info(`Loading ${a.length} custom tools from list (${t.size} unique after normalization)`);break}return V.info(`Registering ${a.length} MCP tools (mode: ${i})`),a.forEach(t=>{try{let i=rr(t);i?(i(e),V.debug(`Registered tool: ${t}`),n.push(t)):(V.warn(`Tool ${t} not found in registry`),r.push(t))}catch(e){e.message&&e.message.includes(`already registered`)?(V.debug(`Tool ${t} already registered, skipping`),n.push(t)):(V.error(`Failed to register tool ${t}: ${e.message}`),r.push(t))}}),V.info(`Successfully registered ${n.length}/${a.length} tools`),r.length>0&&V.warn(`Failed tools: ${r.join(`, `)}`),{registeredTools:n,failedTools:r,normalizedMode:o}}catch(t){V.error(`Error parsing TASK_MASTER_TOOLS environment variable: ${t.message}`),V.info(`Falling back to loading all tools`);let i=Object.keys($);for(let t of i){let i=rr(t);if(i)try{i(e),n.push(t)}catch(e){e.message&&e.message.includes(`already registered`)?(V.debug(`Fallback tool ${t} already registered, skipping`),n.push(t)):(V.warn(`Failed to register fallback tool '${t}': ${e.message}`),r.push(t))}else V.warn(`Tool '${t}' not found in registry`),r.push(t)}return V.info(`Successfully registered ${n.length} fallback tools`),{registeredTools:n,failedTools:r,normalizedMode:`all`}}}L.config(),re();const or=Qe(import.meta.url);P.dirname(or);var sr=class{constructor(){this.options={name:`Task Master MCP Server`,version:se};let e=new $e(this.options);if(e._mcpServer&&R.wrapMcpServerWithSentry)try{e._mcpServer=R.wrapMcpServerWithSentry(e._mcpServer)}catch(e){V.warn(`Failed to wrap MCP server with Sentry: ${e.message}`)}this.server=e,this.initialized=!1,this.init=this.init.bind(this),this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.logger=V}async init(){if(this.initialized)return;let e=ir();this.logger.info(`Task Master MCP Server starting...`),this.logger.info(`Tool mode configuration: ${e}`);let t=ar(this.server,e);return this.logger.info(`Normalized tool mode: ${t.normalizedMode}`),this.logger.info(`Registered ${t.registeredTools.length} tools successfully`),t.registeredTools.length>0&&this.logger.debug(`Registered tools: ${t.registeredTools.join(`, `)}`),t.failedTools.length>0&&this.logger.warn(`Failed to register ${t.failedTools.length} tools: ${t.failedTools.join(`, `)}`),this.initialized=!0,this}async start(){return this.initialized||await this.init(),this.server.on(`connect`,e=>{e.session.server.sendLoggingMessage({data:{context:e.session.context,message:`MCP Server connected: ${e.session.name}`},level:`info`}),this.registerRemoteProvider(e.session)}),await this.server.start({transportType:`stdio`,timeout:12e4}),this}registerRemoteProvider(e){if(e){if(!e.clientCapabilities||!e.clientCapabilities.sampling){e.server.sendLoggingMessage({data:{context:e.context,message:`MCP session missing required sampling capabilities, providers not registered`},level:`info`});return}let n=new lt;n.setSession(e),t.getInstance().registerProvider(`mcp`,n),e.server.sendLoggingMessage({data:{context:e.context,message:`MCP Server connected`},level:`info`})}else e.server.sendLoggingMessage({data:{context:e.context,message:`No MCP sessions available, providers not registered`},level:`warn`})}async stop(){this.server&&await this.server.stop()}};L.config(),process.env.TASK_MASTER_MCP=`true`;async function cr(){let e=new sr;process.on(`SIGINT`,async()=>{await e.stop(),process.exit(0)}),process.on(`SIGTERM`,async()=>{await e.stop(),process.exit(0)});try{await e.start()}catch(e){V.error(`Failed to start MCP server: ${e.message}`),process.exit(1)}}cr();export{};
44
+ ${y.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-ntk5CuRW.js`);await e(P.join(d,`.taskmaster`,`tasks`,`tasks.json`),l,n,!1,{session:p,mcpLog:m,commandName:`research-save`,outputType:`mcp`,projectRoot:d,tag:f},`json`),t.info(`Research saved to subtask ${l}`)}else{let e=(await import(`./update-task-by-id-DP498AAF.js`)).default,r=parseInt(l,10);await e(P.join(d,`.taskmaster`,`tasks`,`tasks.json`),r,n,!1,{session:p,mcpLog:m,commandName:`research-save`,outputType:`mcp`,projectRoot:d,tag:f},`json`,!0),t.info(`Research saved to task ${l}`)}}catch(e){t.warn(`Error saving research to task/subtask: ${e.message}`)}return v(),{success:!0,data:{query:y.query,result:y.result,contextSize:y.contextSize,contextTokens:y.contextTokens,tokenBreakdown:y.tokenBreakdown,systemPromptTokens:y.systemPromptTokens,userPromptTokens:y.userPromptTokens,totalInputTokens:y.totalInputTokens,detailLevel:y.detailLevel,telemetryData:y.telemetryData,tagInfo:y.tagInfo,savedFilePath:y.savedFilePath}}}catch(e){return v(),t.error(`Error in researchDirect: ${e.message}`),{success:!1,error:{code:e.code||`RESEARCH_ERROR`,message:e.message}}}}async function mn(e,t,n={}){let{tasksJsonPath:r,id:i,strength:a=`regular`,prompt:o,research:s=!1,projectRoot:c,tag:l}=e,{session:u}=n;x();let d=D(t);try{if(!r)return t.error(`scopeDownDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i)return t.error(`Missing required parameter: id`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The id parameter is required for scoping down tasks`}};let e=i.split(`,`).map(e=>parseInt(e.trim(),10));t.info(`Scoping down tasks: ${e.join(`, `)}, strength: ${a}, research: ${s}`);let n=await oe(r,e,a,o,{session:u,mcpLog:d,projectRoot:c,commandName:`scope-down`,outputType:`mcp`,tag:l,research:s},`json`);return v(),{success:!0,data:{updatedTasks:n.updatedTasks,tasksUpdated:n.updatedTasks.length,message:`Successfully scoped down ${n.updatedTasks.length} task(s)`,telemetryData:n.telemetryData}}}catch(e){return v(),t.error(`Error in scopeDownDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_DOWN_ERROR`,message:e.message}}}}async function hn(e,t,n={}){let{tasksJsonPath:r,id:i,strength:a=`regular`,prompt:o,research:s=!1,projectRoot:c,tag:l}=e,{session:u}=n;x();let d=D(t);try{if(!r)return t.error(`scopeUpDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i)return t.error(`Missing required parameter: id`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The id parameter is required for scoping up tasks`}};let e=i.split(`,`).map(e=>parseInt(e.trim(),10));t.info(`Scoping up tasks: ${e.join(`, `)}, strength: ${a}, research: ${s}`);let n=await ge(r,e,a,o,{session:u,mcpLog:d,projectRoot:c,commandName:`scope-up`,outputType:`mcp`,tag:l,research:s},`json`);return v(),{success:!0,data:{updatedTasks:n.updatedTasks,tasksUpdated:n.updatedTasks.length,message:`Successfully scoped up ${n.updatedTasks.length} task(s)`,telemetryData:n.telemetryData}}}catch(e){return v(),t.error(`Error in scopeUpDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_UP_ERROR`,message:e.message}}}}async function gn(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,id:a,prompt:o,research:s,metadata:c,projectRoot:l,tag:u}=e,d=D(t);try{if(d.info(`Updating subtask by ID via direct function. ID: ${a}, ProjectRoot: ${l}`),!i){let e=`tasksJsonPath is required but was not provided.`;return d.error(e),{success:!1,error:{code:`MISSING_ARGUMENT`,message:e}}}if(!a||typeof a!=`string`||!a.trim()){let e=`Subtask ID cannot be empty.`;return d.error(e),{success:!1,error:{code:`INVALID_SUBTASK_ID`,message:e}}}if(!o&&!c){let e=`No prompt or metadata specified. Please provide information to append or metadata to update.`;return d.error(e),{success:!1,error:{code:`MISSING_PROMPT`,message:e}}}let e=String(a).trim(),n=i,f=s===!0;t.info(`Updating subtask with ID ${e} with prompt "${o||`(metadata-only)`}" and research: ${f}`);let p=w();p||x();try{let t=await He(n,e,o,f,{mcpLog:d,session:r,projectRoot:l,tag:u,commandName:`update-subtask`,outputType:`mcp`,metadata:c},`json`);if(!t||t.updatedSubtask===null){let e=`Subtask ${a} or its parent task not found.`;return d.error(e),{success:!1,error:{code:`SUBTASK_NOT_FOUND`,message:e}}}let i=e.split(`.`)[0],s=`Successfully updated subtask with ID ${e}`;return d.success(s),{success:!0,data:{message:`Successfully updated subtask with ID ${e}`,subtaskId:e,parentId:i,subtask:t.updatedSubtask,tasksPath:n,useResearch:f,telemetryData:t.telemetryData,tagInfo:t.tagInfo}}}catch(e){return d.error(`Error updating subtask by ID: ${e.message}`),{success:!1,error:{code:`UPDATE_SUBTASK_CORE_ERROR`,message:e.message||`Unknown error updating subtask`}}}finally{!p&&w()&&v()}}catch(e){return d.error(`Setup error in updateSubtaskByIdDirect: ${e.message}`),w()&&v(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function _n(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,id:a,prompt:o,research:s,append:c,metadata:l,projectRoot:u,tag:d}=e,f=D(t);try{if(f.info(`Updating task by ID via direct function. ID: ${a}, ProjectRoot: ${u}`),!a){let e=`No task ID specified. Please provide a task ID to update.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}if(!o&&!l){let e=`No prompt or metadata specified. Please provide a prompt with new information or metadata for the task update.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let t;if(typeof a==`string`)t=a;else if(typeof a==`number`)t=String(a);else{let e=`Invalid task ID type: ${typeof a}. Task ID must be a string or number.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let n=i||E({projectRoot:u,file:e.file},f);if(!n){let e=`tasks.json path could not be resolved.`;return f.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let p=s===!0;f.info(`Updating task with ID ${t} with prompt "${o||`(metadata-only)`}" and research: ${p}`);let m=w();m||x();try{let e=await ae(n,t,o,p,{mcpLog:f,session:r,projectRoot:u,tag:d,commandName:`update-task`,outputType:`mcp`,metadata:l},`json`,c||!1);if(!e||e.updatedTask===null){let n=`Task ${t} was not updated (likely already completed).`;return f.info(n),{success:!0,data:{message:n,taskId:t,updated:!1,telemetryData:e?.telemetryData,tagInfo:e?.tagInfo}}}let i=`Successfully updated task with ID ${t} based on the prompt`;return f.info(i),{success:!0,data:{message:i,taskId:t,tasksPath:n,useResearch:p,updated:!0,updatedTask:e.updatedTask,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}}catch(e){return f.error(`Error updating task by ID: ${e.message}`),{success:!1,error:{code:`UPDATE_TASK_CORE_ERROR`,message:e.message||`Unknown error updating task`}}}finally{!m&&w()&&v()}}catch(e){return f.error(`Setup error in updateTaskByIdDirect: ${e.message}`),w()&&v(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function vn(e,t,n={}){let{session:r}=n,{from:i,prompt:a,research:o,tasksJsonPath:s,projectRoot:c,tag:l}=e,u=D(t);if(!c)return u.error(`updateTasksDirect requires a projectRoot argument.`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`projectRoot is required.`}};if(!i)return u.error(`updateTasksDirect called without from ID`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Starting task ID (from) is required`}};if(!a)return u.error(`updateTasksDirect called without prompt`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Update prompt is required`}};u.info(`Updating tasks via direct function. From: ${i}, Research: ${o}, File: ${s}, ProjectRoot: ${c}`),x();try{let e=await ye(s,i,a,o,{session:r,mcpLog:u,projectRoot:c,tag:l},`json`);return e&&e.success&&Array.isArray(e.updatedTasks)?(u.success(`Successfully updated ${e.updatedTasks.length} tasks.`),{success:!0,data:{message:`Successfully updated ${e.updatedTasks.length} tasks.`,tasksPath:s,updatedCount:e.updatedTasks.length,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}):(u.error(`Core updateTasks function did not return a successful structure.`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e?.message||`Core function failed to update tasks or returned unexpected result.`}})}catch(e){return u.error(`Error executing core updateTasks: ${e.message}`),{success:!1,error:{code:`UPDATE_TASKS_CORE_ERROR`,message:e.message||`Unknown error updating tasks`}}}finally{v()}}async function yn(e,t,n={}){let{tasksJsonPath:r,name:i,projectRoot:a}=e,{session:o}=n;x();let s=D(t);try{if(!r)return t.error(`useTagDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i||typeof i!=`string`)return t.error(`Missing required parameter: name`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Tag name is required and must be a string`}};t.info(`Switching to tag: ${i}`);let e=await Ae(r,i,{},{session:o,mcpLog:s,projectRoot:a},`json`);return v(),{success:!0,data:{tagName:e.currentTag,switched:e.switched,previousTag:e.previousTag,taskCount:e.taskCount,message:`Successfully switched to tag "${e.currentTag}"`}}}catch(e){return v(),t.error(`Error in useTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`USE_TAG_ERROR`,message:e.message}}}}async function bn(e,t){let{tasksJsonPath:n,projectRoot:r,tag:i}=e;if(!n)return t.error(`validateDependenciesDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};try{t.info(`Validating dependencies in tasks: ${n}`);let e=n;return N.existsSync(e)?(x(),await je(e,{projectRoot:r,tag:i}),v(),{success:!0,data:{message:`Dependencies validated successfully`,tasksPath:e}}):{success:!1,error:{code:`FILE_NOT_FOUND`,message:`Tasks file not found at ${e}`}}}catch(e){return v(),t.error(`Error validating dependencies: ${e.message}`),{success:!1,error:{code:`VALIDATION_ERROR`,message:e.message}}}}function xn(e){e.addTool({name:`add_dependency`,description:`Add a dependency relationship between two tasks`,parameters:I.object({id:I.string().describe(`ID of task that will depend on another task`),dependsOn:I.string().describe(`ID of task that will become a dependency`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Add Dependency`,destructiveHint:!0},execute:Q(`add-dependency`,async(e,{log:t,session:n})=>{try{t.info(`Adding dependency for task ${e.id} to depend on ${e.dependsOn}`);let n=r({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await zt({tasksJsonPath:i,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t);return a.success?t.info(`Successfully added dependency: ${a.data.message}`):t.error(`Failed to add dependency: ${a.error.message}`),Y({result:a,log:t,errorPrefix:`Error adding dependency`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in addDependency tool: ${e.message}`),J(e.message)}})})}function Sn(e){e.addTool({name:`add_subtask`,description:`Add a subtask to an existing task`,parameters:I.object({id:I.string().describe(`Parent task ID (required)`),taskId:I.string().optional().describe(`Existing task ID to convert to subtask`),title:I.string().optional().describe(`Title for the new subtask (when creating a new subtask)`),description:I.string().optional().describe(`Description for the new subtask`),details:I.string().optional().describe(`Implementation details for the new subtask`),status:I.string().optional().describe(`Status for the new subtask (default: 'pending')`),dependencies:I.string().optional().describe(`Comma-separated list of dependency IDs for the new subtask`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:I.boolean().optional().describe(`Skip regenerating task files`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Add Subtask`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{let i=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Adding subtask with args: ${JSON.stringify(e)}`);let a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=await Bt({tasksJsonPath:a,id:e.id,taskId:e.taskId,title:e.title,description:e.description,details:e.details,status:e.status,dependencies:e.dependencies,skipGenerate:e.skipGenerate,projectRoot:e.projectRoot,tag:i},t,{session:n});return o.success?t.info(`Subtask added successfully: ${o.data.message}`):t.error(`Failed to add subtask: ${o.error.message}`),Y({result:o,log:t,errorPrefix:`Error adding subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in addSubtask tool: ${e.message}`),J(e.message)}})})}function Cn(e){e.addTool({name:`add_tag`,description:`Create a new tag for organizing tasks in different contexts`,parameters:I.object({name:I.string().describe(`Name of the new tag to create`),copyFromCurrent:I.boolean().optional().describe(`Whether to copy tasks from the current tag (default: false)`),copyFromTag:I.string().optional().describe(`Specific tag to copy tasks from`),fromBranch:I.boolean().optional().describe(`Create tag name from current git branch (ignores name parameter)`),description:I.string().optional().describe(`Optional description for the tag`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Add Tag`,destructiveHint:!1},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting add-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Vt({tasksJsonPath:r,name:e.name,copyFromCurrent:e.copyFromCurrent,copyFromTag:e.copyFromTag,fromBranch:e.fromBranch,description:e.description,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error creating tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in add-tag tool: ${e.message}`),J(e.message)}})})}function wn(e){e.addTool({name:`add_task`,description:`Add a new task using AI`,parameters:I.object({prompt:I.string().optional().describe(`Description of the task to add (required if not using manual fields)`),title:I.string().optional().describe(`Task title (for manual task creation)`),description:I.string().optional().describe(`Task description (for manual task creation)`),details:I.string().optional().describe(`Implementation details (for manual task creation)`),testStrategy:I.string().optional().describe(`Test strategy (for manual task creation)`),dependencies:I.string().optional().describe(`Comma-separated list of task IDs this task depends on`),priority:I.string().optional().describe(`Task priority (high, medium, low)`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),research:I.boolean().optional().describe(`Whether to use research capabilities for task creation`)}),annotations:{title:`Add Task`,destructiveHint:!1},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting add-task with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Ht({tasksJsonPath:a,prompt:e.prompt,title:e.title,description:e.description,details:e.details,testStrategy:e.testStrategy,dependencies:e.dependencies,priority:e.priority,research:e.research,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error adding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in add-task tool: ${e.message}`),J(e.message)}})})}function Tn(e){e.addTool({name:`analyze_project_complexity`,description:`Analyze task complexity and generate expansion recommendations.`,parameters:I.object({threshold:I.coerce.number().int().min(1).max(10).optional().default(5).describe(`Complexity score threshold (1-10) to recommend expansion.`),research:I.boolean().optional().default(!1).describe(`Use Perplexity AI for research-backed analysis.`),output:I.string().optional().describe(`Output file path relative to project root (default: ${s}).`),file:I.string().optional().describe(`Path to the tasks file relative to project root (default: tasks/tasks.json).`),ids:I.string().optional().describe(`Comma-separated list of task IDs to analyze specifically (e.g., "1,3,5").`),from:I.coerce.number().int().positive().optional().describe(`Starting task ID in a range to analyze.`),to:I.coerce.number().int().positive().optional().describe(`Ending task ID in a range to analyze.`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Analyze Project Complexity`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`analyze_project_complexity`;try{t.info(`Executing ${i} tool with args: ${JSON.stringify(e)}`);let a=r({projectRoot:e.projectRoot,tag:e.tag}),o;try{o=E({projectRoot:e.projectRoot,file:e.file},t),t.info(`${i}: Resolved tasks path: ${o}`)}catch(n){return t.error(`${i}: Error finding tasks.json: ${n.message}`),J(`Failed to find tasks.json within project root '${e.projectRoot}': ${n.message}`)}let s=C(e.output,{projectRoot:e.projectRoot,tag:a},t);t.info(`${i}: Report output path: ${s}`);let c=P.dirname(s);try{N.existsSync(c)||(N.mkdirSync(c,{recursive:!0}),t.info(`${i}: Created output directory: ${c}`))}catch(e){return t.error(`${i}: Failed to create output directory ${c}: ${e.message}`),J(`Failed to create output directory: ${e.message}`)}let l=await Ut({tasksJsonPath:o,outputPath:s,threshold:e.threshold,research:e.research,projectRoot:e.projectRoot,tag:a,ids:e.ids,from:e.from,to:e.to},t,{session:n});return t.info(`${i}: Direct function result: success=${l.success}`),Y({result:l,log:t,errorPrefix:`Error analyzing task complexity`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function En(e){e.addTool({name:`clear_subtasks`,description:`Clear subtasks from specified tasks`,parameters:I.object({id:I.string().optional().describe(`Task IDs (comma-separated) to clear subtasks from`),all:I.boolean().optional().describe(`Clear subtasks from all tasks`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}).refine(e=>e.id||e.all,{message:`Either 'id' or 'all' parameter must be provided`,path:[`id`,`all`]}),annotations:{title:`Clear Subtasks`,destructiveHint:!0},execute:Q(`clear-subtasks`,async(e,t)=>{try{t.log.info(`Clearing subtasks with args: ${JSON.stringify(e)}`);let n=r({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=E({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await Wt({tasksJsonPath:i,id:e.id,all:e.all,projectRoot:e.projectRoot,tag:n},t.log,{session:t.session});return a.success?t.log.info(`Subtasks cleared successfully: ${a.data.message}`):t.log.error(`Failed to clear subtasks: ${a.error.message}`),Y({result:a,log:t.log,errorPrefix:`Error clearing subtasks`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in clearSubtasks tool: ${e.message}`),J(e.message)}})})}function Dn(e){e.addTool({name:`complexity_report`,description:`Display the complexity analysis report in a readable format`,parameters:I.object({file:I.string().optional().describe(`Path to the report file (default: ${s})`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Complexity Report`,readOnlyHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Getting complexity report with args: ${JSON.stringify(e)}`);let n=h(e.projectRoot),r=Ue({projectRoot:e.projectRoot,complexityReport:e.file,tag:n},t);if(t.info(`Reading complexity report from path: `,r),!r)return J(`No complexity report found. Run task-master analyze-complexity first.`);let i=await Gt({reportPath:r},t);return i.success?t.info(`Successfully retrieved complexity report`):t.error(`Failed to retrieve complexity report: ${i.error.message}`),Y({result:i,log:t,errorPrefix:`Error retrieving complexity report`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in complexity-report tool: ${e.message}`),J(`Failed to retrieve complexity report: ${e.message}`)}})})}function On(e){e.addTool({name:`copy_tag`,description:`Copy an existing tag to create a new tag with all tasks and metadata`,parameters:I.object({sourceName:I.string().describe(`Name of the source tag to copy from`),targetName:I.string().describe(`Name of the new tag to create`),description:I.string().optional().describe(`Optional description for the new tag`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Copy Tag`,destructiveHint:!1},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting copy-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Kt({tasksJsonPath:r,sourceName:e.sourceName,targetName:e.targetName,description:e.description,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error copying tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in copy-tag tool: ${e.message}`),J(e.message)}})})}function kn(e){e.addTool({name:`delete_tag`,description:`Delete an existing tag and all its tasks`,parameters:I.object({name:I.string().describe(`Name of the tag to delete`),yes:I.boolean().optional().describe(`Skip confirmation prompts (default: true for MCP)`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Delete Tag`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting delete-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await qt({tasksJsonPath:r,name:e.name,yes:e.yes===void 0?!0:e.yes,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error deleting tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in delete-tag tool: ${e.message}`),J(e.message)}})})}function An(e){e.addTool({name:`expand_all`,description:`Expand all pending tasks into subtasks based on complexity or defaults`,parameters:I.object({num:I.string().optional().describe(`Target number of subtasks per task (uses complexity/defaults otherwise)`),research:I.boolean().optional().describe(`Enable research-backed subtask generation (e.g., using Perplexity)`),prompt:I.string().optional().describe(`Additional context to guide subtask generation for all tasks`),force:I.boolean().optional().describe(`Force regeneration of subtasks for tasks that already have them`),file:I.string().optional().describe(`Absolute path to the tasks file in the /tasks folder inside the project root (default: tasks/tasks.json)`),projectRoot:I.string().optional().describe(`Absolute path to the project root directory (derived from session if possible)`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand All Tasks`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Tool expand_all execution started with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t),t.info(`Resolved tasks.json path: ${a}`)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=xe(null,{projectRoot:e.projectRoot,tag:i},t);return t.info(`Using complexity report path: ${o}`),Y({result:await Jt({tasksJsonPath:a,num:e.num,research:e.research,prompt:e.prompt,force:e.force,projectRoot:e.projectRoot,tag:i,complexityReportPath:o},t,{session:n}),log:t,errorPrefix:`Error expanding all tasks`,projectRoot:e.projectRoot})}catch(e){return t.error(`Unexpected error in expand_all tool execute: ${e.message}`),e.stack&&t.error(e.stack),J(`An unexpected error occurred: ${e.message}`)}})})}function jn(e){e.addTool({name:`expand_task`,description:`Expand a task into subtasks for detailed implementation`,parameters:I.object({id:I.string().describe(`ID of task to expand`),num:I.string().optional().describe(`Number of subtasks to generate`),research:I.boolean().optional().default(!1).describe(`Use research role for generation`),prompt:I.string().optional().describe(`Additional context for subtask generation`),file:I.string().optional().describe(`Path to the tasks file relative to project root (e.g., tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),force:I.boolean().optional().default(!1).describe(`Force expansion even if subtasks exist`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting expand-task with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=Ue({...e,tag:i},t);return Y({result:await Yt({tasksJsonPath:a,id:e.id,num:e.num,research:e.research,prompt:e.prompt,force:e.force,complexityReportPath:o,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error expanding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in expand-task tool: ${e.message}`),J(e.message)}})})}function Mn(e){e.addTool({name:`fix_dependencies`,description:`Fix invalid dependencies in tasks automatically`,parameters:I.object({file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Fix Dependencies`,destructiveHint:!0},execute:Q(`fix-dependencies`,async(e,t)=>{try{t.log.info(`Fixing dependencies with args: ${JSON.stringify(e)}`);let n=r({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=E({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await Xt({tasksJsonPath:i,projectRoot:e.projectRoot,tag:n},t.log);return a.success?t.log.info(`Successfully fixed dependencies: ${a.data.message}`):t.log.error(`Failed to fix dependencies: ${a.error.message}`),Y({result:a,log:t.log,errorPrefix:`Error fixing dependencies`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in fixDependencies tool: ${e.message}`),J(e.message)}})})}function Nn(e){e.addTool({name:`initialize_project`,description:`Initializes a new Task Master project structure by calling the core initialization logic. Creates necessary folders and configuration files for Task Master in the current directory.`,parameters:I.object({skipInstall:I.boolean().optional().default(!1).describe(`Skip installing dependencies automatically. Never do this unless you are sure the project is already installed.`),addAliases:I.boolean().optional().default(!0).describe(`Add shell aliases (tm, taskmaster, hamster, ham) to shell config file.`),initGit:I.boolean().optional().default(!0).describe(`Initialize Git repository in project root.`),storeTasksInGit:I.boolean().optional().default(!0).describe(`Store tasks in Git (tasks.json and tasks/ directory).`),yes:I.boolean().optional().default(!0).describe(`Skip prompts and use default values. Always set to true for MCP tools.`),projectRoot:I.string().describe(`The root directory for the project. ALWAYS SET THIS TO THE PROJECT ROOT DIRECTORY. IF NOT SET, THE TOOL WILL NOT WORK.`),rules:I.array(I.enum(A)).optional().describe(`List of rule profiles to include at initialization. If omitted, defaults to Cursor profile only. Available options: ${A.join(`, `)}`)}),annotations:{title:`Initialize Project`,destructiveHint:!0},execute:Z(async(e,t)=>{let{log:n}=t,r=t.session;try{return n.info(`Executing initialize_project tool with args: ${JSON.stringify(e)}`),Y({result:await Zt(e,n,{session:r}),log:n,errorPrefix:`Initialization failed`,projectRoot:e.projectRoot})}catch(e){let t=`Project initialization tool failed: ${e.message||`Unknown error`}`;return n.error(t,e),J(t,{details:e.stack})}})})}function Pn(e){e.addTool({name:`list_tags`,description:`List all available tags with task counts and metadata`,parameters:I.object({showMetadata:I.boolean().optional().describe(`Whether to include metadata in the output (default: false)`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`List Tags`,readOnlyHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting list-tags with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await Qt({tasksJsonPath:r,showMetadata:e.showMetadata,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error listing tags`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in list-tags tool: ${e.message}`),J(e.message)}})})}function Fn(e){e.addTool({name:`models`,description:`Get information about available AI models or set model configurations. Run without arguments to get the current model configuration and API key status for the selected model providers.`,parameters:I.object({setMain:I.string().optional().describe(`Set the primary model for task generation/updates. Model provider API key is required in the MCP config ENV.`),setResearch:I.string().optional().describe(`Set the model for research-backed operations. Model provider API key is required in the MCP config ENV.`),setFallback:I.string().optional().describe(`Set the model to use if the primary fails. Model provider API key is required in the MCP config ENV.`),listAvailableModels:I.boolean().optional().describe(`List all available models not currently in use. Input/output costs values are in dollars (3 is $3.00).`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),openrouter:I.boolean().optional().describe(`Indicates the set model ID is a custom OpenRouter model.`),ollama:I.boolean().optional().describe(`Indicates the set model ID is a custom Ollama model.`),bedrock:I.boolean().optional().describe(`Indicates the set model ID is a custom AWS Bedrock model.`),azure:I.boolean().optional().describe(`Indicates the set model ID is a custom Azure OpenAI model.`),vertex:I.boolean().optional().describe(`Indicates the set model ID is a custom Google Vertex AI model.`),"openai-compatible":I.boolean().optional().describe(`Indicates the set model ID is a custom OpenAI-compatible model. Requires baseURL parameter.`),baseURL:I.string().optional().describe(`Custom base URL for providers that support it (e.g., https://api.example.com/v1).`)}),annotations:{title:`Models`,destructiveHint:!0},execute:Q(`models`,async(e,t)=>{try{return t.log.info(`Starting models tool with args: ${JSON.stringify(e)}`),Y({result:await nn({...e,projectRoot:e.projectRoot},t.log,{session:t.session}),log:t.log,errorPrefix:`Error managing models`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in models tool: ${e.message}`),J(e.message)}})})}function In(e){e.addTool({name:`move_task`,description:`Move a task or subtask to a new position`,parameters:I.object({from:I.string().describe(`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")`),to:I.string().optional().describe(`ID of the destination (e.g., "7" or "7.3"). Required for within-tag moves. For cross-tag moves, if omitted, task will be moved to the target tag maintaining its ID`),file:I.string().optional().describe(`Custom path to tasks.json file`),projectRoot:I.string().describe(`Root directory of the project (typically derived from session)`),tag:I.string().optional().describe(`Tag context to operate on`),fromTag:I.string().optional().describe(`Source tag for cross-tag moves`),toTag:I.string().optional().describe(`Target tag for cross-tag moves`),withDependencies:I.boolean().optional().describe(`Move dependent tasks along with main task`),ignoreDependencies:I.boolean().optional().describe(`Break cross-tag dependencies during move`)}),annotations:{title:`Move Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{if(e.fromTag&&e.toTag&&e.fromTag!==e.toTag){if(!e.from)return J(`Source IDs are required for cross-tag moves`,`MISSING_SOURCE_IDS`);e.to&&t.warn(`The "to" parameter is not used for cross-tag moves and will be ignored. Tasks retain their original IDs in the target tag.`);let r=e.file;return r||=E(e,t),Y({result:await rn({sourceIds:e.from,sourceTag:e.fromTag,targetTag:e.toTag,withDependencies:e.withDependencies||!1,ignoreDependencies:e.ignoreDependencies||!1,tasksJsonPath:r,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error moving tasks between tags`,projectRoot:e.projectRoot})}else{if(!e.to)return J(`Destination ID is required for within-tag moves`,`MISSING_DESTINATION_ID`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a=e.file;a||=E(e,t);let o=e.from.split(`,`).map(e=>e.trim()),s=e.to.split(`,`).map(e=>e.trim());if(o.length!==s.length){if(o.length>1){let r=[],c=[];for(let l=0;l<o.length;l++){let u=o[l],d=s[l];if(u===d){t.info(`Skipping ${u} -> ${d} (same ID)`),c.push({fromId:u,toId:d,reason:`same ID`});continue}let f=l===o.length-1,p=await an({sourceId:u,destinationId:d,tasksJsonPath:a,projectRoot:e.projectRoot,tag:i,generateFiles:f},t,{session:n});p.success?r.push(p.data):t.error(`Failed to move ${u} to ${d}: ${p.error.message}`)}return Y({result:{success:!0,data:{moves:r,skipped:c.length>0?c:void 0,message:`Successfully moved ${r.length} tasks${c.length>0?`, skipped ${c.length}`:``}`}},log:t,errorPrefix:`Error moving multiple tasks`,projectRoot:e.projectRoot})}return Y({result:{success:!0,data:{moves:results,skippedMoves,message:`Successfully moved ${results.length} tasks${skippedMoves.length>0?`, skipped ${skippedMoves.length} moves`:``}`}},log:t,errorPrefix:`Error moving multiple tasks`,projectRoot:e.projectRoot})}else return Y({result:await an({sourceId:e.from,destinationId:e.to,tasksJsonPath:a,projectRoot:e.projectRoot,tag:i,generateFiles:!0},t,{session:n}),log:t,errorPrefix:`Error moving task`,projectRoot:e.projectRoot})}}catch(e){return J(`Failed to move task: ${e.message}`,`MOVE_TASK_ERROR`)}})})}function Ln(e){e.addTool({name:`next_task`,description:`Find the next task to work on based on dependencies and status`,parameters:I.object({file:I.string().optional().describe(`Absolute path to the tasks file`),complexityReport:I.string().optional().describe(`Path to the complexity report file (relative to project root or absolute)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Next Task`,readOnlyHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Finding next task with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=ue(e,n)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o;try{o=de({...e,tag:i},n)}catch(e){t.error(`Error finding complexity report: ${e.message}`),o=null}let s=await on({tasksJsonPath:a,reportPath:o,projectRoot:e.projectRoot,tag:i},t,{session:n});return t.info(`Next task result: ${s.success?`found`:`none`}`),Y({result:s,log:t,errorPrefix:`Error finding next task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error finding next task: ${e.message}`),J(e.message)}})})}function Rn(e){e.addTool({name:`parse_prd`,description:`Parse a Product Requirements Document (PRD) text file to automatically generate initial tasks. Reinitializing the project is not necessary to run this tool. It is recommended to run parse-prd after initializing the project and creating/importing a prd.txt file in the project root's ${i} directory.`,parameters:I.object({input:I.string().optional().default(ne).describe(`Absolute path to the PRD document file (.txt, .md, etc.)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),destination:I.enum([`local`,`hamster`]).optional().default(`local`).describe(`Where to parse the PRD: "local" writes tasks.json, "hamster" creates a cloud brief and tasks`),output:I.string().optional().describe(`Output path for tasks.json file (default: ${a})`),numTasks:I.string().optional().describe(`Approximate number of top-level tasks to generate (default: 10). As the agent, if you have enough information, ensure to enter a number of tasks that would logically scale with project complexity. Setting to 0 will allow Taskmaster to determine the appropriate number of tasks based on the complexity of the PRD. Avoid entering numbers above 50 due to context window limitations.`),force:I.boolean().optional().default(!1).describe(`Overwrite existing output file without prompting.`),research:I.boolean().optional().describe(`Enable Taskmaster to use the research role for potentially more informed task generation. Requires appropriate API key.`),append:I.boolean().optional().describe(`Append generated tasks to existing file.`)}),annotations:{title:`Parse PRD`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n,reportProgress:i})=>{try{let a=r({projectRoot:e.projectRoot,tag:e.tag}),o=dt(i,t);return Y({result:await sn({...e,tag:a},t,{session:n,reportProgress:o}),log:t,errorPrefix:`Error parsing PRD`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in parse_prd: ${e.message}`),J(`Failed to parse PRD: ${e.message}`)}})})}function zn(e){e.addTool({name:`remove_dependency`,description:`Remove a dependency from a task`,parameters:I.object({id:I.string().describe(`Task ID to remove dependency from`),dependsOn:I.string().describe(`Task ID to remove as a dependency`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Dependency`,destructiveHint:!0},execute:Q(`remove-dependency`,async(e,t)=>{try{let n=r({projectRoot:e.projectRoot,tag:e.tag});t.log.info(`Removing dependency for task ${e.id} from ${e.dependsOn} with args: ${JSON.stringify(e)}`);let i;try{i=E({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await ln({tasksJsonPath:i,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t.log);return a.success?t.log.info(`Successfully removed dependency: ${a.data.message}`):t.log.error(`Failed to remove dependency: ${a.error.message}`),Y({result:a,log:t.log,errorPrefix:`Error removing dependency`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in removeDependency tool: ${e.message}`),J(e.message)}})})}function Bn(e){e.addTool({name:`remove_subtask`,description:`Remove a subtask from its parent task`,parameters:I.object({id:I.string().describe(`Subtask ID to remove in format 'parentId.subtaskId' (required)`),convert:I.boolean().optional().describe(`Convert the subtask to a standalone task instead of deleting it`),file:I.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:I.boolean().optional().describe(`Skip regenerating task files`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Subtask`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{let i=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Removing subtask with args: ${JSON.stringify(e)}`);let a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let o=await un({tasksJsonPath:a,id:e.id,convert:e.convert,skipGenerate:e.skipGenerate,projectRoot:e.projectRoot,tag:i},t,{session:n});return o.success?t.info(`Subtask removed successfully: ${o.data.message}`):t.error(`Failed to remove subtask: ${o.error.message}`),Y({result:o,log:t,errorPrefix:`Error removing subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in removeSubtask tool: ${e.message}`),J(e.message)}})})}function Vn(e){e.addTool({name:`remove_task`,description:`Remove a task or subtask permanently from the tasks list`,parameters:I.object({id:I.string().describe(`ID of the task or subtask to remove (e.g., '5' or '5.2'). Can be comma-separated to update multiple tasks/subtasks at once.`),file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),confirm:I.boolean().optional().describe(`Whether to skip confirmation prompt (default: false)`),tag:I.string().optional().describe(`Specify which tag context to operate on. Defaults to the current active tag.`)}),annotations:{title:`Remove Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Removing task(s) with ID(s): ${e.id}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}t.info(`Using tasks file path: ${a}`);let o=await dn({tasksJsonPath:a,id:e.id,projectRoot:e.projectRoot,tag:i},t,{session:n});return o.success?t.info(`Successfully removed task: ${e.id}`):t.error(`Failed to remove task: ${o.error.message}`),Y({result:o,log:t,errorPrefix:`Error removing task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in remove-task tool: ${e.message}`),J(`Failed to remove task: ${e.message}`)}})})}function Hn(e){e.addTool({name:`rename_tag`,description:`Rename an existing tag`,parameters:I.object({oldName:I.string().describe(`Current name of the tag to rename`),newName:I.string().describe(`New name for the tag`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Rename Tag`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting rename-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await fn({tasksJsonPath:r,oldName:e.oldName,newName:e.newName,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error renaming tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in rename-tag tool: ${e.message}`),J(e.message)}})})}function Un(e){e.addTool({name:`research`,description:`Perform AI-powered research queries with project context`,parameters:I.object({query:I.string().describe(`Research query/prompt (required)`),taskIds:I.string().optional().describe(`Comma-separated list of task/subtask IDs for context (e.g., "15,16.2,17")`),filePaths:I.string().optional().describe(`Comma-separated list of file paths for context (e.g., "src/api.js,docs/readme.md")`),customContext:I.string().optional().describe(`Additional custom context text to include in the research`),includeProjectTree:I.boolean().optional().describe(`Include project file tree structure in context (default: false)`),detailLevel:I.enum([`low`,`medium`,`high`]).optional().describe(`Detail level for the research response (default: medium)`),saveTo:I.string().optional().describe(`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`),saveToFile:I.boolean().optional().describe(`Save research results to .taskmaster/docs/research/ directory (default: false)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Research`,destructiveHint:!0,openWorldHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{let i=r({projectRoot:e.projectRoot,tag:e.tag});return t.info(`Starting research with query: "${e.query.substring(0,100)}${e.query.length>100?`...`:``}"`),Y({result:await pn({query:e.query,taskIds:e.taskIds,filePaths:e.filePaths,customContext:e.customContext,includeProjectTree:e.includeProjectTree||!1,detailLevel:e.detailLevel||`medium`,saveTo:e.saveTo,saveToFile:e.saveToFile||!1,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error performing research`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in research tool: ${e.message}`),J(e.message)}})})}async function Wn(e,t,n={}){let{projectRoot:r,language:i}=e,a=D(t);t.info(`Executing response-language_direct with args: ${JSON.stringify(e)}`),t.info(`Using project root: ${r}`);try{return x(),We(i,{mcpLog:a,projectRoot:r})}catch(e){return{success:!1,error:{code:`DIRECT_FUNCTION_ERROR`,message:e.message,details:e.stack}}}finally{v()}}function Gn(e){e.addTool({name:`response-language`,description:`Get or set the response language for the project`,parameters:I.object({projectRoot:I.string().describe(`The root directory for the project. ALWAYS SET THIS TO THE PROJECT ROOT DIRECTORY. IF NOT SET, THE TOOL WILL NOT WORK.`),language:I.string().describe(`The new response language to set. like "中文" "English" or "español".`)}),annotations:{title:`Response Language`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{return t.info(`Executing response-language tool with args: ${JSON.stringify(e)}`),Y({result:await Wn({...e,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error setting response language`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in response-language tool: ${e.message}`),J(e.message)}})})}async function Kn(e,t,n={}){x();try{let{action:t,profiles:n,projectRoot:r,yes:i,force:a}=e;if(!t||!Array.isArray(n)||n.length===0||!r)return{success:!1,error:{code:`MISSING_ARGUMENT`,message:`action, profiles, and projectRoot are required.`}};let o=[],s=[];if(t===O.REMOVE){if(!a&&Ke(r,n)){let e=Ge(r);return e.filter(e=>!n.includes(e)),{success:!1,error:{code:`CRITICAL_REMOVAL_BLOCKED`,message:`CRITICAL: This operation would remove ALL remaining rule profiles (${n.join(`, `)}), leaving your project with no rules configurations. This could significantly impact functionality. Currently installed profiles: ${e.join(`, `)}. If you're certain you want to proceed, set force: true or use the CLI with --force flag.`}}}for(let e of n){if(!Ye(e)){o.push({profileName:e,success:!1,error:`The requested rule profile for '${e}' is unavailable. Supported profiles are: ${A.join(`, `)}.`});continue}let t=Je(r,k(e));o.push(t)}let e=o.filter(e=>e.success).map(e=>e.profileName),t=o.filter(e=>e.skipped).map(e=>e.profileName),i=o.filter(e=>e.error&&!e.success&&!e.skipped),s=o.filter(e=>e.notice),c=``;return e.length>0&&(c+=`Successfully removed Task Master rules: ${e.join(`, `)}.`),t.length>0&&(c+=`Skipped (default or protected): ${t.join(`, `)}.`),i.length>0&&(c+=i.map(e=>`Error removing ${e.profileName}: ${e.error}`).join(` `)),s.length>0&&(c+=` Notices: ${s.map(e=>`${e.profileName} - ${e.notice}`).join(`; `)}.`),v(),{success:i.length===0,data:{summary:c,results:o}}}else if(t===O.ADD){for(let e of n){if(!Ye(e)){s.push({profileName:e,success:!1,error:`Profile not found: static import missing for '${e}'. Valid profiles: ${A.join(`, `)}`});continue}let t=k(e),{success:n,failed:i}=Xe(r,t),a=t.rulesDir,o=P.join(r,a),c=t.profileDir,l=t.mcpConfig!==!1,u=l&&t.mcpConfigPath?P.join(r,t.mcpConfigPath):null,d=l&&u?N.existsSync(u):void 0,f=N.existsSync(o),p=N.existsSync(P.join(r,c)),m=i>0?`${i} rule files failed to convert.`:null,h={profileName:e,mcpConfigCreated:d,rulesDirCreated:f,profileFolderCreated:p,skipped:!1,error:m,success:(l?d:!0)&&f&&n>0&&!m};s.push(h)}let e=s.filter(e=>e.success).map(e=>e.profileName),t=s.filter(e=>e.error&&!e.success),i=``;return e.length>0&&(i+=`Successfully added rules: ${e.join(`, `)}.`),t.length>0&&(i+=t.map(e=>` Error adding ${e.profileName}: ${e.error}`).join(` `)),v(),{success:t.length===0,data:{summary:i,results:s}}}else return v(),{success:!1,error:{code:`INVALID_ACTION`,message:`Unknown action. Use "${O.ADD}" or "${O.REMOVE}".`}}}catch(e){return v(),t.error(`[rulesDirect] Error: ${e.message}`),{success:!1,error:{code:e.code||`RULES_ERROR`,message:e.message}}}}function qn(e){e.addTool({name:`rules`,description:`Add or remove rule profiles from the project.`,parameters:I.object({action:I.enum([`add`,`remove`]).describe(`Whether to add or remove rule profiles.`),profiles:I.array(I.enum(A)).min(1).describe(`List of rule profiles to add or remove (e.g., [\"cursor\", \"roo\"]). Available options: ${A.join(`, `)}`),projectRoot:I.string().describe(`The root directory of the project. Must be an absolute path.`),force:I.boolean().optional().default(!1).describe(`DANGEROUS: Force removal even if it would leave no rule profiles. Only use if you are absolutely certain.`)}),annotations:{title:`Rules`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{return t.info(`[rules tool] Executing action: ${e.action} for profiles: ${e.profiles.join(`, `)} in ${e.projectRoot}`),Y({result:await Kn(e,t,{session:n}),log:t,projectRoot:e.projectRoot})}catch(e){return t.error(`[rules tool] Error: ${e.message}`),J(e.message,{details:e.stack})}})})}function Jn(e){e.addTool({name:`scope_down_task`,description:`Decrease the complexity of one or more tasks using AI`,parameters:I.object({id:I.string().describe(`Comma-separated list of task IDs to scope down (e.g., "1,3,5")`),strength:I.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:I.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),research:I.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Down Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-down with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await mn({tasksJsonPath:a,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error scoping down task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in scope-down tool: ${e.message}`),J(e.message)}})})}function Yn(e){e.addTool({name:`scope_up_task`,description:`Increase the complexity of one or more tasks using AI`,parameters:I.object({id:I.string().describe(`Comma-separated list of task IDs to scope up (e.g., "1,3,5")`),strength:I.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:I.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`),research:I.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Up Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-up with args: ${JSON.stringify(e)}`);let i=r({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await hn({tasksJsonPath:a,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:i},t,{session:n}),log:t,errorPrefix:`Error scoping up task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in scope-up tool: ${e.message}`),J(e.message)}})})}function Xn(e){e.addTool({name:`update_subtask`,description:`Appends timestamped information to a specific subtask without replacing existing content. If you just want to update the subtask status, use set_task_status instead.`,parameters:I.object({id:b.describe(`ID of the subtask to update in format "parentId.subtaskId" (e.g., "5.2"). Parent ID is the ID of the task that contains the subtask.`),prompt:I.string().optional().describe(`Information to add to the subtask. Required unless only updating metadata.`),research:I.boolean().optional().describe(`Use Perplexity AI for research-backed updates`),metadata:I.string().optional().describe(`JSON string of metadata to merge into subtask metadata. Example: '{"ticketId": "JIRA-456", "reviewed": true}'. Requires TASK_MASTER_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Subtask`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`update_subtask`;try{let a=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Updating subtask with args: ${JSON.stringify(e)}`);let o;try{o=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`${i}: Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let s=mt(e.metadata,J);if(s.error)return s.error;let c=s.parsedMetadata;if(!e.prompt&&!c)return J(`Either prompt or metadata must be provided for update-subtask`);let l=await gn({tasksJsonPath:o,id:e.id,prompt:e.prompt,research:e.research,metadata:c,projectRoot:e.projectRoot,tag:a},t,{session:n});return l.success?t.info(`Successfully updated subtask with ID ${e.id}`):t.error(`Failed to update subtask: ${l.error?.message||`Unknown error`}`),Y({result:l,log:t,errorPrefix:`Error updating subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function Zn(e){e.addTool({name:`update_task`,description:`Updates a single task by ID with new information or context provided in the prompt.`,parameters:I.object({id:I.string().describe(`ID of the task (e.g., '15') to update. Subtasks are supported using the update-subtask tool.`),prompt:I.string().optional().describe(`New information or context to incorporate into the task. Required unless only updating metadata.`),research:I.boolean().optional().describe(`Use Perplexity AI for research-backed updates`),append:I.boolean().optional().describe(`Append timestamped information to task details instead of full update`),metadata:I.string().optional().describe(`JSON string of metadata to merge into task metadata. Example: '{"githubIssue": 42, "sprint": "Q1-S3"}'. Requires TASK_MASTER_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Task`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`update_task`;try{let a=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Executing ${i} tool with args: ${JSON.stringify(e)}`);let o;try{o=E({projectRoot:e.projectRoot,file:e.file},t),t.info(`${i}: Resolved tasks path: ${o}`)}catch(e){return t.error(`${i}: Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let s=mt(e.metadata,J);if(s.error)return s.error;let c=s.parsedMetadata;if(!e.prompt&&!c)return J(`Either prompt or metadata must be provided for update-task`);let l=await _n({tasksJsonPath:o,id:e.id,prompt:e.prompt,research:e.research,append:e.append,metadata:c,projectRoot:e.projectRoot,tag:a},t,{session:n});return t.info(`${i}: Direct function result: success=${l.success}`),Y({result:l,log:t,errorPrefix:`Error updating task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function Qn(e){e.addTool({name:`update`,description:`Update multiple upcoming tasks (with ID >= 'from' ID) based on new context or changes provided in the prompt. Use 'update_task' instead for a single specific task or 'update_subtask' for subtasks.`,parameters:I.object({from:I.string().describe(`Task ID from which to start updating (inclusive). IMPORTANT: This tool uses 'from', not 'id'`),prompt:I.string().describe(`Explanation of changes or new context to apply`),research:I.boolean().optional().describe(`Use Perplexity AI for research-backed updates`),file:I.string().optional().describe(`Path to the tasks file relative to project root`),projectRoot:I.string().optional().describe(`The directory of the project. (Optional, usually from session)`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Tasks`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{let i=`update`,{from:a,prompt:o,research:s,file:c,projectRoot:l,tag:u}=e,d=r({projectRoot:e.projectRoot,tag:e.tag});try{t.info(`Executing ${i} tool with normalized root: ${l}`);let r;try{r=E({projectRoot:l,file:c},t),t.info(`${i}: Resolved tasks path: ${r}`)}catch(e){return t.error(`${i}: Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json within project root '${l}': ${e.message}`)}let u=await vn({tasksJsonPath:r,from:a,prompt:o,research:s,projectRoot:l,tag:d},t,{session:n});return t.info(`${i}: Direct function result: success=${u.success}`),Y({result:u,log:t,errorPrefix:`Error updating tasks`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${i} tool execute: ${e.message}`),J(`Internal tool error (${i}): ${e.message}`)}})})}function $n(e){e.addTool({name:`use_tag`,description:`Switch to a different tag context for task operations`,parameters:I.object({name:I.string().describe(`Name of the tag to switch to`),file:I.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Use Tag`,destructiveHint:!0},execute:Z(async(e,{log:t,session:n})=>{try{t.info(`Starting use-tag with args: ${JSON.stringify(e)}`);let r;try{r=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}return Y({result:await yn({tasksJsonPath:r,name:e.name,projectRoot:e.projectRoot},t,{session:n}),log:t,errorPrefix:`Error switching tag`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in use-tag tool: ${e.message}`),J(e.message)}})})}function er(e){e.addTool({name:`validate_dependencies`,description:`Check tasks for dependency issues (like circular references or links to non-existent tasks) without making changes.`,parameters:I.object({file:I.string().optional().describe(`Absolute path to the tasks file`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Validate Dependencies`,readOnlyHint:!0},execute:Q(`validate-dependencies`,async(e,{log:t,session:n})=>{try{let n=r({projectRoot:e.projectRoot,tag:e.tag});t.info(`Validating dependencies with args: ${JSON.stringify(e)}`);let i;try{i=E({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),J(`Failed to find tasks.json: ${e.message}`)}let a=await bn({tasksJsonPath:i,projectRoot:e.projectRoot,tag:n},t);return a.success?t.info(`Successfully validated dependencies: ${a.data.message}`):t.error(`Failed to validate dependencies: ${a.error.message}`),Y({result:a,log:t,errorPrefix:`Error validating dependencies`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in validateDependencies tool: ${e.message}`),J(e.message)}})})}const $={initialize_project:Nn,models:Fn,rules:qn,parse_prd:Rn,"response-language":Gn,analyze_project_complexity:Tn,expand_task:jn,expand_all:An,scope_up_task:Yn,scope_down_task:Jn,get_tasks:Mt,get_task:Pt,next_task:Ln,complexity_report:Dn,set_task_status:Rt,add_task:wn,add_subtask:Sn,update:Qn,update_task:Zn,update_subtask:Xn,remove_task:Vn,remove_subtask:Bn,clear_subtasks:En,move_task:In,add_dependency:xn,remove_dependency:zn,validate_dependencies:er,fix_dependencies:Mn,list_tags:Pn,add_tag:Cn,delete_tag:kn,use_tag:$n,rename_tag:Hn,copy_tag:On,research:Un,autopilot_start:gt,autopilot_resume:vt,autopilot_next:bt,autopilot_status:St,autopilot_complete:wt,autopilot_commit:Et,autopilot_finalize:Ot,autopilot_abort:At,generate:It},tr=[`get_tasks`,`next_task`,`get_task`,`set_task_status`,`update_subtask`,`parse_prd`,`expand_task`],nr=[...tr,`initialize_project`,`analyze_project_complexity`,`expand_all`,`add_subtask`,`remove_task`,`add_task`,`complexity_report`];function rr(e){return $[e]||null}function ir(){let e=process.env.TASK_MASTER_TOOLS;if(!e||e.trim()===``)return V.debug(`No TASK_MASTER_TOOLS env var found, defaulting to "core"`),`core`;let t=e.trim();return V.debug(`TASK_MASTER_TOOLS env var: "${t}"`),t}function ar(e,t=`core`){let n=[],r=[];try{let i=t.trim(),a=[],o=i.toLowerCase();switch(o){case`all`:a=Object.keys($),V.info(`Loading all available tools`);break;case`core`:case`lean`:a=tr,V.info(`Loading core tools only`);break;case`standard`:a=nr,V.info(`Loading standard tools`);break;default:let e=i.split(`,`).map(e=>e.trim()).filter(e=>e.length>0),t=new Set,n=[],r={response_language:`response-language`};for(let i of e){let e=null,a=i.toLowerCase();if(r[a]){let t=r[a];for(let n of Object.keys($))if(n.toLowerCase()===t.toLowerCase()){e=n;break}}if(!e){for(let t of Object.keys($))if(t.toLowerCase()===a){e=t;break}}if(!e){let t=a.replace(/_/g,`-`);for(let n of Object.keys($))if(n.toLowerCase()===t){e=n;break}}if(!e){let t=a.replace(/-/g,`_`);for(let n of Object.keys($))if(n.toLowerCase()===t){e=n;break}}e?(t.add(e),V.debug(`Resolved tool "${i}" to "${e}"`)):(n.push(i),V.warn(`Unknown tool specified: "${i}"`))}a=Array.from(t),n.length>0&&V.warn(`Unknown tools: ${n.join(`, `)}`),a.length===0?(V.warn(`No valid tools found in custom list. Loading all tools as fallback.`),a=Object.keys($)):V.info(`Loading ${a.length} custom tools from list (${t.size} unique after normalization)`);break}return V.info(`Registering ${a.length} MCP tools (mode: ${i})`),a.forEach(t=>{try{let i=rr(t);i?(i(e),V.debug(`Registered tool: ${t}`),n.push(t)):(V.warn(`Tool ${t} not found in registry`),r.push(t))}catch(e){e.message&&e.message.includes(`already registered`)?(V.debug(`Tool ${t} already registered, skipping`),n.push(t)):(V.error(`Failed to register tool ${t}: ${e.message}`),r.push(t))}}),V.info(`Successfully registered ${n.length}/${a.length} tools`),r.length>0&&V.warn(`Failed tools: ${r.join(`, `)}`),{registeredTools:n,failedTools:r,normalizedMode:o}}catch(t){V.error(`Error parsing TASK_MASTER_TOOLS environment variable: ${t.message}`),V.info(`Falling back to loading all tools`);let i=Object.keys($);for(let t of i){let i=rr(t);if(i)try{i(e),n.push(t)}catch(e){e.message&&e.message.includes(`already registered`)?(V.debug(`Fallback tool ${t} already registered, skipping`),n.push(t)):(V.warn(`Failed to register fallback tool '${t}': ${e.message}`),r.push(t))}else V.warn(`Tool '${t}' not found in registry`),r.push(t)}return V.info(`Successfully registered ${n.length} fallback tools`),{registeredTools:n,failedTools:r,normalizedMode:`all`}}}L.config(),re();const or=Qe(import.meta.url);P.dirname(or);var sr=class{constructor(){this.options={name:`Task Master MCP Server`,version:se};let e=new $e(this.options);if(e._mcpServer&&R.wrapMcpServerWithSentry)try{e._mcpServer=R.wrapMcpServerWithSentry(e._mcpServer)}catch(e){V.warn(`Failed to wrap MCP server with Sentry: ${e.message}`)}this.server=e,this.initialized=!1,this.init=this.init.bind(this),this.start=this.start.bind(this),this.stop=this.stop.bind(this),this.logger=V}async init(){if(this.initialized)return;let e=ir();this.logger.info(`Task Master MCP Server starting...`),this.logger.info(`Tool mode configuration: ${e}`);let t=ar(this.server,e);return this.logger.info(`Normalized tool mode: ${t.normalizedMode}`),this.logger.info(`Registered ${t.registeredTools.length} tools successfully`),t.registeredTools.length>0&&this.logger.debug(`Registered tools: ${t.registeredTools.join(`, `)}`),t.failedTools.length>0&&this.logger.warn(`Failed to register ${t.failedTools.length} tools: ${t.failedTools.join(`, `)}`),this.initialized=!0,this}async start(){return this.initialized||await this.init(),this.server.on(`connect`,e=>{e.session.server.sendLoggingMessage({data:{context:e.session.context,message:`MCP Server connected: ${e.session.name}`},level:`info`}),this.registerRemoteProvider(e.session)}),await this.server.start({transportType:`stdio`,timeout:12e4}),this}registerRemoteProvider(e){if(e){if(!e.clientCapabilities||!e.clientCapabilities.sampling){e.server.sendLoggingMessage({data:{context:e.context,message:`MCP session missing required sampling capabilities, providers not registered`},level:`info`});return}let n=new lt;n.setSession(e),t.getInstance().registerProvider(`mcp`,n),e.server.sendLoggingMessage({data:{context:e.context,message:`MCP Server connected`},level:`info`})}else e.server.sendLoggingMessage({data:{context:e.context,message:`No MCP sessions available, providers not registered`},level:`warn`})}async stop(){this.server&&await this.server.stop()}};L.config(),process.env.TASK_MASTER_MCP=`true`;async function cr(){let e=new sr;process.on(`SIGINT`,async()=>{await e.stop(),process.exit(0)}),process.on(`SIGTERM`,async()=>{await e.stop(),process.exit(0)});try{await e.start()}catch(e){V.error(`Failed to start MCP server: ${e.message}`),process.exit(1)}}cr();export{};
@@ -1,4 +1,4 @@
1
- import{c as e}from"./ai-services-unified-tvfkaOTr.js";import{Bt as t,D as n,Ft as r,Gt as i,Ht as a,It as o,J as s,Pt as c,Ut as l,Vt as u,Wt as d,hn as f,qt as p,vt as m,yt as h}from"./config-manager-Cm3z1HZv.js";import{r as g}from"./git-utils-DllbRE35.js";import{Ct as _,St as v,Tt as y,x as ee}from"./dependency-manager-CaRCB7TO.js";import*as b from"node:path";import x from"chalk";import S from"fs";import C from"path";import{randomUUID as w}from"crypto";import T from"os";import*as E from"node:fs";import*as te from"node:os";import{execSync as D}from"child_process";import{fileURLToPath as ne}from"url";import O from"boxen";import k from"readline";import re from"figlet";import ie from"gradient-string";import ae from"inquirer";import oe from"ora";import se from"open";const A=[`amp`,`claude`,`cline`,`codex`,`cursor`,`gemini`,`kiro`,`opencode`,`kilo`,`roo`,`trae`,`vscode`,`windsurf`,`zed`],ce=[`architect`,`ask`,`orchestrator`,`code`,`debug`,`test`],j=`# Task files`,M=`tasks.json`,N=`tasks/`;function le(e){return e.trim().replace(/^#/,``).trim()}function P(e){let t=le(e);return t===M||t===N}function ue(e,t){return e.map(e=>{if(P(e)){let n=le(e),r=e.match(/\s*$/)[0];return t?`# ${n}${r}`:`${n}${r}`}return e})}function de(e){let t=[],n=!1;for(let r of e){if(r.trim()===j){n=!0;continue}P(r)||n&&!r.trim()||(n&&r.trim()&&!P(r)&&(n=!1),n||t.push(r))}return t}function fe(e,t){return e.filter(e=>{let n=e.trim();return!n||P(e)||n===j?!1:!t.has(n)})}function pe(e){let t=[j];return e?t.push(`# ${M}`,`# ${N} `):t.push(M,`${N} `),t}function me(e){if(e.some(e=>e.trim())){let t=e[e.length-1];t&&t.trim()&&e.push(``)}}function he(e,t,n){if(!e||typeof e!=`string`)throw Error(`targetPath must be a non-empty string`);if(!e.endsWith(`.gitignore`))throw Error(`targetPath must end with .gitignore`);if(!t||typeof t!=`string`)throw Error(`content must be a non-empty string`);if(typeof n!=`boolean`)throw Error(`storeTasksInGit must be a boolean`)}function ge(e,t,n){try{S.writeFileSync(e,t.join(`
1
+ import{c as e}from"./ai-services-unified-DWAPupZV.js";import{Bt as t,D as n,Ft as r,Gt as i,Ht as a,It as o,J as s,Pt as c,Ut as l,Vt as u,Wt as d,hn as f,qt as p,vt as m,yt as h}from"./config-manager-cNtpB94F.js";import{r as g}from"./git-utils-DllbRE35.js";import{Ct as _,St as v,Tt as y,x as ee}from"./dependency-manager-mDsYzQ71.js";import*as b from"node:path";import x from"chalk";import S from"fs";import C from"path";import{randomUUID as w}from"crypto";import T from"os";import*as E from"node:fs";import*as te from"node:os";import{execSync as D}from"child_process";import{fileURLToPath as ne}from"url";import O from"boxen";import k from"readline";import re from"figlet";import ie from"gradient-string";import ae from"inquirer";import oe from"ora";import se from"open";const A=[`amp`,`claude`,`cline`,`codex`,`cursor`,`gemini`,`kiro`,`opencode`,`kilo`,`roo`,`trae`,`vscode`,`windsurf`,`zed`],ce=[`architect`,`ask`,`orchestrator`,`code`,`debug`,`test`],j=`# Task files`,M=`tasks.json`,N=`tasks/`;function le(e){return e.trim().replace(/^#/,``).trim()}function P(e){let t=le(e);return t===M||t===N}function ue(e,t){return e.map(e=>{if(P(e)){let n=le(e),r=e.match(/\s*$/)[0];return t?`# ${n}${r}`:`${n}${r}`}return e})}function de(e){let t=[],n=!1;for(let r of e){if(r.trim()===j){n=!0;continue}P(r)||n&&!r.trim()||(n&&r.trim()&&!P(r)&&(n=!1),n||t.push(r))}return t}function fe(e,t){return e.filter(e=>{let n=e.trim();return!n||P(e)||n===j?!1:!t.has(n)})}function pe(e){let t=[j];return e?t.push(`# ${M}`,`# ${N} `):t.push(M,`${N} `),t}function me(e){if(e.some(e=>e.trim())){let t=e[e.length-1];t&&t.trim()&&e.push(``)}}function he(e,t,n){if(!e||typeof e!=`string`)throw Error(`targetPath must be a non-empty string`);if(!e.endsWith(`.gitignore`))throw Error(`targetPath must end with .gitignore`);if(!t||typeof t!=`string`)throw Error(`content must be a non-empty string`);if(typeof n!=`boolean`)throw Error(`storeTasksInGit must be a boolean`)}function ge(e,t,n){try{S.writeFileSync(e,t.join(`
2
2
  `)+`
3
3
  `),typeof n==`function`&&n(`success`,`Created ${e} with full template`)}catch(t){throw typeof n==`function`&&n(`error`,`Failed to create ${e}: ${t.message}`),t}}function _e(e,t,n,r){try{let i=de(S.readFileSync(e,`utf8`).split(`
4
4
  `)),a=fe(t,new Set(i.map(e=>e.trim()).filter(e=>e))),o=[...i];a.length>0&&(me(o),o.push(...a)),me(o),o.push(...pe(n)),S.writeFileSync(e,o.join(`
@@ -3510,7 +3510,7 @@ Do you want to continue with these settings? (Y/n): `))).trim().toLowerCase()===
3510
3510
  `));let{storageType:e}=await ae.prompt([{type:`list`,name:`storageType`,message:x.white(`How do you want to build it?
3511
3511
  `),choices:[{name:[x.bold(`Solo (Taskmaster)`),``,x.white(` • Parse your own PRDs into structured task lists and build with any IDE or background agents`),x.white(` • Agents execute tasks with precision, no scope creep, no going off-track`),x.white(` • Tasks live in a local JSON file, everything stays in your repo`),x.white(` • Upgrade to Hamster to bring the Taskmaster experience to your team`),``].join(`
3512
3512
  `),value:`local`,short:`Solo (Taskmaster)`},{name:[x.bold(`Together (Hamster)`),``,x.white(` • Write a brief with your team. Hamster refines it into a plan.`),x.white(` • Your team drafts, refines, and aligns on the same page before executing`),x.white(` • One brief, one plan, one source of truth for execution`),x.white(` • Access tasks on Taskmaster and execute with any AI agent`),``].join(`
3513
- `),value:`cloud`,short:`Together (Hamster)`}],default:`local`,pageSize:20}]);return e}catch(e){if(e.isTtyError||e.name===`ExitPromptError`)return X(`warn`,`Storage selection cancelled, defaulting to local storage`),`local`;throw e}}async function bn(e,n,s,d,f,h=A,_=`local`,v=null){let y=process.cwd();X(`debug`,`Initializing project in ${y}`),Z(C.join(y,u)),Z(C.join(y,i)),Z(C.join(y,a)),Z(C.join(y,l)),Z(C.join(y,p)),hn(y);let b={year:new Date().getFullYear()},S=_===`cloud`?`team`:`solo`;function w(e){let t=q(e);t?J(y,t,{mode:S}):X(`warn`,`Unknown rule profile: ${e}`)}Q(`env.example`,C.join(y,c),b),Q(`config.json`,C.join(y,t),{...b});let T=C.join(y,t);dn(T)?X(`debug`,`Updated config with correct maxTokens values`):X(`debug`,`Could not update maxTokens in config`),vn(T,_,v);try{let e=L(`gitignore`,`utf8`);ve(C.join(y,o),e,s,X)}catch(e){X(`error`,`Failed to create .gitignore: ${e.message}`)}Q(`example_prd.txt`,C.join(y,r)),Q(`example_prd_rpg.txt`,C.join(y,p,`example_prd_rpg.txt`));try{n===!1?X(`info`,`Git initialization skipped due to --no-git flag.`):n===!0?g()?X(`debug`,`Existing Git repository detected – skipping git init despite --git flag.`):(X(`info`,`Initializing Git repository due to --git flag...`),D(`git init`,{cwd:y,stdio:`ignore`}),X(`success`,`Git repository initialized`)):g()?X(`debug`,`Existing Git repository detected – skipping git init.`):(X(`info`,`No Git repository detected. Initializing one in project root...`),D(`git init`,{cwd:y,stdio:`ignore`}),X(`success`,`Git repository initialized`))}catch{X(`warn`,`Git not available, skipping repository initialization`)}if(f.rulesExplicitlyProvided||f.yes){X(`info`,`Generating profile rules from command-line flags...`);for(let e of h)w(e)}e&&mn();let E={cwd:y,stdio:`inherit`};if(m()&&(E.stdio=`ignore`,X(`info`,`Running npm install silently...`)),f.shouldSetupRules&&!m()&&!d&&!f?.yes&&!f.rulesExplicitlyProvided){console.log(O(x.cyan(`Configuring Rule Profiles...`),{padding:.5,margin:{top:1,bottom:.5},borderStyle:`round`,borderColor:`cyan`,width:60})),X(`info`,`Running interactive rules setup. Please select which rule profiles to include.`);try{D(`npx task-master rules --setup`,{stdio:`inherit`,cwd:y}),X(`success`,`Rule profiles configured.`)}catch(e){X(`error`,`Failed to configure rule profiles:`,e.message),X(`warn`,`You may need to run "task-master rules --setup" manually.`)}}else m()||d||f?.yes?f.rulesExplicitlyProvided?X(`debug`,`Skipping interactive rules setup because --rules flag was used.`):X(`debug`,`Skipping interactive rules setup in non-interactive mode.`):f.shouldSetupRules||X(`debug`,`Skipping rules setup - user declined.`);if(f.preferredLanguage&&!d)try{let e=(await import(`./response-language-BspVHfZg.js`)).default;e(f.preferredLanguage,{projectRoot:y,silent:!0}),X(`debug`,`Response language set to: ${f.preferredLanguage}`)}catch(e){X(`warn`,`Failed to set response language: ${e.message}`)}else m()&&!d?X(`debug`,`Skipping response language setup in silent (MCP) mode.`):d&&X(`debug`,`DRY RUN: Skipping response language setup.`);if(!m()&&!d&&!f?.yes&&_===`local`){console.log(O(x.cyan(`Configuring AI Models...`),{padding:.5,margin:{top:1,bottom:.5},borderStyle:`round`,borderColor:`cyan`,width:60})),X(`info`,`Running interactive model setup. Please select your preferred AI models.`);try{D(`npx task-master models --setup`,{stdio:`inherit`,cwd:y}),X(`success`,`AI Models configured.`)}catch(e){X(`error`,`Failed to configure AI models:`,e.message),X(`warn`,`You may need to run "task-master models --setup" manually.`)}}else _===`cloud`&&!d?console.log(O(x.green.bold(`✓ AI Models Managed by Hamster - go ham!
3513
+ `),value:`cloud`,short:`Together (Hamster)`}],default:`local`,pageSize:20}]);return e}catch(e){if(e.isTtyError||e.name===`ExitPromptError`)return X(`warn`,`Storage selection cancelled, defaulting to local storage`),`local`;throw e}}async function bn(e,n,s,d,f,h=A,_=`local`,v=null){let y=process.cwd();X(`debug`,`Initializing project in ${y}`),Z(C.join(y,u)),Z(C.join(y,i)),Z(C.join(y,a)),Z(C.join(y,l)),Z(C.join(y,p)),hn(y);let b={year:new Date().getFullYear()},S=_===`cloud`?`team`:`solo`;function w(e){let t=q(e);t?J(y,t,{mode:S}):X(`warn`,`Unknown rule profile: ${e}`)}Q(`env.example`,C.join(y,c),b),Q(`config.json`,C.join(y,t),{...b});let T=C.join(y,t);dn(T)?X(`debug`,`Updated config with correct maxTokens values`):X(`debug`,`Could not update maxTokens in config`),vn(T,_,v);try{let e=L(`gitignore`,`utf8`);ve(C.join(y,o),e,s,X)}catch(e){X(`error`,`Failed to create .gitignore: ${e.message}`)}Q(`example_prd.txt`,C.join(y,r)),Q(`example_prd_rpg.txt`,C.join(y,p,`example_prd_rpg.txt`));try{n===!1?X(`info`,`Git initialization skipped due to --no-git flag.`):n===!0?g()?X(`debug`,`Existing Git repository detected – skipping git init despite --git flag.`):(X(`info`,`Initializing Git repository due to --git flag...`),D(`git init`,{cwd:y,stdio:`ignore`}),X(`success`,`Git repository initialized`)):g()?X(`debug`,`Existing Git repository detected – skipping git init.`):(X(`info`,`No Git repository detected. Initializing one in project root...`),D(`git init`,{cwd:y,stdio:`ignore`}),X(`success`,`Git repository initialized`))}catch{X(`warn`,`Git not available, skipping repository initialization`)}if(f.rulesExplicitlyProvided||f.yes){X(`info`,`Generating profile rules from command-line flags...`);for(let e of h)w(e)}e&&mn();let E={cwd:y,stdio:`inherit`};if(m()&&(E.stdio=`ignore`,X(`info`,`Running npm install silently...`)),f.shouldSetupRules&&!m()&&!d&&!f?.yes&&!f.rulesExplicitlyProvided){console.log(O(x.cyan(`Configuring Rule Profiles...`),{padding:.5,margin:{top:1,bottom:.5},borderStyle:`round`,borderColor:`cyan`,width:60})),X(`info`,`Running interactive rules setup. Please select which rule profiles to include.`);try{D(`npx task-master rules --setup`,{stdio:`inherit`,cwd:y}),X(`success`,`Rule profiles configured.`)}catch(e){X(`error`,`Failed to configure rule profiles:`,e.message),X(`warn`,`You may need to run "task-master rules --setup" manually.`)}}else m()||d||f?.yes?f.rulesExplicitlyProvided?X(`debug`,`Skipping interactive rules setup because --rules flag was used.`):X(`debug`,`Skipping interactive rules setup in non-interactive mode.`):f.shouldSetupRules||X(`debug`,`Skipping rules setup - user declined.`);if(f.preferredLanguage&&!d)try{let e=(await import(`./response-language-0vTrIr_j.js`)).default;e(f.preferredLanguage,{projectRoot:y,silent:!0}),X(`debug`,`Response language set to: ${f.preferredLanguage}`)}catch(e){X(`warn`,`Failed to set response language: ${e.message}`)}else m()&&!d?X(`debug`,`Skipping response language setup in silent (MCP) mode.`):d&&X(`debug`,`DRY RUN: Skipping response language setup.`);if(!m()&&!d&&!f?.yes&&_===`local`){console.log(O(x.cyan(`Configuring AI Models...`),{padding:.5,margin:{top:1,bottom:.5},borderStyle:`round`,borderColor:`cyan`,width:60})),X(`info`,`Running interactive model setup. Please select your preferred AI models.`);try{D(`npx task-master models --setup`,{stdio:`inherit`,cwd:y}),X(`success`,`AI Models configured.`)}catch(e){X(`error`,`Failed to configure AI models:`,e.message),X(`warn`,`You may need to run "task-master models --setup" manually.`)}}else _===`cloud`&&!d?console.log(O(x.green.bold(`✓ AI Models Managed by Hamster - go ham!
3514
3514
 
3515
3515
  `)+x.white(`Hamster handles all AI model configuration for you.
3516
3516
  `)+x.dim(`• Optimized model selection for your tasks
@@ -0,0 +1 @@
1
+ import"./ai-services-unified-DWAPupZV.js";import"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import"./sentry-DsxpJLVM.js";import{A as e}from"./dependency-manager-mDsYzQ71.js";import"./response-language-BmOan_mF.js";export{e as performResearch};
@@ -0,0 +1 @@
1
+ import"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import{t as e}from"./response-language-BmOan_mF.js";export{e as default};
@@ -1 +1 @@
1
- import{B as e,X as t,p as n,q as r,yt as i}from"./config-manager-Cm3z1HZv.js";function a(a,o={}){let{mcpLog:s,projectRoot:c}=o,l=(e,...t)=>{s&&typeof s[e]==`function`&&s[e](...t)},u=t(null,{projectRoot:c}),d=e(c);if(i(`debug`,`Checking for config file using findConfigPath, found: ${u}`),i(`debug`,`Checking config file using isConfigFilePresent(), exists: ${d}`),!d)return{success:!1,error:{code:`CONFIG_MISSING`,message:`The configuration file is missing. Run "task-master init" to create it.`}};if(typeof a!=`string`||a.trim()===``)return{success:!1,error:{code:`INVALID_RESPONSE_LANGUAGE`,message:`Invalid response language: ${a}. Must be a non-empty string.`}};try{let e=n(c),t=a.trim();return e.global||={},e.global.responseLanguage=t,r(e,c)?{success:!0,data:{responseLanguage:t,message:`Response language set to ${t}`}}:{success:!1,error:{code:`WRITE_ERROR`,message:`Error writing updated configuration to configuration file`}}}catch(e){return l(`error`,`Error setting response language: ${e.message}`),{success:!1,error:{code:`SET_RESPONSE_LANGUAGE_ERROR`,message:e.message}}}}var o=a;export{o as t};
1
+ import{B as e,X as t,p as n,q as r,yt as i}from"./config-manager-cNtpB94F.js";function a(a,o={}){let{mcpLog:s,projectRoot:c}=o,l=(e,...t)=>{s&&typeof s[e]==`function`&&s[e](...t)},u=t(null,{projectRoot:c}),d=e(c);if(i(`debug`,`Checking for config file using findConfigPath, found: ${u}`),i(`debug`,`Checking config file using isConfigFilePresent(), exists: ${d}`),!d)return{success:!1,error:{code:`CONFIG_MISSING`,message:`The configuration file is missing. Run "task-master init" to create it.`}};if(typeof a!=`string`||a.trim()===``)return{success:!1,error:{code:`INVALID_RESPONSE_LANGUAGE`,message:`Invalid response language: ${a}. Must be a non-empty string.`}};try{let e=n(c),t=a.trim();return e.global||={},e.global.responseLanguage=t,r(e,c)?{success:!0,data:{responseLanguage:t,message:`Response language set to ${t}`}}:{success:!1,error:{code:`WRITE_ERROR`,message:`Error writing updated configuration to configuration file`}}}catch(e){return l(`error`,`Error setting response language: ${e.message}`),{success:!1,error:{code:`SET_RESPONSE_LANGUAGE_ERROR`,message:e.message}}}}var o=a;export{o as t};
@@ -1 +1 @@
1
- import{U as e,r as t}from"./config-manager-Cm3z1HZv.js";import{createHash as n}from"crypto";import*as r from"@sentry/node";let i=!1;function a(e){if(e)return n(`sha256`).update(e).digest(`hex`).substring(0,8)}function o(n={}){if(i)return;e(!0);try{if(!t(n.projectRoot)){console.log(`✓ Anonymous telemetry disabled per user preference. Set anonymousTelemetry: true in .taskmaster/config.json to re-enable.`);return}}catch{}finally{e(!1)}let a=n.dsn||`https://ce8c03ca1dd0da5b9837c6ba1b3a0f9d@o4510099843776512.ingest.us.sentry.io/4510381945585664`;if(a)try{r.init({dsn:a,environment:n.environment||process.env.NODE_ENV||`production`,integrations:[r.vercelAIIntegration({recordInputs:!0,recordOutputs:!0}),r.zodErrorsIntegration()],tracesSampleRate:n.tracesSampleRate??1,sendDefaultPii:n.sendDefaultPii??!0,debug:process.env.SENTRY_DEBUG===`true`}),i=!0,process.env.SENTRY_DEBUG===`true`&&(console.log(` DSN: ${a.substring(0,40)}...`),console.log(` Environment: ${n.environment||process.env.NODE_ENV||`production`}`),console.log(` Traces Sample Rate: ${n.tracesSampleRate??1}`))}catch(e){console.error(`Failed to initialize telemetry: ${e.message}`)}}function s(e,t={}){if(!i)return process.env.SENTRY_DEBUG===`true`&&console.log(`⚠️ Sentry not initialized, telemetry config not available`),null;let n={isEnabled:!0,recordInputs:!0,recordOutputs:!0};return e&&(n.functionId=e),Object.keys(t).length>0&&(n.metadata={},t.command&&(n.metadata.command=t.command),t.outputType&&(n.metadata.outputType=t.outputType),t.tag&&(n.metadata.tag=t.tag),t.taskId&&(n.metadata.taskId=t.taskId),t.userId&&(n.metadata.userId=t.userId),t.briefId&&(n.metadata.briefId=t.briefId),t.projectHash&&(n.metadata.projectHash=t.projectHash)),process.env.SENTRY_DEBUG===`true`&&console.log(`📊 Sentry telemetry config created:`,JSON.stringify(n,null,2)),n}export{a as n,o as r,s as t};
1
+ import{U as e,r as t}from"./config-manager-cNtpB94F.js";import{createHash as n}from"crypto";import*as r from"@sentry/node";let i=!1;function a(e){if(e)return n(`sha256`).update(e).digest(`hex`).substring(0,8)}function o(n={}){if(i)return;e(!0);try{if(!t(n.projectRoot)){console.log(`✓ Anonymous telemetry disabled per user preference. Set anonymousTelemetry: true in .taskmaster/config.json to re-enable.`);return}}catch{}finally{e(!1)}let a=n.dsn||`https://ce8c03ca1dd0da5b9837c6ba1b3a0f9d@o4510099843776512.ingest.us.sentry.io/4510381945585664`;if(a)try{r.init({dsn:a,environment:n.environment||process.env.NODE_ENV||`production`,integrations:[r.vercelAIIntegration({recordInputs:!0,recordOutputs:!0}),r.zodErrorsIntegration()],tracesSampleRate:n.tracesSampleRate??1,sendDefaultPii:n.sendDefaultPii??!0,debug:process.env.SENTRY_DEBUG===`true`}),i=!0,process.env.SENTRY_DEBUG===`true`&&(console.log(` DSN: ${a.substring(0,40)}...`),console.log(` Environment: ${n.environment||process.env.NODE_ENV||`production`}`),console.log(` Traces Sample Rate: ${n.tracesSampleRate??1}`))}catch(e){console.error(`Failed to initialize telemetry: ${e.message}`)}}function s(e,t={}){if(!i)return process.env.SENTRY_DEBUG===`true`&&console.log(`⚠️ Sentry not initialized, telemetry config not available`),null;let n={isEnabled:!0,recordInputs:!0,recordOutputs:!0};return e&&(n.functionId=e),Object.keys(t).length>0&&(n.metadata={},t.command&&(n.metadata.command=t.command),t.outputType&&(n.metadata.outputType=t.outputType),t.tag&&(n.metadata.tag=t.tag),t.taskId&&(n.metadata.taskId=t.taskId),t.userId&&(n.metadata.userId=t.userId),t.briefId&&(n.metadata.briefId=t.briefId),t.projectHash&&(n.metadata.projectHash=t.projectHash)),process.env.SENTRY_DEBUG===`true`&&console.log(`📊 Sentry telemetry config created:`,JSON.stringify(n,null,2)),n}export{a as n,o as r,s as t};
@@ -0,0 +1 @@
1
+ import"./ai-services-unified-DWAPupZV.js";import"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import"./sentry-DsxpJLVM.js";import{ct as e,dt as t,ft as n,ht as r,lt as i,mt as a,pt as o,st as s,ut as c}from"./dependency-manager-mDsYzQ71.js";import"./response-language-BmOan_mF.js";export{s as copyTag,e as createTag,i as createTagFromBranch,c as deleteTag,t as renameTag,n as switchCurrentTag,o as tags,a as updateBranchTagMapping,r as useTag};
@@ -1 +1 @@
1
- import"./ai-services-unified-tvfkaOTr.js";import{dt as e,wt as t}from"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import"./sentry-hPhwSfRH.js";import{$ as n,A as r,C as i,D as a,E as o,I as s,J as c,K as l,L as u,M as d,N as f,O as p,P as m,Q as h,S as g,T as _,X as v,Y as y,Z as b,gt as x,j as S,k as C,q as w,w as T}from"./dependency-manager-CaRCB7TO.js";import{t as E}from"./response-language-BnJvZzdq.js";export{n as addSubtask,h as addTask,b as analyzeTaskComplexity,v as clearSubtasks,c as expandAllTasks,y as expandTask,x as findNextTask,e as findTaskById,w as isTaskDependentOn,l as listTasks,u as migrateProject,s as moveTask,m as parsePRD,r as performResearch,t as readComplexityReport,f as removeSubtask,S as removeTask,a as scopeDownTask,p as scopeUpTask,E as setResponseLanguage,_ as setTaskStatus,d as taskExists,o as updateSingleTaskStatus,T as updateSubtaskById,i as updateTaskById,g as updateTasks,C as validateStrength};
1
+ import"./ai-services-unified-DWAPupZV.js";import{dt as e,wt as t}from"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import"./sentry-DsxpJLVM.js";import{$ as n,A as r,C as i,D as a,E as o,I as s,J as c,K as l,L as u,M as d,N as f,O as p,P as m,Q as h,S as g,T as _,X as v,Y as y,Z as b,gt as x,j as S,k as C,q as w,w as T}from"./dependency-manager-mDsYzQ71.js";import{t as E}from"./response-language-BmOan_mF.js";export{n as addSubtask,h as addTask,b as analyzeTaskComplexity,v as clearSubtasks,c as expandAllTasks,y as expandTask,x as findNextTask,e as findTaskById,w as isTaskDependentOn,l as listTasks,u as migrateProject,s as moveTask,m as parsePRD,r as performResearch,t as readComplexityReport,f as removeSubtask,S as removeTask,a as scopeDownTask,p as scopeUpTask,E as setResponseLanguage,_ as setTaskStatus,d as taskExists,o as updateSingleTaskStatus,T as updateSubtaskById,i as updateTaskById,g as updateTasks,C as validateStrength};
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import{U as e,cn as t,hn as n}from"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import{r}from"./sentry-hPhwSfRH.js";import{join as i}from"node:path";import a from"dotenv";const o=process.cwd(),s=t();a.config({path:i(s,`.env`)}),r({projectRoot:s}),process.env.TASKMASTER_ORIGINAL_CWD=o,process.env.DEBUG===`1`&&console.error(`DEBUG - dev.js received args:`,process.argv.slice(2));try{await n.getInstance().hasValidSession()&&e(!0)}catch{e(!1)}const{runCLI:c}=await import(`./commands-BDy1-eeK.js`);c(process.argv);export{};
2
+ import{U as e,cn as t,hn as n}from"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import{r}from"./sentry-DsxpJLVM.js";import{join as i}from"node:path";import a from"dotenv";const o=process.cwd(),s=t();a.config({path:i(s,`.env`)}),r({projectRoot:s}),process.env.TASKMASTER_ORIGINAL_CWD=o,process.env.DEBUG===`1`&&console.error(`DEBUG - dev.js received args:`,process.argv.slice(2));try{await n.getInstance().hasValidSession()&&e(!0)}catch{e(!1)}const{runCLI:c}=await import(`./commands-CV7nje1G.js`);c(process.argv);export{};
@@ -0,0 +1 @@
1
+ import"./ai-services-unified-DWAPupZV.js";import"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import"./sentry-DsxpJLVM.js";import{w as e}from"./dependency-manager-mDsYzQ71.js";import"./response-language-BmOan_mF.js";export{e as default};
@@ -0,0 +1 @@
1
+ import"./ai-services-unified-DWAPupZV.js";import"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";import"./sentry-DsxpJLVM.js";import{C as e}from"./dependency-manager-mDsYzQ71.js";import"./response-language-BmOan_mF.js";export{e as default};
@@ -1 +1 @@
1
- import{At as e,Ct as t,Dt as n,Et as r,Mt as i,Ot as a,St as o,Tt as s,_t as c,at as l,bt as u,ct as d,dt as f,ft as p,gt as m,ht as h,it as g,jt as _,kt as v,lt as y,mt as b,nt as x,ot as S,pt as C,rt as w,st as T,ut as E,vt as D,wt as O,xt as k,yt as A}from"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";export{x as LOG_LEVELS,w as addComplexityToTask,g as aggregateTelemetry,l as createStateJson,S as disableSilentMode,T as enableSilentMode,d as ensureTagMetadata,y as findCycles,E as findProjectRoot,f as findTaskById,p as findTaskInComplexityReport,C as flattenTasksWithSubtasks,b as formatTaskId,h as getCurrentTag,m as getTasksForTag,c as isEmpty,D as isSilentMode,A as log,u as markMigrationForNotice,k as migrateConfigJson,o as normalizeTaskIds,t as performCompleteTagMigration,O as readComplexityReport,s as readJSON,r as resolveEnvVariable,n as resolveTag,a as taskExists,v as traverseDependencies,e as truncate,_ as withFileLockSync,i as writeJSON};
1
+ import{At as e,Ct as t,Dt as n,Et as r,Mt as i,Ot as a,St as o,Tt as s,_t as c,at as l,bt as u,ct as d,dt as f,ft as p,gt as m,ht as h,it as g,jt as _,kt as v,lt as y,mt as b,nt as x,ot as S,pt as C,rt as w,st as T,ut as E,vt as D,wt as O,xt as k,yt as A}from"./config-manager-cNtpB94F.js";import"./git-utils-DllbRE35.js";export{x as LOG_LEVELS,w as addComplexityToTask,g as aggregateTelemetry,l as createStateJson,S as disableSilentMode,T as enableSilentMode,d as ensureTagMetadata,y as findCycles,E as findProjectRoot,f as findTaskById,p as findTaskInComplexityReport,C as flattenTasksWithSubtasks,b as formatTaskId,h as getCurrentTag,m as getTasksForTag,c as isEmpty,D as isSilentMode,A as log,u as markMigrationForNotice,k as migrateConfigJson,o as normalizeTaskIds,t as performCompleteTagMigration,O as readComplexityReport,s as readJSON,r as resolveEnvVariable,n as resolveTag,a as taskExists,v as traverseDependencies,e as truncate,_ as withFileLockSync,i as writeJSON};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hhsw2015/task-master-ai",
3
- "version": "0.43.19",
3
+ "version": "0.43.20",
4
4
  "description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -1 +0,0 @@
1
- import{a as e,i as t,n,r,t as i}from"./ai-services-unified-tvfkaOTr.js";import"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import"./sentry-hPhwSfRH.js";export{i as generateObjectService,n as generateTextService,r as logAiUsage,t as streamObjectService,e as streamTextService};
@@ -1 +0,0 @@
1
- import"./ai-services-unified-tvfkaOTr.js";import"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import"./sentry-hPhwSfRH.js";import{A as e}from"./dependency-manager-CaRCB7TO.js";import"./response-language-BnJvZzdq.js";export{e as performResearch};
@@ -1 +0,0 @@
1
- import"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import{t as e}from"./response-language-BnJvZzdq.js";export{e as default};
@@ -1 +0,0 @@
1
- import"./ai-services-unified-tvfkaOTr.js";import"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import"./sentry-hPhwSfRH.js";import{ct as e,dt as t,ft as n,ht as r,lt as i,mt as a,pt as o,st as s,ut as c}from"./dependency-manager-CaRCB7TO.js";import"./response-language-BnJvZzdq.js";export{s as copyTag,e as createTag,i as createTagFromBranch,c as deleteTag,t as renameTag,n as switchCurrentTag,o as tags,a as updateBranchTagMapping,r as useTag};
@@ -1 +0,0 @@
1
- import"./ai-services-unified-tvfkaOTr.js";import"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import"./sentry-hPhwSfRH.js";import{w as e}from"./dependency-manager-CaRCB7TO.js";import"./response-language-BnJvZzdq.js";export{e as default};
@@ -1 +0,0 @@
1
- import"./ai-services-unified-tvfkaOTr.js";import"./config-manager-Cm3z1HZv.js";import"./git-utils-DllbRE35.js";import"./sentry-hPhwSfRH.js";import{C as e}from"./dependency-manager-CaRCB7TO.js";import"./response-language-BnJvZzdq.js";export{e as default};