taskgraph-ai 0.49.1 → 0.52.6

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.
Files changed (41) hide show
  1. package/README.md +76 -32
  2. package/dist/ai-services-unified-BbSRBK0N.js +3 -0
  3. package/dist/ai-services-unified-CQMZv2X-.js +1 -0
  4. package/dist/assets/AGENTS.md +12 -31
  5. package/dist/assets/example_prd_rpg.txt +1 -4
  6. package/dist/assets/scripts_README.md +12 -14
  7. package/dist/commands-DOZyxFfM.js +231 -0
  8. package/dist/config-manager-BsUS_HoV.js +1 -0
  9. package/dist/config-manager-CKzRb4tZ.js +1 -0
  10. package/dist/dependency-manager-BcQJdp1Y.js +971 -0
  11. package/dist/git-utils--i2q96hv.js +1 -0
  12. package/dist/git-utils-BezpEZd4.js +1 -0
  13. package/dist/{init-wtXaFE45.js → init-S96FNSm7.js} +65 -389
  14. package/dist/mcp-server.js +6 -6
  15. package/dist/research-cdWIHSpn.js +1 -0
  16. package/dist/response-language-Bjbf2_9z.js +1 -0
  17. package/dist/{response-language-BHhde6n_.js → response-language-Ln6H6G2z.js} +1 -1
  18. package/dist/src-Cio2Sps9.js +207 -0
  19. package/dist/tag-management-BzAE-dVv.js +1 -0
  20. package/dist/task-manager-Utma-ZPy.js +1 -0
  21. package/dist/taskgraph.js +1 -1
  22. package/dist/update-subtask-by-id-UcjCRJbf.js +1 -0
  23. package/dist/update-task-by-id-98Q5zy74.js +1 -0
  24. package/dist/utils-BzS6gmZZ.js +1 -0
  25. package/package.json +16 -30
  26. package/dist/ai-services-unified--6CT6QUI.js +0 -1
  27. package/dist/ai-services-unified-D8PahWkz.js +0 -3
  28. package/dist/commands-CceFmRJA.js +0 -230
  29. package/dist/config-manager-CvDCaURh.js +0 -1
  30. package/dist/config-manager-DD5sEcpv.js +0 -270
  31. package/dist/dependency-manager-B7SaMC6u.js +0 -966
  32. package/dist/git-utils-DllbRE35.js +0 -1
  33. package/dist/git-utils-PBP1PRVP.js +0 -1
  34. package/dist/research-BRpAIbWg.js +0 -1
  35. package/dist/response-language-Dz-rFnaJ.js +0 -1
  36. package/dist/sentry-DNoFrfjb.js +0 -1
  37. package/dist/tag-management-BEKnBGXA.js +0 -1
  38. package/dist/task-manager-BQkOlw_W.js +0 -1
  39. package/dist/update-subtask-by-id-BOFRADbR.js +0 -1
  40. package/dist/update-task-by-id-DTHqRii_.js +0 -1
  41. package/dist/utils-DYpucGVy.js +0 -1
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
- import"./ai-services-unified-D8PahWkz.js";import{$t as e,B as t,Bt as n,Ft as r,G as i,Gt as a,I as o,K as s,Kt as c,Ot as l,P as u,Qt as d,R as f,Ut as p,Vt as m,Xt as h,_t as g,an as _,c as v,et as y,ft as b,jt as x,lt as S,nn as ee,on as C,p as te,rt as w,un as ne,ut as T,wt as re,z as E}from"./config-manager-DD5sEcpv.js";import"./git-utils-DllbRE35.js";import{r as ie}from"./sentry-DNoFrfjb.js";import{$ as ae,A as oe,B as se,C as ce,D as le,E as ue,F as de,H as D,J as fe,K as pe,M as me,N as he,P as ge,Q as _e,R as ve,S as ye,U as O,V as be,X as xe,Z as Se,at as Ce,et as we,i as Te,it as Ee,j as De,k as Oe,n as ke,nt as Ae,q as je,r as Me,t as Ne,x as Pe,z as Fe}from"./dependency-manager-B7SaMC6u.js";import{t as Ie}from"./response-language-BHhde6n_.js";import{n as k,t as Le}from"./init-wtXaFE45.js";import A from"chalk";import j from"node:path";import M from"fs";import N from"path";import Re from"os";import P from"node:fs";import{z as F}from"zod";import"child_process";import I from"dotenv";import*as L from"@sentry/node";import{fileURLToPath as R}from"url";import{FastMCP as ze}from"fastmcp";import{LRUCache as Be}from"lru-cache";const z={debug:0,info:1,warn:2,error:3,success:4},Ve=z[te().toLowerCase()]??z.info;function B(e,...t){if(w())return;let n={debug:A.dim(`[DEBUG]`),info:A.blue(`[INFO]`),warn:A.yellow(`[WARN]`),error:A.red(`[ERROR]`),success:A.green(`[SUCCESS]`)};if(z[e]!==void 0&&z[e]>=Ve){let r=n[e]||``,i=t;try{switch(e){case`error`:i=t.map(e=>typeof e==`string`?A.red(e):e);break;case`warn`:i=t.map(e=>typeof e==`string`?A.yellow(e):e);break;case`success`:i=t.map(e=>typeof e==`string`?A.green(e):e);break;case`info`:i=t.map(e=>typeof e==`string`?A.blue(e):e);break;case`debug`:i=t.map(e=>typeof e==`string`?A.dim(e):e);break}}catch(e){console.error(`Internal Logger Error applying chalk color:`,e),i=t}console.error(r,...i)}}function He(){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=He();function H(){return{version:C||`unknown`,name:_||`taskgraph-ai`}}function U(e,t,n){t||=H();let r=`Error: ${e}
2
+ import{C as e,S as t,_ as n,a as r,b as i,i as a,p as o,u as s,v as c,x as l}from"./src-Cio2Sps9.js";import{Et as u,I as d,L as f,M as p,Nt as m,P as h,Q as g,R as _,St as v,U as y,W as b,ct as x,f as ee,ht as te,kt as ne,s as re,st as S,tt as C,ut as w}from"./config-manager-CKzRb4tZ.js";import{$ as ie,A as ae,B as oe,C as se,D as ce,E as le,F as ue,H as T,J as de,K as fe,M as pe,N as me,P as he,Q as ge,R as _e,S as ve,U as E,V as ye,X as be,Z as xe,at as Se,et as Ce,i as we,it as Te,j as Ee,k as De,n as Oe,nt as ke,q as Ae,r as je,t as Me,x as Ne,z as Pe}from"./dependency-manager-BcQJdp1Y.js";import{t as Fe}from"./response-language-Ln6H6G2z.js";import{n as D,t as Ie}from"./init-S96FNSm7.js";import O from"chalk";import k from"node:path";import A from"path";import{z as j}from"zod";import M from"node:fs";import N from"dotenv";import P from"fs";import{fileURLToPath as F}from"url";import{FastMCP as Le}from"fastmcp";import Re from"os";import{LRUCache as ze}from"lru-cache";const I={debug:0,info:1,warn:2,error:3,success:4},Be=I[ee().toLowerCase()]??I.info;function L(e,...t){if(C())return;let n={debug:O.dim(`[DEBUG]`),info:O.blue(`[INFO]`),warn:O.yellow(`[WARN]`),error:O.red(`[ERROR]`),success:O.green(`[SUCCESS]`)};if(I[e]!==void 0&&I[e]>=Be){let r=n[e]||``,i=t;try{switch(e){case`error`:i=t.map(e=>typeof e==`string`?O.red(e):e);break;case`warn`:i=t.map(e=>typeof e==`string`?O.yellow(e):e);break;case`success`:i=t.map(e=>typeof e==`string`?O.green(e):e);break;case`info`:i=t.map(e=>typeof e==`string`?O.blue(e):e);break;case`debug`:i=t.map(e=>typeof e==`string`?O.dim(e):e)}}catch(e){console.error(`Internal Logger Error applying chalk color:`,e),i=t}console.error(r,...i)}}function Ve(){let e=e=>(...t)=>L(e,...t);return{debug:e(`debug`),info:e(`info`),warn:e(`warn`),error:e(`error`),success:e(`success`),log:L}}const R=Ve();function z(){return{version:c||`unknown`,name:n||`taskgraph-ai`}}function B(e,t,n){t||=z();let r=`Error: ${e}
3
3
  Version: ${t.version}
4
4
  Name: ${t.name}`;return n&&(r+=`
5
- Current Tag: ${n.currentTag}`),{content:[{type:`text`,text:r}],isError:!0}}function Ue(e,t){if(typeof e!=`function`){t?.debug?.(`reportProgress not available - operation will run without progress updates`);return}return e}function We(e){try{let t=j.join(e,`.taskgraph`,`state.json`);return P.existsSync(t)&&JSON.parse(P.readFileSync(t,`utf-8`)).currentTag||`master`}catch{return null}}async function W(e){let{result:t,log:n,errorPrefix:r=`API error`,projectRoot:i,tag:a}=e,o=H(),s=a===void 0?i?We(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 G(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 Ge(e){try{return e?.roots?.[0]?.uri?G(e.roots[0].uri):e?.roots?.roots?.[0]?.uri?G(e.roots.roots[0].uri):null}catch{return null}}function K(e){return async(t,n)=>{let{log:r,session:i}=n,a=null,o=`unknown`;try{if(process.env.TASKGRAPH_PROJECT_ROOT){let e=process.env.TASKGRAPH_PROJECT_ROOT;a=j.isAbsolute(e)?e:j.resolve(process.cwd(),e),o=`TASKGRAPH_PROJECT_ROOT environment variable`,r?.info?.(`Using project root from ${o}: ${a}`)}else if(i?.env?.TASKGRAPH_PROJECT_ROOT){let e=i.env.TASKGRAPH_PROJECT_ROOT;a=j.isAbsolute(e)?e:j.resolve(process.cwd(),e),o=`TASKGRAPH_PROJECT_ROOT session environment variable`,r?.info?.(`Using project root from ${o}: ${a}`)}else if(t.projectRoot)a=G(t.projectRoot),o=`args.projectRoot`,r?.info?.(`Using project root from ${o}: ${a}`);else{let e=Ge(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.`),W({result:{success:!1,error:{message:`Could not determine project root. Please provide projectRoot argument or ensure TASKGRAPH_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),W({result:{success:!1,error:{message:`Operation failed: ${e.message}`}}})}}}function q(e,t){return K(async(n,r)=>{let i=j.join(n.projectRoot,`.env`);P.existsSync(i)&&I.config({path:i,quiet:!0});let a=await h({projectPath:n.projectRoot,loggerConfig:{mcpMode:!0,logCallback:r.log}});if(ne.includes(e)){let t=await a.auth.guardCommand(e,a.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 r.log.info(e),W({result:{success:!1,error:{message:e}},log:r.log,projectRoot:n.projectRoot})}}return t(n,{log:r.log,session:r.session,tmCore:a})})}function J(e,t){if(!e)return{parsedMetadata:null};if(process.env.TASKGRAPH_ALLOW_METADATA_UPDATES!==`true`)return{parsedMetadata:null,error:t(`Metadata updates are disabled. Set TASKGRAPH_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 Ke=F.object({taskId:p.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:F.string().describe(`Absolute path to the project root directory`),maxAttempts:F.number().optional().default(3).describe(`Maximum attempts per subtask (default: 3)`),force:F.boolean().optional().default(!1).describe(`Force start even if workflow state exists`)});function qe(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:Ke,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=c(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 W({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 W({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`),W({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 W({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),W({result:{success:!1,error:{message:`Failed to start workflow: ${e.message}`}},log:t,projectRoot:i})}})})}const Je=F.object({projectRoot:F.string().describe(`Absolute path to the project root directory`)});function Ye(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:Je,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 W({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}`),W({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),W({result:{success:!1,error:{message:`Failed to resume workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const Xe=F.object({projectRoot:F.string().describe(`Absolute path to the project root directory`)});function Ze(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:Xe,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 W({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}`),W({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),W({result:{success:!1,error:{message:`Failed to get next action: ${e.message}`}},log:t,projectRoot:r})}})})}const Qe=F.object({projectRoot:F.string().describe(`Absolute path to the project root directory`)});function $e(e){e.addTool({name:`autopilot_status`,description:`Get comprehensive workflow status including current phase, progress, subtask details, and activity history.`,parameters:Qe,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 W({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}`),W({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),W({result:{success:!1,error:{message:`Failed to get workflow status: ${e.message}`}},log:t,projectRoot:r})}})})}const et=F.object({projectRoot:F.string().describe(`Absolute path to the project root directory`),testResults:F.object({total:F.number().describe(`Total number of tests`),passed:F.number().describe(`Number of passing tests`),failed:F.number().describe(`Number of failing tests`),skipped:F.number().optional().describe(`Number of skipped tests`)}).describe(`Test results from running the test suite`)});function tt(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:et,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 W({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 W({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 W({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}`),W({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),W({result:{success:!1,error:{message:`Failed to complete phase: ${e.message}`}},log:t,projectRoot:r})}})})}const nt=F.object({projectRoot:F.string().describe(`Absolute path to the project root directory`),files:F.array(F.string()).optional().describe(`Specific files to stage (relative to project root). If not provided, stages all changes.`),customMessage:F.string().optional().describe(`Custom commit message to use instead of auto-generated message`)});function rt(t){t.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:nt,annotations:{title:`Commit Autopilot Changes`,destructiveHint:!0},execute:q(`autopilot-commit`,async(t,{log:n,tmCore:r})=>{let{projectRoot:i,files:a,customMessage:o}=t;try{if(n.info(`Creating commit for workflow in ${i}`),!await r.workflow.hasWorkflow())return W({result:{success:!1,error:{message:`No active workflow found. Start a workflow with autopilot_start`}},log:n,projectRoot:i});await r.workflow.resume();let t=r.workflow.getStatus(),s=r.workflow.getContext();if(t.tddPhase!==`COMMIT`)return n.warn(`Not in COMMIT phase (currently in ${t.tddPhase})`),W({result:{success:!1,error:{message:`Cannot commit: currently in ${t.tddPhase} phase. Complete the ${t.tddPhase} phase first using autopilot_complete_phase`}},log:n,projectRoot:i});if(!t.currentSubtask)return W({result:{success:!1,error:{message:`No active subtask to commit`}},log:n,projectRoot:i});let c=new e(i);try{a&&a.length>0?(await c.stageFiles(a),n.info(`Staged ${a.length} files`)):(await c.stageFiles([`.`]),n.info(`Staged all changes`))}catch(e){return n.error(`Failed to stage files: ${e.message}`),W({result:{success:!1,error:{message:`Failed to stage files: ${e.message}`}},log:n,projectRoot:i})}if(!await c.hasStagedChanges())return n.warn(`No staged changes to commit`),W({result:{success:!1,error:{message:`No staged changes to commit. Make code changes before committing`}},log:n,projectRoot:i});let l=await c.getStatus(),u;if(o)u=o,n.info(`Using custom commit message`);else{let e=new d,r={type:t.tddPhase===`COMMIT`?`feat`:`test`,description:t.currentSubtask.title,changedFiles:l.staged,taskId:t.taskId,phase:t.tddPhase,testsPassing:s.lastTestResults?.passed,testsFailing:s.lastTestResults?.failed};u=e.generateMessage(r),n.info(`Generated commit message automatically`)}try{await c.createCommit(u),n.info(`Commit created successfully`)}catch(e){return n.error(`Failed to create commit: ${e.message}`),W({result:{success:!1,error:{message:`Failed to create commit: ${e.message}`}},log:n,projectRoot:i})}let f=await c.getLastCommit(),p=await r.workflow.commit();n.info(`Commit completed. Current phase: ${p.tddPhase||p.phase}`);let m=p.phase===`COMPLETE`,h=r.workflow.getNextAction();return W({result:{success:!0,data:{message:m?`Workflow completed successfully`:`Commit created and workflow advanced`,commitSha:f.sha,commitMessage:u,...p,isComplete:m,nextAction:h.action,nextSteps:h.nextSteps}},log:n,projectRoot:i})}catch(e){return n.error(`Error in autopilot-commit: ${e.message}`),e.stack&&n.debug(e.stack),W({result:{success:!1,error:{message:`Failed to commit: ${e.message}`}},log:n,projectRoot:i})}})})}const it=F.object({projectRoot:F.string().describe(`Absolute path to the project root directory`)});function at(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:it,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 W({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 W({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 W({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),W({result:{success:!1,error:{message:`Failed to finalize workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const ot=F.object({projectRoot:F.string().describe(`Absolute path to the project root directory`)});function st(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:ot,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`),W({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`),W({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),W({result:{success:!1,error:{message:`Failed to abort workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const ct=F.object({projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),status:F.string().optional().describe(`Filter tasks by status (e.g., 'pending', 'done') or multiple statuses separated by commas (e.g., 'blocked,deferred')`),withSubtasks:F.boolean().optional().describe(`Include subtasks nested within their parent tasks in the response`),tag:F.string().optional().describe(`Tag context to operate on`)});function lt(e){e.addTool({name:`get_tasks`,description:`Get all tasks from TaskGraph, optionally filtering by status and including subtasks.`,parameters:ct,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 W({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),W({result:{success:!1,error:{message:`Failed to get tasks: ${e.message}`}},log:t,projectRoot:r})}})})}const ut=F.object({id:m.describe(`Task ID(s) to get (can be comma-separated for multiple tasks)`),status:F.string().optional().describe(`Filter subtasks by status (e.g., 'pending', 'done')`),projectRoot:F.string().describe(`Absolute path to the project root directory (Optional, usually from session)`),tag:F.string().optional().describe(`Tag context to operate on`)});function dt(e){e.addTool({name:`get_task`,description:`Get detailed information about a specific task`,parameters:ut,annotations:{title:`Get Task`,readOnlyHint:!0},execute:q(`get-task`,async(e,{log:t,tmCore:r})=>{let{id:i,status:a,projectRoot:o,tag:s}=e;try{t.info(`Getting task details for ID: ${i}${a?` (filtering subtasks by status: ${a})`:``} in root: ${o}`);let e=n(i),c=await Promise.all(e.map(e=>r.tasks.get(e,s))),l=[];for(let e of c)if(e.task)if(a&&e.task.subtasks){let t=a.split(`,`).map(e=>e.trim().toLowerCase()),n=e.task.subtasks.filter(e=>t.includes(String(e.status).toLowerCase()));l.push({...e.task,subtasks:n})}else l.push(e.task);return l.length===0?(t.warn(`No tasks found for ID(s): ${i}`),W({result:{success:!1,error:{message:`No tasks found for ID(s): ${i}`}},log:t,projectRoot:o})):(t.info(`Successfully retrieved ${l.length} task(s) for ID(s): ${i}`),W({result:{success:!0,data:e.length===1?l[0]:l},log:t,projectRoot:o,tag:s}))}catch(e){return t.error(`Error in get-task: ${e.message}`),e.stack&&t.debug(e.stack),W({result:{success:!1,error:{message:`Failed to get task: ${e.message}`}},log:t,projectRoot:o})}})})}const ft=F.object({output:F.string().optional().describe(`Output directory for generated files (default: same directory as tasks file)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)});function pt(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`}`),W({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),W({result:{success:!1,error:{message:`Failed to generate task files: ${e.message}`}},log:t,projectRoot:r})}})})}const mt=F.object({id:m.describe(`Task ID or subtask ID (e.g., '15', '15.2'). Can be comma-separated to update multiple tasks/subtasks at once.`),status:F.enum(ee).describe(`New status to set (e.g., 'pending', 'done', 'in-progress', 'review', 'deferred', 'cancelled').`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Optional tag context to operate on`)});function ht(e){e.addTool({name:`set_task_status`,description:`Set the status of one or more tasks or subtasks.`,parameters:mt,annotations:{title:`Set Task Status`,destructiveHint:!0},execute:q(`set-task-status`,async(e,{log:t,tmCore:r})=>{let{id:i,status:a,projectRoot:o,tag:s}=e;try{t.info(`Setting status of task(s) ${i} to: ${a}${s?` in tag: ${s}`:` in current tag`}`);let e=n(i),c=[];for(let n of e){let e=await r.tasks.updateStatus(n,a,s);c.push(e),t.info(`Updated task ${n}: ${e.oldStatus} → ${e.newStatus}`)}return t.info(`Successfully updated status for ${c.length} task(s) to "${a}"`),W({result:{success:!0,data:{message:`Successfully updated ${c.length} task(s) to "${a}"`,tasks:c}},log:t,projectRoot:o,tag:s})}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),W({result:{success:!1,error:{message:`Failed to set task status: ${n.message}`}},log:t,projectRoot:o,tag:s})}})})}async function gt(e,t){let{tasksJsonPath:n,id:r,dependsOn:a,tag:o,projectRoot:c}=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(!a)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Dependency ID (dependsOn) is required`}};let l=n,u=r&&r.includes&&r.includes(`.`)?r:parseInt(r,10),d=a&&a.includes&&a.includes(`.`)?a:parseInt(a,10);return t.info(`Adding dependency: task ${u} will depend on ${d}`),s(),await Ne(l,u,d,{projectRoot:c,tag:o}),i(),{success:!0,data:{message:`Successfully added dependency: Task ${u} now depends on ${d}`,taskId:u,dependencyId:d}}}catch(e){return i(),t.error(`Error in addDependencyDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function _t(e,t){let{tasksJsonPath:n,id:r,taskId:a,title:o,description:c,details:l,status:u,dependencies:d,skipGenerate:f,projectRoot:p,tag:m}=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(!a&&!o)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Either taskId or title must be provided`}};let h=n,g=[];d&&(g=d.split(`,`).map(e=>e.includes(`.`)?e.trim():parseInt(e.trim(),10)));let _=a?parseInt(a,10):null,v=parseInt(r,10),y=!f;s();let b={projectRoot:p,tag:m};if(_){t.info(`Converting task ${_} to a subtask of ${v}`);let e=await O(h,v,_,null,y,b);return i(),{success:!0,data:{message:`Task ${_} successfully converted to a subtask of task ${v}`,subtask:e}}}else{t.info(`Creating new subtask for parent task ${v}`);let e=await O(h,v,null,{title:o,description:c||``,details:l||``,status:u||`pending`,dependencies:g},y,b);return i(),{success:!0,data:{message:`New subtask ${v}.${e.id} successfully created`,subtask:e}}}}catch(e){return i(),t.error(`Error in addSubtaskDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}new class{constructor(e={}){this.config={maxCacheSize:e.maxCacheSize||1e3,ttl:e.ttl||1e3*60*5,maxContextSize:e.maxContextSize||4e3},this.cache=new Be({max:this.config.maxCacheSize,ttl:this.config.ttl,updateAgeOnGet:!0}),this.stats={hits:0,misses:0,invalidations:0}}async getContext(e,t={}){let n=this._getCacheKey(e,t),r=this.cache.get(n);if(r)return this.stats.hits++,r;this.stats.misses++;let i={id:e,metadata:{...t,created:new Date().toISOString()}};return this.cache.set(n,i),i}async updateContext(e,t){let n=await this.getContext(e);Object.assign(n.metadata,t);let r=this._getCacheKey(e,n.metadata);return this.cache.set(r,n),n}invalidateContext(e,t={}){let n=this._getCacheKey(e,t);this.cache.delete(n),this.stats.invalidations++}getCachedData(e){let t=this.cache.get(e);if(t!==void 0)return this.stats.hits++,t;this.stats.misses++}setCachedData(e,t){this.cache.set(e,t)}invalidateCacheKey(e){this.cache.delete(e),this.stats.invalidations++}getStats(){return{hits:this.stats.hits,misses:this.stats.misses,invalidations:this.stats.invalidations,size:this.cache.size,maxSize:this.config.maxCacheSize,ttl:this.config.ttl}}_getCacheKey(e,t){return`${e}:${JSON.stringify(t)}`}};const Y={info:()=>{},warn:()=>{},error:()=>{},debug:()=>{},success:()=>{}};function X(e,t=Y){let n=e?.file,r=e?.projectRoot;if(n&&N.isAbsolute(n))return n;let i=r?E(r):null;if(n&&i)return N.resolve(i,n);if(i){let e=f(n,{projectRoot:i},t);if(e===null&&!n){let e=N.join(i,`.taskgraph`,`tasks`,`tasks.json`);return t?.info?.(`Core findTasksPath returned null, using default path: ${e}`),e}return e}return f(n,null,t)}function vt(e,t=Y){let n=e?.input,r=e?.projectRoot;if(n&&N.isAbsolute(n))return n;let i=r?E(r):null;return n&&i?N.resolve(i,n):i?o(n,{projectRoot:i},t):o(n,null,t)}function yt(e,t=Y){let n=e?.complexityReport,r=e?.projectRoot,i=e?.tag;if(n&&N.isAbsolute(n))return n;let a=r?E(r):null;return n&&a?N.resolve(a,n):a?u(n,{projectRoot:a,tag:i},t):u(n,null,t)}function bt(e,t){if(!t?.projectRoot)throw Error(`projectRoot is required in args to resolve project paths`);let n=E(t.projectRoot);return N.isAbsolute(e)?e:N.resolve(n,e)}function Z(e,t=Y){return X(e,t)}function xt(e,t=Y){return yt(e,t)}function St(e,n,r=Y){return t(e,n,r)}R(import.meta.url);function Q(e){return{info:(t,...n)=>e.info(t,...n),warn:(t,...n)=>e.warn(t,...n),error:(t,...n)=>e.error(t,...n),debug:(t,...n)=>e.debug?e.debug(t,...n):null,success:(t,...n)=>e.info(t,...n)}}async function Ct(e,t,n={}){let{tasksJsonPath:r,name:a,copyFromCurrent:o=!1,copyFromTag:c,fromBranch:l=!1,description:u,projectRoot:d}=e,{session:f}=n;s();let p=Q(t);try{if(!r)return t.error(`addTagDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(l){t.info(`Creating tag from current git branch`);let e=await import(`./git-utils-PBP1PRVP.js`);if(!await e.isGitRepository(d))return t.error(`Not in a git repository`),i(),{success:!1,error:{code:`NOT_GIT_REPO`,message:`Not in a git repository. Cannot use fromBranch option.`}};let n=await e.getCurrentBranch(d);if(!n)return t.error(`Could not determine current git branch`),i(),{success:!1,error:{code:`NO_CURRENT_BRANCH`,message:`Could not determine current git branch.`}};let a=await _e(r,n,{copyFromCurrent:o,copyFromTag:c,description:u||`Tag created from git branch "${n}"`},{session:f,mcpLog:p,projectRoot:d},`json`);return i(),{success:!0,data:{branchName:a.branchName,tagName:a.tagName,created:a.created,mappingUpdated:a.mappingUpdated,message:`Successfully created tag "${a.tagName}" from git branch "${a.branchName}"`}}}else{if(!a||typeof a!=`string`)return t.error(`Missing required parameter: name`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Tag name is required and must be a string`}};t.info(`Creating new tag: ${a}`);let e=await Se(r,a,{copyFromCurrent:o,copyFromTag:c,description:u},{session:f,mcpLog:p,projectRoot:d},`json`);return i(),{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 i(),t.error(`Error in addTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`ADD_TAG_ERROR`,message:e.message}}}}async function wt(e,t,n={}){let{tasksJsonPath:r,prompt:a,dependencies:o,priority:c,research:l,projectRoot:u,tag:d}=e,{session:f}=n;s();let p=Q(t);try{if(!r)return t.error(`addTaskDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let n=r,s=e.title&&e.description;if(!e.prompt&&!s)return t.error(`Missing required parameters: either prompt or title+description must be provided`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Either the prompt parameter or both title and description parameters are required for adding a task`}};let m=Array.isArray(o)?o:o?String(o).split(`,`).map(e=>parseInt(e.trim(),10)):[],h=c||`medium`,g=null,_,v,y;if(s){g={title:e.title,description:e.description,details:e.details||``,testStrategy:e.testStrategy||``},t.info(`Adding new task manually with title: "${e.title}", dependencies: [${m.join(`, `)}], priority: ${c}`);let r=await D(n,null,m,h,{session:f,mcpLog:p,projectRoot:u,commandName:`add-task`,outputType:`mcp`,tag:d},`json`,g,!1);_=r.newTaskId,v=r.telemetryData,y=r.tagInfo}else{t.info(`Adding new task with prompt: "${a}", dependencies: [${m.join(`, `)}], priority: ${h}, research: ${l}`);let e=await D(n,a,m,h,{session:f,mcpLog:p,projectRoot:u,commandName:`add-task`,outputType:`mcp`,tag:d},`json`,null,l);_=e.newTaskId,v=e.telemetryData,y=e.tagInfo}return i(),{success:!0,data:{taskId:_,message:`Successfully added new task #${_}`,telemetryData:v,tagInfo:y}}}catch(e){return i(),t.error(`Error in addTaskDirect: ${e.message}`),{success:!1,error:{code:e.code||`ADD_TASK_ERROR`,message:e.message}}}}async function Tt(e,t,n={}){let{session:r}=n,{tasksJsonPath:a,outputPath:o,threshold:c,research:l,projectRoot:u,ids:d,from:f,to:p,tag:m}=e,h=Q(t);try{if(t.info(`Analyzing task complexity with args: ${JSON.stringify(e)}`),!a)return t.error(`analyzeTaskComplexityDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!o)return t.error(`analyzeTaskComplexityDirect called without outputPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`outputPath is required`}};let n=a,g=o;if(t.info(`Analyzing task complexity from: ${n}`),t.info(`Output report will be saved to: ${g}`),d)t.info(`Analyzing specific task IDs: ${d}`);else if(f||p){let e=f===void 0?`first`:f,n=p===void 0?`last`:p;t.info(`Analyzing tasks in range: ${e} to ${n}`)}l&&t.info(`Using research role for complexity analysis`);let _={file:a,output:o,threshold:c,research:l===!0,projectRoot:u,id:d,from:f,to:p,tag:m},v=w();v||s();let y;try{y=await be(_,{session:r,mcpLog:h,commandName:`analyze-complexity`,outputType:`mcp`,projectRoot:u,tag:m}),y.report}catch(e){return t.error(`Error in analyzeTaskComplexity core function: ${e.message}`),!v&&w()&&i(),{success:!1,error:{code:`ANALYZE_CORE_ERROR`,message:`Error running core complexity analysis: ${e.message}`}}}finally{!v&&w()&&i()}if(!M.existsSync(g))return{success:!1,error:{code:`ANALYZE_REPORT_MISSING`,message:`Analysis completed but no report file was created at the expected path.`}};if(!y||!y.report||typeof y.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(y.report.complexityAnalysis)?y.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 ${o}`,reportPath:o,reportSummary:{taskCount:e.length,highComplexityTasks:t,mediumComplexityTasks:n,lowComplexityTasks:r},fullReport:y.report,telemetryData:y.telemetryData,tagInfo:y.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()&&i(),t.error(`Error in analyzeTaskComplexityDirect setup: ${e.message}`),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message}}}}async function Et(e,t){let{tasksJsonPath:n,id:r,all:a,tag:o,projectRoot:c}=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&&!a)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Either task IDs with id parameter or all parameter must be provided`}};let l=n;if(!M.existsSync(l))return{success:!1,error:{code:`FILE_NOT_FOUND_ERROR`,message:`Tasks file not found at ${l}`}};let u,d=T(l,c,o);if(!d||!d.tasks)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`No tasks found in tasks file: ${l}`}};let f=d.tag||o,p=d.tasks;if(a){if(t.info(`Clearing subtasks from all tasks in tag '${f}'`),p.length===0)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`No tasks found in tag context '${f}'`}};u=p.map(e=>e.id).join(`,`)}else u=r;t.info(`Clearing subtasks from tasks: ${u} in tag '${f}'`),s(),se(l,u,{projectRoot:c,tag:f}),i();let m=T(l,c,f),h=u.split(`,`).map(e=>parseInt(e.trim(),10)),g=h.length,_=m.tasks||[],v=h.map(e=>{let t=_.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 ${g} task(s) in tag '${f}'`,tasksCleared:v,tag:f}}}catch(e){return i(),t.error(`Error in clearSubtasksDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Dt(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{s();let e=S(n);return i(),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 i(),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 i(),t.error(`Unexpected error during complexityReport: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}catch(e){return i(),t.error(`Error in complexityReportDirect: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}async function Ot(e,t,n={}){let{tasksJsonPath:r,sourceName:a,targetName:o,description:c,projectRoot:l}=e,{session:u}=n;s();let d=Q(t);try{if(!r)return t.error(`copyTagDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a||typeof a!=`string`)return t.error(`Missing required parameter: sourceName`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Source tag name is required and must be a string`}};if(!o||typeof o!=`string`)return t.error(`Missing required parameter: targetName`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Target tag name is required and must be a string`}};t.info(`Copying tag from "${a}" to "${o}"`);let e=await xe(r,a,o,{description:c},{session:u,mcpLog:d,projectRoot:l},`json`);return i(),{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 i(),t.error(`Error in copyTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`COPY_TAG_ERROR`,message:e.message}}}}async function kt(e,t,n={}){let{tasksJsonPath:r,name:a,yes:o=!1,projectRoot:c}=e,{session:l}=n;s();let u=Q(t);try{if(!r)return t.error(`deleteTagDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a||typeof a!=`string`)return t.error(`Missing required parameter: name`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Tag name is required and must be a string`}};t.info(`Deleting tag: ${a}`);let e=await ae(r,a,{yes:o},{session:l,mcpLog:u,projectRoot:c},`json`);return i(),{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 i(),t.error(`Error in deleteTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`DELETE_TAG_ERROR`,message:e.message}}}}async function At(e,n,r={}){let{session:a}=r,{tasksJsonPath:o,num:c,research:l,prompt:u,force:d,projectRoot:f,tag:p,complexityReportPath:m}=e,h=Q(n),g=m||t(null,{projectRoot:f,tag:p},n);if(n.info(`Expand all tasks will use complexity report at: ${g}`),!o)return n.error(`expandAllTasksDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};s();try{n.info(`Calling core expandAllTasks with args: ${JSON.stringify({num:c,research:l,prompt:u,force:d,projectRoot:f,tag:p})}`);let e=await ve(o,c?parseInt(c,10):void 0,l===!0,u||``,d===!0,{session:a,mcpLog:h,projectRoot:f,tag:p,complexityReportPath:g},`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 n.error(`Error during core expandAllTasks execution: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}finally{i()}}async function jt(e,t,n={}){let{session:r}=n,{tasksJsonPath:a,id:o,num:c,research:l,prompt:u,force:d,projectRoot:f,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)})}`),!a)return t.error(`expandTaskDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let h=a;t.info(`[expandTaskDirect] Using tasksPath: ${h}`);let _=o?parseInt(o,10):null;if(!_)return t.error(`Task ID is required`),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Task ID is required`}};let v=c?parseInt(c,10):void 0,y=l===!0,b=u||``,x=d===!0;try{t.info(`[expandTaskDirect] Expanding task ${_} into ${v||`default`} subtasks. Research: ${y}, Force: ${x}`),t.info(`[expandTaskDirect] Attempting to read JSON from: ${h}`);let e=T(h,f);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 ${_} in data`);let n=e.tasks.find(e=>e.id===_);if(t.info(`[expandTaskDirect] Task found: ${n?`Yes`:`No`}`),!n)return{success:!1,error:{code:`TASK_NOT_FOUND`,message:`Task with ID ${_} not found`}};if(n.status===`done`||n.status===`completed`)return{success:!1,error:{code:`TASK_COMPLETED`,message:`Task ${_} is already marked as ${n.status} and cannot be expanded`}};let a=n.subtasks&&n.subtasks.length>0;if(a&&!x)return t.info(`Task ${_} already has ${n.subtasks.length} subtasks. Use --force to overwrite.`),{success:!0,data:{message:`Task ${_} already has subtasks. Expansion skipped.`,task:n,subtasksAdded:0,hasExistingSubtasks:a}};a&&x&&(t.info(`Force flag set. Clearing existing subtasks for task ${_}.`),n.subtasks=[]),JSON.parse(JSON.stringify(n));let o=n.subtasks?n.subtasks.length:0;n.subtasks||=[],g(h,e,f,p);let c=Q(t),l;try{l=w(),l||s();let e=await Fe(h,_,v,y,b,{complexityReportPath:m,mcpLog:c,session:r,projectRoot:f,commandName:`expand-task`,outputType:`mcp`,tag:p},x);!l&&w()&&i();let n=T(h,f).tasks.find(e=>e.id===_),u=n.subtasks?n.subtasks.length-o:0;return t.info(`Successfully expanded task ${_} with ${u} new subtasks`),{success:!0,data:{task:e.task,subtasksAdded:u,hasExistingSubtasks:a,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}}catch(e){return!l&&w()&&i(),t.error(`Error expanding task: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message||`Failed to expand task`}}}}catch(e){return t.error(`Error expanding task: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message||`Failed to expand task`}}}}async function Mt(e,t){let{tasksJsonPath:n,projectRoot:r,tag:a}=e;try{if(t.info(`Fixing invalid dependencies in tasks: ${n}`),!n)return t.error(`fixDependenciesDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let e=n;return M.existsSync(e)?(s(),await ke(e,{projectRoot:r,tag:a}),i(),{success:!0,data:{message:`Dependencies fixed successfully`,tasksPath:e,tag:a||`master`}}):{success:!1,error:{code:`FILE_NOT_FOUND`,message:`Tasks file not found at ${e}`}}}catch(e){return i(),t.error(`Error fixing dependencies: ${e.message}`),{success:!1,error:{code:`FIX_DEPENDENCIES_ERROR`,message:e.message}}}}async function Nt(e,t,n={}){let{session:r}=n,a=Re.homedir();t.info(`Args received in direct function: ${JSON.stringify(e)}`);let o=e.projectRoot;if(!o||typeof o!=`string`||o===`/`||o===a)return t.error(`Invalid target directory received from tool layer: '${o}'`),{success:!1,error:{code:`INVALID_TARGET_DIRECTORY`,message:`Cannot initialize project: Invalid target directory '${o}' received. Please ensure a valid workspace/folder is open or specified.`,details:`Received args.projectRoot: ${e.projectRoot}`}};t.info(`Validated target directory for initialization: ${o}`);let c=process.cwd(),l,u=!1,d=null;t.info(`Temporarily changing CWD to ${o} for initialization.`),process.chdir(o),s();try{let n={addAliases:e.addAliases,initGit:e.initGit,storeTasksInGit:e.storeTasksInGit,skipInstall:e.skipInstall,yes:!0};Array.isArray(e.rules)&&e.rules.length>0?(n.rules=e.rules,n.rulesExplicitlyProvided=!0,t.info(`Including rules: ${e.rules.join(`, `)}`)):(n.rules=[`claude`],n.rulesExplicitlyProvided=!0,t.info(`No rule profiles specified, defaulting to: Claude`)),t.info(`Initializing project with options: ${JSON.stringify(n)}`),l={message:`Project initialized successfully.`,next_step:`Now that the project is initialized, the next step is to create the tasks by parsing a PRD. This will create the tasks folder and the initial task files (tasks folder will be created when parse-prd is run). The parse-prd tool will require a prd.txt file as input (typically found in .taskgraph/docs/ directory). You can create a prd.txt file by asking the user about their idea, and then using the .taskgraph/templates/example_prd.txt file as a template to generate a prd.txt file in .taskgraph/docs/. You may skip all of this if the user already has a prd.txt file. You can THEN use the parse-prd tool to create the tasks. So: step 1 after initialization is to create a prd.txt file in .taskgraph/docs/prd.txt or confirm the user already has one. Step 2 is to use the parse-prd tool to create the tasks. Do not bother looking for tasks after initialization, just use the parse-prd tool to create the tasks after creating a prd.txt from which to parse the tasks. You do NOT need to reinitialize the project to parse-prd.`,...await Le(n)},u=!0,t.info(`Project initialization completed successfully in ${o}.`)}catch(e){t.error(`Core initializeProject failed: ${e.message}`),d={code:`INITIALIZATION_FAILED`,message:`Core project initialization failed: ${e.message}`,details:e.stack},u=!1}finally{i(),t.info(`Restoring original CWD: ${c}`),process.chdir(c)}return u?{success:!0,data:l}:{success:!1,error:d}}async function Pt(e,t,n={}){let{tasksJsonPath:r,showMetadata:a=!1,projectRoot:o}=e,{session:c}=n;s();let l=Q(t);try{if(!r)return t.error(`listTagsDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};t.info(`Listing all tags`);let e=await Ae(r,{showMetadata:a},{session:c,mcpLog:l,projectRoot:o},`json`),n=e.tags.map(e=>{let t=e.tasks||[],n=t.reduce((e,t)=>{let n=t.status||`pending`;return e[n]=(e[n]||0)+1,e},{}),r=t.reduce((e,t)=>(t.subtasks&&t.subtasks.length>0&&(e.totalSubtasks+=t.subtasks.length,t.subtasks.forEach(t=>{let n=t.status||`pending`;e.subtasksByStatus[n]=(e.subtasksByStatus[n]||0)+1})),e),{totalSubtasks:0,subtasksByStatus:{}});return{name:e.name,isCurrent:e.isCurrent,taskCount:t.length,completedTasks:e.completedTasks,statusBreakdown:n,subtaskCounts:r,created:e.created,description:e.description}});return i(),{success:!0,data:{tags:n,currentTag:e.currentTag,totalTags:e.totalTags,message:`Found ${e.totalTags} tag(s)`}}}catch(e){return i(),t.error(`Error in listTagsDirect: ${e.message}`),{success:!1,error:{code:e.code||`LIST_TAGS_ERROR`,message:e.message}}}}const Ft=[`main`,`research`,`fallback`];async function It(e,t){for(let n of Ft){let r=`set${n.charAt(0).toUpperCase()+n.slice(1)}`;if(e[r])return await fe(n,e[r],t)}return null}async function Lt(e,t,n={}){let{session:r}=n,{projectRoot:a}=e,o=Q(t);t.info(`Executing models_direct with args: ${JSON.stringify(e)}`),t.info(`Using project root: ${a}`);try{s();try{return e.listAvailableModels===!0?await pe({session:r,mcpLog:o,projectRoot:a}):await It(e,{session:r,mcpLog:o,projectRoot:a})||await je({session:r,mcpLog:o,projectRoot:a})}finally{i()}}catch(e){return t.error(`Error in models_direct: ${e.message}`),{success:!1,error:{code:`DIRECT_FUNCTION_ERROR`,message:e.message,details:e.stack}}}}async function Rt(e,t,n={}){let{session:r}=n,{projectRoot:a}=e;if(t.info(`moveTaskCrossTagDirect called with args: ${JSON.stringify(e)}`),!e.sourceIds)return{success:!1,error:{message:`Source IDs are required`,code:`MISSING_SOURCE_IDS`}};if(!e.sourceTag)return{success:!1,error:{message:`Source tag is required for cross-tag moves`,code:`MISSING_SOURCE_TAG`}};if(!e.targetTag)return{success:!1,error:{message:`Target tag is required for cross-tag moves`,code:`MISSING_TARGET_TAG`}};if(e.sourceTag===e.targetTag)return{success:!1,error:{message:`Source and target tags are the same ("${e.sourceTag}")`,code:`SAME_SOURCE_TARGET_TAG`,suggestions:[`Use different tags for cross-tag moves`,`Use within-tag move: taskgraph move --from=<id> --to=<id> --tag=<tag>`,`Check available tags: taskgraph tags`]}};try{let n=e.tasksJsonPath||e.file;if(!n){if(!e.projectRoot)return{success:!1,error:{message:`Project root is required if tasksJsonPath is not provided`,code:`MISSING_PROJECT_ROOT`}};n=Z(e,t)}s();try{let t=e.sourceIds.split(`,`).map(e=>e.trim()),r={withDependencies:e.withDependencies||!1,ignoreDependencies:e.ignoreDependencies||!1};return{success:!0,data:{...await ge(n,t,e.sourceTag,e.targetTag,r,{projectRoot:a}),message:`Successfully moved ${t.length} task(s) from "${e.sourceTag}" to "${e.targetTag}"`,moveOptions:r,sourceTag:e.sourceTag,targetTag:e.targetTag}}}finally{i()}}catch(e){t.error(`Failed to move tasks between tags: ${e.message}`),t.error(`Error code: ${e.code}, Error name: ${e.name}`);let n=`MOVE_TASK_CROSS_TAG_ERROR`,r=[];return e.code===`CROSS_TAG_DEPENDENCY_CONFLICTS`?(n=`CROSS_TAG_DEPENDENCY_CONFLICT`,r=[`Use --with-dependencies to move dependent tasks together`,`Use --ignore-dependencies to break cross-tag dependencies`,`Run taskgraph validate-dependencies to check for issues`,`Move dependencies first, then move the main task`]):e.code===`CANNOT_MOVE_SUBTASK`?(n=`SUBTASK_MOVE_RESTRICTION`,r=[`Promote subtask to full task first: taskgraph remove-subtask --id=<subtaskId> --convert`,`Move the parent task with all subtasks using --with-dependencies`]):e.code===`TASK_NOT_FOUND`||e.code===`INVALID_SOURCE_TAG`||e.code===`INVALID_TARGET_TAG`?(n=`TAG_OR_TASK_NOT_FOUND`,r=[`Check available tags: taskgraph tags`,`Verify task IDs exist: taskgraph list`,`Check task details: taskgraph show <id>`]):e.message.includes(`cross-tag dependency conflicts`)?(n=`CROSS_TAG_DEPENDENCY_CONFLICT`,r=[`Use --with-dependencies to move dependent tasks together`,`Use --ignore-dependencies to break cross-tag dependencies`,`Run taskgraph validate-dependencies to check for issues`,`Move dependencies first, then move the main task`]):e.message.includes(`Cannot move subtask`)?(n=`SUBTASK_MOVE_RESTRICTION`,r=[`Promote subtask to full task first: taskgraph remove-subtask --id=<subtaskId> --convert`,`Move the parent task with all subtasks using --with-dependencies`]):e.message.includes(`not found`)?(n=`TAG_OR_TASK_NOT_FOUND`,r=[`Check available tags: taskgraph tags`,`Verify task IDs exist: taskgraph list`,`Check task details: taskgraph show <id>`]):(e.code===`TASK_ALREADY_EXISTS`||e.message?.includes(`already exists in target tag`))&&(n=`TASK_ALREADY_EXISTS`,r=[`Choose a different target tag without conflicting IDs`,`Move a different set of IDs (avoid existing ones)`,`If needed, move within-tag to a new ID first, then cross-tag move`]),{success:!1,error:{message:e.message,code:n,suggestions:r}}}}async function zt(e,t,n={}){let{session:r}=n,{projectRoot:a,tag:o}=e;if(!e.sourceId)return{success:!1,error:{message:`Source ID is required`,code:`MISSING_SOURCE_ID`}};if(!e.destinationId)return{success:!1,error:{message:`Destination ID is required`,code:`MISSING_DESTINATION_ID`}};try{let n=e.tasksJsonPath||e.file;if(!n){if(!e.projectRoot)return{success:!1,error:{message:`Project root is required if tasksJsonPath is not provided`,code:`MISSING_PROJECT_ROOT`}};n=Z(e,t)}s();let r=e.generateFiles!==!1,c=await de(n,e.sourceId,e.destinationId,r,{projectRoot:a,tag:o});return i(),{success:!0,data:{...c,message:`Successfully moved task/subtask ${e.sourceId} to ${e.destinationId}`}}}catch(e){return i(),t.error(`Failed to move task: ${e.message}`),{success:!1,error:{message:e.message,code:`MOVE_TASK_ERROR`}}}}async function Bt(e,t,n={}){let{tasksJsonPath:r,reportPath:a,projectRoot:o,tag:c}=e,{session:l}=n;if(!r)return t.error(`nextTaskDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let u=async()=>{try{s(),t.info(`Finding next task from ${r}`);let e=T(r,o,c);if(!e||!e.tasks)return i(),{success:!1,error:{code:`INVALID_TASKS_FILE`,message:`No valid tasks found in ${r}`}};let n=S(a),l=Ce(e.tasks,n);if(!l)return t.info(`No eligible next task found. All tasks are either completed or have unsatisfied dependencies`),{success:!0,data:{message:`No eligible next task found. All tasks are either completed or have unsatisfied dependencies`,nextTask:null}};let u=typeof l.id==`string`&&l.id.includes(`.`),d=u?`subtask`:`task`,f=u?`Subtasks can be updated with timestamped details as you implement them. This is useful for tracking progress, marking milestones and insights (of successful or successive falures in attempting to implement the subtask). Research can be used when updating the subtask to collect up-to-date information, and can be helpful to solve a repeating problem the agent is unable to solve. It is a good idea to get-task the parent task to collect the overall context of the task, and to get-task the subtask to collect the specific details of the subtask.`:`Tasks can be updated to reflect a change in the direction of the task, or to reformulate the task per your prompt. Research can be used when updating the task to collect up-to-date information. It is best to update subtasks as you work on them, and to update the task for more high-level changes that may affect pending subtasks or the general direction of the task.`;return i(),t.info(`Successfully found next task ${l.id}: ${l.title}. Is subtask: ${u}`),{success:!0,data:{nextTask:l,isSubtask:u,nextSteps:`When ready to work on the ${d}, use set-status to set the status to "in progress" ${f}`}}}catch(e){return i(),t.error(`Error finding next task: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message||`Failed to find next task`}}}};try{let e=await u();return t.info(`nextTaskDirect completed.`),e}catch(e){return t.error(`Unexpected error during nextTask: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}async function Vt(e,t,n={}){let{session:a,reportProgress:o}=n,{input:c,output:l,numTasks:u,force:d,append:f,research:p,projectRoot:m,tag:h}=e,g=Q(t);if(!m)return g.error(`parsePRDDirect requires a projectRoot argument.`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`projectRoot is required.`}};let _;if(c)try{_=vt({input:c,projectRoot:m},a)}catch(e){return g.error(`Error resolving PRD path: ${e.message}`),{success:!1,error:{code:`FILE_NOT_FOUND`,message:e.message}}}else return g.error(`parsePRDDirect called without input path`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Input path is required`}};let y=l?N.isAbsolute(l)?l:N.resolve(m,l):bt(r,e)||N.resolve(m,r);if(!M.existsSync(_)){let e=`Input PRD file not found at resolved path: ${_}`;return g.error(e),{success:!1,error:{code:`FILE_NOT_FOUND`,message:e}}}let b=N.dirname(y);try{M.existsSync(b)||(g.info(`Creating output directory: ${b}`),M.mkdirSync(b,{recursive:!0}))}catch(e){let t=`Failed to create output directory ${b}: ${e.message}`;return g.error(t),{success:!1,error:{code:`DIRECTORY_CREATE_FAILED`,message:t}}}let x=v(m);u&&(x=typeof u==`string`?parseInt(u,10):u,(Number.isNaN(x)||x<0)&&(x=v(m),g.warn(`Invalid numTasks value: ${u}. Using default: ${x}`))),f&&(g.info(`Append mode enabled.`),d&&g.warn(`Both --force and --append flags were provided. --force takes precedence; append mode will be ignored.`)),p&&g.info(`Research mode enabled. Using Claude Code web research for enhanced PRD analysis.`),g.info(`Parsing PRD via direct function. Input: ${_}, Output: ${y}, NumTasks: ${x}, Force: ${d}, Append: ${f}, Research: ${p}, ProjectRoot: ${m}`);let S=w();S||s();try{let e=await he(_,y,x,{session:a,mcpLog:g,projectRoot:m,tag:h,force:d,append:f,research:p,reportProgress:o,commandName:`parse-prd`,outputType:`mcp`},`json`);if(e&&e.success){let t=`Successfully parsed PRD and generated tasks in ${e.tasksPath}`;return g.success(t),{success:!0,data:{message:t,outputPath:e.tasksPath,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}}else return g.error(`Core parsePRD function did not return a successful structure.`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e?.message||`Core function failed to parse PRD or returned unexpected result.`}}}catch(e){return g.error(`Error executing core parsePRD: ${e.message}`),{success:!1,error:{code:`PARSE_PRD_CORE_ERROR`,message:e.message||`Unknown error parsing PRD`}}}finally{!S&&w()&&i()}}async function Ht(e,t){let{tasksJsonPath:n,id:r,dependsOn:a,projectRoot:o,tag:c}=e;try{if(t.info(`Removing dependency with args: ${JSON.stringify(e)}`),!n)return t.error(`removeDependencyDirect 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(!a)return{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Dependency ID (dependsOn) is required`}};let l=n,u=r&&r.includes&&r.includes(`.`)?r:parseInt(r,10),d=a&&a.includes&&a.includes(`.`)?a:parseInt(a,10);return t.info(`Removing dependency: task ${u} no longer depends on ${d}`),s(),await Me(l,u,d,{projectRoot:o,tag:c}),i(),{success:!0,data:{message:`Successfully removed dependency: Task ${u} no longer depends on ${d}`,taskId:u,dependencyId:d}}}catch(e){return i(),t.error(`Error in removeDependencyDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Ut(e,t){let{tasksJsonPath:n,id:r,convert:a,skipGenerate:o,projectRoot:c,tag:l}=e;try{if(s(),t.info(`Removing subtask with args: ${JSON.stringify(e)}`),!n)return t.error(`removeSubtaskDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!r)return i(),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Subtask ID is required and must be in format "parentId.subtaskId"`}};if(!r.includes(`.`))return i(),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Invalid subtask ID format: ${r}. Expected format: "parentId.subtaskId"`}};let u=n,d=a===!0,f=!o;t.info(`Removing subtask ${r} (convertToTask: ${d}, generateFiles: ${f})`);let p=await me(u,r,d,f,{projectRoot:c,tag:l});return i(),d&&p?{success:!0,data:{message:`Subtask ${r} successfully converted to task #${p.id}`,task:p}}:{success:!0,data:{message:`Subtask ${r} successfully removed`}}}catch(e){return i(),t.error(`Error in removeSubtaskDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Wt(e,t,n={}){let{tasksJsonPath:r,id:a,projectRoot:o,tag:c}=e,{session:l}=n;try{if(!r)return t.error(`removeTaskDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a)return t.error(`Task ID is required`),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Task ID is required`}};let e=a.split(`,`).map(e=>e.trim());t.info(`Removing ${e.length} task(s) with ID(s): ${e.join(`, `)} from ${r}${c?` in tag '${c}'`:``}`);let n=T(r,o,c);if(!n||!n.tasks)return{success:!1,error:{code:`INVALID_TASKS_FILE`,message:`No valid tasks found in ${r}${c?` for tag '${c}'`:``}`}};let l=e.filter(e=>!De(n.tasks,e));if(l.length>0)return{success:!1,error:{code:`INVALID_TASK_ID`,message:`The following tasks were not found${c?` in tag '${c}'`:``}: ${l.join(`, `)}`}};s();try{let n=await oe(r,a,{projectRoot:o,tag:c});return n.success?(t.info(`Successfully removed ${n.removedTasks.length} task(s)`),{success:!0,data:{totalTasks:e.length,successful:n.removedTasks.length,failed:e.length-n.removedTasks.length,removedTasks:n.removedTasks,message:n.message,tasksPath:r,tag:c}}):{success:!1,error:{code:`REMOVE_TASK_ERROR`,message:n.error||`Failed to remove tasks`}}}finally{i()}}catch(e){return i(),t.error(`Unexpected error in removeTaskDirect: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}async function Gt(e,t,n={}){let{tasksJsonPath:r,oldName:a,newName:o,projectRoot:c}=e,{session:l}=n;s();let u=Q(t);try{if(!r)return t.error(`renameTagDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a||typeof a!=`string`)return t.error(`Missing required parameter: oldName`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Old tag name is required and must be a string`}};if(!o||typeof o!=`string`)return t.error(`Missing required parameter: newName`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`New tag name is required and must be a string`}};t.info(`Renaming tag from "${a}" to "${o}"`);let e=await we(r,a,o,{},{session:l,mcpLog:u,projectRoot:c},`json`);return i(),{success:!0,data:{oldName:e.oldName,newName:e.newName,renamed:e.renamed,taskCount:e.taskCount,wasCurrentTag:e.wasCurrentTag,message:`Successfully renamed tag from "${e.oldName}" to "${e.newName}"`}}}catch(e){return i(),t.error(`Error in renameTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`RENAME_TAG_ERROR`,message:e.message}}}}async function Kt(e,t,n={}){let{query:r,taskIds:a,filePaths:o,customContext:c,includeProjectTree:l=!1,detailLevel:u=`medium`,saveTo:d,saveToFile:f=!1,projectRoot:p,tag:m}=e,{session:h}=n;s();let g=Q(t);try{if(!r||typeof r!=`string`||r.trim().length===0)return t.error(`Missing or invalid required parameter: query`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The query parameter is required and must be a non-empty string`}};let e=a?a.split(`,`).map(e=>e.trim()).filter(e=>e.length>0):[],n=o?o.split(`,`).map(e=>e.trim()).filter(e=>e.length>0):[],s=[`low`,`medium`,`high`];if(!s.includes(u))return t.error(`Invalid detail level: ${u}`),i(),{success:!1,error:{code:`INVALID_PARAMETER`,message:`Detail level must be one of: ${s.join(`, `)}`}};t.info(`Performing research query: "${r.substring(0,100)}${r.length>100?`...`:``}", taskIds: [${e.join(`, `)}], filePaths: [${n.join(`, `)}], detailLevel: ${u}, includeProjectTree: ${l}, projectRoot: ${p}`);let _={taskIds:e,filePaths:n,customContext:c||``,includeProjectTree:l,detailLevel:u,projectRoot:p,tag:m,saveToFile:f},v={session:h,mcpLog:g,commandName:`research`,outputType:`mcp`},y=await Oe(r.trim(),_,v,`json`,!1);if(d)try{let e=d.includes(`.`),n=`## Research Query: ${r.trim()}
5
+ Current Tag: ${n.currentTag}`),{content:[{type:`text`,text:r}],isError:!0}}function He(e,t){if(typeof e!=`function`)t?.debug?.(`reportProgress not available - operation will run without progress updates`);else return e}function Ue(e){try{let t=k.join(e,`.taskgraph`,`state.json`);return M.existsSync(t)&&JSON.parse(M.readFileSync(t,`utf-8`)).currentTag||`master`}catch{return null}}async function V(e){let{result:t,log:n,errorPrefix:r=`API error`,projectRoot:i,tag:a}=e,o=z(),s=a===void 0?i?Ue(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 H(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,`/`),k.resolve(t)}catch{return k.resolve(e)}}function We(e){try{return e?.roots?.[0]?.uri?H(e.roots[0].uri):e?.roots?.roots?.[0]?.uri?H(e.roots.roots[0].uri):null}catch{return null}}function U(e){return async(t,n)=>{let{log:r,session:i}=n,a=null,o=`unknown`;try{if(process.env.TASKGRAPH_PROJECT_ROOT){let e=process.env.TASKGRAPH_PROJECT_ROOT;a=k.isAbsolute(e)?e:k.resolve(process.cwd(),e),o=`TASKGRAPH_PROJECT_ROOT environment variable`,r?.info?.(`Using project root from ${o}: ${a}`)}else if(i?.env?.TASKGRAPH_PROJECT_ROOT){let e=i.env.TASKGRAPH_PROJECT_ROOT;a=k.isAbsolute(e)?e:k.resolve(process.cwd(),e),o=`TASKGRAPH_PROJECT_ROOT session environment variable`,r?.info?.(`Using project root from ${o}: ${a}`)}else if(t.projectRoot)a=H(t.projectRoot),o=`args.projectRoot`,r?.info?.(`Using project root from ${o}: ${a}`);else{let e=We(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.`),V({result:{success:!1,error:{message:`Could not determine project root. Please provide projectRoot argument or ensure TASKGRAPH_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),V({result:{success:!1,error:{message:`Operation failed: ${e.message}`}}})}}}function W(e){return U(async(t,n)=>{let r=k.join(t.projectRoot,`.env`);M.existsSync(r)&&N.config({path:r,quiet:!0});let i=await s({projectPath:t.projectRoot,loggerConfig:{mcpMode:!0,logCallback:n.log}});return e(t,{log:n.log,session:n.session,tmCore:i})})}function G(e,t){if(!e)return{parsedMetadata:null};if(process.env.TASKGRAPH_ALLOW_METADATA_UPDATES!==`true`)return{parsedMetadata:null,error:t(`Metadata updates are disabled. Set TASKGRAPH_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 Ge=j.object({taskId:a.describe(`Main task ID to start workflow for (e.g., "1", "2"). Subtask IDs (e.g., "2.3", "1.1") are not allowed.`),projectRoot:j.string().describe(`Absolute path to the project root directory`),maxAttempts:j.number().optional().default(3).describe(`Maximum attempts per subtask (default: 3)`),force:j.boolean().optional().default(!1).describe(`Force start even if workflow state exists`)});function Ke(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:Ge,annotations:{title:`Start Autopilot Workflow`,destructiveHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{taskId:r,projectRoot:i,maxAttempts:a,force:o}=e;try{t.info(`Starting autopilot workflow for task ${r} in ${i}`);let e=n.config.getActiveTag(),s=await n.tasks.get(r);if(!s||!s.task)return V({result:{success:!1,error:{message:`Task ${r} not found`}},log:t,projectRoot:i});let c=s.task;if(!c.subtasks||c.subtasks.length===0)return V({result:{success:!1,error:{message:`Task ${r} has no subtasks. Please use expand_task (with id="${r}") 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`),V({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 l=await n.workflow.start({taskId:r,taskTitle:c.title,subtasks:c.subtasks.map(e=>({id:e.id,title:e.title,status:e.status,maxAttempts:a})),maxAttempts:a,force:o,tag:e});t.info(`Workflow started successfully for task ${r}`);let u=n.workflow.getNextAction();return V({result:{success:!0,data:{message:`Workflow started for task ${r}`,taskId:r,branchName:l.branchName,phase:l.phase,tddPhase:l.tddPhase,progress:l.progress,currentSubtask:l.currentSubtask,nextAction:u.action,nextSteps:u.nextSteps}},log:t,projectRoot:i})}catch(e){return t.error(`Error in autopilot-start: ${e.message}`),e.stack&&t.debug(e.stack),V({result:{success:!1,error:{message:`Failed to start workflow: ${e.message}`}},log:t,projectRoot:i})}})})}const qe=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`)});function Je(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:qe,annotations:{title:`Resume Autopilot Workflow`,readOnlyHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Resuming autopilot workflow in ${r}`),!await n.workflow.hasWorkflow())return V({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}`),V({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),V({result:{success:!1,error:{message:`Failed to resume workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const Ye=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`)});function Xe(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:Ye,annotations:{title:`Get Next Autopilot Action`,readOnlyHint:!0},execute:W(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 V({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}`),V({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),V({result:{success:!1,error:{message:`Failed to get next action: ${e.message}`}},log:t,projectRoot:r})}})})}const Ze=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`)});function Qe(e){e.addTool({name:`autopilot_status`,description:`Get comprehensive workflow status including current phase, progress, subtask details, and activity history.`,parameters:Ze,annotations:{title:`Get Autopilot Status`,readOnlyHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Getting workflow status for ${r}`),!await n.workflow.hasWorkflow())return V({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}`),V({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),V({result:{success:!1,error:{message:`Failed to get workflow status: ${e.message}`}},log:t,projectRoot:r})}})})}const $e=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`),testResults:j.object({total:j.number().describe(`Total number of tests`),passed:j.number().describe(`Number of passing tests`),failed:j.number().describe(`Number of failing tests`),skipped:j.number().optional().describe(`Number of skipped tests`)}).describe(`Test results from running the test suite`)});function et(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:$e,annotations:{title:`Complete Autopilot Phase`,destructiveHint:!0},execute:W(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 V({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 V({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 V({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}`),V({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),V({result:{success:!1,error:{message:`Failed to complete phase: ${e.message}`}},log:t,projectRoot:r})}})})}const tt=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`),files:j.array(j.string()).optional().describe(`Specific files to stage (relative to project root). If not provided, stages all changes.`),customMessage:j.string().optional().describe(`Custom commit message to use instead of auto-generated message`)});function nt(n){n.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:W(async(n,{log:r,tmCore:i})=>{let{projectRoot:a,files:o,customMessage:s}=n;try{if(r.info(`Creating commit for workflow in ${a}`),!await i.workflow.hasWorkflow())return V({result:{success:!1,error:{message:`No active workflow found. Start a workflow with autopilot_start`}},log:r,projectRoot:a});await i.workflow.resume();let n=i.workflow.getStatus(),c=i.workflow.getContext();if(n.tddPhase!==`COMMIT`)return r.warn(`Not in COMMIT phase (currently in ${n.tddPhase})`),V({result:{success:!1,error:{message:`Cannot commit: currently in ${n.tddPhase} phase. Complete the ${n.tddPhase} phase first using autopilot_complete_phase`}},log:r,projectRoot:a});if(!n.currentSubtask)return V({result:{success:!1,error:{message:`No active subtask to commit`}},log:r,projectRoot:a});let l=new e(a);try{o&&o.length>0?(await l.stageFiles(o),r.info(`Staged ${o.length} files`)):(await l.stageFiles([`.`]),r.info(`Staged all changes`))}catch(e){return r.error(`Failed to stage files: ${e.message}`),V({result:{success:!1,error:{message:`Failed to stage files: ${e.message}`}},log:r,projectRoot:a})}if(!await l.hasStagedChanges())return r.warn(`No staged changes to commit`),V({result:{success:!1,error:{message:`No staged changes to commit. Make code changes before committing`}},log:r,projectRoot:a});let u=await l.getStatus(),d;if(s)d=s,r.info(`Using custom commit message`);else{let e=new t,i={type:n.tddPhase===`COMMIT`?`feat`:`test`,description:n.currentSubtask.title,changedFiles:u.staged,taskId:n.taskId,phase:n.tddPhase,testsPassing:c.lastTestResults?.passed,testsFailing:c.lastTestResults?.failed};d=e.generateMessage(i),r.info(`Generated commit message automatically`)}try{await l.createCommit(d),r.info(`Commit created successfully`)}catch(e){return r.error(`Failed to create commit: ${e.message}`),V({result:{success:!1,error:{message:`Failed to create commit: ${e.message}`}},log:r,projectRoot:a})}let f=await l.getLastCommit(),p=await i.workflow.commit();r.info(`Commit completed. Current phase: ${p.tddPhase||p.phase}`);let m=p.phase===`COMPLETE`,h=i.workflow.getNextAction();return V({result:{success:!0,data:{message:m?`Workflow completed successfully`:`Commit created and workflow advanced`,commitSha:f.sha,commitMessage:d,...p,isComplete:m,nextAction:h.action,nextSteps:h.nextSteps}},log:r,projectRoot:a})}catch(e){return r.error(`Error in autopilot-commit: ${e.message}`),e.stack&&r.debug(e.stack),V({result:{success:!1,error:{message:`Failed to commit: ${e.message}`}},log:r,projectRoot:a})}})})}const rt=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`)});function it(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:rt,annotations:{title:`Finalize Autopilot Workflow`,destructiveHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{projectRoot:r}=e;try{if(t.info(`Finalizing workflow in ${r}`),!await n.workflow.hasWorkflow())return V({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 V({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 V({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),V({result:{success:!1,error:{message:`Failed to finalize workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const at=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`)});function ot(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:at,annotations:{title:`Abort Autopilot Workflow`,destructiveHint:!0},execute:W(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`),V({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`),V({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),V({result:{success:!1,error:{message:`Failed to abort workflow: ${e.message}`}},log:t,projectRoot:r})}})})}const st=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`),repo:j.string().optional().describe(`Repository as owner/name (default: detected through gh)`)});function ct(e){e.addTool({name:`github_status`,description:`Check whether the gh CLI is usable, which GitHub repository tasks would be pushed to, and how many tasks are already linked to issues.`,parameters:st,annotations:{title:`GitHub Sync Status`,readOnlyHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{projectRoot:r,repo:i}=e;try{return t.info(`Checking GitHub sync status for ${r}`),V({result:{success:!0,data:await n.github.status({repo:i})},log:t,projectRoot:r})}catch(e){return t.error(`Error in github_status: ${e.message}`),V({result:{success:!1,error:{message:`Failed to get GitHub status: ${e.message}`}},log:t,projectRoot:r})}})})}const lt=j.object({projectRoot:j.string().describe(`Absolute path to the project root directory`),dryRun:j.boolean().optional().default(!0).describe(`Preview the plan without writing to GitHub (default: true). Pass false to create and update issues.`),tag:j.string().optional().describe(`Tag to push (default: the active tag)`),allTags:j.boolean().optional().describe(`Push every tag instead of one`),id:j.string().optional().describe(`Only push these top-level task IDs, comma separated`),repo:j.string().optional().describe(`Repository as owner/name (default: detected through gh)`),includeDetails:j.boolean().optional().describe(`Include the task details field in issue bodies`),closeOrphans:j.boolean().optional().describe(`Close open issues whose task no longer exists`)});function ut(e){e.addTool({name:`github_push`,description:`Push tasks to GitHub Issues through the gh CLI: creates issues, updates changed ones and closes finished ones. Runs as a dry run unless dryRun is false, so call it once to review the plan before writing.`,parameters:lt,annotations:{title:`Push Tasks to GitHub`,readOnlyHint:!1,destructiveHint:!1,openWorldHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{projectRoot:r,id:i,dryRun:a=!0,...o}=e;try{return t.info(`Pushing tasks to GitHub for ${r} (dryRun: ${a})`),V({result:{success:!0,data:await n.github.push({...o,dryRun:a,taskIds:i})},log:t,projectRoot:r})}catch(e){return t.error(`Error in github_push: ${e.message}`),V({result:{success:!1,error:{message:`Failed to push to GitHub: ${e.message}`}},log:t,projectRoot:r})}})})}const dt=j.object({projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),status:j.string().optional().describe(`Filter tasks by status (e.g., 'pending', 'done') or multiple statuses separated by commas (e.g., 'blocked,deferred')`),withSubtasks:j.boolean().optional().describe(`Include subtasks nested within their parent tasks in the response`),tag:j.string().optional().describe(`Tag context to operate on`)});function ft(e){e.addTool({name:`get_tasks`,description:`Get all tasks from TaskGraph, optionally filtering by status and including subtasks.`,parameters:dt,annotations:{title:`Get Tasks`,readOnlyHint:!0},execute:W(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 V({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),V({result:{success:!1,error:{message:`Failed to get tasks: ${e.message}`}},log:t,projectRoot:r})}})})}const pt=j.object({id:l.describe(`Task ID(s) to get (can be comma-separated for multiple tasks)`),status:j.string().optional().describe(`Filter subtasks by status (e.g., 'pending', 'done')`),projectRoot:j.string().describe(`Absolute path to the project root directory (Optional, usually from session)`),tag:j.string().optional().describe(`Tag context to operate on`)});function mt(e){e.addTool({name:`get_task`,description:`Get detailed information about a specific task`,parameters:pt,annotations:{title:`Get Task`,readOnlyHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{id:r,status:a,projectRoot:o,tag:s}=e;try{t.info(`Getting task details for ID: ${r}${a?` (filtering subtasks by status: ${a})`:``} in root: ${o}`);let e=i(r),c=await Promise.all(e.map(e=>n.tasks.get(e,s))),l=[];for(let e of c)if(e.task){if(a&&e.task.subtasks){let t=a.split(`,`).map(e=>e.trim().toLowerCase()),n=e.task.subtasks.filter(e=>t.includes(String(e.status).toLowerCase()));l.push({...e.task,subtasks:n})}else l.push(e.task)}return l.length===0?(t.warn(`No tasks found for ID(s): ${r}`),V({result:{success:!1,error:{message:`No tasks found for ID(s): ${r}`}},log:t,projectRoot:o})):(t.info(`Successfully retrieved ${l.length} task(s) for ID(s): ${r}`),V({result:{success:!0,data:e.length===1?l[0]:l},log:t,projectRoot:o,tag:s}))}catch(e){return t.error(`Error in get-task: ${e.message}`),e.stack&&t.debug(e.stack),V({result:{success:!1,error:{message:`Failed to get task: ${e.message}`}},log:t,projectRoot:o})}})})}const ht=j.object({output:j.string().optional().describe(`Output directory for generated files (default: same directory as tasks file)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)});function gt(e){e.addTool({name:`generate`,description:`Generates individual task files in tasks/ directory based on tasks.json. Only works with local file storage.`,parameters:ht,annotations:{title:`Generate Task Files`,destructiveHint:!0},execute:W(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?k.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`}`),V({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),V({result:{success:!1,error:{message:`Failed to generate task files: ${e.message}`}},log:t,projectRoot:r})}})})}const _t=j.object({id:l.describe(`Task ID or subtask ID (e.g., '15', '15.2'). Can be comma-separated to update multiple tasks/subtasks at once.`),status:j.enum(o).describe(`New status to set (e.g., 'pending', 'done', 'in-progress', 'review', 'deferred', 'cancelled').`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Optional tag context to operate on`)});function vt(e){e.addTool({name:`set_task_status`,description:`Set the status of one or more tasks or subtasks.`,parameters:_t,annotations:{title:`Set Task Status`,destructiveHint:!0},execute:W(async(e,{log:t,tmCore:n})=>{let{id:r,status:a,projectRoot:o,tag:s}=e;try{t.info(`Setting status of task(s) ${r} to: ${a}${s?` in tag: ${s}`:` in current tag`}`);let e=i(r),c=[];for(let r of e){let e=await n.tasks.updateStatus(r,a,s);c.push(e),t.info(`Updated task ${r}: ${e.oldStatus} → ${e.newStatus}`)}return t.info(`Successfully updated status for ${c.length} task(s) to "${a}"`),V({result:{success:!0,data:{message:`Successfully updated ${c.length} task(s) to "${a}"`,tasks:c}},log:t,projectRoot:o,tag:s})}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),V({result:{success:!1,error:{message:`Failed to set task status: ${n.message}`}},log:t,projectRoot:o,tag:s})}})})}async function yt(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}`),b(),await Me(s,c,l,{projectRoot:o,tag:a}),y(),{success:!0,data:{message:`Successfully added dependency: Task ${c} now depends on ${l}`,taskId:c,dependencyId:l}}}catch(e){return y(),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;b();let v={projectRoot:d,tag:f};if(h){t.info(`Converting task ${h} to a subtask of ${g}`);let e=await E(p,g,h,null,_,v);return y(),{success:!0,data:{message:`Task ${h} successfully converted to a subtask of task ${g}`,subtask:e}}}{t.info(`Creating new subtask for parent task ${g}`);let e=await E(p,g,null,{title:a,description:o||``,details:s||``,status:c||`pending`,dependencies:m},_,v);return y(),{success:!0,data:{message:`New subtask ${g}.${e.id} successfully created`,subtask:e}}}}catch(e){return y(),t.error(`Error in addSubtaskDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}new class{constructor(e={}){this.config={maxCacheSize:e.maxCacheSize||1e3,ttl:e.ttl||3e5,maxContextSize:e.maxContextSize||4e3},this.cache=new ze({max:this.config.maxCacheSize,ttl:this.config.ttl,updateAgeOnGet:!0}),this.stats={hits:0,misses:0,invalidations:0}}async getContext(e,t={}){let n=this._getCacheKey(e,t),r=this.cache.get(n);if(r)return this.stats.hits++,r;this.stats.misses++;let i={id:e,metadata:{...t,created:(/* @__PURE__ */ new Date()).toISOString()}};return this.cache.set(n,i),i}async updateContext(e,t){let n=await this.getContext(e);Object.assign(n.metadata,t);let r=this._getCacheKey(e,n.metadata);return this.cache.set(r,n),n}invalidateContext(e,t={}){let n=this._getCacheKey(e,t);this.cache.delete(n),this.stats.invalidations++}getCachedData(e){let t=this.cache.get(e);if(t!==void 0)return this.stats.hits++,t;this.stats.misses++}setCachedData(e,t){this.cache.set(e,t)}invalidateCacheKey(e){this.cache.delete(e),this.stats.invalidations++}getStats(){return{hits:this.stats.hits,misses:this.stats.misses,invalidations:this.stats.invalidations,size:this.cache.size,maxSize:this.config.maxCacheSize,ttl:this.config.ttl}}_getCacheKey(e,t){return`${e}:${JSON.stringify(t)}`}};const K={info:()=>{},warn:()=>{},error:()=>{},debug:()=>{},success:()=>{}};function q(e,t=K){let n=e?.file,r=e?.projectRoot;if(n&&A.isAbsolute(n))return n;let i=r?f(r):null;if(n&&i)return A.resolve(i,n);if(i){let e=d(n,{projectRoot:i},t);if(e===null&&!n){let e=A.join(i,`.taskgraph`,`tasks`,`tasks.json`);return t?.info?.(`Core findTasksPath returned null, using default path: ${e}`),e}return e}return d(n,null,t)}function xt(e,t=K){let n=e?.input,r=e?.projectRoot;if(n&&A.isAbsolute(n))return n;let i=r?f(r):null;return n&&i?A.resolve(i,n):i?h(n,{projectRoot:i},t):h(n,null,t)}function J(e,t=K){let n=e?.complexityReport,r=e?.projectRoot,i=e?.tag;if(n&&A.isAbsolute(n))return n;let a=r?f(r):null;return n&&a?A.resolve(a,n):a?p(n,{projectRoot:a,tag:i},t):p(n,null,t)}function St(e,t){if(!t?.projectRoot)throw Error(`projectRoot is required in args to resolve project paths`);let n=f(t.projectRoot);return A.isAbsolute(e)?e:A.resolve(n,e)}function Y(e,t=K){return q(e,t)}function X(e,t=K){return J(e,t)}function Ct(e,t,n=K){return _(e,t,n)}F(import.meta.url);function Z(e){return{info:(t,...n)=>e.info(t,...n),warn:(t,...n)=>e.warn(t,...n),error:(t,...n)=>e.error(t,...n),debug:(t,...n)=>e.debug?e.debug(t,...n):null,success:(t,...n)=>e.info(t,...n)}}async function wt(e,t,n={}){let{tasksJsonPath:r,name:i,copyFromCurrent:a=!1,copyFromTag:o,fromBranch:s=!1,description:c,projectRoot:l}=e,{session:u}=n;b();let d=Z(t);try{if(!r)return t.error(`addTagDirect called without tasksJsonPath`),y(),{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-BezpEZd4.js`);if(!await e.isGitRepository(l))return t.error(`Not in a git repository`),y(),{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`),y(),{success:!1,error:{code:`NO_CURRENT_BRANCH`,message:`Could not determine current git branch.`}};let i={copyFromCurrent:a,copyFromTag:o,description:c||`Tag created from git branch "${n}"`},s=await ge(r,n,i,{session:u,mcpLog:d,projectRoot:l},`json`);return y(),{success:!0,data:{branchName:s.branchName,tagName:s.tagName,created:s.created,mappingUpdated:s.mappingUpdated,message:`Successfully created tag "${s.tagName}" from git branch "${s.branchName}"`}}}{if(!i||typeof i!=`string`)return t.error(`Missing required parameter: name`),y(),{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 xe(r,i,{copyFromCurrent:a,copyFromTag:o,description:c},{session:u,mcpLog:d,projectRoot:l},`json`);return y(),{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 y(),t.error(`Error in addTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`ADD_TAG_ERROR`,message:e.message}}}}async function Tt(e,t,n={}){let{tasksJsonPath:r,prompt:i,dependencies:a,priority:o,research:s,projectRoot:c,tag:l}=e,{session:u}=n;b();let d=Z(t);try{if(!r)return t.error(`addTaskDirect called without tasksJsonPath`),y(),{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`),y(),{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,_,v;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 T(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,v=r.tagInfo}else{t.info(`Adding new task with prompt: "${i}", dependencies: [${p.join(`, `)}], priority: ${m}, research: ${s}`);let e=await T(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,v=e.tagInfo}return y(),{success:!0,data:{taskId:g,message:`Successfully added new task #${g}`,telemetryData:_,tagInfo:v}}}catch(e){return y(),t.error(`Error in addTaskDirect: ${e.message}`),{success:!1,error:{code:e.code||`ADD_TASK_ERROR`,message:e.message}}}}async function Et(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=Z(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=C();g||b();let _;try{_=await ye(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&&C()&&y(),{success:!1,error:{code:`ANALYZE_CORE_ERROR`,message:`Error running core complexity analysis: ${e.message}`}}}finally{!g&&C()&&y()}if(!P.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 C()&&y(),t.error(`Error in analyzeTaskComplexityDirect setup: ${e.message}`),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message}}}}async function Dt(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(!P.existsSync(s))return{success:!1,error:{code:`FILE_NOT_FOUND_ERROR`,message:`Tasks file not found at ${s}`}};let c,l=x(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}'`),b(),oe(s,c,{projectRoot:o,tag:u}),y();let f=x(s,o,u),p=c.split(`,`).map(e=>parseInt(e.trim(),10)),m=p.length,h=f.tasks||[],g=p.map(e=>{let t=h.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 ${m} task(s) in tag '${u}'`,tasksCleared:g,tag:u}}}catch(e){return y(),t.error(`Error in clearSubtasksDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Ot(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{b();let e=S(n);return y(),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 y(),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 y(),t.error(`Unexpected error during complexityReport: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}catch(e){return y(),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;b();let l=Z(t);try{if(!r)return t.error(`copyTagDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i||typeof i!=`string`)return t.error(`Missing required parameter: sourceName`),y(),{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`),y(),{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 be(r,i,a,{description:o},{session:c,mcpLog:l,projectRoot:s},`json`);return y(),{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 y(),t.error(`Error in copyTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`COPY_TAG_ERROR`,message:e.message}}}}async function At(e,t,n={}){let{tasksJsonPath:r,name:i,yes:a=!1,projectRoot:o}=e,{session:s}=n;b();let c=Z(t);try{if(!r)return t.error(`deleteTagDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i||typeof i!=`string`)return t.error(`Missing required parameter: name`),y(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Tag name is required and must be a string`}};t.info(`Deleting tag: ${i}`);let e=await ie(r,i,{yes:a},{session:s,mcpLog:c,projectRoot:o},`json`);return y(),{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 y(),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=Z(t),p=d||_(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`}};b();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 _e(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{y()}}async function Mt(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,id:a,num:o,research:s,prompt:c,force:l,projectRoot:u,tag:d,complexityReportPath:f}=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 p=i;t.info(`[expandTaskDirect] Using tasksPath: ${p}`);let m=a?parseInt(a,10):null;if(!m)return t.error(`Task ID is required`),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Task ID is required`}};let h=o?parseInt(o,10):void 0,g=s===!0,_=c||``,v=l===!0;try{t.info(`[expandTaskDirect] Expanding task ${m} into ${h||`default`} subtasks. Research: ${g}, Force: ${v}`),t.info(`[expandTaskDirect] Attempting to read JSON from: ${p}`);let e=x(p,u);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: ${p}`),{success:!1,error:{code:`INVALID_TASKS_FILE`,message:`No valid tasks found in ${p}. readJSON returned: ${JSON.stringify(e)}`}};t.info(`[expandTaskDirect] Searching for task ID ${m} in data`);let n=e.tasks.find(e=>e.id===m);if(t.info(`[expandTaskDirect] Task found: ${n?`Yes`:`No`}`),!n)return{success:!1,error:{code:`TASK_NOT_FOUND`,message:`Task with ID ${m} not found`}};if(n.status===`done`||n.status===`completed`)return{success:!1,error:{code:`TASK_COMPLETED`,message:`Task ${m} is already marked as ${n.status} and cannot be expanded`}};let i=n.subtasks&&n.subtasks.length>0;if(i&&!v)return t.info(`Task ${m} already has ${n.subtasks.length} subtasks. Use --force to overwrite.`),{success:!0,data:{message:`Task ${m} already has subtasks. Expansion skipped.`,task:n,subtasksAdded:0,hasExistingSubtasks:i}};i&&v&&(t.info(`Force flag set. Clearing existing subtasks for task ${m}.`),n.subtasks=[]),JSON.parse(JSON.stringify(n));let a=n.subtasks?n.subtasks.length:0;n.subtasks||=[],te(p,e,u,d);let o=Z(t),s;try{s=C(),s||b();let e=await Pe(p,m,h,g,_,{complexityReportPath:f,mcpLog:o,session:r,projectRoot:u,commandName:`expand-task`,outputType:`mcp`,tag:d},v);!s&&C()&&y();let n=x(p,u).tasks.find(e=>e.id===m),c=n.subtasks?n.subtasks.length-a:0;return t.info(`Successfully expanded task ${m} with ${c} new subtasks`),{success:!0,data:{task:e.task,subtasksAdded:c,hasExistingSubtasks:i,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}}catch(e){return!s&&C()&&y(),t.error(`Error expanding task: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message||`Failed to expand task`}}}}catch(e){return t.error(`Error expanding task: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message||`Failed to expand task`}}}}async function Nt(e,t){let{tasksJsonPath:n,projectRoot:r,tag:i}=e;try{if(t.info(`Fixing invalid dependencies in tasks: ${n}`),!n)return t.error(`fixDependenciesDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let e=n;return P.existsSync(e)?(b(),await Oe(e,{projectRoot:r,tag:i}),y(),{success:!0,data:{message:`Dependencies fixed successfully`,tasksPath:e,tag:i||`master`}}):{success:!1,error:{code:`FILE_NOT_FOUND`,message:`Tasks file not found at ${e}`}}}catch(e){return y(),t.error(`Error fixing dependencies: ${e.message}`),{success:!1,error:{code:`FIX_DEPENDENCIES_ERROR`,message:e.message}}}}async function Pt(e,t,n={}){let{session:r}=n,i=Re.homedir();t.info(`Args received in direct function: ${JSON.stringify(e)}`);let a=e.projectRoot;if(!a||typeof a!=`string`||a===`/`||a===i)return t.error(`Invalid target directory received from tool layer: '${a}'`),{success:!1,error:{code:`INVALID_TARGET_DIRECTORY`,message:`Cannot initialize project: Invalid target directory '${a}' received. Please ensure a valid workspace/folder is open or specified.`,details:`Received args.projectRoot: ${e.projectRoot}`}};t.info(`Validated target directory for initialization: ${a}`);let o=process.cwd(),s,c=!1,l=null;t.info(`Temporarily changing CWD to ${a} for initialization.`),process.chdir(a),b();try{let n={addAliases:e.addAliases,initGit:e.initGit,storeTasksInGit:e.storeTasksInGit,skipInstall:e.skipInstall,yes:!0};Array.isArray(e.rules)&&e.rules.length>0?(n.rules=e.rules,n.rulesExplicitlyProvided=!0,t.info(`Including rules: ${e.rules.join(`, `)}`)):(n.rules=[`claude`],n.rulesExplicitlyProvided=!0,t.info(`No rule profiles specified, defaulting to: Claude`)),t.info(`Initializing project with options: ${JSON.stringify(n)}`),s={message:`Project initialized successfully.`,next_step:`Now that the project is initialized, the next step is to create the tasks by parsing a PRD. This will create the tasks folder and the initial task files (tasks folder will be created when parse-prd is run). The parse-prd tool will require a prd.txt file as input (typically found in .taskgraph/docs/ directory). You can create a prd.txt file by asking the user about their idea, and then using the .taskgraph/templates/example_prd.txt file as a template to generate a prd.txt file in .taskgraph/docs/. You may skip all of this if the user already has a prd.txt file. You can THEN use the parse-prd tool to create the tasks. So: step 1 after initialization is to create a prd.txt file in .taskgraph/docs/prd.txt or confirm the user already has one. Step 2 is to use the parse-prd tool to create the tasks. Do not bother looking for tasks after initialization, just use the parse-prd tool to create the tasks after creating a prd.txt from which to parse the tasks. You do NOT need to reinitialize the project to parse-prd.`,...await Ie(n)},c=!0,t.info(`Project initialization completed successfully in ${a}.`)}catch(e){t.error(`Core initializeProject failed: ${e.message}`),l={code:`INITIALIZATION_FAILED`,message:`Core project initialization failed: ${e.message}`,details:e.stack},c=!1}finally{y(),t.info(`Restoring original CWD: ${o}`),process.chdir(o)}return c?{success:!0,data:s}:{success:!1,error:l}}async function Ft(e,t,n={}){let{tasksJsonPath:r,showMetadata:i=!1,projectRoot:a}=e,{session:o}=n;b();let s=Z(t);try{if(!r)return t.error(`listTagsDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};t.info(`Listing all tags`);let e=await ke(r,{showMetadata:i},{session:o,mcpLog:s,projectRoot:a},`json`),n=e.tags.map(e=>{let t=e.tasks||[],n=t.reduce((e,t)=>{let n=t.status||`pending`;return e[n]=(e[n]||0)+1,e},{}),r=t.reduce((e,t)=>(t.subtasks&&t.subtasks.length>0&&(e.totalSubtasks+=t.subtasks.length,t.subtasks.forEach(t=>{let n=t.status||`pending`;e.subtasksByStatus[n]=(e.subtasksByStatus[n]||0)+1})),e),{totalSubtasks:0,subtasksByStatus:{}});return{name:e.name,isCurrent:e.isCurrent,taskCount:t.length,completedTasks:e.completedTasks,statusBreakdown:n,subtaskCounts:r,created:e.created,description:e.description}});return y(),{success:!0,data:{tags:n,currentTag:e.currentTag,totalTags:e.totalTags,message:`Found ${e.totalTags} tag(s)`}}}catch(e){return y(),t.error(`Error in listTagsDirect: ${e.message}`),{success:!1,error:{code:e.code||`LIST_TAGS_ERROR`,message:e.message}}}}const It=[`main`,`research`,`fallback`];async function Lt(e,t){for(let n of It){let r=`set${n.charAt(0).toUpperCase()+n.slice(1)}`;if(e[r])return await de(n,e[r],t)}return null}async function Rt(e,t,n={}){let{session:r}=n,{projectRoot:i}=e,a=Z(t);t.info(`Executing models_direct with args: ${JSON.stringify(e)}`),t.info(`Using project root: ${i}`);try{b();try{return e.listAvailableModels===!0?await fe({session:r,mcpLog:a,projectRoot:i}):await Lt(e,{session:r,mcpLog:a,projectRoot:i})||await Ae({session:r,mcpLog:a,projectRoot:i})}finally{y()}}catch(e){return t.error(`Error in models_direct: ${e.message}`),{success:!1,error:{code:`DIRECT_FUNCTION_ERROR`,message:e.message,details:e.stack}}}}async function zt(e,t,n={}){let{session:r}=n,{projectRoot:i}=e;if(t.info(`moveTaskCrossTagDirect called with args: ${JSON.stringify(e)}`),!e.sourceIds)return{success:!1,error:{message:`Source IDs are required`,code:`MISSING_SOURCE_IDS`}};if(!e.sourceTag)return{success:!1,error:{message:`Source tag is required for cross-tag moves`,code:`MISSING_SOURCE_TAG`}};if(!e.targetTag)return{success:!1,error:{message:`Target tag is required for cross-tag moves`,code:`MISSING_TARGET_TAG`}};if(e.sourceTag===e.targetTag)return{success:!1,error:{message:`Source and target tags are the same ("${e.sourceTag}")`,code:`SAME_SOURCE_TARGET_TAG`,suggestions:[`Use different tags for cross-tag moves`,`Use within-tag move: taskgraph move --from=<id> --to=<id> --tag=<tag>`,`Check available tags: taskgraph tags`]}};try{let n=e.tasksJsonPath||e.file;if(!n){if(!e.projectRoot)return{success:!1,error:{message:`Project root is required if tasksJsonPath is not provided`,code:`MISSING_PROJECT_ROOT`}};n=Y(e,t)}b();try{let t=e.sourceIds.split(`,`).map(e=>e.trim()),r={withDependencies:e.withDependencies||!1,ignoreDependencies:e.ignoreDependencies||!1};return{success:!0,data:{...await ue(n,t,e.sourceTag,e.targetTag,r,{projectRoot:i}),message:`Successfully moved ${t.length} task(s) from "${e.sourceTag}" to "${e.targetTag}"`,moveOptions:r,sourceTag:e.sourceTag,targetTag:e.targetTag}}}finally{y()}}catch(e){t.error(`Failed to move tasks between tags: ${e.message}`),t.error(`Error code: ${e.code}, Error name: ${e.name}`);let n=`MOVE_TASK_CROSS_TAG_ERROR`,r=[];return e.code===`CROSS_TAG_DEPENDENCY_CONFLICTS`?(n=`CROSS_TAG_DEPENDENCY_CONFLICT`,r=[`Use --with-dependencies to move dependent tasks together`,`Use --ignore-dependencies to break cross-tag dependencies`,`Run taskgraph validate-dependencies to check for issues`,`Move dependencies first, then move the main task`]):e.code===`CANNOT_MOVE_SUBTASK`?(n=`SUBTASK_MOVE_RESTRICTION`,r=[`Promote subtask to full task first: taskgraph remove-subtask --id=<subtaskId> --convert`,`Move the parent task with all subtasks using --with-dependencies`]):e.code===`TASK_NOT_FOUND`||e.code===`INVALID_SOURCE_TAG`||e.code===`INVALID_TARGET_TAG`?(n=`TAG_OR_TASK_NOT_FOUND`,r=[`Check available tags: taskgraph tags`,`Verify task IDs exist: taskgraph list`,`Check task details: taskgraph show <id>`]):e.message.includes(`cross-tag dependency conflicts`)?(n=`CROSS_TAG_DEPENDENCY_CONFLICT`,r=[`Use --with-dependencies to move dependent tasks together`,`Use --ignore-dependencies to break cross-tag dependencies`,`Run taskgraph validate-dependencies to check for issues`,`Move dependencies first, then move the main task`]):e.message.includes(`Cannot move subtask`)?(n=`SUBTASK_MOVE_RESTRICTION`,r=[`Promote subtask to full task first: taskgraph remove-subtask --id=<subtaskId> --convert`,`Move the parent task with all subtasks using --with-dependencies`]):e.message.includes(`not found`)?(n=`TAG_OR_TASK_NOT_FOUND`,r=[`Check available tags: taskgraph tags`,`Verify task IDs exist: taskgraph list`,`Check task details: taskgraph show <id>`]):(e.code===`TASK_ALREADY_EXISTS`||e.message?.includes(`already exists in target tag`))&&(n=`TASK_ALREADY_EXISTS`,r=[`Choose a different target tag without conflicting IDs`,`Move a different set of IDs (avoid existing ones)`,`If needed, move within-tag to a new ID first, then cross-tag move`]),{success:!1,error:{message:e.message,code:n,suggestions:r}}}}async function Q(e,t,n={}){let{session:r}=n,{projectRoot:i,tag:a}=e;if(!e.sourceId)return{success:!1,error:{message:`Source ID is required`,code:`MISSING_SOURCE_ID`}};if(!e.destinationId)return{success:!1,error:{message:`Destination ID is required`,code:`MISSING_DESTINATION_ID`}};try{let n=e.tasksJsonPath||e.file;if(!n){if(!e.projectRoot)return{success:!1,error:{message:`Project root is required if tasksJsonPath is not provided`,code:`MISSING_PROJECT_ROOT`}};n=Y(e,t)}b();let r=e.generateFiles!==!1,o=await he(n,e.sourceId,e.destinationId,r,{projectRoot:i,tag:a});return y(),{success:!0,data:{...o,message:`Successfully moved task/subtask ${e.sourceId} to ${e.destinationId}`}}}catch(e){return y(),t.error(`Failed to move task: ${e.message}`),{success:!1,error:{message:e.message,code:`MOVE_TASK_ERROR`}}}}async function Bt(e,t,n={}){let{tasksJsonPath:r,reportPath:i,projectRoot:a,tag:o}=e,{session:s}=n;if(!r)return t.error(`nextTaskDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};let c=async()=>{try{b(),t.info(`Finding next task from ${r}`);let e=x(r,a,o);if(!e||!e.tasks)return y(),{success:!1,error:{code:`INVALID_TASKS_FILE`,message:`No valid tasks found in ${r}`}};let n=S(i),s=Se(e.tasks,n);if(!s)return t.info(`No eligible next task found. All tasks are either completed or have unsatisfied dependencies`),{success:!0,data:{message:`No eligible next task found. All tasks are either completed or have unsatisfied dependencies`,nextTask:null}};let c=typeof s.id==`string`&&s.id.includes(`.`),l=c?`subtask`:`task`,u=c?`Subtasks can be updated with timestamped details as you implement them. This is useful for tracking progress, marking milestones and insights (of successful or successive falures in attempting to implement the subtask). Research can be used when updating the subtask to collect up-to-date information, and can be helpful to solve a repeating problem the agent is unable to solve. It is a good idea to get-task the parent task to collect the overall context of the task, and to get-task the subtask to collect the specific details of the subtask.`:`Tasks can be updated to reflect a change in the direction of the task, or to reformulate the task per your prompt. Research can be used when updating the task to collect up-to-date information. It is best to update subtasks as you work on them, and to update the task for more high-level changes that may affect pending subtasks or the general direction of the task.`;return y(),t.info(`Successfully found next task ${s.id}: ${s.title}. Is subtask: ${c}`),{success:!0,data:{nextTask:s,isSubtask:c,nextSteps:`When ready to work on the ${l}, use set-status to set the status to "in progress" ${u}`}}}catch(e){return y(),t.error(`Error finding next task: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message||`Failed to find next task`}}}};try{let e=await c();return t.info(`nextTaskDirect completed.`),e}catch(e){return t.error(`Unexpected error during nextTask: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}async function Vt(e,t,n={}){let{session:r,reportProgress:i}=n,{input:a,output:o,numTasks:s,force:c,append:l,research:u,projectRoot:d,tag:f}=e,p=Z(t);if(!d)return p.error(`parsePRDDirect requires a projectRoot argument.`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`projectRoot is required.`}};let m;if(a)try{m=xt({input:a,projectRoot:d},r)}catch(e){return p.error(`Error resolving PRD path: ${e.message}`),{success:!1,error:{code:`FILE_NOT_FOUND`,message:e.message}}}else return p.error(`parsePRDDirect called without input path`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Input path is required`}};let h=o?A.isAbsolute(o)?o:A.resolve(d,o):St(`.taskgraph/tasks/tasks.json`,e)||A.resolve(d,`.taskgraph/tasks/tasks.json`);if(!P.existsSync(m)){let e=`Input PRD file not found at resolved path: ${m}`;return p.error(e),{success:!1,error:{code:`FILE_NOT_FOUND`,message:e}}}let g=A.dirname(h);try{P.existsSync(g)||(p.info(`Creating output directory: ${g}`),P.mkdirSync(g,{recursive:!0}))}catch(e){let t=`Failed to create output directory ${g}: ${e.message}`;return p.error(t),{success:!1,error:{code:`DIRECTORY_CREATE_FAILED`,message:t}}}let _=re(d);s&&(_=typeof s==`string`?parseInt(s,10):s,(Number.isNaN(_)||_<0)&&(_=re(d),p.warn(`Invalid numTasks value: ${s}. Using default: ${_}`))),l&&(p.info(`Append mode enabled.`),c&&p.warn(`Both --force and --append flags were provided. --force takes precedence; append mode will be ignored.`)),u&&p.info(`Research mode enabled. Using Claude Code web research for enhanced PRD analysis.`),p.info(`Parsing PRD via direct function. Input: ${m}, Output: ${h}, NumTasks: ${_}, Force: ${c}, Append: ${l}, Research: ${u}, ProjectRoot: ${d}`);let v=C();v||b();try{let e=await me(m,h,_,{session:r,mcpLog:p,projectRoot:d,tag:f,force:c,append:l,research:u,reportProgress:i,commandName:`parse-prd`,outputType:`mcp`},`json`);if(e&&e.success){let t=`Successfully parsed PRD and generated tasks in ${e.tasksPath}`;return p.success(t),{success:!0,data:{message:t,outputPath:e.tasksPath,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}}return p.error(`Core parsePRD function did not return a successful structure.`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e?.message||`Core function failed to parse PRD or returned unexpected result.`}}}catch(e){return p.error(`Error executing core parsePRD: ${e.message}`),{success:!1,error:{code:`PARSE_PRD_CORE_ERROR`,message:e.message||`Unknown error parsing PRD`}}}finally{!v&&C()&&y()}}async function Ht(e,t){let{tasksJsonPath:n,id:r,dependsOn:i,projectRoot:a,tag:o}=e;try{if(t.info(`Removing dependency with args: ${JSON.stringify(e)}`),!n)return t.error(`removeDependencyDirect 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(`Removing dependency: task ${c} no longer depends on ${l}`),b(),await je(s,c,l,{projectRoot:a,tag:o}),y(),{success:!0,data:{message:`Successfully removed dependency: Task ${c} no longer depends on ${l}`,taskId:c,dependencyId:l}}}catch(e){return y(),t.error(`Error in removeDependencyDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Ut(e,t){let{tasksJsonPath:n,id:r,convert:i,skipGenerate:a,projectRoot:o,tag:s}=e;try{if(b(),t.info(`Removing subtask with args: ${JSON.stringify(e)}`),!n)return t.error(`removeSubtaskDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!r)return y(),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Subtask ID is required and must be in format "parentId.subtaskId"`}};if(!r.includes(`.`))return y(),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Invalid subtask ID format: ${r}. Expected format: "parentId.subtaskId"`}};let c=n,l=i===!0,u=!a;t.info(`Removing subtask ${r} (convertToTask: ${l}, generateFiles: ${u})`);let d=await pe(c,r,l,u,{projectRoot:o,tag:s});return y(),l&&d?{success:!0,data:{message:`Subtask ${r} successfully converted to task #${d.id}`,task:d}}:{success:!0,data:{message:`Subtask ${r} successfully removed`}}}catch(e){return y(),t.error(`Error in removeSubtaskDirect: ${e.message}`),{success:!1,error:{code:`CORE_FUNCTION_ERROR`,message:e.message}}}}async function Wt(e,t,n={}){let{tasksJsonPath:r,id:i,projectRoot:a,tag:o}=e,{session:s}=n;try{if(!r)return t.error(`removeTaskDirect called without tasksJsonPath`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i)return t.error(`Task ID is required`),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:`Task ID is required`}};let e=i.split(`,`).map(e=>e.trim());t.info(`Removing ${e.length} task(s) with ID(s): ${e.join(`, `)} from ${r}${o?` in tag '${o}'`:``}`);let n=x(r,a,o);if(!n||!n.tasks)return{success:!1,error:{code:`INVALID_TASKS_FILE`,message:`No valid tasks found in ${r}${o?` for tag '${o}'`:``}`}};let s=e.filter(e=>!Ee(n.tasks,e));if(s.length>0)return{success:!1,error:{code:`INVALID_TASK_ID`,message:`The following tasks were not found${o?` in tag '${o}'`:``}: ${s.join(`, `)}`}};b();try{let n=await ae(r,i,{projectRoot:a,tag:o});return n.success?(t.info(`Successfully removed ${n.removedTasks.length} task(s)`),{success:!0,data:{totalTasks:e.length,successful:n.removedTasks.length,failed:e.length-n.removedTasks.length,removedTasks:n.removedTasks,message:n.message,tasksPath:r,tag:o}}):{success:!1,error:{code:`REMOVE_TASK_ERROR`,message:n.error||`Failed to remove tasks`}}}finally{y()}}catch(e){return y(),t.error(`Unexpected error in removeTaskDirect: ${e.message}`),{success:!1,error:{code:`UNEXPECTED_ERROR`,message:e.message}}}}async function Gt(e,t,n={}){let{tasksJsonPath:r,oldName:i,newName:a,projectRoot:o}=e,{session:s}=n;b();let c=Z(t);try{if(!r)return t.error(`renameTagDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i||typeof i!=`string`)return t.error(`Missing required parameter: oldName`),y(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Old tag name is required and must be a string`}};if(!a||typeof a!=`string`)return t.error(`Missing required parameter: newName`),y(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`New tag name is required and must be a string`}};t.info(`Renaming tag from "${i}" to "${a}"`);let e=await Ce(r,i,a,{},{session:s,mcpLog:c,projectRoot:o},`json`);return y(),{success:!0,data:{oldName:e.oldName,newName:e.newName,renamed:e.renamed,taskCount:e.taskCount,wasCurrentTag:e.wasCurrentTag,message:`Successfully renamed tag from "${e.oldName}" to "${e.newName}"`}}}catch(e){return y(),t.error(`Error in renameTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`RENAME_TAG_ERROR`,message:e.message}}}}async function Kt(e,t,n={}){let{query:r,taskIds:i,filePaths:a,customContext:o,includeProjectTree:s=!1,detailLevel:c=`medium`,saveTo:l,saveToFile:u=!1,projectRoot:d,tag:f}=e,{session:p}=n;b();let m=Z(t);try{if(!r||typeof r!=`string`||r.trim().length===0)return t.error(`Missing or invalid required parameter: query`),y(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The query parameter is required and must be a non-empty string`}};let e=i?i.split(`,`).map(e=>e.trim()).filter(e=>e.length>0):[],n=a?a.split(`,`).map(e=>e.trim()).filter(e=>e.length>0):[],h=[`low`,`medium`,`high`];if(!h.includes(c))return t.error(`Invalid detail level: ${c}`),y(),{success:!1,error:{code:`INVALID_PARAMETER`,message:`Detail level must be one of: ${h.join(`, `)}`}};t.info(`Performing research query: "${r.substring(0,100)}${r.length>100?`...`:``}", taskIds: [${e.join(`, `)}], filePaths: [${n.join(`, `)}], detailLevel: ${c}, includeProjectTree: ${s}, projectRoot: ${d}`);let g={taskIds:e,filePaths:n,customContext:o||``,includeProjectTree:s,detailLevel:c,projectRoot:d,tag:f,saveToFile:u},_={session:p,mcpLog:m,commandName:`research`,outputType:`mcp`},v=await De(r.trim(),g,_,`json`,!1);if(l)try{let e=l.includes(`.`),n=`## Research Query: ${r.trim()}
6
6
 
7
- **Detail Level:** ${y.detailLevel}
8
- **Context Size:** ${y.contextSize} characters
9
- **Timestamp:** ${new Date().toLocaleDateString()} ${new Date().toLocaleTimeString()}
7
+ **Detail Level:** ${v.detailLevel}
8
+ **Context Size:** ${v.contextSize} characters
9
+ **Timestamp:** ${(/* @__PURE__ */ new Date()).toLocaleDateString()} ${(/* @__PURE__ */ new Date()).toLocaleTimeString()}
10
10
 
11
11
  ### Results
12
12
 
13
- ${y.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-BOFRADbR.js`);await e(N.join(p,`.taskgraph`,`tasks`,`tasks.json`),d,n,!1,{session:h,mcpLog:g,commandName:`research-save`,outputType:`mcp`,projectRoot:p,tag:m},`json`),t.info(`Research saved to subtask ${d}`)}else{let e=(await import(`./update-task-by-id-DTHqRii_.js`)).default,r=parseInt(d,10);await e(N.join(p,`.taskgraph`,`tasks`,`tasks.json`),r,n,!1,{session:h,mcpLog:g,commandName:`research-save`,outputType:`mcp`,projectRoot:p,tag:m},`json`,!0),t.info(`Research saved to task ${d}`)}}catch(e){t.warn(`Error saving research to task/subtask: ${e.message}`)}return i(),{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 i(),t.error(`Error in researchDirect: ${e.message}`),{success:!1,error:{code:e.code||`RESEARCH_ERROR`,message:e.message}}}}async function qt(e,t,n={}){let{tasksJsonPath:r,id:a,strength:o=`regular`,prompt:c,research:l=!1,projectRoot:u,tag:d}=e,{session:f}=n;s();let p=Q(t);try{if(!r)return t.error(`scopeDownDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a)return t.error(`Missing required parameter: id`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The id parameter is required for scoping down tasks`}};let e=a.split(`,`).map(e=>parseInt(e.trim(),10));t.info(`Scoping down tasks: ${e.join(`, `)}, strength: ${o}, research: ${l}`);let n=await ue(r,e,o,c,{session:f,mcpLog:p,projectRoot:u,commandName:`scope-down`,outputType:`mcp`,tag:d,research:l},`json`);return i(),{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 i(),t.error(`Error in scopeDownDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_DOWN_ERROR`,message:e.message}}}}async function Jt(e,t,n={}){let{tasksJsonPath:r,id:a,strength:o=`regular`,prompt:c,research:l=!1,projectRoot:u,tag:d}=e,{session:f}=n;s();let p=Q(t);try{if(!r)return t.error(`scopeUpDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a)return t.error(`Missing required parameter: id`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`The id parameter is required for scoping up tasks`}};let e=a.split(`,`).map(e=>parseInt(e.trim(),10));t.info(`Scoping up tasks: ${e.join(`, `)}, strength: ${o}, research: ${l}`);let n=await le(r,e,o,c,{session:f,mcpLog:p,projectRoot:u,commandName:`scope-up`,outputType:`mcp`,tag:d,research:l},`json`);return i(),{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 i(),t.error(`Error in scopeUpDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_UP_ERROR`,message:e.message}}}}async function Yt(e,t,n={}){let{session:r}=n,{tasksJsonPath:a,id:o,prompt:c,research:l,metadata:u,projectRoot:d,tag:f}=e,p=Q(t);try{if(p.info(`Updating subtask by ID via direct function. ID: ${o}, ProjectRoot: ${d}`),!a){let e=`tasksJsonPath is required but was not provided.`;return p.error(e),{success:!1,error:{code:`MISSING_ARGUMENT`,message:e}}}if(!o||typeof o!=`string`||!o.trim()){let e=`Subtask ID cannot be empty.`;return p.error(e),{success:!1,error:{code:`INVALID_SUBTASK_ID`,message:e}}}if(!c&&!u){let e=`No prompt or metadata specified. Please provide information to append or metadata to update.`;return p.error(e),{success:!1,error:{code:`MISSING_PROMPT`,message:e}}}let e=String(o).trim(),n=a,m=l===!0;t.info(`Updating subtask with ID ${e} with prompt "${c||`(metadata-only)`}" and research: ${m}`);let h=w();h||s();try{let t=await ce(n,e,c,m,{mcpLog:p,session:r,projectRoot:d,tag:f,commandName:`update-subtask`,outputType:`mcp`,metadata:u},`json`);if(!t||t.updatedSubtask===null){let e=`Subtask ${o} or its parent task not found.`;return p.error(e),{success:!1,error:{code:`SUBTASK_NOT_FOUND`,message:e}}}let i=e.split(`.`)[0],a=`Successfully updated subtask with ID ${e}`;return p.success(a),{success:!0,data:{message:`Successfully updated subtask with ID ${e}`,subtaskId:e,parentId:i,subtask:t.updatedSubtask,tasksPath:n,useResearch:m,telemetryData:t.telemetryData,tagInfo:t.tagInfo}}}catch(e){return p.error(`Error updating subtask by ID: ${e.message}`),{success:!1,error:{code:`UPDATE_SUBTASK_CORE_ERROR`,message:e.message||`Unknown error updating subtask`}}}finally{!h&&w()&&i()}}catch(e){return p.error(`Setup error in updateSubtaskByIdDirect: ${e.message}`),w()&&i(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function Xt(e,t,n={}){let{session:r}=n,{tasksJsonPath:a,id:o,prompt:c,research:l,append:u,metadata:d,projectRoot:f,tag:p}=e,m=Q(t);try{if(m.info(`Updating task by ID via direct function. ID: ${o}, ProjectRoot: ${f}`),!o){let e=`No task ID specified. Please provide a task ID to update.`;return m.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}if(!c&&!d){let e=`No prompt or metadata specified. Please provide a prompt with new information or metadata for the task update.`;return m.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let t;if(typeof o==`string`)t=o;else if(typeof o==`number`)t=String(o);else{let e=`Invalid task ID type: ${typeof o}. Task ID must be a string or number.`;return m.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let n=a||Z({projectRoot:f,file:e.file},m);if(!n){let e=`tasks.json path could not be resolved.`;return m.error(e),{success:!1,error:{code:`INPUT_VALIDATION_ERROR`,message:e}}}let h=l===!0;m.info(`Updating task with ID ${t} with prompt "${c||`(metadata-only)`}" and research: ${h}`);let g=w();g||s();try{let e=await ye(n,t,c,h,{mcpLog:m,session:r,projectRoot:f,tag:p,commandName:`update-task`,outputType:`mcp`,metadata:d},`json`,u||!1);if(!e||e.updatedTask===null){let n=`Task ${t} was not updated (likely already completed).`;return m.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 m.info(i),{success:!0,data:{message:i,taskId:t,tasksPath:n,useResearch:h,updated:!0,updatedTask:e.updatedTask,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}}catch(e){return m.error(`Error updating task by ID: ${e.message}`),{success:!1,error:{code:`UPDATE_TASK_CORE_ERROR`,message:e.message||`Unknown error updating task`}}}finally{!g&&w()&&i()}}catch(e){return m.error(`Setup error in updateTaskByIdDirect: ${e.message}`),w()&&i(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function Zt(e,t,n={}){let{session:r}=n,{from:a,prompt:o,research:c,tasksJsonPath:l,projectRoot:u,tag:d}=e,f=Q(t);if(!u)return f.error(`updateTasksDirect requires a projectRoot argument.`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`projectRoot is required.`}};if(!a)return f.error(`updateTasksDirect called without from ID`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Starting task ID (from) is required`}};if(!o)return f.error(`updateTasksDirect called without prompt`),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`Update prompt is required`}};f.info(`Updating tasks via direct function. From: ${a}, Research: ${c}, File: ${l}, ProjectRoot: ${u}`),s();try{let e=await Pe(l,a,o,c,{session:r,mcpLog:f,projectRoot:u,tag:d},`json`);return e&&e.success&&Array.isArray(e.updatedTasks)?(f.success(`Successfully updated ${e.updatedTasks.length} tasks.`),{success:!0,data:{message:`Successfully updated ${e.updatedTasks.length} tasks.`,tasksPath:l,updatedCount:e.updatedTasks.length,telemetryData:e.telemetryData,tagInfo:e.tagInfo}}):(f.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 f.error(`Error executing core updateTasks: ${e.message}`),{success:!1,error:{code:`UPDATE_TASKS_CORE_ERROR`,message:e.message||`Unknown error updating tasks`}}}finally{i()}}async function Qt(e,t,n={}){let{tasksJsonPath:r,name:a,projectRoot:o}=e,{session:c}=n;s();let l=Q(t);try{if(!r)return t.error(`useTagDirect called without tasksJsonPath`),i(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!a||typeof a!=`string`)return t.error(`Missing required parameter: name`),i(),{success:!1,error:{code:`MISSING_PARAMETER`,message:`Tag name is required and must be a string`}};t.info(`Switching to tag: ${a}`);let e=await Ee(r,a,{},{session:c,mcpLog:l,projectRoot:o},`json`);return i(),{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 i(),t.error(`Error in useTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`USE_TAG_ERROR`,message:e.message}}}}async function $t(e,t){let{tasksJsonPath:n,projectRoot:r,tag:a}=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 M.existsSync(e)?(s(),await Te(e,{projectRoot:r,tag:a}),i(),{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 i(),t.error(`Error validating dependencies: ${e.message}`),{success:!1,error:{code:`VALIDATION_ERROR`,message:e.message}}}}function en(e){e.addTool({name:`add_dependency`,description:`Add a dependency relationship between two tasks`,parameters:F.object({id:F.string().describe(`ID of task that will depend on another task`),dependsOn:F.string().describe(`ID of task that will become a dependency`),file:F.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.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=b({projectRoot:e.projectRoot,tag:e.tag}),r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let i=await gt({tasksJsonPath:r,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t);return i.success?t.info(`Successfully added dependency: ${i.data.message}`):t.error(`Failed to add dependency: ${i.error.message}`),W({result:i,log:t,errorPrefix:`Error adding dependency`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in addDependency tool: ${e.message}`),U(e.message)}})})}function tn(e){e.addTool({name:`add_subtask`,description:`Add a subtask to an existing task`,parameters:F.object({id:F.string().describe(`Parent task ID (required)`),taskId:F.string().optional().describe(`Existing task ID to convert to subtask`),title:F.string().optional().describe(`Title for the new subtask (when creating a new subtask)`),description:F.string().optional().describe(`Description for the new subtask`),details:F.string().optional().describe(`Implementation details for the new subtask`),status:F.string().optional().describe(`Status for the new subtask (default: 'pending')`),dependencies:F.string().optional().describe(`Comma-separated list of dependency IDs for the new subtask`),file:F.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:F.boolean().optional().describe(`Skip regenerating task files`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Add Subtask`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{let r=b({projectRoot:e.projectRoot,tag:e.tag});t.info(`Adding subtask with args: ${JSON.stringify(e)}`);let i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let a=await _t({tasksJsonPath:i,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:r},t,{session:n});return a.success?t.info(`Subtask added successfully: ${a.data.message}`):t.error(`Failed to add subtask: ${a.error.message}`),W({result:a,log:t,errorPrefix:`Error adding subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in addSubtask tool: ${e.message}`),U(e.message)}})})}function nn(e){e.addTool({name:`add_tag`,description:`Create a new tag for organizing tasks in different contexts`,parameters:F.object({name:F.string().describe(`Name of the new tag to create`),copyFromCurrent:F.boolean().optional().describe(`Whether to copy tasks from the current tag (default: false)`),copyFromTag:F.string().optional().describe(`Specific tag to copy tasks from`),fromBranch:F.boolean().optional().describe(`Create tag name from current git branch (ignores name parameter)`),description:F.string().optional().describe(`Optional description for the tag`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Add Tag`,destructiveHint:!1},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting add-tag with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await Ct({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}`),U(e.message)}})})}function rn(e){e.addTool({name:`add_task`,description:`Add a new task using AI`,parameters:F.object({prompt:F.string().optional().describe(`Description of the task to add (required if not using manual fields)`),title:F.string().optional().describe(`Task title (for manual task creation)`),description:F.string().optional().describe(`Task description (for manual task creation)`),details:F.string().optional().describe(`Implementation details (for manual task creation)`),testStrategy:F.string().optional().describe(`Test strategy (for manual task creation)`),dependencies:F.string().optional().describe(`Comma-separated list of task IDs this task depends on`),priority:F.string().optional().describe(`Task priority (high, medium, low)`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`),research:F.boolean().optional().describe(`Whether to use research capabilities for task creation`)}),annotations:{title:`Add Task`,destructiveHint:!1},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting add-task with args: ${JSON.stringify(e)}`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await wt({tasksJsonPath:i,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:r},t,{session:n}),log:t,errorPrefix:`Error adding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in add-task tool: ${e.message}`),U(e.message)}})})}function an(e){e.addTool({name:`analyze_project_complexity`,description:`Analyze task complexity and generate expansion recommendations.`,parameters:F.object({threshold:F.coerce.number().int().min(1).max(10).optional().default(5).describe(`Complexity score threshold (1-10) to recommend expansion.`),research:F.boolean().optional().default(!1).describe(`Use Claude Code web research for research-backed analysis.`),output:F.string().optional().describe(`Output file path relative to project root (default: ${re}).`),file:F.string().optional().describe(`Path to the tasks file relative to project root (default: tasks/tasks.json).`),ids:F.string().optional().describe(`Comma-separated list of task IDs to analyze specifically (e.g., "1,3,5").`),from:F.coerce.number().int().positive().optional().describe(`Starting task ID in a range to analyze.`),to:F.coerce.number().int().positive().optional().describe(`Ending task ID in a range to analyze.`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Analyze Project Complexity`,destructiveHint:!0},execute:K(async(e,{log:n,session:r})=>{let i=`analyze_project_complexity`;try{n.info(`Executing ${i} tool with args: ${JSON.stringify(e)}`);let a=b({projectRoot:e.projectRoot,tag:e.tag}),o;try{o=Z({projectRoot:e.projectRoot,file:e.file},n),n.info(`${i}: Resolved tasks path: ${o}`)}catch(t){return n.error(`${i}: Error finding tasks.json: ${t.message}`),U(`Failed to find tasks.json within project root '${e.projectRoot}': ${t.message}`)}let s=t(e.output,{projectRoot:e.projectRoot,tag:a},n);n.info(`${i}: Report output path: ${s}`);let c=N.dirname(s);try{M.existsSync(c)||(M.mkdirSync(c,{recursive:!0}),n.info(`${i}: Created output directory: ${c}`))}catch(e){return n.error(`${i}: Failed to create output directory ${c}: ${e.message}`),U(`Failed to create output directory: ${e.message}`)}let l=await Tt({tasksJsonPath:o,outputPath:s,threshold:e.threshold,research:e.research,projectRoot:e.projectRoot,tag:a,ids:e.ids,from:e.from,to:e.to},n,{session:r});return n.info(`${i}: Direct function result: success=${l.success}`),W({result:l,log:n,errorPrefix:`Error analyzing task complexity`,projectRoot:e.projectRoot})}catch(e){return n.error(`Critical error in ${i} tool execute: ${e.message}`),U(`Internal tool error (${i}): ${e.message}`)}})})}function on(e){e.addTool({name:`clear_subtasks`,description:`Clear subtasks from specified tasks`,parameters:F.object({id:F.string().optional().describe(`Task IDs (comma-separated) to clear subtasks from`),all:F.boolean().optional().describe(`Clear subtasks from all tasks`),file:F.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.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=b({projectRoot:e.projectRoot,tag:e.tag}),r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let i=await Et({tasksJsonPath:r,id:e.id,all:e.all,projectRoot:e.projectRoot,tag:n},t.log,{session:t.session});return i.success?t.log.info(`Subtasks cleared successfully: ${i.data.message}`):t.log.error(`Failed to clear subtasks: ${i.error.message}`),W({result:i,log:t.log,errorPrefix:`Error clearing subtasks`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in clearSubtasks tool: ${e.message}`),U(e.message)}})})}function sn(e){e.addTool({name:`complexity_report`,description:`Display the complexity analysis report in a readable format`,parameters:F.object({file:F.string().optional().describe(`Path to the report file (default: ${re})`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Complexity Report`,readOnlyHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Getting complexity report with args: ${JSON.stringify(e)}`);let n=y(e.projectRoot),r=xt({projectRoot:e.projectRoot,complexityReport:e.file,tag:n},t);if(t.info(`Reading complexity report from path: `,r),!r)return U(`No complexity report found. Run taskgraph analyze-complexity first.`);let i=await Dt({reportPath:r},t);return i.success?t.info(`Successfully retrieved complexity report`):t.error(`Failed to retrieve complexity report: ${i.error.message}`),W({result:i,log:t,errorPrefix:`Error retrieving complexity report`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in complexity-report tool: ${e.message}`),U(`Failed to retrieve complexity report: ${e.message}`)}})})}function cn(e){e.addTool({name:`copy_tag`,description:`Copy an existing tag to create a new tag with all tasks and metadata`,parameters:F.object({sourceName:F.string().describe(`Name of the source tag to copy from`),targetName:F.string().describe(`Name of the new tag to create`),description:F.string().optional().describe(`Optional description for the new tag`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Copy Tag`,destructiveHint:!1},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting copy-tag with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await Ot({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}`),U(e.message)}})})}function ln(e){e.addTool({name:`delete_tag`,description:`Delete an existing tag and all its tasks`,parameters:F.object({name:F.string().describe(`Name of the tag to delete`),yes:F.boolean().optional().describe(`Skip confirmation prompts (default: true for MCP)`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Delete Tag`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting delete-tag with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await kt({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}`),U(e.message)}})})}function un(e){e.addTool({name:`expand_all`,description:`Expand all pending tasks into subtasks based on complexity or defaults`,parameters:F.object({num:F.string().optional().describe(`Target number of subtasks per task (uses complexity/defaults otherwise)`),research:F.boolean().optional().describe(`Enable research-backed subtask generation (web research via Claude Code)`),prompt:F.string().optional().describe(`Additional context to guide subtask generation for all tasks`),force:F.boolean().optional().describe(`Force regeneration of subtasks for tasks that already have them`),file:F.string().optional().describe(`Absolute path to the tasks file in the /tasks folder inside the project root (default: tasks/tasks.json)`),projectRoot:F.string().optional().describe(`Absolute path to the project root directory (derived from session if possible)`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand All Tasks`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Tool expand_all execution started with args: ${JSON.stringify(e)}`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t),t.info(`Resolved tasks.json path: ${i}`)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let a=St(null,{projectRoot:e.projectRoot,tag:r},t);return t.info(`Using complexity report path: ${a}`),W({result:await At({tasksJsonPath:i,num:e.num,research:e.research,prompt:e.prompt,force:e.force,projectRoot:e.projectRoot,tag:r,complexityReportPath:a},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),U(`An unexpected error occurred: ${e.message}`)}})})}function dn(e){e.addTool({name:`expand_task`,description:`Expand a task into subtasks for detailed implementation`,parameters:F.object({id:F.string().describe(`ID of task to expand`),num:F.string().optional().describe(`Number of subtasks to generate`),research:F.boolean().optional().default(!1).describe(`Use research role for generation`),prompt:F.string().optional().describe(`Additional context for subtask generation`),file:F.string().optional().describe(`Path to the tasks file relative to project root (e.g., tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),force:F.boolean().optional().default(!1).describe(`Force expansion even if subtasks exist`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand Task`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting expand-task with args: ${JSON.stringify(e)}`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let a=xt({...e,tag:r},t);return W({result:await jt({tasksJsonPath:i,id:e.id,num:e.num,research:e.research,prompt:e.prompt,force:e.force,complexityReportPath:a,projectRoot:e.projectRoot,tag:r},t,{session:n}),log:t,errorPrefix:`Error expanding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in expand-task tool: ${e.message}`),U(e.message)}})})}function fn(e){e.addTool({name:`fix_dependencies`,description:`Fix invalid dependencies in tasks automatically`,parameters:F.object({file:F.string().optional().describe(`Absolute path to the tasks file`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.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=b({projectRoot:e.projectRoot,tag:e.tag}),r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let i=await Mt({tasksJsonPath:r,projectRoot:e.projectRoot,tag:n},t.log);return i.success?t.log.info(`Successfully fixed dependencies: ${i.data.message}`):t.log.error(`Failed to fix dependencies: ${i.error.message}`),W({result:i,log:t.log,errorPrefix:`Error fixing dependencies`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in fixDependencies tool: ${e.message}`),U(e.message)}})})}function pn(e){e.addTool({name:`initialize_project`,description:`Initializes a new TaskGraph project structure by calling the core initialization logic. Creates necessary folders and configuration files for TaskGraph in the current directory.`,parameters:F.object({skipInstall:F.boolean().optional().default(!1).describe(`Skip installing dependencies automatically. Never do this unless you are sure the project is already installed.`),addAliases:F.boolean().optional().default(!0).describe(`Add shell aliases (tm, taskgraph) to shell config file.`),initGit:F.boolean().optional().default(!0).describe(`Initialize Git repository in project root.`),storeTasksInGit:F.boolean().optional().default(!0).describe(`Store tasks in Git (tasks.json and tasks/ directory).`),yes:F.boolean().optional().default(!0).describe(`Skip prompts and use default values. Always set to true for MCP tools.`),projectRoot:F.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:F.array(F.enum(k)).optional().describe(`List of rule profiles to include at initialization. If omitted, defaults to the Claude profile. Available options: ${k.join(`, `)}`)}),annotations:{title:`Initialize Project`,destructiveHint:!0},execute:K(async(e,t)=>{let{log:n}=t,r=t.session;try{return n.info(`Executing initialize_project tool with args: ${JSON.stringify(e)}`),W({result:await Nt(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),U(t,{details:e.stack})}})})}function mn(e){e.addTool({name:`list_tags`,description:`List all available tags with task counts and metadata`,parameters:F.object({showMetadata:F.boolean().optional().describe(`Whether to include metadata in the output (default: false)`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`List Tags`,readOnlyHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting list-tags with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await Pt({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}`),U(e.message)}})})}function hn(e){e.addTool({name:`models`,description:`Get information about available AI models or set model configurations. TaskGraph uses Claude Code (models: opus, sonnet, haiku). Run without arguments to get the current model configuration.`,parameters:F.object({setMain:F.string().optional().describe(`Set the primary model for task generation/updates. One of: opus, sonnet, haiku.`),setResearch:F.string().optional().describe(`Set the model for research-backed operations. One of: opus, sonnet, haiku.`),setFallback:F.string().optional().describe(`Set the model to use if the primary fails. One of: opus, sonnet, haiku.`),listAvailableModels:F.boolean().optional().describe(`List all available models.`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Models`,destructiveHint:!0},execute:q(`models`,async(e,t)=>{try{return t.log.info(`Starting models tool with args: ${JSON.stringify(e)}`),W({result:await Lt({...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}`),U(e.message)}})})}function gn(e){e.addTool({name:`move_task`,description:`Move a task or subtask to a new position`,parameters:F.object({from:F.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:F.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:F.string().optional().describe(`Custom path to tasks.json file`),projectRoot:F.string().describe(`Root directory of the project (typically derived from session)`),tag:F.string().optional().describe(`Tag context to operate on`),fromTag:F.string().optional().describe(`Source tag for cross-tag moves`),toTag:F.string().optional().describe(`Target tag for cross-tag moves`),withDependencies:F.boolean().optional().describe(`Move dependent tasks along with main task`),ignoreDependencies:F.boolean().optional().describe(`Break cross-tag dependencies during move`)}),annotations:{title:`Move Task`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{if(e.fromTag&&e.toTag&&e.fromTag!==e.toTag){if(!e.from)return U(`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||=Z(e,t),W({result:await Rt({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 U(`Destination ID is required for within-tag moves`,`MISSING_DESTINATION_ID`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i=e.file;i||=Z(e,t);let a=e.from.split(`,`).map(e=>e.trim()),o=e.to.split(`,`).map(e=>e.trim());if(a.length!==o.length){if(a.length>1){let s=[],c=[];for(let l=0;l<a.length;l++){let u=a[l],d=o[l];if(u===d){t.info(`Skipping ${u} -> ${d} (same ID)`),c.push({fromId:u,toId:d,reason:`same ID`});continue}let f=l===a.length-1,p=await zt({sourceId:u,destinationId:d,tasksJsonPath:i,projectRoot:e.projectRoot,tag:r,generateFiles:f},t,{session:n});p.success?s.push(p.data):t.error(`Failed to move ${u} to ${d}: ${p.error.message}`)}return W({result:{success:!0,data:{moves:s,skipped:c.length>0?c:void 0,message:`Successfully moved ${s.length} tasks${c.length>0?`, skipped ${c.length}`:``}`}},log:t,errorPrefix:`Error moving multiple tasks`,projectRoot:e.projectRoot})}return W({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 W({result:await zt({sourceId:e.from,destinationId:e.to,tasksJsonPath:i,projectRoot:e.projectRoot,tag:r,generateFiles:!0},t,{session:n}),log:t,errorPrefix:`Error moving task`,projectRoot:e.projectRoot})}}catch(e){return U(`Failed to move task: ${e.message}`,`MOVE_TASK_ERROR`)}})})}function _n(e){e.addTool({name:`next_task`,description:`Find the next task to work on based on dependencies and status`,parameters:F.object({file:F.string().optional().describe(`Absolute path to the tasks file`),complexityReport:F.string().optional().describe(`Path to the complexity report file (relative to project root or absolute)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Next Task`,readOnlyHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Finding next task with args: ${JSON.stringify(e)}`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=X(e,n)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let a;try{a=yt({...e,tag:r},n)}catch(e){t.error(`Error finding complexity report: ${e.message}`),a=null}let o=await Bt({tasksJsonPath:i,reportPath:a,projectRoot:e.projectRoot,tag:r},t,{session:n});return t.info(`Next task result: ${o.success?`found`:`none`}`),W({result:o,log:t,errorPrefix:`Error finding next task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error finding next task: ${e.message}`),U(e.message)}})})}function vn(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 ${x} directory.`,parameters:F.object({input:F.string().optional().default(l).describe(`Absolute path to the PRD document file (.txt, .md, etc.)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`),output:F.string().optional().describe(`Output path for tasks.json file (default: ${r})`),numTasks:F.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 TaskGraph 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:F.boolean().optional().default(!1).describe(`Overwrite existing output file without prompting.`),research:F.boolean().optional().describe(`Enable TaskGraph to use the research role for potentially more informed task generation. Requires appropriate API key.`),append:F.boolean().optional().describe(`Append generated tasks to existing file.`)}),annotations:{title:`Parse PRD`,destructiveHint:!0},execute:K(async(e,{log:t,session:n,reportProgress:r})=>{try{let i=b({projectRoot:e.projectRoot,tag:e.tag}),a=Ue(r,t);return W({result:await Vt({...e,tag:i},t,{session:n,reportProgress:a}),log:t,errorPrefix:`Error parsing PRD`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in parse_prd: ${e.message}`),U(`Failed to parse PRD: ${e.message}`)}})})}function yn(e){e.addTool({name:`remove_dependency`,description:`Remove a dependency from a task`,parameters:F.object({id:F.string().describe(`Task ID to remove dependency from`),dependsOn:F.string().describe(`Task ID to remove as a dependency`),file:F.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Dependency`,destructiveHint:!0},execute:q(`remove-dependency`,async(e,t)=>{try{let n=b({projectRoot:e.projectRoot,tag:e.tag});t.log.info(`Removing dependency for task ${e.id} from ${e.dependsOn} with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let i=await Ht({tasksJsonPath:r,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t.log);return i.success?t.log.info(`Successfully removed dependency: ${i.data.message}`):t.log.error(`Failed to remove dependency: ${i.error.message}`),W({result:i,log:t.log,errorPrefix:`Error removing dependency`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in removeDependency tool: ${e.message}`),U(e.message)}})})}function bn(e){e.addTool({name:`remove_subtask`,description:`Remove a subtask from its parent task`,parameters:F.object({id:F.string().describe(`Subtask ID to remove in format 'parentId.subtaskId' (required)`),convert:F.boolean().optional().describe(`Convert the subtask to a standalone task instead of deleting it`),file:F.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:F.boolean().optional().describe(`Skip regenerating task files`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Subtask`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{let r=b({projectRoot:e.projectRoot,tag:e.tag});t.info(`Removing subtask with args: ${JSON.stringify(e)}`);let i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let a=await Ut({tasksJsonPath:i,id:e.id,convert:e.convert,skipGenerate:e.skipGenerate,projectRoot:e.projectRoot,tag:r},t,{session:n});return a.success?t.info(`Subtask removed successfully: ${a.data.message}`):t.error(`Failed to remove subtask: ${a.error.message}`),W({result:a,log:t,errorPrefix:`Error removing subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in removeSubtask tool: ${e.message}`),U(e.message)}})})}function xn(e){e.addTool({name:`remove_task`,description:`Remove a task or subtask permanently from the tasks list`,parameters:F.object({id:F.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:F.string().optional().describe(`Absolute path to the tasks file`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),confirm:F.boolean().optional().describe(`Whether to skip confirmation prompt (default: false)`),tag:F.string().optional().describe(`Specify which tag context to operate on. Defaults to the current active tag.`)}),annotations:{title:`Remove Task`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Removing task(s) with ID(s): ${e.id}`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}t.info(`Using tasks file path: ${i}`);let a=await Wt({tasksJsonPath:i,id:e.id,projectRoot:e.projectRoot,tag:r},t,{session:n});return a.success?t.info(`Successfully removed task: ${e.id}`):t.error(`Failed to remove task: ${a.error.message}`),W({result:a,log:t,errorPrefix:`Error removing task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in remove-task tool: ${e.message}`),U(`Failed to remove task: ${e.message}`)}})})}function Sn(e){e.addTool({name:`rename_tag`,description:`Rename an existing tag`,parameters:F.object({oldName:F.string().describe(`Current name of the tag to rename`),newName:F.string().describe(`New name for the tag`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Rename Tag`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting rename-tag with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await Gt({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}`),U(e.message)}})})}function Cn(e){e.addTool({name:`research`,description:`Perform AI-powered research queries with project context`,parameters:F.object({query:F.string().describe(`Research query/prompt (required)`),taskIds:F.string().optional().describe(`Comma-separated list of task/subtask IDs for context (e.g., "15,16.2,17")`),filePaths:F.string().optional().describe(`Comma-separated list of file paths for context (e.g., "src/api.js,docs/readme.md")`),customContext:F.string().optional().describe(`Additional custom context text to include in the research`),includeProjectTree:F.boolean().optional().describe(`Include project file tree structure in context (default: false)`),detailLevel:F.enum([`low`,`medium`,`high`]).optional().describe(`Detail level for the research response (default: medium)`),saveTo:F.string().optional().describe(`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`),saveToFile:F.boolean().optional().describe(`Save research results to .taskgraph/docs/research/ directory (default: false)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Research`,destructiveHint:!0,openWorldHint:!0},execute:K(async(e,{log:t,session:n})=>{try{let r=b({projectRoot:e.projectRoot,tag:e.tag});return t.info(`Starting research with query: "${e.query.substring(0,100)}${e.query.length>100?`...`:``}"`),W({result:await Kt({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:r},t,{session:n}),log:t,errorPrefix:`Error performing research`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in research tool: ${e.message}`),U(e.message)}})})}async function wn(e,t,n={}){let{projectRoot:r,language:a}=e,o=Q(t);t.info(`Executing response-language_direct with args: ${JSON.stringify(e)}`),t.info(`Using project root: ${r}`);try{return s(),Ie(a,{mcpLog:o,projectRoot:r})}catch(e){return{success:!1,error:{code:`DIRECT_FUNCTION_ERROR`,message:e.message,details:e.stack}}}finally{i()}}function Tn(e){e.addTool({name:`response-language`,description:`Get or set the response language for the project`,parameters:F.object({projectRoot:F.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:F.string().describe(`The new response language to set. like "中文" "English" or "español".`)}),annotations:{title:`Response Language`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{return t.info(`Executing response-language tool with args: ${JSON.stringify(e)}`),W({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}`),U(e.message)}})})}function En(e){e.addTool({name:`scope_down_task`,description:`Decrease the complexity of one or more tasks using AI`,parameters:F.object({id:F.string().describe(`Comma-separated list of task IDs to scope down (e.g., "1,3,5")`),strength:F.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:F.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`),research:F.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Down Task`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-down with args: ${JSON.stringify(e)}`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await qt({tasksJsonPath:i,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:r},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}`),U(e.message)}})})}function Dn(e){e.addTool({name:`scope_up_task`,description:`Increase the complexity of one or more tasks using AI`,parameters:F.object({id:F.string().describe(`Comma-separated list of task IDs to scope up (e.g., "1,3,5")`),strength:F.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:F.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`),research:F.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Up Task`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-up with args: ${JSON.stringify(e)}`);let r=b({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await Jt({tasksJsonPath:i,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:r},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}`),U(e.message)}})})}function On(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:F.object({id:a.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:F.string().optional().describe(`Information to add to the subtask. Required unless only updating metadata.`),research:F.boolean().optional().describe(`Use Claude Code web research for research-backed updates`),metadata:F.string().optional().describe(`JSON string of metadata to merge into subtask metadata. Example: '{"ticketId": "JIRA-456", "reviewed": true}'. Requires TASKGRAPH_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:F.string().optional().describe(`Absolute path to the tasks file`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Subtask`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{let r=`update_subtask`;try{let i=b({projectRoot:e.projectRoot,tag:e.tag});t.info(`Updating subtask with args: ${JSON.stringify(e)}`);let a;try{a=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`${r}: Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let o=J(e.metadata,U);if(o.error)return o.error;let s=o.parsedMetadata;if(!e.prompt&&!s)return U(`Either prompt or metadata must be provided for update-subtask`);let c=await Yt({tasksJsonPath:a,id:e.id,prompt:e.prompt,research:e.research,metadata:s,projectRoot:e.projectRoot,tag:i},t,{session:n});return c.success?t.info(`Successfully updated subtask with ID ${e.id}`):t.error(`Failed to update subtask: ${c.error?.message||`Unknown error`}`),W({result:c,log:t,errorPrefix:`Error updating subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${r} tool execute: ${e.message}`),U(`Internal tool error (${r}): ${e.message}`)}})})}function kn(e){e.addTool({name:`update_task`,description:`Updates a single task by ID with new information or context provided in the prompt.`,parameters:F.object({id:F.string().describe(`ID of the task (e.g., '15') to update. Subtasks are supported using the update-subtask tool.`),prompt:F.string().optional().describe(`New information or context to incorporate into the task. Required unless only updating metadata.`),research:F.boolean().optional().describe(`Use Claude Code web research for research-backed updates`),append:F.boolean().optional().describe(`Append timestamped information to task details instead of full update`),metadata:F.string().optional().describe(`JSON string of metadata to merge into task metadata. Example: '{"githubIssue": 42, "sprint": "Q1-S3"}'. Requires TASKGRAPH_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:F.string().optional().describe(`Absolute path to the tasks file`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Task`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{let r=`update_task`;try{let i=b({projectRoot:e.projectRoot,tag:e.tag});t.info(`Executing ${r} tool with args: ${JSON.stringify(e)}`);let a;try{a=Z({projectRoot:e.projectRoot,file:e.file},t),t.info(`${r}: Resolved tasks path: ${a}`)}catch(e){return t.error(`${r}: Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let o=J(e.metadata,U);if(o.error)return o.error;let s=o.parsedMetadata;if(!e.prompt&&!s)return U(`Either prompt or metadata must be provided for update-task`);let c=await Xt({tasksJsonPath:a,id:e.id,prompt:e.prompt,research:e.research,append:e.append,metadata:s,projectRoot:e.projectRoot,tag:i},t,{session:n});return t.info(`${r}: Direct function result: success=${c.success}`),W({result:c,log:t,errorPrefix:`Error updating task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${r} tool execute: ${e.message}`),U(`Internal tool error (${r}): ${e.message}`)}})})}function An(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:F.object({from:F.string().describe(`Task ID from which to start updating (inclusive). IMPORTANT: This tool uses 'from', not 'id'`),prompt:F.string().describe(`Explanation of changes or new context to apply`),research:F.boolean().optional().describe(`Use Claude Code web research for research-backed updates`),file:F.string().optional().describe(`Path to the tasks file relative to project root`),projectRoot:F.string().optional().describe(`The directory of the project. (Optional, usually from session)`),tag:F.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Tasks`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{let r=`update`,{from:i,prompt:a,research:o,file:s,projectRoot:c,tag:l}=e,u=b({projectRoot:e.projectRoot,tag:e.tag});try{t.info(`Executing ${r} tool with normalized root: ${c}`);let l;try{l=Z({projectRoot:c,file:s},t),t.info(`${r}: Resolved tasks path: ${l}`)}catch(e){return t.error(`${r}: Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json within project root '${c}': ${e.message}`)}let d=await Zt({tasksJsonPath:l,from:i,prompt:a,research:o,projectRoot:c,tag:u},t,{session:n});return t.info(`${r}: Direct function result: success=${d.success}`),W({result:d,log:t,errorPrefix:`Error updating tasks`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${r} tool execute: ${e.message}`),U(`Internal tool error (${r}): ${e.message}`)}})})}function jn(e){e.addTool({name:`use_tag`,description:`Switch to a different tag context for task operations`,parameters:F.object({name:F.string().describe(`Name of the tag to switch to`),file:F.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Use Tag`,destructiveHint:!0},execute:K(async(e,{log:t,session:n})=>{try{t.info(`Starting use-tag with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}return W({result:await Qt({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}`),U(e.message)}})})}function Mn(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:F.object({file:F.string().optional().describe(`Absolute path to the tasks file`),projectRoot:F.string().describe(`The directory of the project. Must be an absolute path.`),tag:F.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=b({projectRoot:e.projectRoot,tag:e.tag});t.info(`Validating dependencies with args: ${JSON.stringify(e)}`);let r;try{r=Z({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),U(`Failed to find tasks.json: ${e.message}`)}let i=await $t({tasksJsonPath:r,projectRoot:e.projectRoot,tag:n},t);return i.success?t.info(`Successfully validated dependencies: ${i.data.message}`):t.error(`Failed to validate dependencies: ${i.error.message}`),W({result:i,log:t,errorPrefix:`Error validating dependencies`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in validateDependencies tool: ${e.message}`),U(e.message)}})})}const $={initialize_project:pn,models:hn,parse_prd:vn,"response-language":Tn,analyze_project_complexity:an,expand_task:dn,expand_all:un,scope_up_task:Dn,scope_down_task:En,get_tasks:lt,get_task:dt,next_task:_n,complexity_report:sn,set_task_status:ht,add_task:rn,add_subtask:tn,update:An,update_task:kn,update_subtask:On,remove_task:xn,remove_subtask:bn,clear_subtasks:on,move_task:gn,add_dependency:en,remove_dependency:yn,validate_dependencies:Mn,fix_dependencies:fn,list_tags:mn,add_tag:nn,delete_tag:ln,use_tag:jn,rename_tag:Sn,copy_tag:cn,research:Cn,autopilot_start:qe,autopilot_resume:Ye,autopilot_next:Ze,autopilot_status:$e,autopilot_complete:tt,autopilot_commit:rt,autopilot_finalize:at,autopilot_abort:st,generate:pt},Nn=[`get_tasks`,`next_task`,`get_task`,`set_task_status`,`update_subtask`,`parse_prd`,`expand_task`],Pn=[...Nn,`initialize_project`,`analyze_project_complexity`,`expand_all`,`add_subtask`,`remove_task`,`add_task`,`complexity_report`];function Fn(e){return $[e]||null}function In(){let e=process.env.TASKGRAPH_TOOLS;if(!e||e.trim()===``)return V.debug(`No TASKGRAPH_TOOLS env var found, defaulting to "core"`),`core`;let t=e.trim();return V.debug(`TASKGRAPH_TOOLS env var: "${t}"`),t}function Ln(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=Nn,V.info(`Loading core tools only`);break;case`standard`:a=Pn,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=Fn(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 TASKGRAPH_TOOLS environment variable: ${t.message}`),V.info(`Falling back to loading all tools`);let i=Object.keys($);for(let t of i){let i=Fn(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`}}}I.config({quiet:!0}),ie();const Rn=R(import.meta.url);N.dirname(Rn);var zn=class{constructor(){this.options={name:`TaskGraph MCP Server`,version:C};let e=new ze(this.options);if(e._mcpServer&&L.wrapMcpServerWithSentry)try{e._mcpServer=L.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=In();this.logger.info(`TaskGraph MCP Server starting...`),this.logger.info(`Tool mode configuration: ${e}`);let t=Ln(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`})}),await this.server.start({transportType:`stdio`,timeout:12e4}),this}async stop(){this.server&&await this.server.stop()}};I.config({quiet:!0}),process.env.TASKGRAPH_MCP=`true`;async function Bn(){let e=new zn;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)}}Bn();export{};
13
+ ${v.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-UcjCRJbf.js`);await e(A.join(d,`.taskgraph`,`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-98Q5zy74.js`)).default,r=parseInt(l,10);await e(A.join(d,`.taskgraph`,`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 y(),{success:!0,data:{query:v.query,result:v.result,contextSize:v.contextSize,contextTokens:v.contextTokens,tokenBreakdown:v.tokenBreakdown,systemPromptTokens:v.systemPromptTokens,userPromptTokens:v.userPromptTokens,totalInputTokens:v.totalInputTokens,detailLevel:v.detailLevel,telemetryData:v.telemetryData,tagInfo:v.tagInfo,savedFilePath:v.savedFilePath}}}catch(e){return y(),t.error(`Error in researchDirect: ${e.message}`),{success:!1,error:{code:e.code||`RESEARCH_ERROR`,message:e.message}}}}async function qt(e,t,n={}){let{tasksJsonPath:r,id:i,strength:a=`regular`,prompt:o,research:s=!1,projectRoot:c,tag:l}=e,{session:u}=n;b();let d=Z(t);try{if(!r)return t.error(`scopeDownDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i)return t.error(`Missing required parameter: id`),y(),{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 le(r,e,a,o,{session:u,mcpLog:d,projectRoot:c,commandName:`scope-down`,outputType:`mcp`,tag:l,research:s},`json`);return y(),{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 y(),t.error(`Error in scopeDownDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_DOWN_ERROR`,message:e.message}}}}async function Jt(e,t,n={}){let{tasksJsonPath:r,id:i,strength:a=`regular`,prompt:o,research:s=!1,projectRoot:c,tag:l}=e,{session:u}=n;b();let d=Z(t);try{if(!r)return t.error(`scopeUpDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i)return t.error(`Missing required parameter: id`),y(),{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 ce(r,e,a,o,{session:u,mcpLog:d,projectRoot:c,commandName:`scope-up`,outputType:`mcp`,tag:l,research:s},`json`);return y(),{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 y(),t.error(`Error in scopeUpDirect: ${e.message}`),{success:!1,error:{code:e.code||`SCOPE_UP_ERROR`,message:e.message}}}}async function Yt(e,t,n={}){let{session:r}=n,{tasksJsonPath:i,id:a,prompt:o,research:s,metadata:c,projectRoot:l,tag:u}=e,d=Z(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=C();p||b();try{let t=await se(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&&C()&&y()}}catch(e){return d.error(`Setup error in updateSubtaskByIdDirect: ${e.message}`),C()&&y(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function Xt(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=Z(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||Y({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=C();m||b();try{let e=await ve(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&&C()&&y()}}catch(e){return f.error(`Setup error in updateTaskByIdDirect: ${e.message}`),C()&&y(),{success:!1,error:{code:`DIRECT_FUNCTION_SETUP_ERROR`,message:e.message||`Unknown setup error`}}}}async function Zt(e,t,n={}){let{session:r}=n,{from:i,prompt:a,research:o,tasksJsonPath:s,projectRoot:c,tag:l}=e,u=Z(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}`),b();try{let e=await Ne(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{y()}}async function Qt(e,t,n={}){let{tasksJsonPath:r,name:i,projectRoot:a}=e,{session:o}=n;b();let s=Z(t);try{if(!r)return t.error(`useTagDirect called without tasksJsonPath`),y(),{success:!1,error:{code:`MISSING_ARGUMENT`,message:`tasksJsonPath is required`}};if(!i||typeof i!=`string`)return t.error(`Missing required parameter: name`),y(),{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 Te(r,i,{},{session:o,mcpLog:s,projectRoot:a},`json`);return y(),{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 y(),t.error(`Error in useTagDirect: ${e.message}`),{success:!1,error:{code:e.code||`USE_TAG_ERROR`,message:e.message}}}}async function $t(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 P.existsSync(e)?(b(),await we(e,{projectRoot:r,tag:i}),y(),{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 y(),t.error(`Error validating dependencies: ${e.message}`),{success:!1,error:{code:`VALIDATION_ERROR`,message:e.message}}}}function en(e){e.addTool({name:`add_dependency`,description:`Add a dependency relationship between two tasks`,parameters:j.object({id:j.string().describe(`ID of task that will depend on another task`),dependsOn:j.string().describe(`ID of task that will become a dependency`),file:j.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Add Dependency`,destructiveHint:!0},execute:W(`add-dependency`,async(e,{log:t,session:n})=>{try{t.info(`Adding dependency for task ${e.id} to depend on ${e.dependsOn}`);let n=w({projectRoot:e.projectRoot,tag:e.tag}),r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let i=await yt({tasksJsonPath:r,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t);return i.success?t.info(`Successfully added dependency: ${i.data.message}`):t.error(`Failed to add dependency: ${i.error.message}`),V({result:i,log:t,errorPrefix:`Error adding dependency`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in addDependency tool: ${e.message}`),B(e.message)}})})}function tn(e){e.addTool({name:`add_subtask`,description:`Add a subtask to an existing task`,parameters:j.object({id:j.string().describe(`Parent task ID (required)`),taskId:j.string().optional().describe(`Existing task ID to convert to subtask`),title:j.string().optional().describe(`Title for the new subtask (when creating a new subtask)`),description:j.string().optional().describe(`Description for the new subtask`),details:j.string().optional().describe(`Implementation details for the new subtask`),status:j.string().optional().describe(`Status for the new subtask (default: 'pending')`),dependencies:j.string().optional().describe(`Comma-separated list of dependency IDs for the new subtask`),file:j.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:j.boolean().optional().describe(`Skip regenerating task files`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Add Subtask`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{let r=w({projectRoot:e.projectRoot,tag:e.tag});t.info(`Adding subtask with args: ${JSON.stringify(e)}`);let i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let a=await bt({tasksJsonPath:i,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:r},t,{session:n});return a.success?t.info(`Subtask added successfully: ${a.data.message}`):t.error(`Failed to add subtask: ${a.error.message}`),V({result:a,log:t,errorPrefix:`Error adding subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in addSubtask tool: ${e.message}`),B(e.message)}})})}function nn(e){e.addTool({name:`add_tag`,description:`Create a new tag for organizing tasks in different contexts`,parameters:j.object({name:j.string().describe(`Name of the new tag to create`),copyFromCurrent:j.boolean().optional().describe(`Whether to copy tasks from the current tag (default: false)`),copyFromTag:j.string().optional().describe(`Specific tag to copy tasks from`),fromBranch:j.boolean().optional().describe(`Create tag name from current git branch (ignores name parameter)`),description:j.string().optional().describe(`Optional description for the tag`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Add Tag`,destructiveHint:!1},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting add-tag with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await wt({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}`),B(e.message)}})})}function rn(e){e.addTool({name:`add_task`,description:`Add a new task using AI`,parameters:j.object({prompt:j.string().optional().describe(`Description of the task to add (required if not using manual fields)`),title:j.string().optional().describe(`Task title (for manual task creation)`),description:j.string().optional().describe(`Task description (for manual task creation)`),details:j.string().optional().describe(`Implementation details (for manual task creation)`),testStrategy:j.string().optional().describe(`Test strategy (for manual task creation)`),dependencies:j.string().optional().describe(`Comma-separated list of task IDs this task depends on`),priority:j.string().optional().describe(`Task priority (high, medium, low)`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`),research:j.boolean().optional().describe(`Whether to use research capabilities for task creation`)}),annotations:{title:`Add Task`,destructiveHint:!1},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting add-task with args: ${JSON.stringify(e)}`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await Tt({tasksJsonPath:i,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:r},t,{session:n}),log:t,errorPrefix:`Error adding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in add-task tool: ${e.message}`),B(e.message)}})})}function an(e){e.addTool({name:`analyze_project_complexity`,description:`Analyze task complexity and generate expansion recommendations.`,parameters:j.object({threshold:j.coerce.number().int().min(1).max(10).optional().default(5).describe(`Complexity score threshold (1-10) to recommend expansion.`),research:j.boolean().optional().default(!1).describe(`Use Claude Code web research for research-backed analysis.`),output:j.string().optional().describe(`Output file path relative to project root (default: ${v}).`),file:j.string().optional().describe(`Path to the tasks file relative to project root (default: tasks/tasks.json).`),ids:j.string().optional().describe(`Comma-separated list of task IDs to analyze specifically (e.g., "1,3,5").`),from:j.coerce.number().int().positive().optional().describe(`Starting task ID in a range to analyze.`),to:j.coerce.number().int().positive().optional().describe(`Ending task ID in a range to analyze.`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Analyze Project Complexity`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{let r=`analyze_project_complexity`;try{t.info(`Executing ${r} tool with args: ${JSON.stringify(e)}`);let i=w({projectRoot:e.projectRoot,tag:e.tag}),a;try{a=Y({projectRoot:e.projectRoot,file:e.file},t),t.info(`${r}: Resolved tasks path: ${a}`)}catch(n){return t.error(`${r}: Error finding tasks.json: ${n.message}`),B(`Failed to find tasks.json within project root '${e.projectRoot}': ${n.message}`)}let o=_(e.output,{projectRoot:e.projectRoot,tag:i},t);t.info(`${r}: Report output path: ${o}`);let s=A.dirname(o);try{P.existsSync(s)||(P.mkdirSync(s,{recursive:!0}),t.info(`${r}: Created output directory: ${s}`))}catch(e){return t.error(`${r}: Failed to create output directory ${s}: ${e.message}`),B(`Failed to create output directory: ${e.message}`)}let c=await Et({tasksJsonPath:a,outputPath:o,threshold:e.threshold,research:e.research,projectRoot:e.projectRoot,tag:i,ids:e.ids,from:e.from,to:e.to},t,{session:n});return t.info(`${r}: Direct function result: success=${c.success}`),V({result:c,log:t,errorPrefix:`Error analyzing task complexity`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${r} tool execute: ${e.message}`),B(`Internal tool error (${r}): ${e.message}`)}})})}function on(e){e.addTool({name:`clear_subtasks`,description:`Clear subtasks from specified tasks`,parameters:j.object({id:j.string().optional().describe(`Task IDs (comma-separated) to clear subtasks from`),all:j.boolean().optional().describe(`Clear subtasks from all tasks`),file:j.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.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:W(`clear-subtasks`,async(e,t)=>{try{t.log.info(`Clearing subtasks with args: ${JSON.stringify(e)}`);let n=w({projectRoot:e.projectRoot,tag:e.tag}),r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let i=await Dt({tasksJsonPath:r,id:e.id,all:e.all,projectRoot:e.projectRoot,tag:n},t.log,{session:t.session});return i.success?t.log.info(`Subtasks cleared successfully: ${i.data.message}`):t.log.error(`Failed to clear subtasks: ${i.error.message}`),V({result:i,log:t.log,errorPrefix:`Error clearing subtasks`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in clearSubtasks tool: ${e.message}`),B(e.message)}})})}function sn(e){e.addTool({name:`complexity_report`,description:`Display the complexity analysis report in a readable format`,parameters:j.object({file:j.string().optional().describe(`Path to the report file (default: ${v})`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Complexity Report`,readOnlyHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Getting complexity report with args: ${JSON.stringify(e)}`);let n=g(e.projectRoot),r=X({projectRoot:e.projectRoot,complexityReport:e.file,tag:n},t);if(t.info(`Reading complexity report from path: `,r),!r)return B(`No complexity report found. Run taskgraph analyze-complexity first.`);let i=await Ot({reportPath:r},t);return i.success?t.info(`Successfully retrieved complexity report`):t.error(`Failed to retrieve complexity report: ${i.error.message}`),V({result:i,log:t,errorPrefix:`Error retrieving complexity report`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in complexity-report tool: ${e.message}`),B(`Failed to retrieve complexity report: ${e.message}`)}})})}function cn(e){e.addTool({name:`copy_tag`,description:`Copy an existing tag to create a new tag with all tasks and metadata`,parameters:j.object({sourceName:j.string().describe(`Name of the source tag to copy from`),targetName:j.string().describe(`Name of the new tag to create`),description:j.string().optional().describe(`Optional description for the new tag`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Copy Tag`,destructiveHint:!1},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting copy-tag with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({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}`),B(e.message)}})})}function ln(e){e.addTool({name:`delete_tag`,description:`Delete an existing tag and all its tasks`,parameters:j.object({name:j.string().describe(`Name of the tag to delete`),yes:j.boolean().optional().describe(`Skip confirmation prompts (default: true for MCP)`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Delete Tag`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting delete-tag with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await At({tasksJsonPath:r,name:e.name,yes:e.yes===void 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}`),B(e.message)}})})}function un(e){e.addTool({name:`expand_all`,description:`Expand all pending tasks into subtasks based on complexity or defaults`,parameters:j.object({num:j.string().optional().describe(`Target number of subtasks per task (uses complexity/defaults otherwise)`),research:j.boolean().optional().describe(`Enable research-backed subtask generation (web research via Claude Code)`),prompt:j.string().optional().describe(`Additional context to guide subtask generation for all tasks`),force:j.boolean().optional().describe(`Force regeneration of subtasks for tasks that already have them`),file:j.string().optional().describe(`Absolute path to the tasks file in the /tasks folder inside the project root (default: tasks/tasks.json)`),projectRoot:j.string().optional().describe(`Absolute path to the project root directory (derived from session if possible)`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand All Tasks`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Tool expand_all execution started with args: ${JSON.stringify(e)}`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t),t.info(`Resolved tasks.json path: ${i}`)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let a=Ct(null,{projectRoot:e.projectRoot,tag:r},t);return t.info(`Using complexity report path: ${a}`),V({result:await jt({tasksJsonPath:i,num:e.num,research:e.research,prompt:e.prompt,force:e.force,projectRoot:e.projectRoot,tag:r,complexityReportPath:a},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),B(`An unexpected error occurred: ${e.message}`)}})})}function dn(e){e.addTool({name:`expand_task`,description:`Expand a task into subtasks for detailed implementation`,parameters:j.object({id:j.string().describe(`ID of task to expand`),num:j.string().optional().describe(`Number of subtasks to generate`),research:j.boolean().optional().default(!1).describe(`Use research role for generation`),prompt:j.string().optional().describe(`Additional context for subtask generation`),file:j.string().optional().describe(`Path to the tasks file relative to project root (e.g., tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),force:j.boolean().optional().default(!1).describe(`Force expansion even if subtasks exist`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Expand Task`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting expand-task with args: ${JSON.stringify(e)}`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let a=X({...e,tag:r},t);return V({result:await Mt({tasksJsonPath:i,id:e.id,num:e.num,research:e.research,prompt:e.prompt,force:e.force,complexityReportPath:a,projectRoot:e.projectRoot,tag:r},t,{session:n}),log:t,errorPrefix:`Error expanding task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in expand-task tool: ${e.message}`),B(e.message)}})})}function fn(e){e.addTool({name:`fix_dependencies`,description:`Fix invalid dependencies in tasks automatically`,parameters:j.object({file:j.string().optional().describe(`Absolute path to the tasks file`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Fix Dependencies`,destructiveHint:!0},execute:W(`fix-dependencies`,async(e,t)=>{try{t.log.info(`Fixing dependencies with args: ${JSON.stringify(e)}`);let n=w({projectRoot:e.projectRoot,tag:e.tag}),r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let i=await Nt({tasksJsonPath:r,projectRoot:e.projectRoot,tag:n},t.log);return i.success?t.log.info(`Successfully fixed dependencies: ${i.data.message}`):t.log.error(`Failed to fix dependencies: ${i.error.message}`),V({result:i,log:t.log,errorPrefix:`Error fixing dependencies`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in fixDependencies tool: ${e.message}`),B(e.message)}})})}function pn(e){e.addTool({name:`initialize_project`,description:`Initializes a new TaskGraph project structure by calling the core initialization logic. Creates necessary folders and configuration files for TaskGraph in the current directory.`,parameters:j.object({skipInstall:j.boolean().optional().default(!1).describe(`Skip installing dependencies automatically. Never do this unless you are sure the project is already installed.`),addAliases:j.boolean().optional().default(!0).describe(`Add shell aliases (tm, taskgraph) to shell config file.`),initGit:j.boolean().optional().default(!0).describe(`Initialize Git repository in project root.`),storeTasksInGit:j.boolean().optional().default(!0).describe(`Store tasks in Git (tasks.json and tasks/ directory).`),yes:j.boolean().optional().default(!0).describe(`Skip prompts and use default values. Always set to true for MCP tools.`),projectRoot:j.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:j.array(j.enum(D)).optional().describe(`List of rule profiles to include at initialization. If omitted, defaults to the Claude profile. Available options: ${D.join(`, `)}`)}),annotations:{title:`Initialize Project`,destructiveHint:!0},execute:U(async(e,t)=>{let{log:n}=t,r=t.session;try{return n.info(`Executing initialize_project tool with args: ${JSON.stringify(e)}`),V({result:await Pt(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),B(t,{details:e.stack})}})})}function mn(e){e.addTool({name:`list_tags`,description:`List all available tags with task counts and metadata`,parameters:j.object({showMetadata:j.boolean().optional().describe(`Whether to include metadata in the output (default: false)`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`List Tags`,readOnlyHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting list-tags with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await Ft({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}`),B(e.message)}})})}function hn(e){e.addTool({name:`models`,description:`Get information about available AI models or set model configurations. TaskGraph uses Claude Code (models: opus, sonnet, haiku). Run without arguments to get the current model configuration.`,parameters:j.object({setMain:j.string().optional().describe(`Set the primary model for task generation/updates. One of: opus, sonnet, haiku.`),setResearch:j.string().optional().describe(`Set the model for research-backed operations. One of: opus, sonnet, haiku.`),setFallback:j.string().optional().describe(`Set the model to use if the primary fails. One of: opus, sonnet, haiku.`),listAvailableModels:j.boolean().optional().describe(`List all available models.`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Models`,destructiveHint:!0},execute:W(`models`,async(e,t)=>{try{return t.log.info(`Starting models tool with args: ${JSON.stringify(e)}`),V({result:await Rt({...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}`),B(e.message)}})})}function gn(e){e.addTool({name:`move_task`,description:`Move a task or subtask to a new position`,parameters:j.object({from:j.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:j.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:j.string().optional().describe(`Custom path to tasks.json file`),projectRoot:j.string().describe(`Root directory of the project (typically derived from session)`),tag:j.string().optional().describe(`Tag context to operate on`),fromTag:j.string().optional().describe(`Source tag for cross-tag moves`),toTag:j.string().optional().describe(`Target tag for cross-tag moves`),withDependencies:j.boolean().optional().describe(`Move dependent tasks along with main task`),ignoreDependencies:j.boolean().optional().describe(`Break cross-tag dependencies during move`)}),annotations:{title:`Move Task`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{if(e.fromTag&&e.toTag&&e.fromTag!==e.toTag){if(!e.from)return B(`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||=Y(e,t),V({result:await zt({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})}{if(!e.to)return B(`Destination ID is required for within-tag moves`,`MISSING_DESTINATION_ID`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i=e.file;i||=Y(e,t);let a=e.from.split(`,`).map(e=>e.trim()),o=e.to.split(`,`).map(e=>e.trim());if(a.length!==o.length){if(a.length>1){let s=[],c=[];for(let l=0;l<a.length;l++){let u=a[l],d=o[l];if(u===d){t.info(`Skipping ${u} -> ${d} (same ID)`),c.push({fromId:u,toId:d,reason:`same ID`});continue}let f=l===a.length-1,p=await Q({sourceId:u,destinationId:d,tasksJsonPath:i,projectRoot:e.projectRoot,tag:r,generateFiles:f},t,{session:n});p.success?s.push(p.data):t.error(`Failed to move ${u} to ${d}: ${p.error.message}`)}return V({result:{success:!0,data:{moves:s,skipped:c.length>0?c:void 0,message:`Successfully moved ${s.length} tasks${c.length>0?`, skipped ${c.length}`:``}`}},log:t,errorPrefix:`Error moving multiple tasks`,projectRoot:e.projectRoot})}return V({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})}return V({result:await Q({sourceId:e.from,destinationId:e.to,tasksJsonPath:i,projectRoot:e.projectRoot,tag:r,generateFiles:!0},t,{session:n}),log:t,errorPrefix:`Error moving task`,projectRoot:e.projectRoot})}}catch(e){return B(`Failed to move task: ${e.message}`,`MOVE_TASK_ERROR`)}})})}function _n(e){e.addTool({name:`next_task`,description:`Find the next task to work on based on dependencies and status`,parameters:j.object({file:j.string().optional().describe(`Absolute path to the tasks file`),complexityReport:j.string().optional().describe(`Path to the complexity report file (relative to project root or absolute)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Next Task`,readOnlyHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Finding next task with args: ${JSON.stringify(e)}`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=q(e,n)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let a;try{a=J({...e,tag:r},n)}catch(e){t.error(`Error finding complexity report: ${e.message}`),a=null}let o=await Bt({tasksJsonPath:i,reportPath:a,projectRoot:e.projectRoot,tag:r},t,{session:n});return t.info(`Next task result: ${o.success?`found`:`none`}`),V({result:o,log:t,errorPrefix:`Error finding next task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error finding next task: ${e.message}`),B(e.message)}})})}function vn(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 ${ne} directory.`,parameters:j.object({input:j.string().optional().default(u).describe(`Absolute path to the PRD document file (.txt, .md, etc.)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`),output:j.string().optional().describe(`Output path for tasks.json file (default: ${m})`),numTasks:j.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 TaskGraph 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:j.boolean().optional().default(!1).describe(`Overwrite existing output file without prompting.`),research:j.boolean().optional().describe(`Enable TaskGraph to use the research role for potentially more informed task generation. Requires appropriate API key.`),append:j.boolean().optional().describe(`Append generated tasks to existing file.`)}),annotations:{title:`Parse PRD`,destructiveHint:!0},execute:U(async(e,{log:t,session:n,reportProgress:r})=>{try{let i=w({projectRoot:e.projectRoot,tag:e.tag}),a=He(r,t);return V({result:await Vt({...e,tag:i},t,{session:n,reportProgress:a}),log:t,errorPrefix:`Error parsing PRD`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in parse_prd: ${e.message}`),B(`Failed to parse PRD: ${e.message}`)}})})}function yn(e){e.addTool({name:`remove_dependency`,description:`Remove a dependency from a task`,parameters:j.object({id:j.string().describe(`Task ID to remove dependency from`),dependsOn:j.string().describe(`Task ID to remove as a dependency`),file:j.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Dependency`,destructiveHint:!0},execute:W(`remove-dependency`,async(e,t)=>{try{let n=w({projectRoot:e.projectRoot,tag:e.tag});t.log.info(`Removing dependency for task ${e.id} from ${e.dependsOn} with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t.log)}catch(e){return t.log.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let i=await Ht({tasksJsonPath:r,id:e.id,dependsOn:e.dependsOn,projectRoot:e.projectRoot,tag:n},t.log);return i.success?t.log.info(`Successfully removed dependency: ${i.data.message}`):t.log.error(`Failed to remove dependency: ${i.error.message}`),V({result:i,log:t.log,errorPrefix:`Error removing dependency`,projectRoot:e.projectRoot})}catch(e){return t.log.error(`Error in removeDependency tool: ${e.message}`),B(e.message)}})})}function bn(e){e.addTool({name:`remove_subtask`,description:`Remove a subtask from its parent task`,parameters:j.object({id:j.string().describe(`Subtask ID to remove in format 'parentId.subtaskId' (required)`),convert:j.boolean().optional().describe(`Convert the subtask to a standalone task instead of deleting it`),file:j.string().optional().describe(`Absolute path to the tasks file (default: tasks/tasks.json)`),skipGenerate:j.boolean().optional().describe(`Skip regenerating task files`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Remove Subtask`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{let r=w({projectRoot:e.projectRoot,tag:e.tag});t.info(`Removing subtask with args: ${JSON.stringify(e)}`);let i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let a=await Ut({tasksJsonPath:i,id:e.id,convert:e.convert,skipGenerate:e.skipGenerate,projectRoot:e.projectRoot,tag:r},t,{session:n});return a.success?t.info(`Subtask removed successfully: ${a.data.message}`):t.error(`Failed to remove subtask: ${a.error.message}`),V({result:a,log:t,errorPrefix:`Error removing subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in removeSubtask tool: ${e.message}`),B(e.message)}})})}function xn(e){e.addTool({name:`remove_task`,description:`Remove a task or subtask permanently from the tasks list`,parameters:j.object({id:j.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:j.string().optional().describe(`Absolute path to the tasks file`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),confirm:j.boolean().optional().describe(`Whether to skip confirmation prompt (default: false)`),tag:j.string().optional().describe(`Specify which tag context to operate on. Defaults to the current active tag.`)}),annotations:{title:`Remove Task`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Removing task(s) with ID(s): ${e.id}`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}t.info(`Using tasks file path: ${i}`);let a=await Wt({tasksJsonPath:i,id:e.id,projectRoot:e.projectRoot,tag:r},t,{session:n});return a.success?t.info(`Successfully removed task: ${e.id}`):t.error(`Failed to remove task: ${a.error.message}`),V({result:a,log:t,errorPrefix:`Error removing task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in remove-task tool: ${e.message}`),B(`Failed to remove task: ${e.message}`)}})})}function Sn(e){e.addTool({name:`rename_tag`,description:`Rename an existing tag`,parameters:j.object({oldName:j.string().describe(`Current name of the tag to rename`),newName:j.string().describe(`New name for the tag`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Rename Tag`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting rename-tag with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await Gt({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}`),B(e.message)}})})}function Cn(e){e.addTool({name:`research`,description:`Perform AI-powered research queries with project context`,parameters:j.object({query:j.string().describe(`Research query/prompt (required)`),taskIds:j.string().optional().describe(`Comma-separated list of task/subtask IDs for context (e.g., "15,16.2,17")`),filePaths:j.string().optional().describe(`Comma-separated list of file paths for context (e.g., "src/api.js,docs/readme.md")`),customContext:j.string().optional().describe(`Additional custom context text to include in the research`),includeProjectTree:j.boolean().optional().describe(`Include project file tree structure in context (default: false)`),detailLevel:j.enum([`low`,`medium`,`high`]).optional().describe(`Detail level for the research response (default: medium)`),saveTo:j.string().optional().describe(`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`),saveToFile:j.boolean().optional().describe(`Save research results to .taskgraph/docs/research/ directory (default: false)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Research`,destructiveHint:!0,openWorldHint:!0},execute:U(async(e,{log:t,session:n})=>{try{let r=w({projectRoot:e.projectRoot,tag:e.tag});return t.info(`Starting research with query: "${e.query.substring(0,100)}${e.query.length>100?`...`:``}"`),V({result:await Kt({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:r},t,{session:n}),log:t,errorPrefix:`Error performing research`,projectRoot:e.projectRoot})}catch(e){return t.error(`Error in research tool: ${e.message}`),B(e.message)}})})}async function wn(e,t,n={}){let{projectRoot:r,language:i}=e,a=Z(t);t.info(`Executing response-language_direct with args: ${JSON.stringify(e)}`),t.info(`Using project root: ${r}`);try{return b(),Fe(i,{mcpLog:a,projectRoot:r})}catch(e){return{success:!1,error:{code:`DIRECT_FUNCTION_ERROR`,message:e.message,details:e.stack}}}finally{y()}}function Tn(e){e.addTool({name:`response-language`,description:`Get or set the response language for the project`,parameters:j.object({projectRoot:j.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:j.string().describe(`The new response language to set. like "中文" "English" or "español".`)}),annotations:{title:`Response Language`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{return t.info(`Executing response-language tool with args: ${JSON.stringify(e)}`),V({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}`),B(e.message)}})})}function En(e){e.addTool({name:`scope_down_task`,description:`Decrease the complexity of one or more tasks using AI`,parameters:j.object({id:j.string().describe(`Comma-separated list of task IDs to scope down (e.g., "1,3,5")`),strength:j.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:j.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`),research:j.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Down Task`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-down with args: ${JSON.stringify(e)}`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await qt({tasksJsonPath:i,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:r},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}`),B(e.message)}})})}function Dn(e){e.addTool({name:`scope_up_task`,description:`Increase the complexity of one or more tasks using AI`,parameters:j.object({id:j.string().describe(`Comma-separated list of task IDs to scope up (e.g., "1,3,5")`),strength:j.string().optional().describe(`Strength level: light, regular, or heavy (default: regular)`),prompt:j.string().optional().describe(`Custom prompt for specific scoping adjustments`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`),research:j.boolean().optional().describe(`Whether to use research capabilities for scoping`)}),annotations:{title:`Scope Up Task`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting scope-up with args: ${JSON.stringify(e)}`);let r=w({projectRoot:e.projectRoot,tag:e.tag}),i;try{i=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await Jt({tasksJsonPath:i,id:e.id,strength:e.strength,prompt:e.prompt,research:e.research,projectRoot:e.projectRoot,tag:r},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}`),B(e.message)}})})}function On(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:j.object({id:r.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:j.string().optional().describe(`Information to add to the subtask. Required unless only updating metadata.`),research:j.boolean().optional().describe(`Use Claude Code web research for research-backed updates`),metadata:j.string().optional().describe(`JSON string of metadata to merge into subtask metadata. Example: '{"ticketId": "JIRA-456", "reviewed": true}'. Requires TASKGRAPH_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:j.string().optional().describe(`Absolute path to the tasks file`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Subtask`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{let r=`update_subtask`;try{let i=w({projectRoot:e.projectRoot,tag:e.tag});t.info(`Updating subtask with args: ${JSON.stringify(e)}`);let a;try{a=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`${r}: Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let o=G(e.metadata,B);if(o.error)return o.error;let s=o.parsedMetadata;if(!e.prompt&&!s)return B(`Either prompt or metadata must be provided for update-subtask`);let c=await Yt({tasksJsonPath:a,id:e.id,prompt:e.prompt,research:e.research,metadata:s,projectRoot:e.projectRoot,tag:i},t,{session:n});return c.success?t.info(`Successfully updated subtask with ID ${e.id}`):t.error(`Failed to update subtask: ${c.error?.message||`Unknown error`}`),V({result:c,log:t,errorPrefix:`Error updating subtask`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${r} tool execute: ${e.message}`),B(`Internal tool error (${r}): ${e.message}`)}})})}function kn(e){e.addTool({name:`update_task`,description:`Updates a single task by ID with new information or context provided in the prompt.`,parameters:j.object({id:j.string().describe(`ID of the task (e.g., '15') to update. Subtasks are supported using the update-subtask tool.`),prompt:j.string().optional().describe(`New information or context to incorporate into the task. Required unless only updating metadata.`),research:j.boolean().optional().describe(`Use Claude Code web research for research-backed updates`),append:j.boolean().optional().describe(`Append timestamped information to task details instead of full update`),metadata:j.string().optional().describe(`JSON string of metadata to merge into task metadata. Example: '{"githubIssue": 42, "sprint": "Q1-S3"}'. Requires TASKGRAPH_ALLOW_METADATA_UPDATES=true in MCP environment.`),file:j.string().optional().describe(`Absolute path to the tasks file`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Task`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{let r=`update_task`;try{let i=w({projectRoot:e.projectRoot,tag:e.tag});t.info(`Executing ${r} tool with args: ${JSON.stringify(e)}`);let a;try{a=Y({projectRoot:e.projectRoot,file:e.file},t),t.info(`${r}: Resolved tasks path: ${a}`)}catch(e){return t.error(`${r}: Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let o=G(e.metadata,B);if(o.error)return o.error;let s=o.parsedMetadata;if(!e.prompt&&!s)return B(`Either prompt or metadata must be provided for update-task`);let c=await Xt({tasksJsonPath:a,id:e.id,prompt:e.prompt,research:e.research,append:e.append,metadata:s,projectRoot:e.projectRoot,tag:i},t,{session:n});return t.info(`${r}: Direct function result: success=${c.success}`),V({result:c,log:t,errorPrefix:`Error updating task`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${r} tool execute: ${e.message}`),B(`Internal tool error (${r}): ${e.message}`)}})})}function An(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:j.object({from:j.string().describe(`Task ID from which to start updating (inclusive). IMPORTANT: This tool uses 'from', not 'id'`),prompt:j.string().describe(`Explanation of changes or new context to apply`),research:j.boolean().optional().describe(`Use Claude Code web research for research-backed updates`),file:j.string().optional().describe(`Path to the tasks file relative to project root`),projectRoot:j.string().optional().describe(`The directory of the project. (Optional, usually from session)`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Update Tasks`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{let r=`update`,{from:i,prompt:a,research:o,file:s,projectRoot:c,tag:l}=e,u=w({projectRoot:e.projectRoot,tag:e.tag});try{t.info(`Executing ${r} tool with normalized root: ${c}`);let l;try{l=Y({projectRoot:c,file:s},t),t.info(`${r}: Resolved tasks path: ${l}`)}catch(e){return t.error(`${r}: Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json within project root '${c}': ${e.message}`)}let d=await Zt({tasksJsonPath:l,from:i,prompt:a,research:o,projectRoot:c,tag:u},t,{session:n});return t.info(`${r}: Direct function result: success=${d.success}`),V({result:d,log:t,errorPrefix:`Error updating tasks`,projectRoot:e.projectRoot})}catch(e){return t.error(`Critical error in ${r} tool execute: ${e.message}`),B(`Internal tool error (${r}): ${e.message}`)}})})}function jn(e){e.addTool({name:`use_tag`,description:`Switch to a different tag context for task operations`,parameters:j.object({name:j.string().describe(`Name of the tag to switch to`),file:j.string().optional().describe(`Path to the tasks file (default: tasks/tasks.json)`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`)}),annotations:{title:`Use Tag`,destructiveHint:!0},execute:U(async(e,{log:t,session:n})=>{try{t.info(`Starting use-tag with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}return V({result:await Qt({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}`),B(e.message)}})})}function Mn(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:j.object({file:j.string().optional().describe(`Absolute path to the tasks file`),projectRoot:j.string().describe(`The directory of the project. Must be an absolute path.`),tag:j.string().optional().describe(`Tag context to operate on`)}),annotations:{title:`Validate Dependencies`,readOnlyHint:!0},execute:W(`validate-dependencies`,async(e,{log:t,session:n})=>{try{let n=w({projectRoot:e.projectRoot,tag:e.tag});t.info(`Validating dependencies with args: ${JSON.stringify(e)}`);let r;try{r=Y({projectRoot:e.projectRoot,file:e.file},t)}catch(e){return t.error(`Error finding tasks.json: ${e.message}`),B(`Failed to find tasks.json: ${e.message}`)}let i=await $t({tasksJsonPath:r,projectRoot:e.projectRoot,tag:n},t);return i.success?t.info(`Successfully validated dependencies: ${i.data.message}`):t.error(`Failed to validate dependencies: ${i.error.message}`),V({result:i,log:t,errorPrefix:`Error validating dependencies`,projectRoot:e.projectRoot,tag:n})}catch(e){return t.error(`Error in validateDependencies tool: ${e.message}`),B(e.message)}})})}const $={initialize_project:pn,models:hn,parse_prd:vn,"response-language":Tn,analyze_project_complexity:an,expand_task:dn,expand_all:un,scope_up_task:Dn,scope_down_task:En,get_tasks:ft,get_task:mt,next_task:_n,complexity_report:sn,set_task_status:vt,add_task:rn,add_subtask:tn,update:An,update_task:kn,update_subtask:On,remove_task:xn,remove_subtask:bn,clear_subtasks:on,move_task:gn,add_dependency:en,remove_dependency:yn,validate_dependencies:Mn,fix_dependencies:fn,list_tags:mn,add_tag:nn,delete_tag:ln,use_tag:jn,rename_tag:Sn,copy_tag:cn,research:Cn,autopilot_start:Ke,autopilot_resume:Je,autopilot_next:Xe,autopilot_status:Qe,autopilot_complete:et,autopilot_commit:nt,autopilot_finalize:it,autopilot_abort:ot,generate:gt,github_status:ct,github_push:ut},Nn=[`get_tasks`,`next_task`,`get_task`,`set_task_status`,`update_subtask`,`parse_prd`,`expand_task`],Pn=[...Nn,`initialize_project`,`analyze_project_complexity`,`expand_all`,`add_subtask`,`remove_task`,`add_task`,`complexity_report`];function Fn(e){return $[e]||null}function In(){let e=process.env.TASKGRAPH_TOOLS;if(!e||e.trim()===``)return R.debug(`No TASKGRAPH_TOOLS env var found, defaulting to "core"`),`core`;let t=e.trim();return R.debug(`TASKGRAPH_TOOLS env var: "${t}"`),t}function Ln(e,t=`core`){let n=[],r=[];try{let i=t.trim(),a=[],o=i.toLowerCase();switch(o){case`all`:a=Object.keys($),R.info(`Loading all available tools`);break;case`core`:case`lean`:a=Nn,R.info(`Loading core tools only`);break;case`standard`:a=Pn,R.info(`Loading standard tools`);break;default:let e=i.split(`,`).map(e=>e.trim()).filter(e=>e.length>0),t=/* @__PURE__ */ 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),R.debug(`Resolved tool "${i}" to "${e}"`)):(n.push(i),R.warn(`Unknown tool specified: "${i}"`))}a=Array.from(t),n.length>0&&R.warn(`Unknown tools: ${n.join(`, `)}`),a.length===0?(R.warn(`No valid tools found in custom list. Loading all tools as fallback.`),a=Object.keys($)):R.info(`Loading ${a.length} custom tools from list (${t.size} unique after normalization)`)}return R.info(`Registering ${a.length} MCP tools (mode: ${i})`),a.forEach(t=>{try{let i=Fn(t);i?(i(e),R.debug(`Registered tool: ${t}`),n.push(t)):(R.warn(`Tool ${t} not found in registry`),r.push(t))}catch(e){e.message&&e.message.includes(`already registered`)?(R.debug(`Tool ${t} already registered, skipping`),n.push(t)):(R.error(`Failed to register tool ${t}: ${e.message}`),r.push(t))}}),R.info(`Successfully registered ${n.length}/${a.length} tools`),r.length>0&&R.warn(`Failed tools: ${r.join(`, `)}`),{registeredTools:n,failedTools:r,normalizedMode:o}}catch(t){R.error(`Error parsing TASKGRAPH_TOOLS environment variable: ${t.message}`),R.info(`Falling back to loading all tools`);let i=Object.keys($);for(let t of i){let i=Fn(t);if(i)try{i(e),n.push(t)}catch(e){e.message&&e.message.includes(`already registered`)?(R.debug(`Fallback tool ${t} already registered, skipping`),n.push(t)):(R.warn(`Failed to register fallback tool '${t}': ${e.message}`),r.push(t))}else R.warn(`Tool '${t}' not found in registry`),r.push(t)}return R.info(`Successfully registered ${n.length} fallback tools`),{registeredTools:n,failedTools:r,normalizedMode:`all`}}}N.config({quiet:!0});const Rn=F(import.meta.url);A.dirname(Rn);var zn=class{constructor(){this.options={name:`TaskGraph MCP Server`,version:c};let e=new Le(this.options);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=R}async init(){if(this.initialized)return;let e=In();this.logger.info(`TaskGraph MCP Server starting...`),this.logger.info(`Tool mode configuration: ${e}`);let t=Ln(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`})}),await this.server.start({transportType:`stdio`,timeout:12e4}),this}async stop(){this.server&&await this.server.stop()}};N.config({quiet:!0}),process.env.TASKGRAPH_MCP=`true`;async function Bn(){let e=new zn;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){R.error(`Failed to start MCP server: ${e.message}`),process.exit(1)}}Bn();export{};