warp-task-master
Version:
BETA: Experimental Task Master fork with Warp AI integration and human-readable profile names. For production use, see task-master-ai.
40 lines • 216 kB
JavaScript
#!/usr/bin/env node
import"./ai-services-unified-Bp0J8TPk.js";import{COMPLEXITY_REPORT_FILE as e,CUSTOM_PROVIDERS as t,ConfigurationError as n,LEGACY_CONFIG_FILE as r,LEGACY_TASKS_FILE as i,TASKMASTER_CONFIG_FILE as a,TASKMASTER_DIR as o,TASKMASTER_DOCS_DIR as s,TASKMASTER_REPORTS_DIR as c,TASKMASTER_TASKS_FILE as l,findProjectRoot as u,findProjectRoot$1 as d,findTaskById as f,getAvailableModels as p,getBaseUrlForRole as m,getConfig as h,getDebugFlag as g,getDefaultNumTasks as _,getProjectName as v,isApiKeySet as y,isConfigFilePresent as ee,log as te,readJSON as b,writeConfig as ne}from"./utils-Can7ymw4.js";import"./git-utils-TLODVPko.js";import{addDependency as re,add_subtask_default as ie,add_task_default as ae,analyze_task_complexity_default as oe,clear_subtasks_default as se,confirmTaskOverwrite as ce,displayApiKeyStatus as le,displayAvailableModels as ue,displayBanner as de,displayComplexityReport as fe,displayCrossTagDependencyError as pe,displayCurrentTagIndicator as x,displayDependencyValidationHints as me,displayHelp as he,displayInvalidTagCombinationError as ge,displayModelConfiguration as _e,displayNextTask as ve,displaySubtaskMoveError as ye,displayTaggedTasksFYI as be,expand_all_tasks_default as xe,expand_task_default as Se,fixDependenciesCommand as Ce,generate_task_files_default as we,getApiKeyStatusReport as Te,getAvailableModelsList as Ee,getModelConfiguration as De,getStatusWithColor as Oe,getTaskMasterVersion as ke,list_tasks_default as Ae,migrateProject as je,moveTasksBetweenTags as Me,move_task_default as Ne,package_default as Pe,parse_prd_default as Fe,removeDependency as Ie,remove_subtask_default as Le,remove_task_default as Re,response_language_default as ze,scopeDownTask as Be,scopeUpTask as Ve,setModel as S,startLoadingIndicator as He,stopLoadingIndicator as Ue,task_exists_default as We,update_subtask_by_id_default as Ge,update_task_by_id_default as Ke,update_tasks_default as qe,validateDependenciesCommand as Je,validateStrength as Ye}from"./task-manager-Cy89-0WA.js";import"./ai-providers-DH3IjRav.js";import{copyTag as Xe,createTag as Ze,deleteTag as Qe,renameTag as $e,tags as et,useTag as tt}from"./tag-management-BMInu0L6.js";import{RULES_ACTIONS as C,RULES_SETUP_ACTION as w,RULE_PROFILES as nt,categorizeProfileResults as rt,categorizeRemovalResults as it,convertAllRulesToProfileRules as at,generateProfileRemovalSummary as ot,generateProfileSummary as st,getInstalledProfiles as ct,getRulesProfile as lt,initializeProject as ut,isValidProfile as dt,isValidRulesAction as ft,removeProfileRules as pt,runInteractiveProfilesSetup as mt,wouldRemovalLeaveNoProfiles as ht}from"./rules-actions-Btv3To_x.js";import gt from"dotenv";import{Command as T}from"commander";import E from"path";import D from"chalk";import O from"boxen";import k from"fs";import _t from"https";import vt from"http";import A from"inquirer";import yt from"@inquirer/search";import j from"ora";import{URL as bt}from"url";import{z as M}from"zod";import{spawn as N}from"child_process";import{promises as P}from"node:fs";import F from"node:path";import I from"os";import xt from"crypto";import{createClient as St}from"@supabase/supabase-js";import"node:crypto";import Ct from"cli-table3";import{marked as L}from"marked";import{markedTerminal as wt}from"marked-terminal";import Tt from"open";const R={MODELS:{MAIN:`claude-sonnet-4-20250514`,FALLBACK:`claude-3-7-sonnet-20250219`},TASKS:{DEFAULT_PRIORITY:`medium`,DEFAULT_COMPLEXITY:`moderate`,MAX_SUBTASKS:20,MAX_CONCURRENT:5,TASK_ID_PREFIX:`TASK-`},TAGS:{DEFAULT_TAG:`master`,MAX_TAGS_PER_TASK:10,NAMING_CONVENTION:`kebab-case`},STORAGE:{TYPE:`auto`,ENCODING:`utf8`,MAX_BACKUPS:5},RETRY:{ATTEMPTS:3,DELAY:1e3,MAX_DELAY:3e4,BACKOFF_MULTIPLIER:2,TIMEOUT:3e4},LOGGING:{LEVEL:`info`,MAX_FILE_SIZE:10,MAX_FILES:5},SECURITY:{MAX_REQUESTS_PER_MINUTE:60,MAX_PROMPT_LENGTH:1e5,ALLOWED_EXTENSIONS:[`.txt`,`.md`,`.json`]},VERSION:`1.0.0`},z={FILE_NOT_FOUND:`FILE_NOT_FOUND`,FILE_READ_ERROR:`FILE_READ_ERROR`,FILE_WRITE_ERROR:`FILE_WRITE_ERROR`,PARSE_ERROR:`PARSE_ERROR`,JSON_PARSE_ERROR:`JSON_PARSE_ERROR`,YAML_PARSE_ERROR:`YAML_PARSE_ERROR`,VALIDATION_ERROR:`VALIDATION_ERROR`,SCHEMA_VALIDATION_ERROR:`SCHEMA_VALIDATION_ERROR`,TYPE_VALIDATION_ERROR:`TYPE_VALIDATION_ERROR`,API_ERROR:`API_ERROR`,NETWORK_ERROR:`NETWORK_ERROR`,AUTHENTICATION_ERROR:`AUTHENTICATION_ERROR`,AUTHORIZATION_ERROR:`AUTHORIZATION_ERROR`,TASK_NOT_FOUND:`TASK_NOT_FOUND`,TASK_DEPENDENCY_ERROR:`TASK_DEPENDENCY_ERROR`,TASK_STATUS_ERROR:`TASK_STATUS_ERROR`,STORAGE_ERROR:`STORAGE_ERROR`,DATABASE_ERROR:`DATABASE_ERROR`,CONFIG_ERROR:`CONFIG_ERROR`,MISSING_CONFIGURATION:`MISSING_CONFIGURATION`,INVALID_CONFIGURATION:`INVALID_CONFIGURATION`,PROVIDER_ERROR:`PROVIDER_ERROR`,PROVIDER_NOT_FOUND:`PROVIDER_NOT_FOUND`,PROVIDER_INITIALIZATION_ERROR:`PROVIDER_INITIALIZATION_ERROR`,INTERNAL_ERROR:`INTERNAL_ERROR`,INVALID_INPUT:`INVALID_INPUT`,NOT_IMPLEMENTED:`NOT_IMPLEMENTED`,UNKNOWN_ERROR:`UNKNOWN_ERROR`};var B=class e extends Error{code;context;cause;timestamp;constructor(t,n=z.UNKNOWN_ERROR,r={},i){super(t),this.name=`TaskMasterError`,this.code=n,this.cause=i,this.timestamp=new Date,this.context={timestamp:this.timestamp,...r},Object.setPrototypeOf(this,e.prototype),Error.captureStackTrace&&Error.captureStackTrace(this,e),i?.stack&&(this.stack=`${this.stack}\nCaused by: ${i.stack}`)}getUserMessage(){return this.context.userMessage||this.message}getSanitizedDetails(){let{details:e,resource:t,operation:n}=this.context;return{code:this.code,message:this.getUserMessage(),...t&&{resource:t},...n&&{operation:n},...e&&typeof e==`object`&&!this.containsSensitiveInfo(e)&&{details:e}}}containsSensitiveInfo(e){if(typeof e!=`object`||!e)return!1;let t=[`password`,`token`,`key`,`secret`,`auth`,`credential`],n=JSON.stringify(e).toLowerCase();return t.some(e=>n.includes(e))}toJSON(){let t={name:this.name,message:this.message,code:this.code,context:this.context,stack:this.stack};return this.cause&&(this.cause instanceof e?t.cause=this.cause.toJSON():t.cause={name:this.cause.name,message:this.cause.message,code:z.UNKNOWN_ERROR,context:{},stack:this.cause.stack}),t}toString(){let e=`${this.name}[${this.code}]: ${this.message}`;return this.context.operation&&(e+=` (operation: ${this.context.operation})`),this.context.resource&&(e+=` (resource: ${this.context.resource})`),this.cause&&(e+=`\nCaused by: ${this.cause.toString()}`),e}is(e){return this.code===e}hasCode(t){return this.is(t)?!0:this.cause instanceof e?this.cause.hasCode(t):!1}withContext(t){return new e(this.message,this.code,{...this.context,...t},this.cause)}wrap(t,n=z.INTERNAL_ERROR,r={}){return new e(t,n,r,this)}},Et=class{localConfigPath;globalConfigPath;constructor(e){this.localConfigPath=F.join(e,`.taskmaster`,`config.json`),this.globalConfigPath=F.join(process.env.HOME||``,`.taskmaster`,`config.json`)}getDefaultConfig(){return{models:{main:R.MODELS.MAIN,fallback:R.MODELS.FALLBACK},storage:{type:R.STORAGE.TYPE,encoding:R.STORAGE.ENCODING,enableBackup:!1,maxBackups:R.STORAGE.MAX_BACKUPS,enableCompression:!1,atomicOperations:!0},version:R.VERSION}}async loadLocalConfig(){try{let e=await P.readFile(this.localConfigPath,`utf-8`);return JSON.parse(e)}catch(e){if(e.code===`ENOENT`)return console.debug(`No local config.json found, using defaults`),null;throw new B(`Failed to load local configuration`,z.CONFIG_ERROR,{configPath:this.localConfigPath},e)}}async loadGlobalConfig(){return null}async hasLocalConfig(){try{return await P.access(this.localConfigPath),!0}catch{return!1}}async hasGlobalConfig(){try{return await P.access(this.globalConfigPath),!0}catch{return!1}}};const V={DEFAULTS:0,GLOBAL:1,LOCAL:2,ENVIRONMENT:3};var Dt=class{configSources=[];addSource(e){this.configSources.push(e)}clearSources(){this.configSources=[]}merge(){let e=[...this.configSources].sort((e,t)=>e.precedence-t.precedence),t={};for(let n of e)t=this.deepMerge(t,n.config);return t}deepMerge(e,t){if(!t)return e;if(!e)return t;let n={...e};for(let e in t){if(t[e]===null||t[e]===void 0)continue;typeof t[e]==`object`&&!Array.isArray(t[e])?n[e]=this.deepMerge(n[e]||{},t[e]):n[e]=t[e]}return n}getSources(){return[...this.configSources].sort((e,t)=>t.precedence-e.precedence)}hasSource(e){return this.configSources.some(t=>t.name===e)}removeSource(e){let t=this.configSources.length;return this.configSources=this.configSources.filter(t=>t.name!==e),this.configSources.length<t}},Ot=class{stateFilePath;currentState;constructor(e){this.stateFilePath=F.join(e,`.taskmaster`,`state.json`),this.currentState={currentTag:R.TAGS.DEFAULT_TAG}}async loadState(){try{let e=await P.readFile(this.stateFilePath,`utf-8`),t=JSON.parse(e),n={currentTag:t.currentTag||t.activeTag||R.TAGS.DEFAULT_TAG,lastUpdated:t.lastUpdated,metadata:t.metadata};return process.env.TASKMASTER_TAG&&(n.currentTag=process.env.TASKMASTER_TAG),this.currentState=n,n}catch(e){return e.code===`ENOENT`?(console.debug(`No state.json found, using default state`),process.env.TASKMASTER_TAG&&(this.currentState.currentTag=process.env.TASKMASTER_TAG),this.currentState):(console.warn(`Failed to load state file:`,e.message),this.currentState)}}async saveState(){let e=F.dirname(this.stateFilePath);try{await P.mkdir(e,{recursive:!0});let t={...this.currentState,lastUpdated:new Date().toISOString()};await P.writeFile(this.stateFilePath,JSON.stringify(t,null,2),`utf-8`)}catch(e){throw new B(`Failed to save runtime state`,z.CONFIG_ERROR,{statePath:this.stateFilePath},e)}}getCurrentTag(){return this.currentState.currentTag}async setCurrentTag(e){this.currentState.currentTag=e,await this.saveState()}getState(){return{...this.currentState}}async updateMetadata(e){this.currentState.metadata={...this.currentState.metadata,...e},await this.saveState()}async clearState(){try{await P.unlink(this.stateFilePath)}catch(e){if(e.code!==`ENOENT`)throw e}this.currentState={currentTag:R.TAGS.DEFAULT_TAG}}},kt=class{localConfigPath;backupDir;constructor(e){this.localConfigPath=F.join(e,`.taskmaster`,`config.json`),this.backupDir=F.join(e,`.taskmaster`,`backups`)}async saveConfig(e,t={}){let{createBackup:n=!1,atomic:r=!0}=t;try{n&&await this.configExists()&&await this.createBackup();let t=F.dirname(this.localConfigPath);await P.mkdir(t,{recursive:!0});let i=JSON.stringify(e,null,2);if(r){let e=`${this.localConfigPath}.tmp`;await P.writeFile(e,i,`utf-8`),await P.rename(e,this.localConfigPath)}else await P.writeFile(this.localConfigPath,i,`utf-8`)}catch(e){throw new B(`Failed to save configuration`,z.CONFIG_ERROR,{configPath:this.localConfigPath},e)}}async createBackup(){try{await P.mkdir(this.backupDir,{recursive:!0});let e=new Date().toISOString().replace(/[:.]/g,`-`),t=F.join(this.backupDir,`config-${e}.json`),n=await P.readFile(this.localConfigPath,`utf-8`);return await P.writeFile(t,n,`utf-8`),await this.cleanOldBackups(),t}catch(e){throw console.warn(`Failed to create backup:`,e),e}}async cleanOldBackups(e=5){try{let t=(await P.readdir(this.backupDir)).filter(e=>e.startsWith(`config-`)&&e.endsWith(`.json`)).sort().reverse().slice(e);for(let e of t)await P.unlink(F.join(this.backupDir,e))}catch(e){console.warn(`Failed to clean old backups:`,e)}}async configExists(){try{return await P.access(this.localConfigPath),!0}catch{return!1}}async deleteConfig(){try{await P.unlink(this.localConfigPath)}catch(e){if(e.code!==`ENOENT`)throw new B(`Failed to delete configuration`,z.CONFIG_ERROR,{configPath:this.localConfigPath},e)}}async getBackups(){try{return(await P.readdir(this.backupDir)).filter(e=>e.startsWith(`config-`)&&e.endsWith(`.json`)).sort().reverse()}catch{return[]}}async restoreFromBackup(e){let t=F.join(this.backupDir,e);try{let e=await P.readFile(t,`utf-8`);await P.writeFile(this.localConfigPath,e,`utf-8`)}catch(e){throw new B(`Failed to restore from backup`,z.CONFIG_ERROR,{backupPath:t},e)}}},At=class e{static DEFAULT_MAPPINGS=[{env:`TASKMASTER_STORAGE_TYPE`,path:[`storage`,`type`],validate:e=>[`file`,`api`].includes(e)},{env:`TASKMASTER_API_ENDPOINT`,path:[`storage`,`apiEndpoint`]},{env:`TASKMASTER_API_TOKEN`,path:[`storage`,`apiAccessToken`]},{env:`TASKMASTER_MODEL_MAIN`,path:[`models`,`main`]},{env:`TASKMASTER_MODEL_RESEARCH`,path:[`models`,`research`]},{env:`TASKMASTER_MODEL_FALLBACK`,path:[`models`,`fallback`]},{env:`TASKMASTER_RESPONSE_LANGUAGE`,path:[`custom`,`responseLanguage`]}];static RUNTIME_STATE_MAPPINGS=[{env:`TASKMASTER_TAG`,path:[`activeTag`],isRuntimeState:!0}];mappings;constructor(t){this.mappings=t||[...e.DEFAULT_MAPPINGS,...e.RUNTIME_STATE_MAPPINGS]}loadConfig(){let e={};for(let t of this.mappings){if(t.isRuntimeState)continue;let n=process.env[t.env];if(!n)continue;if(t.validate&&!t.validate(n)){console.warn(`Invalid value for ${t.env}: ${n}`);continue}this.setNestedProperty(e,t.path,n)}return e}getRuntimeState(){let e={};for(let t of this.mappings){if(!t.isRuntimeState)continue;let n=process.env[t.env];if(n){let r=t.path[t.path.length-1];e[r]=n}}return e}setNestedProperty(e,t,n){let r=t[t.length-1],i=t.slice(0,-1),a=e;for(let e of i)a[e]||(a[e]={}),a=a[e];a[r]=n}hasEnvVar(e){return e in process.env&&process.env[e]!==void 0}getAllTaskmasterEnvVars(){let e={};for(let[t,n]of Object.entries(process.env))t.startsWith(`TASKMASTER_`)&&n!==void 0&&(e[t]=n);return e}addMapping(e){this.mappings.push(e)}getMappings(){return[...this.mappings]}},jt=class e{projectRoot;config={};initialized=!1;loader;merger;stateManager;persistence;envProvider;static async create(t){let n=new e(t);return await n.initialize(),n}constructor(e){this.projectRoot=e,this.loader=new Et(e),this.merger=new Dt,this.stateManager=new Ot(e),this.persistence=new kt(e),this.envProvider=new At}async initialize(){if(this.initialized)return;this.merger.clearSources(),this.merger.addSource({name:`defaults`,config:this.loader.getDefaultConfig(),precedence:V.DEFAULTS});let e=await this.loader.loadGlobalConfig();e&&this.merger.addSource({name:`global`,config:e,precedence:V.GLOBAL});let t=await this.loader.loadLocalConfig();t&&this.merger.addSource({name:`local`,config:t,precedence:V.LOCAL});let n=this.envProvider.loadConfig();Object.keys(n).length>0&&this.merger.addSource({name:`environment`,config:n,precedence:V.ENVIRONMENT}),this.config=this.merger.merge(),await this.stateManager.loadState(),this.initialized=!0}getConfig(){return this.config}getStorageConfig(){let e=this.config.storage,t=e?.type||`auto`,n=e?.basePath??this.projectRoot;return t===`api`||t===`auto`?{type:t,basePath:n,apiEndpoint:e?.apiEndpoint,apiAccessToken:e?.apiAccessToken,apiConfigured:!!(e?.apiEndpoint||e?.apiAccessToken)}:{type:t,basePath:n,apiConfigured:!1}}getModelConfig(){return this.config.models||{main:R.MODELS.MAIN,fallback:R.MODELS.FALLBACK}}getResponseLanguage(){return this.config.custom?.responseLanguage||`English`}getProjectRoot(){return this.projectRoot}isApiExplicitlyConfigured(){return this.getStorageConfig().type===`api`}getActiveTag(){return this.stateManager.getCurrentTag()}async setActiveTag(e){await this.stateManager.setCurrentTag(e)}async updateConfig(e){Object.assign(this.config,e),await this.persistence.saveConfig(this.config),this.initialized=!1,await this.initialize()}async setResponseLanguage(e){this.config.custom||(this.config.custom={}),this.config.custom.responseLanguage=e,await this.persistence.saveConfig(this.config)}async saveConfig(){await this.persistence.saveConfig(this.config,{createBackup:!0,atomic:!0})}async reset(){await this.persistence.deleteConfig(),await this.stateManager.clearState(),this.initialized=!1,this.config={},await this.initialize()}getConfigSources(){return this.merger.getSources()}},Mt=class{detectFormat(e){return!e||typeof e!=`object`?`standard`:Object.keys(e).some(e=>e!==`tasks`&&e!==`metadata`)?`legacy`:`standard`}extractTasks(e,t){return e?this.detectFormat(e)===`legacy`?this.extractTasksFromLegacy(e,t):this.extractTasksFromStandard(e):[]}extractTasksFromLegacy(e,t){if(t in e)return e[t]?.tasks||[];let n=Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`);if(t===`master`&&n.length>0){let t=n[0];return e[t]?.tasks||[]}return[]}extractTasksFromStandard(e){return e?.tasks||[]}extractMetadata(e,t){return e?this.detectFormat(e)===`legacy`?this.extractMetadataFromLegacy(e,t):this.extractMetadataFromStandard(e):null}extractMetadataFromLegacy(e,t){if(t in e){let n=e[t];return!n?.metadata&&n?.tasks?this.generateMetadataFromTasks(n.tasks,t):n?.metadata||null}let n=Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`);if(t===`master`&&n.length>0){let t=n[0],r=e[t];return!r?.metadata&&r?.tasks?this.generateMetadataFromTasks(r.tasks,t):r?.metadata||null}return null}extractMetadataFromStandard(e){return e?.metadata||null}extractTags(e){return e?this.detectFormat(e)===`legacy`?Object.keys(e).filter(e=>e!==`tasks`&&e!==`metadata`):[`master`]:[]}convertToSaveFormat(e,t,n,r){let i=r||`master`,a=this.normalizeTasks(e);return n&&this.detectFormat(n)===`legacy`?this.convertToLegacyFormat(a,t,i):this.convertToStandardFormat(a,t,r)}convertToLegacyFormat(e,t,n){return{[n]:{tasks:e,metadata:{...t,tags:[n]}}}}convertToStandardFormat(e,t,n){return{tasks:e,metadata:{...t,tags:n?[n]:[]}}}normalizeTasks(e){return e.map(e=>({...e,id:String(e.id),dependencies:e.dependencies?.map(e=>String(e))||[],subtasks:e.subtasks?.map(e=>({...e,id:Number(e.id),parentId:String(e.parentId)}))||[]}))}generateMetadataFromTasks(e,t){return{version:`1.0.0`,lastModified:new Date().toISOString(),taskCount:e.length,completedCount:e.filter(e=>e.status===`done`).length,tags:[t]}}},Nt=class{fileLocks=new Map;async readJson(e){try{let t=await P.readFile(e,`utf-8`);return JSON.parse(t)}catch(t){throw t.code===`ENOENT`?t:t instanceof SyntaxError?Error(`Invalid JSON in file ${e}: ${t.message}`):Error(`Failed to read file ${e}: ${t.message}`)}}async writeJson(e,t){let n=e,r=this.fileLocks.get(n);r&&await r;let i=this.performAtomicWrite(e,t);this.fileLocks.set(n,i);try{await i}finally{this.fileLocks.delete(n)}}async performAtomicWrite(e,t){let n=`${e}.tmp`;try{let r=JSON.stringify(t,null,2);await P.writeFile(n,r,`utf-8`),await P.rename(n,e)}catch(t){try{await P.unlink(n)}catch{}throw Error(`Failed to write file ${e}: ${t.message}`)}}async exists(e){try{return await P.access(e,P.constants.F_OK),!0}catch{return!1}}async getStats(e){return P.stat(e)}async readDir(e){return P.readdir(e)}async ensureDir(e){try{await P.mkdir(e,{recursive:!0})}catch(t){throw Error(`Failed to create directory ${e}: ${t.message}`)}}async deleteFile(e){try{await P.unlink(e)}catch(t){if(t.code!==`ENOENT`)throw Error(`Failed to delete file ${e}: ${t.message}`)}}async moveFile(e,t){try{await P.rename(e,t)}catch(n){throw Error(`Failed to move file from ${e} to ${t}: ${n.message}`)}}async copyFile(e,t){try{await P.copyFile(e,t)}catch(n){throw Error(`Failed to copy file from ${e} to ${t}: ${n.message}`)}}async cleanup(){let e=Array.from(this.fileLocks.values());e.length>0&&await Promise.all(e),this.fileLocks.clear()}},Pt=class{basePath;tasksDir;tasksFilePath;constructor(e){this.basePath=F.join(e,`.taskmaster`),this.tasksDir=F.join(this.basePath,`tasks`),this.tasksFilePath=F.join(this.tasksDir,`tasks.json`)}getBasePath(){return this.basePath}getTasksDir(){return this.tasksDir}getTasksPath(){return this.tasksFilePath}},Ft=class{formatHandler;fileOps;pathResolver;constructor(e){this.formatHandler=new Mt,this.fileOps=new Nt,this.pathResolver=new Pt(e)}async initialize(){await this.fileOps.ensureDir(this.pathResolver.getTasksDir())}async close(){await this.fileOps.cleanup()}async getStats(){let e=this.pathResolver.getTasksPath();try{let t=await this.fileOps.getStats(e),n=await this.fileOps.readJson(e),r=this.formatHandler.extractTags(n),i=0,a=r.map(e=>{let r=this.formatHandler.extractTasks(n,e).length;return i+=r,{tag:e,taskCount:r,lastModified:t.mtime.toISOString()}});return{totalTasks:i,totalTags:r.length,lastModified:t.mtime.toISOString(),storageSize:0,tagStats:a}}catch(e){if(e.code===`ENOENT`)return{totalTasks:0,totalTags:0,lastModified:new Date().toISOString(),storageSize:0,tagStats:[]};throw Error(`Failed to get storage stats: ${e.message}`)}}async loadTasks(e){let t=this.pathResolver.getTasksPath(),n=e||`master`;try{let e=await this.fileOps.readJson(t);return this.formatHandler.extractTasks(e,n)}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to load tasks: ${e.message}`)}}async loadTask(e,t){let n=await this.loadTasks(t);if(e.includes(`.`)){let[t,r]=e.split(`.`),i=n.find(e=>String(e.id)===t);if(!i||!i.subtasks)return null;let a=i.subtasks.find(e=>String(e.id)===r);if(!a)return null;let o=e=>{let t=String(e);return t.includes(`.`)?t:`${i.id}.${t}`},s=a.dependencies?.map(e=>o(e))??[];return{...a,id:e,title:a.title||`Subtask ${r}`,description:a.description||``,status:a.status||`pending`,priority:a.priority||i.priority||`medium`,dependencies:s,details:a.details||``,testStrategy:a.testStrategy||``,subtasks:[],tags:i.tags||[],assignee:a.assignee||i.assignee,complexity:a.complexity||i.complexity,createdAt:a.createdAt||i.createdAt,updatedAt:a.updatedAt||i.updatedAt,parentTask:{id:i.id,title:i.title,status:i.status},isSubtask:!0}}return n.find(t=>String(t.id)===String(e))||null}async saveTasks(e,t){let n=this.pathResolver.getTasksPath(),r=t||`master`;await this.fileOps.ensureDir(this.pathResolver.getTasksDir());let i={};try{i=await this.fileOps.readJson(n)}catch(e){if(e.code!==`ENOENT`)throw Error(`Failed to read existing tasks: ${e.message}`)}let a={version:`1.0.0`,lastModified:new Date().toISOString(),taskCount:e.length,completedCount:e.filter(e=>e.status===`done`).length,tags:[r]},o=this.normalizeTaskIds(e);if(this.formatHandler.detectFormat(i)===`legacy`||Object.keys(i).some(e=>e!==`tasks`&&e!==`metadata`))i[r]={tasks:o,metadata:a};else if(r===`master`)i={tasks:o,metadata:a};else{let e=i.tasks||[],t=i.metadata||a;i={master:{tasks:e,metadata:t},[r]:{tasks:o,metadata:a}}}await this.fileOps.writeJson(n,i)}normalizeTaskIds(e){return e.map(e=>({...e,id:String(e.id),dependencies:e.dependencies?.map(e=>String(e))||[],subtasks:e.subtasks?.map(e=>({...e,id:Number(e.id),parentId:String(e.parentId)}))||[]}))}async exists(e){let t=this.pathResolver.getTasksPath();return this.fileOps.exists(t)}async getAllTags(){try{let e=this.pathResolver.getTasksPath(),t=await this.fileOps.readJson(e);return this.formatHandler.extractTags(t)}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to get tags: ${e.message}`)}}async loadMetadata(e){let t=this.pathResolver.getTasksPath(),n=e||`master`;try{let e=await this.fileOps.readJson(t);return this.formatHandler.extractMetadata(e,n)}catch(e){if(e.code===`ENOENT`)return null;throw Error(`Failed to load metadata: ${e.message}`)}}async saveMetadata(e,t){let n=await this.loadTasks(t);await this.saveTasks(n,t)}async appendTasks(e,t){let n=[...await this.loadTasks(t),...e];await this.saveTasks(n,t)}async updateTask(e,t,n){let r=await this.loadTasks(n),i=r.findIndex(t=>String(t.id)===String(e));if(i===-1)throw Error(`Task ${e} not found`);r[i]={...r[i],...t,id:String(e)},await this.saveTasks(r,n)}async updateTaskStatus(e,t,n){let r=await this.loadTasks(n);if(e.includes(`.`))return this.updateSubtaskStatusInFile(r,e,t,n);let i=r.findIndex(t=>String(t.id)===String(e));if(i===-1)throw Error(`Task ${e} not found`);let a=r[i].status;return a===t?{success:!0,oldStatus:a,newStatus:t,taskId:String(e)}:(r[i]={...r[i],status:t,updatedAt:new Date().toISOString()},await this.saveTasks(r,n),{success:!0,oldStatus:a,newStatus:t,taskId:String(e)})}async updateSubtaskStatusInFile(e,t,n,r){let i=t.split(`.`);if(i.length!==2)throw Error(`Invalid subtask ID format: ${t}. Expected format: parentId.subtaskId`);let[a,o]=i,s=o.trim();if(!/^\d+$/.test(s))throw Error(`Invalid subtask ID: ${s}. Subtask ID must be a positive integer.`);let c=Number(s),l=e.findIndex(e=>String(e.id)===String(a));if(l===-1)throw Error(`Parent task ${a} not found`);let u=e[l],d=u.subtasks.findIndex(e=>e.id===c||String(e.id)===s);if(d===-1)throw Error(`Subtask ${t} not found in parent task ${a}`);let f=u.subtasks[d].status||`pending`;if(f===n)return{success:!0,oldStatus:f,newStatus:n,taskId:t};let p=new Date().toISOString();u.subtasks[d]={...u.subtasks[d],status:n,updatedAt:p};let m=u.subtasks,h=u.status;if(m.length>0){let e=e=>e.status||`pending`,t=t=>{let n=e(t);return n===`done`||n===`completed`},n=m.every(t),r=m.some(t=>e(t)===`in-progress`),i=m.some(t);n?h=`done`:(r||i)&&(h=`in-progress`)}return e[l]={...u,...h===u.status?{}:{status:h},updatedAt:p},await this.saveTasks(e,r),{success:!0,oldStatus:f,newStatus:n,taskId:t}}async deleteTask(e,t){let n=await this.loadTasks(t),r=n.filter(t=>String(t.id)!==String(e));if(r.length===n.length)throw Error(`Task ${e} not found`);await this.saveTasks(r,t)}async deleteTag(e){let t=this.pathResolver.getTasksPath();try{let n=await this.fileOps.readJson(t);if(this.formatHandler.detectFormat(n)===`legacy`)if(e in n)delete n[e],await this.fileOps.writeJson(t,n);else throw Error(`Tag ${e} not found`);else if(e===`master`)await this.fileOps.deleteFile(t);else throw Error(`Tag ${e} not found in standard format`)}catch(t){throw t.code===`ENOENT`?Error(`Tag ${e} not found - file doesn't exist`):t}}async renameTag(e,t){let n=this.pathResolver.getTasksPath();try{let r=await this.fileOps.readJson(n);if(this.formatHandler.detectFormat(r)===`legacy`)if(e in r)r[t]=r[e],delete r[e],r[t].metadata&&(r[t].metadata.tags=[t]),await this.fileOps.writeJson(n,r);else throw Error(`Tag ${e} not found`);else if(e===`master`){let e=r.tasks||[],i=r.metadata||{},a={[t]:{tasks:e,metadata:{...i,tags:[t]}}};await this.fileOps.writeJson(n,a)}else throw Error(`Tag ${e} not found in standard format`)}catch(t){throw t.code===`ENOENT`?Error(`Tag ${e} not found - file doesn't exist`):t}}async copyTag(e,t){let n=await this.loadTasks(e);if(n.length===0)throw Error(`Source tag ${e} not found or has no tasks`);await this.saveTasks(n,t)}},It=class{static mapDatabaseTasksToTasks(e,t){if(!e||e.length===0)return[];let n=this.groupDependenciesByTaskId(t),r=e.filter(e=>!e.parent_task_id),i=this.groupSubtasksByParentId(e);return r.map(e=>this.mapDatabaseTaskToTask(e,i.get(e.id)||[],n))}static mapDatabaseTaskToTask(e,t,n){let r=t.map((t,r)=>({id:r+1,parentId:e.id,title:t.title,description:t.description||``,status:this.mapStatus(t.status),priority:this.mapPriority(t.priority),dependencies:n.get(t.id)||[],details:t.metadata?.details||``,testStrategy:t.metadata?.testStrategy||``,createdAt:t.created_at,updatedAt:t.updated_at,assignee:t.assignee_id||void 0,complexity:t.complexity?this.mapComplexityToInternal(t.complexity):void 0}));return{id:e.display_id||e.id,title:e.title,description:e.description||``,status:this.mapStatus(e.status),priority:this.mapPriority(e.priority),dependencies:n.get(e.id)||[],details:e.metadata?.details||``,testStrategy:e.metadata?.testStrategy||``,subtasks:r,createdAt:e.created_at,updatedAt:e.updated_at,assignee:e.assignee_id||void 0,complexity:e.complexity?this.mapComplexityToInternal(e.complexity):void 0,effort:e.estimated_hours||void 0,actualEffort:e.actual_hours||void 0}}static groupDependenciesByTaskId(e){let t=new Map;if(e)for(let n of e){let e=t.get(n.task_id)||[];e.push(n.depends_on_task_id),t.set(n.task_id,e)}return t}static groupSubtasksByParentId(e){let t=new Map;for(let n of e)if(n.parent_task_id){let e=t.get(n.parent_task_id)||[];e.push(n),t.set(n.parent_task_id,e)}for(let e of t.values())e.sort((e,t)=>e.subtask_position-t.subtask_position);return t}static mapStatus(e){switch(e){case`todo`:return`pending`;case`in_progress`:return`in-progress`;case`done`:return`done`;default:return`pending`}}static mapPriority(e){switch(e){case`urgent`:return`critical`;default:return e}}static mapComplexityToInternal(e){return e<=2?`simple`:e<=5?`moderate`:e<=8?`complex`:`very-complex`}},H=class extends Error{constructor(e,t,n){super(e),this.code=t,this.cause=n,this.name=`AuthenticationError`,n&&n instanceof Error&&(this.stack=`${this.stack}\nCaused by: ${n.stack}`)}};const Lt={baseUrl:process.env.TM_PUBLIC_BASE_DOMAIN||`https://tryhamster.com`,configDir:E.join(I.homedir(),`.taskmaster`),configFile:E.join(I.homedir(),`.taskmaster`,`auth.json`)};function Rt(e){return{...Lt,...e}}let U=function(e){return e[e.SILENT=0]=`SILENT`,e[e.ERROR=1]=`ERROR`,e[e.WARN=2]=`WARN`,e[e.INFO=3]=`INFO`,e[e.DEBUG=4]=`DEBUG`,e}({});var zt=class e{config;static DEFAULT_CONFIG={level:U.WARN,silent:!1,prefix:``,timestamp:!1,colors:!0,mcpMode:!1};constructor(t={}){let n={};if((process.env.MCP_MODE===`true`||process.env.TASK_MASTER_MCP===`true`)&&(n.mcpMode=!0),(process.env.TASK_MASTER_SILENT===`true`||process.env.TM_SILENT===`true`)&&(n.silent=!0),process.env.TASK_MASTER_LOG_LEVEL||process.env.TM_LOG_LEVEL){let e=(process.env.TASK_MASTER_LOG_LEVEL||process.env.TM_LOG_LEVEL||``).toUpperCase();e in U&&(n.level=U[e])}(process.env.NO_COLOR===`true`||process.env.TASK_MASTER_NO_COLOR===`true`)&&(n.colors=!1),this.config={...e.DEFAULT_CONFIG,...t,...n},this.config.mcpMode&&(this.config.silent=!0)}shouldLog(e){return this.config.silent||this.config.mcpMode?!1:e<=this.config.level}formatMessage(e,t,...n){let r=``;if(this.config.timestamp){let e=new Date().toISOString();r+=this.config.colors?D.gray(`[${e}] `):`[${e}] `}if(this.config.prefix&&(r+=this.config.colors?D.cyan(`[${this.config.prefix}] `):`[${this.config.prefix}] `),this.config.colors)switch(e){case U.ERROR:t=D.red(t);break;case U.WARN:t=D.yellow(t);break;case U.INFO:break;case U.DEBUG:t=D.gray(t);break}return r+=t,n.length>0&&(r+=` `+n.map(e=>typeof e==`object`?JSON.stringify(e,null,2):String(e)).join(` `)),r}error(e,...t){this.shouldLog(U.ERROR)&&console.error(this.formatMessage(U.ERROR,e,...t))}warn(e,...t){this.shouldLog(U.WARN)&&console.warn(this.formatMessage(U.WARN,e,...t))}info(e,...t){this.shouldLog(U.INFO)&&console.log(this.formatMessage(U.INFO,e,...t))}debug(e,...t){this.shouldLog(U.DEBUG)&&console.log(this.formatMessage(U.DEBUG,e,...t))}log(e,...t){this.config.silent||this.config.mcpMode||(t.length>0?console.log(e,...t):console.log(e))}setConfig(e){this.config={...this.config,...e},this.config.mcpMode&&(this.config.silent=!0)}getConfig(){return{...this.config}}child(t,n){let r=this.config.prefix?`${this.config.prefix}:${t}`:t;return new e({...this.config,...n,prefix:r})}};let Bt=null;const Vt=new Map;function Ht(e){return new zt(e)}function W(e,t){return e?(Vt.has(e)||Vt.set(e,Ht({prefix:e,...t})),Vt.get(e)):(Bt||(Bt=Ht(t)),Bt)}var Ut=class e{static instance=null;logger=W(`CredentialStore`);config;CLOCK_SKEW_MS=3e4;constructor(e){this.config=Rt(e)}static getInstance(t){return e.instance?t&&W(`CredentialStore`).warn(`getInstance called with config after initialization; config is ignored.`):e.instance=new e(t),e.instance}static resetInstance(){e.instance=null}getCredentials(e){try{if(!k.existsSync(this.config.configFile))return null;let t=JSON.parse(k.readFileSync(this.config.configFile,`utf-8`)),n;if(typeof t.expiresAt==`number`)n=Number.isFinite(t.expiresAt)?t.expiresAt:void 0;else if(typeof t.expiresAt==`string`){let e=Date.parse(t.expiresAt);n=Number.isNaN(e)?void 0:e}else n=void 0;if(n===void 0)return this.logger.warn(`No valid expiration time provided for token`),null;t.expiresAt=n;let r=Date.now(),i=e?.allowExpired??!1;return r>=n-this.CLOCK_SKEW_MS&&!i?(this.logger.warn(`Authentication token has expired or is about to expire`,{expiresAt:t.expiresAt,currentTime:new Date(r).toISOString(),skewWindow:`${this.CLOCK_SKEW_MS/1e3}s`}),null):t}catch(e){this.logger.error(`Failed to read auth credentials: ${e.message}`);try{if(k.existsSync(this.config.configFile)){let e=`${this.config.configFile}.corrupt-${Date.now()}-${process.pid}-${Math.random().toString(36).slice(2,8)}`;k.renameSync(this.config.configFile,e),this.logger.warn(`Quarantined corrupt auth file to: ${e}`)}}catch(e){this.logger.debug(`Could not quarantine corrupt file: ${e.message}`)}return null}}saveCredentials(e){try{if(k.existsSync(this.config.configDir)||k.mkdirSync(this.config.configDir,{recursive:!0,mode:448}),e={...e,savedAt:new Date().toISOString()},e.expiresAt!==void 0){let t;if(typeof e.expiresAt==`number`)t=Number.isFinite(e.expiresAt)?e.expiresAt:void 0;else if(typeof e.expiresAt==`string`){let n=Date.parse(e.expiresAt);t=Number.isNaN(n)?void 0:n}if(t===void 0)throw new H(`Invalid expiresAt format: ${e.expiresAt}`,`SAVE_FAILED`);e.expiresAt=new Date(t).toISOString()}let t=`${this.config.configFile}.tmp`;k.writeFileSync(t,JSON.stringify(e,null,2),{mode:384}),k.renameSync(t,this.config.configFile)}catch(e){throw new H(`Failed to save auth credentials: ${e.message}`,`SAVE_FAILED`,e)}}clearCredentials(){try{k.existsSync(this.config.configFile)&&k.unlinkSync(this.config.configFile)}catch(e){throw new H(`Failed to clear credentials: ${e.message}`,`CLEAR_FAILED`,e)}}hasValidCredentials(){return this.getCredentials({allowExpired:!1})!==null}getConfig(){return{...this.config}}cleanupCorruptFiles(e=10080*60*1e3){try{let t=E.dirname(this.config.configFile),n=`${E.basename(this.config.configFile)}.corrupt-`;if(!k.existsSync(t))return;let r=k.readdirSync(t,{withFileTypes:!0}),i=Date.now();for(let a of r){if(!a.isFile())continue;let r=a.name;if(!r.startsWith(n))continue;let o=r.slice(n.length);if(!/^\d+$/.test(o))continue;let s=E.join(t,r);try{let t=k.statSync(s);i-t.mtimeMs>e&&(k.unlinkSync(s),this.logger.debug(`Cleaned up old corrupt file: ${r}`))}catch(e){this.logger.debug(`Could not clean up corrupt file ${r}: ${e.message}`)}}}catch(e){this.logger.debug(`Error during corrupt file cleanup: ${e.message}`)}}};const G=`sb-taskmaster-auth-token`;var Wt=class{store;logger=W(`SupabaseSessionStorage`);constructor(e){this.store=e}buildSessionFromCredentials(e){return{access_token:e.token,refresh_token:e.refreshToken||``,expires_at:e.expiresAt?Math.floor(new Date(e.expiresAt).getTime()/1e3):Math.floor(Date.now()/1e3)+3600,token_type:`bearer`,user:{id:e.userId,email:e.email||``,aud:`authenticated`,role:`authenticated`,email_confirmed_at:new Date().toISOString(),app_metadata:{},user_metadata:{},created_at:new Date().toISOString(),updated_at:new Date().toISOString()}}}parseSessionToCredentials(e){try{let t=JSON.parse(e);return{token:t.access_token,refreshToken:t.refresh_token,userId:t.user?.id||`unknown`,email:t.user?.email,expiresAt:t.expires_at?new Date(t.expires_at*1e3).toISOString():void 0}}catch(e){return this.logger.error(`Error parsing session:`,e),{}}}getItem(e){if(e===G||e.includes(`auth-token`))try{let e=this.store.getCredentials({allowExpired:!0});if(e&&e.token){let t=this.buildSessionFromCredentials(e);return JSON.stringify(t)}}catch(e){this.logger.error(`Error getting session:`,e)}return null}setItem(e,t){if(e===G||e.includes(`auth-token`))try{let e=this.parseSessionToCredentials(t),n=this.store.getCredentials({allowExpired:!0});if(e.token){let t={...n,...e,savedAt:new Date().toISOString(),selectedContext:n?.selectedContext};this.store.saveCredentials(t)}}catch(e){this.logger.error(`Error setting session:`,e)}}removeItem(e){if(e===G||e.includes(`auth-token`))try{let e=this.store.getCredentials({allowExpired:!0});if(e){let t={...e,token:``,refreshToken:void 0,expiresAt:void 0};this.store.saveCredentials(t)}}catch(e){this.logger.error(`Error removing session:`,e)}}clear(){this.removeItem(G)}},Gt=class{client=null;sessionStorage;logger=W(`SupabaseAuthClient`);constructor(){let e=Ut.getInstance();this.sessionStorage=new Wt(e)}getClient(){if(!this.client){let e=process.env.TM_PUBLIC_SUPABASE_URL,t=process.env.TM_PUBLIC_SUPABASE_ANON_KEY;if(!e||!t)throw new H(`Supabase configuration missing. Please set TM_PUBLIC_SUPABASE_URL and TM_PUBLIC_SUPABASE_ANON_KEY environment variables.`,`CONFIG_MISSING`);this.client=St(e,t,{auth:{storage:this.sessionStorage,autoRefreshToken:!0,persistSession:!0,detectSessionInUrl:!1}})}return this.client}async initialize(){let e=this.getClient();try{let{data:{session:t},error:n}=await e.auth.getSession();return n?(this.logger.warn(`Failed to restore session:`,n),null):(t&&this.logger.info(`Session restored successfully`),t)}catch(e){return this.logger.error(`Error initializing session:`,e),null}}async signInWithPKCE(){let e=this.getClient();try{let{data:t,error:n}=await e.auth.signInWithOAuth({provider:`github`,options:{redirectTo:process.env.TM_AUTH_CALLBACK_URL||`http://localhost:3421/auth/callback`,scopes:`email`}});if(n)throw new H(`Failed to initiate PKCE flow: ${n.message}`,`PKCE_INIT_FAILED`);if(!t?.url)throw new H(`No authorization URL returned`,`INVALID_RESPONSE`);return{url:t.url,codeVerifier:``}}catch(e){throw e instanceof H?e:new H(`Failed to start PKCE flow: ${e.message}`,`PKCE_FAILED`)}}async exchangeCodeForSession(e){let t=this.getClient();try{let{data:n,error:r}=await t.auth.exchangeCodeForSession(e);if(r)throw new H(`Failed to exchange code: ${r.message}`,`CODE_EXCHANGE_FAILED`);if(!n?.session)throw new H(`No session returned from code exchange`,`INVALID_RESPONSE`);return this.logger.info(`Successfully exchanged code for session`),n.session}catch(e){throw e instanceof H?e:new H(`Code exchange failed: ${e.message}`,`CODE_EXCHANGE_FAILED`)}}async getSession(){let e=this.getClient();try{let{data:{session:t},error:n}=await e.auth.getSession();return n?(this.logger.warn(`Failed to get session:`,n),null):t}catch(e){return this.logger.error(`Error getting session:`,e),null}}async refreshSession(){let e=this.getClient();try{this.logger.info(`Refreshing session...`);let{data:{session:t},error:n}=await e.auth.refreshSession();if(n)throw this.logger.error(`Failed to refresh session:`,n),new H(`Failed to refresh session: ${n.message}`,`REFRESH_FAILED`);return t&&this.logger.info(`Successfully refreshed session`),t}catch(e){throw e instanceof H?e:new H(`Failed to refresh session: ${e.message}`,`REFRESH_FAILED`)}}async getUser(){let e=this.getClient();try{let{data:{user:t},error:n}=await e.auth.getUser();return n?(this.logger.warn(`Failed to get user:`,n),null):t}catch(e){return this.logger.error(`Error getting user:`,e),null}}async signOut(){let e=this.getClient();try{let{error:t}=await e.auth.signOut({scope:`global`});t&&this.logger.warn(`Failed to sign out:`,t),this.sessionStorage.clear()}catch(e){this.logger.error(`Error during sign out:`,e)}}async setSession(e){let t=this.getClient();try{let{error:n}=await t.auth.setSession({access_token:e.access_token,refresh_token:e.refresh_token});if(n)throw new H(`Failed to set session: ${n.message}`,`SESSION_SET_FAILED`);this.logger.info(`Session set successfully`)}catch(e){throw e instanceof H?e:new H(`Failed to set session: ${e.message}`,`SESSION_SET_FAILED`)}}},Kt=class{logger=W(`OAuthService`);credentialStore;supabaseClient;baseUrl;authorizationUrl=null;originalState=null;authorizationReady=null;resolveAuthorizationReady=null;constructor(e,t={}){this.credentialStore=e,this.supabaseClient=new Gt,this.baseUrl=Rt(t).baseUrl}async authenticate(e={}){let{openBrowser:t,timeout:n=3e5,onAuthUrl:r,onWaitingForAuth:i,onSuccess:a,onError:o}=e;try{let e=this.startFlow(n);this.authorizationReady&&await this.authorizationReady;let o=this.getAuthorizationUrl();if(!o)throw new H(`Failed to generate authorization URL`,`URL_GENERATION_FAILED`);if(r&&r(o),t)try{await t(o),this.logger.debug(`Browser opened successfully with URL:`,o)}catch(e){this.logger.warn(`Failed to open browser automatically:`,e)}i&&i();let s=await e;return a&&a(s),s}catch(e){let t=e instanceof H?e:new H(`OAuth authentication failed: ${e.message}`,`OAUTH_FAILED`,e);throw o&&o(t),t}}async startFlow(e=3e5){let t=this.generateState();return this.originalState=t,this.authorizationReady=new Promise(e=>{this.resolveAuthorizationReady=e}),new Promise((n,r)=>{let i,a=vt.createServer();a.listen(0,`127.0.0.1`,()=>{let e=a.address();if(!e||typeof e==`string`){r(Error(`Failed to get server address`));return}let o=e.port,s=`http://localhost:${o}/callback`;a.on(`request`,async(e,t)=>{let s=new bt(e.url,`http://127.0.0.1:${o}`);s.pathname===`/callback`?await this.handleCallback(s,t,a,n,r,i):(t.writeHead(404),t.end())});let c={callback:s,state:t,name:`Task Master CLI`,version:this.getCliVersion(),device:I.hostname(),user:I.userInfo().username,platform:I.platform(),timestamp:Date.now()},l=new bt(`${this.baseUrl}/auth/cli/sign-in`),u=Buffer.from(JSON.stringify(c)).toString(`base64`);l.searchParams.append(`cli`,u),this.authorizationUrl=l.toString(),this.logger.info(`OAuth session started - ${c.name} v${c.version} on port ${o}`),this.logger.debug(`CLI data:`,c),this.resolveAuthorizationReady&&(this.resolveAuthorizationReady(),this.resolveAuthorizationReady=null)}),i=setTimeout(()=>{a.listening&&(a.close(),this.resolveAuthorizationReady&&(this.resolveAuthorizationReady(),this.resolveAuthorizationReady=null),r(new H(`Authentication timeout`,`AUTH_TIMEOUT`)))},e)})}async handleCallback(e,t,n,r,i,a){let o=e.searchParams.get(`type`),s=e.searchParams.get(`state`),c=e.searchParams.get(`access_token`),l=e.searchParams.get(`refresh_token`),u=e.searchParams.get(`expires_in`),d=e.searchParams.get(`error`),f=e.searchParams.get(`error_description`);if(t.writeHead(200),t.end(),d){n.listening&&n.close(),i(new H(f||d||`Authentication failed`,`OAUTH_ERROR`));return}if(s!==this.originalState){n.listening&&n.close(),i(new H(`Invalid state parameter`,`INVALID_STATE`));return}let p=e.searchParams.get(`code`);if(p&&o===`pkce_callback`)try{this.logger.info(`Received authorization code for PKCE flow`);let e=await this.supabaseClient.exchangeCodeForSession(p),t={token:e.access_token,refreshToken:e.refresh_token,userId:e.user.id,email:e.user.email,expiresAt:e.expires_at?new Date(e.expires_at*1e3).toISOString():void 0,tokenType:`standard`,savedAt:new Date().toISOString()};this.credentialStore.saveCredentials(t),n.listening&&n.close(),a&&clearTimeout(a),r(t);return}catch(e){n.listening&&n.close(),i(e);return}if(c&&(o===`oauth_success`||o===`session_transfer`))try{this.logger.info(`Received tokens via ${o}`);let e={access_token:c,refresh_token:l||``,expires_at:u?Math.floor(Date.now()/1e3)+parseInt(u):void 0,expires_in:u?parseInt(u):void 0,token_type:`bearer`,user:null};await this.supabaseClient.setSession(e);let t=await this.supabaseClient.getUser(),i=u?new Date(Date.now()+parseInt(u)*1e3).toISOString():void 0,s={token:c,refreshToken:l||void 0,userId:t?.id||`unknown`,email:t?.email,expiresAt:i,tokenType:`standard`,savedAt:new Date().toISOString()};this.credentialStore.saveCredentials(s),n.listening&&n.close(),a&&clearTimeout(a),r(s)}catch(e){n.listening&&n.close(),i(e)}else n.listening&&n.close(),i(new H(`No access token received`,`NO_TOKEN`))}generateState(){return xt.randomBytes(32).toString(`base64url`)}getCliVersion(){return Pe.version||`unknown`}getAuthorizationUrl(){return this.authorizationUrl}},qt=class{logger=W(`OrganizationService`);constructor(e){this.supabaseClient=e}async getOrganizations(){try{let{data:e,error:t}=await this.supabaseClient.from(`user_accounts`).select(`
id,
name,
slug
`);if(t)throw new B(`Failed to fetch organizations: ${t.message}`,z.API_ERROR,{operation:`getOrganizations`},t);return!e||e.length===0?(this.logger.debug(`No organizations found for user`),[]):e.map(e=>({id:e.id??``,name:e.name??``,slug:e.slug??e.id??``}))}catch(e){throw e instanceof B?e:new B(`Failed to fetch organizations`,z.API_ERROR,{operation:`getOrganizations`},e)}}async getOrganization(e){try{let{data:t,error:n}=await this.supabaseClient.from(`accounts`).select(`
id,
name,
slug
`).eq(`id`,e).single();if(n){if(n.code===`PGRST116`)return null;throw new B(`Failed to fetch organization: ${n.message}`,z.API_ERROR,{operation:`getOrganization`,orgId:e},n)}if(!t)return null;let r=t;return{id:r.id,name:r.name,slug:r.slug||r.id}}catch(t){throw t instanceof B?t:new B(`Failed to fetch organization`,z.API_ERROR,{operation:`getOrganization`,orgId:e},t)}}async getBriefs(e){try{let{data:t,error:n}=await this.supabaseClient.from(`brief`).select(`
id,
account_id,
document_id,
status,
created_at,
updated_at
`).eq(`account_id`,e);if(n)throw new B(`Failed to fetch briefs: ${n.message}`,z.API_ERROR,{operation:`getBriefs`,orgId:e},n);return!t||t.length===0?(this.logger.debug(`No briefs found for organization ${e}`),[]):t.map(e=>({id:e.id,accountId:e.account_id,documentId:e.document_id,status:e.status,createdAt:e.created_at,updatedAt:e.updated_at}))}catch(t){throw t instanceof B?t:new B(`Failed to fetch briefs`,z.API_ERROR,{operation:`getBriefs`,orgId:e},t)}}async getBrief(e){try{let{data:t,error:n}=await this.supabaseClient.from(`brief`).select(`
id,
account_id,
document_id,
status,
created_at,
updated_at
`).eq(`id`,e).single();if(n){if(n.code===`PGRST116`)return null;throw new B(`Failed to fetch brief: ${n.message}`,z.API_ERROR,{operation:`getBrief`,briefId:e},n)}if(!t)return null;let r=t;return{id:r.id,accountId:r.account_id,documentId:r.document_id,status:r.status,createdAt:r.created_at,updatedAt:r.updated_at}}catch(t){throw t instanceof B?t:new B(`Failed to fetch brief`,z.API_ERROR,{operation:`getBrief`,briefId:e},t)}}async validateOrgAccess(e){try{return await this.getOrganization(e)!==null}catch(e){return this.logger.error(`Failed to validate org access: ${e}`),!1}}async validateBriefAccess(e){try{return await this.getBrief(e)!==null}catch(e){return this.logger.error(`Failed to validate brief access: ${e}`),!1}}async getTasks(e){try{let{data:t,error:n}=await this.supabaseClient.from(`tasks`).select(`
*,
document:document_id (
id,
document_name,
title,
description
)
`).eq(`brief_id`,e).order(`position`,{ascending:!0}).order(`subtask_position`,{ascending:!0}).order(`created_at`,{ascending:!0});if(n)throw new B(`Failed to fetch tasks: ${n.message}`,z.API_ERROR,{operation:`getTasks`,briefId:e},n);return!t||t.length===0?(this.logger.debug(`No tasks found for brief ${e}`),[]):t.map(e=>({id:e.id,briefId:e.brief_id,documentId:e.document_id,position:e.position,subtaskPosition:e.subtask_position,status:e.status,createdAt:e.created_at,updatedAt:e.updated_at,document:e.document?{id:e.document.id,document_name:e.document.document_name,title:e.document.title,description:e.document.description}:void 0}))}catch(t){throw t instanceof B?t:new B(`Failed to fetch tasks`,z.API_ERROR,{operation:`getTasks`,briefId:e},t)}}},K=class e{static instance=null;credentialStore;oauthService;supabaseClient;organizationService;constructor(e){this.credentialStore=Ut.getInstance(e),this.supabaseClient=new Gt,this.oauthService=new Kt(this.credentialStore,e),this.initializeSupabaseSession()}async initializeSupabaseSession(){try{await this.supabaseClient.initialize()}catch(e){W(`AuthManager`).debug(`No existing session to restore`)}}static getInstance(t){return e.instance?t&&W(`AuthManager`).warn(`getInstance called with config after initialization; config is ignored.`):e.instance=new e(t),e.instance}static resetInstance(){e.instance=null,Ut.resetInstance()}getCredentials(){return this.credentialStore.getCredentials()}async authenticateWithOAuth(e={}){return this.oauthService.authenticate(e)}getAuthorizationUrl(){return this.oauthService.getAuthorizationUrl()}async refreshToken(){try{let e=await this.supabaseClient.refreshSession();if(!e)throw new H(`Failed to refresh session`,`REFRESH_FAILED`);let t=this.credentialStore.getCredentials({allowExpired:!0}),n={token:e.access_token,refreshToken:e.refresh_token,userId:e.user.id,email:e.user.email,expiresAt:e.expires_at?new Date(e.expires_at*1e3).toISOString():void 0,savedAt:new Date().toISOString(),selectedContext:t?.selectedContext};return this.credentialStore.saveCredentials(n),n}catch(e){throw e instanceof H?e:new H(`Token refresh failed: ${e.message}`,`REFRESH_FAILED`)}}async logout(){try{await this.supabaseClient.signOut()}catch(e){W(`AuthManager`).warn(`Failed to sign out from Supabase:`,e)}this.credentialStore.clearCredentials()}isAuthenticated(){return this.credentialStore.hasValidCredentials()}getContext(){return this.getCredentials()?.selectedContext||null}async updateContext(e){let t=this.getCredentials();if(!t)throw new H(`Not authenticated`,`NOT_AUTHENTICATED`);let n={...t.selectedContext||{},...e,updatedAt:new Date().toISOString()},r={...t,selectedContext:n};this.credentialStore.saveCredentials(r)}async clearContext(){let e=this.getCredentials();if(!e)throw new H(`Not authenticated`,`NOT_AUTHENTICATED`);let{selectedContext:t,...n}=e;this.credentialStore.saveCredentials(n)}async getOrganizationService(){if(!this.organizationService){let e=this.getCredentials();if(!e||!e.token)throw new H(`Not authenticated`,`NOT_AUTHENTICATED`);await this.supabaseClient.initialize();let t=this.supabaseClient.getClient();this.organizationService=new qt(t)}return this.organizationService}async getOrganizations(){return(await this.getOrganizationService()).getOrganizations()}async getBriefs(e){return(await this.getOrganizationService()).getBriefs(e)}async getOrganization(e){return(await this.getOrganizationService()).getOrganization(e)}async getBrief(e){return(await this.getOrganizationService()).getBrief(e)}async getTasks(e){return(await this.getOrganizationService()).getTasks(e)}};const Jt=M.enum([`pending`,`in-progress`,`done`,`review`,`deferred`,`cancelled`,`blocked`]),Yt=M.object({title:M.string().min(1).optional(),description:M.string().optional(),status:Jt.optional(),priority:M.enum([`low`,`medium`,`high`,`critical`]).optional(),details:M.string().optional(),testStrategy:M.string().optional()}).partial();var Xt=class{constructor(e){this.supabase=e}async getTasks(e){let t=K.getInstance().getContext();if(!t||!t.briefId)throw Error(`No brief selected. Please select a brief first using: tm context brief`);let{data:n,error:r}=await this.supabase.from(`tasks`).select(`
*,
document:document_id (
id,
document_name,
title,
description
)
`).eq(`brief_id`,t.briefId).order(`position`,{ascending:!0}).order(`subtask_position`,{ascending:!0}).order(`created_at`,{ascending:!0});if(r)throw Error(`Failed to fetch tasks: ${r.message}`);if(!n||n.length===0)return[];let i=n.map(e=>e.id),{data:a,erro