UNPKG

task-master-ai

Version:

A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.

36 lines (28 loc) 140 kB
#!/usr/bin/env node import{o as e,s as t}from"./ai-services-unified-CsFt27lZ.js";import{$t as n,An as r,Dt as i,Ht as a,Kt as o,Mt as s,Nt as c,Qt as l,Sn as u,Tn as d,Tt as f,fn as p,ht as m,in as h,ln as g,m 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,wn as te,wt as T,x as ne,zt as re}from"./config-manager-DTKWXIqv.js";import"./git-utils-DllbRE35.js";import{r as ie}from"./sentry-CZp3yiwv.js";import{$ as ae,A as oe,B as E,C as se,D 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-BJq6jWA5.js";import{t as We}from"./response-language-pkLR39Qe.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-CvDnJeks.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[ne().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(` `);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` CRITICAL JSON GENERATION INSTRUCTIONS: You must respond with ONLY valid JSON that matches this exact structure for "${t}": ${JSON.stringify(n,null,2)} STRICT REQUIREMENTS: 1. Response must start with { and end with } 2. Use double quotes for all strings and property names 3. Do not include any text before or after the JSON 4. Do not wrap in markdown code blocks 5. Do not include explanations or comments 6. Follow the exact property names and types shown above 7. All required fields must be present Begin your response immediately with the opening brace {`}catch{return` CRITICAL JSON GENERATION INSTRUCTIONS: You must respond with ONLY valid JSON for "${t}". STRICT REQUIREMENTS: 1. Response must start with { and end with } 2. Use double quotes for all strings and property names 3. Do not include any text before or after the JSON 4. Do not wrap in markdown code blocks 5. Do not include explanations or comments Begin your response immediately with the opening brace {`}}function q(e){if(!e||e._def===void 0)return{};let t=e._def;switch(t.typeName){case`ZodObject`:let e={},n=t.shape();for(let[t,r]of Object.entries(n))e[t]=q(r);return e;case`ZodString`:if(t.checks){let e=t.checks.find(e=>e.kind===`min`),n=t.checks.find(e=>e.kind===`max`);if(e&&n)return`<string between `+e.value+`-`+n.value+` characters>`;if(e)return`<string with at least `+e.value+` characters>`;if(n)return`<string up to `+n.value+` characters>`}return`<string>`;case`ZodNumber`:if(t.checks){let e=t.checks.find(e=>e.kind===`int`),n=t.checks.find(e=>e.kind===`min`),r=t.checks.find(e=>e.kind===`max`);if(e&&n&&n.value>0)return`<positive integer>`;if(e)return`<integer>`;if(n||r)return`<number`+(n?` >= `+n.value:``)+(r?` <= `+r.value:``)+`>`}return`<number>`;case`ZodBoolean`:return`<boolean>`;case`ZodArray`:return[q(t.type)];case`ZodOptional`:return q(t.innerType);case`ZodNullable`:return q(t.innerType);case`ZodEnum`:return t.values[0]||`enum_value`;case`ZodLiteral`:return t.value;case`ZodUnion`:return t.options&&t.options.length>0?q(t.options[0]):`union_value`;case`ZodRecord`:return{key:q(t.valueType)};default:return`<${t.typeName||`unknown`}>`}}function ot(e,t){let n=[...e],r=n.findIndex(e=>e.role===`system`);if(r>=0){let e=n[r].content;n[r]={...n[r],content:e+` `+t}}else n.unshift({role:`system`,content:t});return n}var st=class{specificationVersion=`v1`;defaultObjectGenerationMode=`json`;supportsImageUrls=!1;supportsStructuredOutputs=!0;constructor(e){this.session=e.session,this.modelId=e.modelId,this.settings=e.settings||{},this.provider=`mcp-ai-sdk`,this.maxTokens=this.settings.maxTokens,this.temperature=this.settings.temperature,this.validateSession()}validateSession(){if(!this.session?.clientCapabilities?.sampling)throw new H(`MCP session must have client sampling capabilities`)}async doGenerate(e){try{let{messages:t,systemPrompt:n}=G(e.prompt),r=await this.session.requestSampling({messages:t,systemPrompt:n,temperature:this.settings.temperature,maxTokens:this.settings.maxTokens,includeContext:`thisServer`},{timeout:24e4}),i=it(r);return{text:i.text,finishReason:i.finishReason||`stop`,usage:{promptTokens:i.usage?.inputTokens||0,completionTokens:i.usage?.outputTokens||0,totalTokens:(i.usage?.inputTokens||0)+(i.usage?.outputTokens||0)},rawResponse:r,warnings:i.warnings}}catch(e){throw W(e)}}async doGenerateObject(e){try{let{schema:t,mode:n=`json`,...r}=e;if(!t)throw new H(`Schema is required for object generation`);let i=at(t,r.objectName||`generated_object`),{messages:a,systemPrompt:o}=G(ot(e.prompt,i)),s=await this.session.requestSampling({messages:a,systemPrompt:o,temperature:this.settings.temperature,maxTokens:this.settings.maxTokens,includeContext:`thisServer`},{timeout:24e4}),c=it(s),l=rt(c.text),u;try{u=JSON.parse(l)}catch(e){throw new H(`Failed to parse JSON response: ${e.message}. Response: ${c.text.substring(0,200)}...`)}try{return{object:t.parse(u),finishReason:c.finishReason||`stop`,usage:{promptTokens:c.usage?.inputTokens||0,completionTokens:c.usage?.outputTokens||0,totalTokens:(c.usage?.inputTokens||0)+(c.usage?.outputTokens||0)},rawResponse:s,warnings:c.warnings}}catch(e){throw new H(`Generated object does not match schema: ${e.message}. Generated: ${JSON.stringify(u,null,2)}`)}}catch(e){throw W(e)}}async doStream(e){try{let t=await this.doGenerate(e);return this.simulateStreaming(t)}catch(e){throw W(e)}}async*simulateStreaming(e){let t=e.text,n=Math.max(1,Math.floor(t.length/10));for(let e=0;e<t.length;e+=n){let r=t.slice(e,e+n);e+n,t.length,yield{type:`text-delta`,textDelta:r},await new Promise(e=>setTimeout(e,50))}yield{type:`finish`,finishReason:e.finishReason,usage:e.usage}}};function ct(e={}){if(!e.session)throw Error(`MCP provider requires session object`);let t=function(t,n={}){if(new.target)throw Error(`The MCP model function cannot be called with the new keyword.`);return new st({session:e.session,modelId:t||`claude-3-5-sonnet-20241022`,settings:{temperature:n.temperature,maxTokens:n.maxTokens,...e.defaultSettings,...n}})};return t.languageModel=(e,n)=>t(e,n),t.chat=(e,n)=>t(e,n),t}var lt=class extends e{constructor(){super(),this.name=`mcp`,this.session=null}getRequiredApiKeyName(){return`MCP_API_KEY`}isRequiredApiKey(){return!1}validateAuth(e){if(!this.session)throw Error(`MCP Provider requires active MCP session`);if(!this.session.clientCapabilities?.sampling)throw Error(`MCP session must have client sampling capabilities`)}getClient(e){try{return ct({session:this.session,defaultSettings:{temperature:e.temperature,maxTokens:e.maxTokens}})}catch(e){this.handleError(`client initialization`,e)}}setSession(e){this.session=e,e?this.logger?.debug(`Updated MCP Provider session`):this.logger?.warn(`Set null session on MCP Provider`)}hasValidSession(){return!!(this.session&&this.session.clientCapabilities?.sampling)}};function ut(){return{version:d||`unknown`,name:te||`task-master-ai`}}function J(e,t,n){t||=ut();let r=`Error: ${e} Version: ${t.version} Name: ${t.name}`;return n&&(r+=` Current Tag: ${n.currentTag}`),{content:[{type:`text`,text:r}],isError:!0}}function dt(e,t){if(typeof e!=`function`){t?.debug?.(`reportProgress not available - operation will run without progress updates`);return}return e}function ft(e){try{let t=j.join(e,`.taskmaster`,`state.json`);return F.existsSync(t)&&JSON.parse(F.readFileSync(t,`utf-8`)).currentTag||`master`}catch{return null}}async function Y(e){let{result:t,log:n,errorPrefix:r=`API error`,projectRoot:i,tag:a}=e,o=ut(),s=a===void 0?i?ft(i):null:a;if(!t.success){let e=t.error?.message||`Unknown ${r}`;n?.error?.(`${r}: ${e}`);let i=`Error: ${e}\nVersion: ${o.version}\nName: ${o.name}`;return s&&(i+=`\nCurrent Tag: ${s}`),{content:[{type:`text`,text:i}],isError:!0}}n?.info?.(`Successfully completed operation`);let c={data:t.data,version:o};return s&&(c.tag=s),{content:[{type:`text`,text:JSON.stringify(c,null,2)}]}}function X(e){if(!e)return process.cwd();try{let t=e;try{t=decodeURIComponent(t)}catch{}return(t.startsWith(`file:///`)||t.startsWith(`file://`))&&(t=t.slice(7)),t.startsWith(`/`)&&/[A-Za-z]:/.test(t.substring(1,3))&&(t=t.substring(1)),t=t.replace(/\\/g,`/`),j.resolve(t)}catch{return j.resolve(e)}}function pt(e){try{return e?.roots?.[0]?.uri?X(e.roots[0].uri):e?.roots?.roots?.[0]?.uri?X(e.roots.roots[0].uri):null}catch{return null}}function Z(e){return async(t,n)=>{let{log:r,session:i}=n,a=null,o=`unknown`;try{if(process.env.TASK_MASTER_PROJECT_ROOT){let e=process.env.TASK_MASTER_PROJECT_ROOT;a=j.isAbsolute(e)?e:j.resolve(process.cwd(),e),o=`TASK_MASTER_PROJECT_ROOT environment variable`,r?.info?.(`Using project root from ${o}: ${a}`)}else if(i?.env?.TASK_MASTER_PROJECT_ROOT){let e=i.env.TASK_MASTER_PROJECT_ROOT;a=j.isAbsolute(e)?e:j.resolve(process.cwd(),e),o=`TASK_MASTER_PROJECT_ROOT session environment variable`,r?.info?.(`Using project root from ${o}: ${a}`)}else if(t.projectRoot)a=X(t.projectRoot),o=`args.projectRoot`,r?.info?.(`Using project root from ${o}: ${a}`);else{let e=pt(i);e&&(a=e,o=`session`,r?.info?.(`Using project root from ${o}: ${a}`))}return a?await e({...t,projectRoot:a},n):(r?.error?.(`Could not determine project root from environment, args, or session.`),Y({result:{success:!1,error:{message:`Could not determine project root. Please provide projectRoot argument or ensure TASK_MASTER_PROJECT_ROOT environment variable is set.`}}}))}catch(e){return r?.error?.(`Error within withNormalizedProjectRoot HOF (Normalized Root: ${a}): ${e.message}`),e.stack&&r?.debug&&r.debug(e.stack),Y({result:{success:!1,error:{message:`Operation failed: ${e.message}`}}})}}}function Q(e,t){return Z(async(n,i)=>{let a=j.join(n.projectRoot,`.env`);F.existsSync(a)&&L.config({path:a});let o=await g({projectPath:n.projectRoot,loggerConfig:{mcpMode:!0,logCallback:i.log}});if(r.includes(e)){let t=await o.auth.guardCommand(e,o.tasks.getStorageType());if(t.isBlocked){let e=`You're working on the ${t.briefName} Brief in Hamster so this command is managed for you. This command is only available for local file storage. Log out with 'tm auth logout' to use local commands.`;return i.log.info(e),Y({result:{success:!1,error:{message:e}},log:i.log,projectRoot:n.projectRoot})}}return t(n,{log:i.log,session:i.session,tmCore:o})})}function mt(e,t){if(!e)return{parsedMetadata:null};if(process.env.TASK_MASTER_ALLOW_METADATA_UPDATES!==`true`)return{parsedMetadata:null,error:t(`Metadata updates are disabled. Set TASK_MASTER_ALLOW_METADATA_UPDATES=true in your MCP server environment to enable metadata modifications.`)};try{let n=JSON.parse(e);return typeof n!=`object`||!n||Array.isArray(n)?{parsedMetadata:null,error:t(`Invalid metadata: must be a JSON object (not null or array)`)}:{parsedMetadata:n}}catch(e){return{parsedMetadata:null,error:t(`Invalid metadata JSON: ${e instanceof Error?e.message:`Unknown parse error`}. Provide a valid JSON object string.`)}}}const ht=I.object({taskId:S.describe(`Main task ID to start workflow for (e.g., "1", "2", "HAM-123"). Subtask IDs (e.g., "2.3", "1.1") are not allowed.`),projectRoot:I.string().describe(`Absolute path to the project root directory`),maxAttempts:I.number().optional().default(3).describe(`Maximum attempts per subtask (default: 3)`),force:I.boolean().optional().default(!1).describe(`Force start even if workflow state exists`)});function gt(e){e.addTool({name:`autopilot_start`,description:`Initialize and start a new TDD workflow for a task. Creates a git branch and sets up the workflow state machine.`,parameters:ht,annotations:{title:`Start Autopilot Workflow`,destructiveHint:!0},execute:Q(`autopilot-start`,async(e,{log:t,tmCore:n})=>{let{taskId:r,projectRoot:i,maxAttempts:a,force:o}=e,s=h(r);try{t.info(`Starting autopilot workflow for task ${s} in ${i}`);let e=n.config.getActiveTag(),r=n.auth.getContext()?.orgSlug,c=await n.tasks.get(s);if(!c||!c.task)return Y({result:{success:!1,error:{message:`Task ${s} not found`}},log:t,projectRoot:i});let l=c.task;if(!l.subtasks||l.subtasks.length===0)return Y({result:{success:!1,error:{message:`Task ${s} has no subtasks. Please use expand_task (with id="${s}") to create subtasks first. For improved results, consider running analyze_complexity before expanding the task.`}},log:t,projectRoot:i});if(await n.workflow.hasWorkflow()&&!o)return t.warn(`Workflow state already exists`),Y({result:{success:!1,error:{message:`Workflow already in progress. Use force=true to override or resume the existing workflow. Suggestion: Use autopilot_resume to continue the existing workflow`}},log:t,projectRoot:i});let u=await n.workflow.start({taskId:s,taskTitle:l.title,subtasks:l.subtasks.map(e=>({id:e.id,title:e.title,status:e.status,maxAttempts:a})),maxAttempts:a,force:o,tag:e,orgSlug:r});t.info(`Workflow started successfully for task ${s}`);let d=n.workflow.getNextAction();return Y({result:{success:!0,data:{message:`Workflow started for task ${s}`,taskId:s,branchName:u.branchName,phase:u.phase,tddPhase:u.tddPhase,progress:u.progress,currentSubtask:u.currentSubtask,nextAction:d.action,nextSteps:d.nextSteps}},log:t,projectRoot:i})}catch(e){return t.error(`Error in autopilot-start: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to start workflow: ${e.message}`}},log:t,projectRoot:i})}})})}const _t=I.object({projectRoot:I.string().describe(`Absolute path to the project root directory`)});function vt(e){e.addTool({name:`autopilot_resume`,description:`Resume a previously started TDD workflow from saved state. Restores the workflow state machine and continues from where it left off.`,parameters:_t,annotations:{title:`Resume Autopilot Workflow`,readOnlyHint:!0},execute:Q(`autopilot-resume`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Resuming autopilot workflow in ${r}`),!await n.workflow.hasWorkflow())return Y({result:{success:!1,error:{message:`No workflow state found. Start a new workflow with autopilot_start`}},log:t,projectRoot:r});let e=await n.workflow.resume(),i=n.workflow.getNextAction();return t.info(`Workflow resumed successfully for task ${e.taskId}`),Y({result:{success:!0,data:{message:`Workflow resumed`,...e,nextAction:i.action,actionDescription:i.description,nextSteps:i.nextSteps}},log:t,projectRoot:r})}catch(e){return t.error(`Error in autopilot-resume: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to resume workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const yt=I.object({projectRoot:I.string().describe(`Absolute path to the project root directory`)});function bt(e){e.addTool({name:`autopilot_next`,description:`Get the next action to perform in the TDD workflow. Returns detailed context about what needs to be done next, including the current phase, subtask, and expected actions.`,parameters:yt,annotations:{title:`Get Next Autopilot Action`,readOnlyHint:!0},execute:Q(`autopilot-next`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Getting next action for workflow in ${r}`),!await n.workflow.hasWorkflow())return Y({result:{success:!1,error:{message:`No active workflow found. Start a workflow with autopilot_start`}},log:t,projectRoot:r});await n.workflow.resume();let e=n.workflow.getNextAction(),i=n.workflow.getStatus();return t.info(`Next action determined: ${e.action}`),Y({result:{success:!0,data:{action:e.action,actionDescription:e.description,...i,nextSteps:e.nextSteps}},log:t,projectRoot:r})}catch(e){return t.error(`Error in autopilot-next: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to get next action: ${e.message}`}},log:t,projectRoot:r})}})})}const xt=I.object({projectRoot:I.string().describe(`Absolute path to the project root directory`)});function St(e){e.addTool({name:`autopilot_status`,description:`Get comprehensive workflow status including current phase, progress, subtask details, and activity history.`,parameters:xt,annotations:{title:`Get Autopilot Status`,readOnlyHint:!0},execute:Q(`autopilot-status`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Getting workflow status for ${r}`),!await n.workflow.hasWorkflow())return Y({result:{success:!1,error:{message:`No active workflow found. Start a workflow with autopilot_start`}},log:t,projectRoot:r});await n.workflow.resume();let e=n.workflow.getStatus();return t.info(`Workflow status retrieved for task ${e.taskId}`),Y({result:{success:!0,data:e},log:t,projectRoot:r})}catch(e){return t.error(`Error in autopilot-status: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to get workflow status: ${e.message}`}},log:t,projectRoot:r})}})})}const Ct=I.object({projectRoot:I.string().describe(`Absolute path to the project root directory`),testResults:I.object({total:I.number().describe(`Total number of tests`),passed:I.number().describe(`Number of passing tests`),failed:I.number().describe(`Number of failing tests`),skipped:I.number().optional().describe(`Number of skipped tests`)}).describe(`Test results from running the test suite`)});function wt(e){e.addTool({name:`autopilot_complete_phase`,description:`Complete the current TDD phase (RED or GREEN) with test result validation. RED phase: expects failures (if 0 failures, feature is already implemented and subtask auto-completes). GREEN phase: expects all tests passing. For COMMIT phase, use autopilot_commit instead.`,parameters:Ct,annotations:{title:`Complete Autopilot Phase`,destructiveHint:!0},execute:Q(`autopilot-complete-phase`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r,testResults:i}=e;try{if(t.info(`Completing current phase in workflow for ${r}`),!await n.workflow.hasWorkflow())return Y({result:{success:!1,error:{message:`No active workflow found. Start a workflow with autopilot_start`}},log:t,projectRoot:r});await n.workflow.resume();let e=n.workflow.getStatus();if(!e.tddPhase)return Y({result:{success:!1,error:{message:`Cannot complete phase: not in a TDD phase (current phase: ${e.phase})`}},log:t,projectRoot:r});if(e.tddPhase===`COMMIT`)return Y({result:{success:!1,error:{message:`Cannot complete COMMIT phase with this tool. Use autopilot_commit instead`}},log:t,projectRoot:r});let a=e.tddPhase,o={total:i.total,passed:i.passed,failed:i.failed,skipped:i.skipped??0,phase:a},s=await n.workflow.completePhase(o),c=n.workflow.getNextAction();return t.info(`Phase completed. New phase: ${s.tddPhase||s.phase}`),Y({result:{success:!0,data:{message:`Phase completed. Transitioned to ${s.tddPhase||s.phase}`,...s,nextAction:c.action,actionDescription:c.description,nextSteps:c.nextSteps}},log:t,projectRoot:r})}catch(e){return t.error(`Error in autopilot-complete: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to complete phase: ${e.message}`}},log:t,projectRoot:r})}})})}const Tt=I.object({projectRoot:I.string().describe(`Absolute path to the project root directory`),files:I.array(I.string()).optional().describe(`Specific files to stage (relative to project root). If not provided, stages all changes.`),customMessage:I.string().optional().describe(`Custom commit message to use instead of auto-generated message`)});function Et(e){e.addTool({name:`autopilot_commit`,description:`Create a git commit with automatic staging, message generation, and metadata embedding. Generates appropriate commit messages based on subtask context and TDD phase.`,parameters:Tt,annotations:{title:`Commit Autopilot Changes`,destructiveHint:!0},execute:Q(`autopilot-commit`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r,files:i,customMessage:a}=e;try{if(t.info(`Creating commit for workflow in ${r}`),!await n.workflow.hasWorkflow())return Y({result:{success:!1,error:{message:`No active workflow found. Start a workflow with autopilot_start`}},log:t,projectRoot:r});await n.workflow.resume();let e=n.workflow.getStatus(),o=n.workflow.getContext();if(e.tddPhase!==`COMMIT`)return t.warn(`Not in COMMIT phase (currently in ${e.tddPhase})`),Y({result:{success:!1,error:{message:`Cannot commit: currently in ${e.tddPhase} phase. Complete the ${e.tddPhase} phase first using autopilot_complete_phase`}},log:t,projectRoot:r});if(!e.currentSubtask)return Y({result:{success:!1,error:{message:`No active subtask to commit`}},log:t,projectRoot:r});let s=new y(r);try{i&&i.length>0?(await s.stageFiles(i),t.info(`Staged ${i.length} files`)):(await s.stageFiles([`.`]),t.info(`Staged all changes`))}catch(e){return t.error(`Failed to stage files: ${e.message}`),Y({result:{success:!1,error:{message:`Failed to stage files: ${e.message}`}},log:t,projectRoot:r})}if(!await s.hasStagedChanges())return t.warn(`No staged changes to commit`),Y({result:{success:!1,error:{message:`No staged changes to commit. Make code changes before committing`}},log:t,projectRoot:r});let c=await s.getStatus(),l;if(a)l=a,t.info(`Using custom commit message`);else{let n=new p,r={type:e.tddPhase===`COMMIT`?`feat`:`test`,description:e.currentSubtask.title,changedFiles:c.staged,taskId:e.taskId,phase:e.tddPhase,testsPassing:o.lastTestResults?.passed,testsFailing:o.lastTestResults?.failed};l=n.generateMessage(r),t.info(`Generated commit message automatically`)}try{await s.createCommit(l),t.info(`Commit created successfully`)}catch(e){return t.error(`Failed to create commit: ${e.message}`),Y({result:{success:!1,error:{message:`Failed to create commit: ${e.message}`}},log:t,projectRoot:r})}let u=await s.getLastCommit(),d=await n.workflow.commit();t.info(`Commit completed. Current phase: ${d.tddPhase||d.phase}`);let f=d.phase===`COMPLETE`,m=n.workflow.getNextAction();return Y({result:{success:!0,data:{message:f?`Workflow completed successfully`:`Commit created and workflow advanced`,commitSha:u.sha,commitMessage:l,...d,isComplete:f,nextAction:m.action,nextSteps:m.nextSteps}},log:t,projectRoot:r})}catch(e){return t.error(`Error in autopilot-commit: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to commit: ${e.message}`}},log:t,projectRoot:r})}})})}const Dt=I.object({projectRoot:I.string().describe(`Absolute path to the project root directory`)});function Ot(e){e.addTool({name:`autopilot_finalize`,description:`Finalize and complete the workflow. Validates that all changes are committed and working tree is clean before marking workflow as complete.`,parameters:Dt,annotations:{title:`Finalize Autopilot Workflow`,destructiveHint:!0},execute:Q(`autopilot-finalize`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Finalizing workflow in ${r}`),!await n.workflow.hasWorkflow())return Y({result:{success:!1,error:{message:`No active workflow found. Start a workflow with autopilot_start`}},log:t,projectRoot:r});await n.workflow.resume();let e=n.workflow.getStatus();if(e.phase!==`FINALIZE`)return Y({result:{success:!1,error:{message:`Cannot finalize: workflow is in ${e.phase} phase. Complete all subtasks first.`}},log:t,projectRoot:r});let i=await n.workflow.finalize();t.info(`Workflow finalized successfully`);let a=n.workflow.getNextAction();return Y({result:{success:!0,data:{message:`Workflow completed successfully`,...i,nextAction:a.action,nextSteps:a.nextSteps}},log:t,projectRoot:r})}catch(e){return t.error(`Error in autopilot-finalize: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to finalize workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const kt=I.object({projectRoot:I.string().describe(`Absolute path to the project root directory`)});function At(e){e.addTool({name:`autopilot_abort`,description:`Abort the current TDD workflow and clean up workflow state. This will remove the workflow state file but will NOT delete the git branch or any code changes.`,parameters:kt,annotations:{title:`Abort Autopilot Workflow`,destructiveHint:!0},execute:Q(`autopilot-abort`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Aborting autopilot workflow in ${r}`),!await n.workflow.hasWorkflow())return t.warn(`No active workflow to abort`),Y({result:{success:!0,data:{message:`No active workflow to abort`,hadWorkflow:!1}},log:t,projectRoot:r});await n.workflow.resume();let e=n.workflow.getStatus();return await n.workflow.abort(),t.info(`Workflow state deleted`),Y({result:{success:!0,data:{message:`Workflow aborted`,hadWorkflow:!0,taskId:e.taskId,branchName:e.branchName,note:`Git branch and code changes were preserved. You can manually clean them up if needed.`}},log:t,projectRoot:r})}catch(e){return t.error(`Error in autopilot-abort: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to abort workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const jt=I.object({projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),status:I.string().optional().describe(`Filter tasks by status (e.g., 'pending', 'done') or multiple statuses separated by commas (e.g., 'blocked,deferred')`),withSubtasks:I.boolean().optional().describe(`Include subtasks nested within their parent tasks in the response`),tag:I.string().optional().describe(`Tag context to operate on`)});function Mt(e){e.addTool({name:`get_tasks`,description:`Get all tasks from Task Master, optionally filtering by status and including subtasks.`,parameters:jt,annotations:{title:`Get Tasks`,readOnlyHint:!0},execute:Q(`get-tasks`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r,status:i,withSubtasks:a,tag:o}=e;try{t.info(`Getting tasks from ${r}${i?` with status filter: ${i}`:``}${o?` for tag: ${o}`:``}`);let e=i&&i!==`all`?{status:i.split(`,`).map(e=>e.trim())}:void 0,s=await n.tasks.list({tag:o,filter:e,includeSubtasks:a});t.info(`Retrieved ${s.tasks?.length||0} tasks (${s.filtered} filtered, ${s.total} total)`);let c=s.tasks??[],l=s.total,u=c.reduce((e,t)=>(e[t.status]=(e[t.status]||0)+1,e),{}),d=l>0?(u.done||0)/l*100:0,f=c.reduce((e,t)=>(t.subtasks?.forEach(t=>{e.total++,e[t.status]=(e[t.status]||0)+1}),e),{total:0}),p=f.total>0?(f.done||0)/f.total*100:0;return Y({result:{success:!0,data:{tasks:c,filter:i||`all`,stats:{total:l,completed:u.done||0,inProgress:u[`in-progress`]||0,pending:u.pending||0,blocked:u.blocked||0,deferred:u.deferred||0,cancelled:u.cancelled||0,review:u.review||0,completionPercentage:d,subtasks:{total:f.total,completed:f.done||0,inProgress:f[`in-progress`]||0,pending:f.pending||0,blocked:f.blocked||0,deferred:f.deferred||0,cancelled:f.cancelled||0,completionPercentage:p}}}},log:t,projectRoot:r,tag:s.tag})}catch(e){return t.error(`Error in get-tasks: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to get tasks: ${e.message}`}},log:t,projectRoot:r})}})})}const Nt=I.object({id:n.describe(`Task ID(s) to get (can be comma-separated for multiple tasks)`),status:I.string().optional().describe(`Filter subtasks by status (e.g., 'pending', 'done')`),projectRoot:I.string().describe(`Absolute path to the project root directory (Optional, usually from session)`),tag:I.string().optional().describe(`Tag context to operate on`)});function Pt(e){e.addTool({name:`get_task`,description:`Get detailed information about a specific task`,parameters:Nt,annotations:{title:`Get Task`,readOnlyHint:!0},execute:Q(`get-task`,async(e,{log:t,tmCore:n})=>{let{id:r,status:i,projectRoot:a,tag:o}=e;try{t.info(`Getting task details for ID: ${r}${i?` (filtering subtasks by status: ${i})`:``} in root: ${a}`);let e=l(r),s=await Promise.all(e.map(e=>n.tasks.get(e,o))),c=[];for(let e of s)if(e.task)if(i&&e.task.subtasks){let t=i.split(`,`).map(e=>e.trim().toLowerCase()),n=e.task.subtasks.filter(e=>t.includes(String(e.status).toLowerCase()));c.push({...e.task,subtasks:n})}else c.push(e.task);return c.length===0?(t.warn(`No tasks found for ID(s): ${r}`),Y({result:{success:!1,error:{message:`No tasks found for ID(s): ${r}`}},log:t,projectRoot:a})):(t.info(`Successfully retrieved ${c.length} task(s) for ID(s): ${r}`),Y({result:{success:!0,data:e.length===1?c[0]:c},log:t,projectRoot:a,tag:o}))}catch(e){return t.error(`Error in get-task: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to get task: ${e.message}`}},log:t,projectRoot:a})}})})}const Ft=I.object({output:I.string().optional().describe(`Output directory for generated files (default: same directory as 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`)});function It(e){e.addTool({name:`generate`,description:`Generates individual task files in tasks/ directory based on tasks.json. Only works with local file storage.`,parameters:Ft,annotations:{title:`Generate Task Files`,destructiveHint:!0},execute:Q(`generate`,async(e,{log:t,tmCore:n})=>{let{projectRoot:r,tag:i,output:a}=e;try{t.info(`Generating task files with args: ${JSON.stringify(e)}`);let o=a?j.resolve(r,a):void 0,s=await n.tasks.generateTaskFiles({tag:i,outputDir:o});return s.success?(t.info(`Successfully generated ${s.count} task files in ${s.directory}`),s.orphanedFilesRemoved>0&&t.info(`Removed ${s.orphanedFilesRemoved} orphaned task files`)):t.error(`Failed to generate task files: ${s.error||`Unknown error`}`),Y({result:{success:s.success,data:s.success?{message:`Successfully generated ${s.count} task file(s)`,count:s.count,directory:s.directory,orphanedFilesRemoved:s.orphanedFilesRemoved}:void 0,error:s.success?void 0:{message:s.error||`Unknown error`}},log:t,projectRoot:r,tag:i})}catch(e){return t.error(`Error in generate tool: ${e.message}`),e.stack&&t.debug(e.stack),Y({result:{success:!1,error:{message:`Failed to generate task files: ${e.message}`}},log:t,projectRoot:r})}})})}const Lt=I.object({id:n.describe(`Task ID or subtask ID (e.g., '15', '15.2'). Can be comma-separated to update multiple tasks/subtasks at once.`),status:I.enum(ee).describe(`New status to set (e.g., 'pending', 'done', 'in-progress', 'review', 'deferred', 'cancelled').`),projectRoot:I.string().describe(`The directory of the project. Must be an absolute path.`),tag:I.string().optional().describe(`Optional tag context to operate on`)});function Rt(e){e.addTool({name:`set_task_status`,description:`Set the status of one or more tasks or subtasks.`,parameters:Lt,annotations:{title:`Set Task Status`,destructiveHint:!0},execute:Q(`set-task-status`,async(e,{log:t,tmCore:n})=>{let{id:r,status:i,projectRoot:a,tag:o}=e;try{t.info(`Setting status of task(s) ${r} to: ${i}${o?` in tag: ${o}`:` in current tag`}`);let e=l(r),s=[];for(let r of e){let e=await n.tasks.updateStatus(r,i,o);s.push(e),t.info(`Updated task ${r}: ${e.oldStatus} → ${e.newStatus}`)}return t.info(`Successfully updated status for ${s.length} task(s) to "${i}"`),Y({result:{success:!0,data:{message:`Successfully updated ${s.length} task(s) to "${i}"`,tasks:s}},log:t,projectRoot:a,tag:o})}catch(e){let n=e instanceof Error?e:Error(String(e));return t.error(`Error in set-task-status: ${n.message}`),n.stack&&t.debug(n.stack),Y({result:{success:!1,error:{message:`Failed to set task status: ${n.message}`}},log:t,projectRoot:a,tag:o})}})})}async function zt(e,t){let{tasksJsonPath:n,id:r,dependsOn:i,tag:a,projectRoot:o}=e;try{if(t.info(`Adding dependency with args: ${JSON.stringify(e)}`),!n)return t.error(`addDependencyDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!r)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Task ID (id) is required`}};if(!i)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Dependency ID (dependsOn) is required`}};let s=n,c=r&&r.includes&&r.includes(`.`)?r:parseInt(r,10),l=i&&i.includes&&i.includes(`.`)?i:parseInt(i,10);return t.info(`Adding dependency: task ${c} will depend on ${l}`),x(),await Be(s,c,l,{projectRoot:o,tag:a}),v(),{success:!0,data:{message:`Successfully added dependency: Task ${c} now depends on ${l}`,taskId:c,dependencyId:l}}}catch(e){return v(),t.error(`Error in addDependencyDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Bt(e,t){let{tasksJsonPath:n,id:r,taskId:i,title:a,description:o,details:s,status:c,dependencies:l,skipGenerate:u,projectRoot:d,tag:f}=e;try{if(t.info(`Adding subtask with args: ${JSON.stringify(e)}`),!n)return t.error(`addSubtaskDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!r)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Parent task ID is required`}};if(!i&&!a)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Either taskId or title must be provided`}};let p=n,m=[];l&&(m=l.split(`,`).map(e=>e.includes(`.`)?e.trim():parseInt(e.trim(),10)));let h=i?parseInt(i,10):null,g=parseInt(r,10),_=!u;x();let y={projectRoot:d,tag:f};if(h){t.info(`Converting task ${h} to a subtask of ${g}`);let e=await ae(p,g,h,null,_,y);return v(),{success:!0,data:{message:`Task ${h} successfully converted to a subtask of task ${g}`,subtask:e}}}else{t.info(`Creating new subtask for parent task ${g}`);let e=await ae(p,g,null,{title:a,description:o||``,details:s||``,status:c||`pending`,dependencies:m},_,y);return v(),{success:!0,data:{message:`New subtask ${g}.${e.id} successfully created`,subtask:e}}}}catch(e){return v(),t.error(`Error in addSubtaskDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Vt(e,t,n={}){let{tasksJsonPath:r,name:i,copyFromCurrent:a=!1,copyFromTag:o,fromBranch:s=!1,description:c,projectRoot:l}=e,{session:u}=n;x();let d=D(t);try{if(!r)return t.error(`addTagDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(s){t.info(`Creating tag from current git branch`);let e=await import(`./git-utils-PBP1PRVP.js`);if(!await e.isGitRepository(l))return t.error(`Not in a git repository`),v(),{success:!1,error:{code:`NOT_GIT_REPO`,message:`Not in a git repository. Cannot use fromBranch option.`}};let n=await e.getCurrentBranch(l);if(!n)return t.error(`Could not determine current git branch`),v(),{success:!1,error:{code:`NO_CURRENT_BRANCH`,message:`Could not determine current git branch.`}};let i=await Pe(r,n,{copyFromCurrent:a,copyFromTag:o,description:c||`Tag created from git branch "${n}"`},{session:u,mcpLog:d,projectRoot:l},`json`);return v(),{success:!0,data:{branchName:i.branchName,tagName:i.tagName,created:i.created,mappingUpdated:i.mappingUpdated,message:`Successfully created tag "${i.tagName}" from git branch "${i.branchName}"`}}}else{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(`Creating new tag: ${i}`);let e=await De(r,i,{copyFromCurrent:a,copyFromTag:o,description:c},{session:u,mcpLog:d,projectRoot:l},`json`);return v(),{success:!0,data:{tagName:e.tagName,created:e.created,tasksCopied:e.tasksCopied,sourceTag:e.sourceTag,description:e.description,message:`Successfully created tag "${e.tagName}"`}}}}catch(e){return v(),t.error(`Error in addTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`ADD_TAG_ERROR`,message:e.message}}}}async function Ht(e,t,n={}){let{tasksJsonPath:r,prompt:i,dependencies:a,priority:o,research:s,projectRoot:c,tag:l}=e,{session:u}=n;x();let d=D(t);try{if(!r)return t.error(`addTaskDirect called without tasksJsonPath`),v(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let n=r,f=e.title&&e.description;if(!e.prompt&&!f)return t.error(`Missing required parameters: either prompt or title+description must be provided`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Either the prompt parameter or both title and description parameters are required for adding a task`}};let p=Array.isArray(a)?a:a?String(a).split(`,`).map(e=>parseInt(e.trim(),10)):[],m=o||`medium`,h=null,g,_,y;if(f){h={title:e.title,description:e.description,details:e.details||``,testStrategy:e.testStrategy||``},t.info(`Adding new task manually with title: "${e.title}", dependencies: [${p.join(`, `)}], priority: ${o}`);let r=await ve(n,null,p,m,{session:u,mcpLog:d,projectRoot:c,commandName:`add-task`,outputType:`mcp`,tag:l},`json`,h,!1);g=r.newTaskId,_=r.telemetryData,y=r.tagInfo}else{t.info(`Adding new task with prompt: "${i}", dependencies: [${p.join(`, `)}], priority: ${m}, research: ${s}`);let e=await ve(n,i,p,m,{session:u,mcpLog:d,projectRoot:c,commandName:`add-task`,outputType:`mcp`,tag:l},`json`,null,s);g=e.newTaskId,_=e.telemetryData,y=e.tagInfo}return v(),{success:!0,data:{taskId:g,message:`Successfully added new task #${g}`,telemetryData:_,tagInfo:y}}}catch(e){return v(),t.error(`Error in addTaskDirect: ${e.message}`),{success:!1,error:{code:e.code||`ADD_TASK_ERROR`,message:e.message}}}}async function Ut(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,outputPath:a,threshold:o,research:s,projectRoot:c,ids:l,from:u,to:d,tag:f}=e,p=D(t);try{if(t.info(`Analyzing task complexity with args: ${JSON.stringify(e)}`),!i)return t.error(`analyzeTaskComplexityDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a)return t.error(`analyzeTaskComplexityDirect called without outputPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`outputPath is required`}};let n=i,m=a;if(t.info(`Analyzing task complexity from: ${n}`),t.info(`Output report will be saved to: ${m}`),l)t.info(`Analyzing specific task IDs: ${l}`);else if(u||d){let e=u===void 0?`first`:u,n=d===void 0?`last`:d;t.info(`Analyzing tasks in range: ${e} to ${n}`)}s&&t.info(`Using research role for complexity analysis`);let h={file:i,output:a,threshold:o,research:s===!0,projectRoot:c,id:l,from:u,to:d,tag:f},g=w();g||x();let _;try{_=await Te(h,{session:r,mcpLog:p,commandName:`analyze-complexity`,outputType:`mcp`,projectRoot:c,tag:f}),_.report}catch(e){return t.error(`Error in analyzeTaskComplexity core function: ${e.message}`),!g&&w()&&v(),{success:!1,error:{code:`ANALYZE_CORE_ERROR`,message:`Error running core complexity analysis: ${e.message}`}}}finally{!g&&w()&&v()}if(!N.existsSync(m))return{success:!1,error:{code:`ANALYZE_REPORT_MISSING`,message:`Analysis completed but no report file was created at the expected path.`}};if(!_||!_.report||typeof _.report!=`object`)return t.error(`Core analysis function returned an invalid or undefined response.`),{success:!1,error:{code:`INVALID_CORE_RESPONSE`,message:`Core analysis function returned an invalid response.`}};try{let e=Array.isArray(_.report.complexityAnalysis)?_.report.complexityAnalysis:[],t=e.filter(e=>e.complexityScore>=8).length,n=e.filter(e=>e.complexityScore>=5&&e.complexityScore<8).length,r=e.filter(e=>e.complexityScore<5).length;return{success:!0,data:{message:`Task complexity analysis complete. Report saved to ${a}`,reportPath:a,reportSummary:{taskCount:e.length,highComplexityTasks:t,mediumComplexityTasks:n,lowComplexityTasks:r},fullReport:_.report,telemetryData:_.telemetryData,tagInfo:_.tagInfo}}}catch(e){return t.error(`Internal error processing report data: ${e.message}`),{success:!1,error:{code:`REPORT_PROCESS_ERROR`,message:`Internal error processing complexity report: ${e.message}`}}}}catch(e){return w()&&v(),t.error(`Error in analyzeTaskComplexityDirect setup: ${e.message}`),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message}}}}async function Wt(e,t){let{tasksJsonPath:n,id:r,all:i,tag:a,projectRoot:o}=e;try{if(t.info(`Clearing subtasks with args: ${JSON.stringify(e)}`),!n)return t.error(`clearSubtasksDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!r&&!i)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Either task IDs with id parameter or all parameter must be provided`}};let s=n;if(!N.existsSync(s))return{success:!1,error:{code:`FILE_NOT_FOUND_ERROR`,message:`Tasks file not found at ${s}`}};let c,l=f(s,o,a);if(!l||!l.tasks)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`No tasks found in tasks file: ${s}`}};let u=l.tag||a,d=l.tasks;if(i){if(t.info(`Clearing subtasks from all tasks in tag '${u}'`),d.length===0)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`No tasks found in tag context '${u}'`}};c=d.map(e=>e.id).join(`,`)}else c=r;t.info(`Clearing subtasks from tasks: ${c} in tag '${u}'`),x(),Ce(s,c,{projectRoot:o,tag:u}),v();let p=f(s,o,u),m=c.split(`,`).map(e=>parseInt(e.trim(),10)),h=m.length,g=p.tasks||[],_=m.map(e=>{let t=g.find(t=>t.id===e);return t?{id:e,title:t.title}:{id:e,title:`Task not found`}});return{success:!0,data:{message:`Successfully cleared subtasks from ${h} task(s) in tag '${u}'`,tasksCleared:_,tag:u}}}catch(e){return v(),t.error(`Error in clearSubtasksDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Gt(e,t){let{reportPath:n}=e;try{if(t.info(`Getting complexity report with args: ${JSON.stringify(e)}`),!n)return t.error(`complexityReportDirect called without reportPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`reportPath is required`}};t.info(`Looking for complexity report at: ${n}`),`${n}`;let r=async()=>{try{x();let e=T(n);return v(),e?{success:!0,data:{report:e,reportPath:n}}:(t.warn(`No complexity report found at ${n}`),{success:!1,error:{code:`FILE_NOT_FOUND_ERROR`,message:`No complexity report found at ${n}. Run 'analyze-complexity' first.`}})}catch(e){return v(),t.error(`Error reading complexity report: ${e.message}`),{success:!1,error:{code:`READ_ERROR`,message:e.message}}}};try{let e=await r();return t.info(`complexityReportDirect completed`),e}catch(e){return v(),t.error(`Unexpected error during complexityReport: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}catch(e){return v(),t.error(`Error in complexityReportDirect: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}async function Kt(e,t,n={}){let{tasksJsonPath:r,sourceName:i,targetName:a,description:o,projectRoot:s}=e,{session:c}=n;x();let l=D(t);try{if(!r)return t.error(`copyTagDirect 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: sourceName`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Source tag name is required and must be a string`}};if(!a||typeof a!=`string`)return t.error(`Missing required parameter: targetName`),v(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Target tag name is required and must be a string`}};t.info(`Copying tag from "${i}" to "${a}"`);let e=await ze(r,i,a,{description:o},{session:c,mcpLog:l,projectRoot:s},`json`);return v(),{success:!0,data:{sourceName:e.sourceName,targetName:e.targetName,copied:e.copied,tasksCopied:e.tasksCopied,description:e.description,message:`Successfully copied tag from "${e.sourceName}" to "${e.targetName}"`}}}catch(e){return v(),t.error(`Error in copyTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`COPY_TAG_ERROR`,message:e.message}}}}async function qt(e,t,n={}){let{tasksJsonPath:r,name:i,yes:a=!1,projectRoot:o}=e,{session:s}=n;x();let c=D(t);try{if(!r)return t.error(`deleteTagDirect 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(`Deleting tag: ${i}`);let e=await Ve(r,i,{yes:a},{session:s,mcpLog:c,projectRoot:o},`json`);return v(),{success:!0,data:{tagName:e.tagName,deleted:e.deleted,tasksDeleted:e.tasksDeleted,wasCurrentTag:e.wasCurrentTag,switchedToMaster:e.switchedToMaster,message:`Successfully deleted tag "${e.tagName}"`}}}catch(e){return v(),t.error(`Error in deleteTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`DELETE_TAG_ERROR`,message:e.message}}}}async function Jt(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,num:a,research:o,prompt:s,force:c,projectRoot:l,tag:u,complexityReportPath:d}=e,f=D(t),p=d||C(null,{projectRoot:l,tag:u},t);if(t.info(`Expand all tasks will use complexity report at: ${p}`),!i)return t.error(`expandAllTasksDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};x();try{t.info(`Calling core expandAllTasks with args: ${JSON.stringify({num:a,research:o,prompt:s,force:c,projectRoot:l,tag:u})}`);let e=await pe(i,a?parseInt(a,10):void 0,o===!0,s||``,c===!0,{session:r,mcpLog:f,projectRoot:l,tag:u,complexityReportPath:p},`json`);return{success:!0,data:{message:`Expand all operation completed. Expanded: ${e.expandedCount}, Failed: ${e.failedCount}, Skipped: ${e.skippedCount}`,details:{expandedCount:e.expandedCount,failedCount:e.failedCount,skippedCount:e.skippedCount,tasksToExpand:e.tasksToExpand},telemetryData:e.telemetryData}}}catch(e){return t.error(`Error during core expandAllTasks execution: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}finally{v()}}async function Yt(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,id:a,num:o,research:c,prompt:l,force:u,projectRoot:d,tag:p,complexityReportPath:m}=e;if(t.info(`Session data in expandTaskDirect: ${JSON.stringify({hasSession:!!r,sessionKeys:r?Object.keys(r):[],roots:r?.roots,rootsStr:JSON.stringify(r?.roots)})}`),!i)return t.error(`expandTaskDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let h=i;t.info(`[expandTaskDirect] Using tasksPath: ${h}`);let g=a?parseInt(a,10):null;if(!g)return t.error(`Task ID is required`),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Task ID is required`}};let _=o?parseInt(o,10):void 0,y=c===!0,b=l||``,S=u===!0;try{t.info(`[expandTaskDirect] Expanding task ${g} into ${_||`default`} subtasks. Research: ${y}, Force: ${S}`),t.info(`[expandTaskDirect] Attempting to read JSON from: ${h}`);let e=f(h,d);if(t.info(`[expandTaskDirect] Result of readJSON: ${e?`Data read successfully`:`readJSON returned null or undefined`}`),!e||!e.tasks)return t.error(`[expandTaskDirect] readJSON failed or returned invalid data for path: ${h}`),{success:!1,error:{code:`INVALID_TASKS_FILE`,message:`No valid tasks found in ${h}. readJSON returned: ${JSON.stringify(e)}`}};t.info(`[expandTaskDirect] Searching for task ID ${g} in data`);let n=e.tasks.find(e=>e.id===g);if(t.info(`[expandTaskDirect] Task found: ${n?`Yes`:`No`}`),!n)return{success:!1,error:{code:`TASK_N