@hhsw2015/task-master-ai 0.43.6 → 0.43.8
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.
- package/dist/ai-services-unified--KinsHuW.js +1 -0
- package/dist/ai-services-unified-D0SWrwB5.js +7 -0
- package/dist/{commands-C-gPgxCq.js → commands-D_wCc0QR.js} +5 -5
- package/dist/{config-manager-CT2N6wWU.js → config-manager-BiA1Lh9-.js} +1 -1
- package/dist/{config-manager-CD8Omahk.js → config-manager-Dn_JApjY.js} +1 -1
- package/dist/{dependency-manager-CUyvY_le.js → dependency-manager-D_uegoOJ.js} +5 -5
- package/dist/mcp-server.js +2 -2
- package/dist/{profiles-BWJ0j3U7.js → profiles-BVhvTqG7.js} +2 -2
- package/dist/research-CubqvgZX.js +1 -0
- package/dist/response-language-B4B6uk8r.js +1 -0
- package/dist/{response-language-BM-_PuFA.js → response-language-DeTA_0Bx.js} +1 -1
- package/dist/{sentry-kPx4b_hZ.js → sentry-Dbx7-h6F.js} +1 -1
- package/dist/tag-management-ByKA_1s5.js +1 -0
- package/dist/{task-manager-DGWZ2U4b.js → task-manager-CmxFUtnm.js} +1 -1
- package/dist/task-master.js +1 -1
- package/dist/update-subtask-by-id-D56bbaA6.js +1 -0
- package/dist/update-task-by-id-rlGR5O_g.js +1 -0
- package/dist/{utils-CyMk2Nmj.js → utils-CtCI5DEr.js} +1 -1
- package/package.json +1 -1
- package/dist/ai-services-unified-C50UqIsi.js +0 -1
- package/dist/ai-services-unified-mf7kh9Iz.js +0 -7
- package/dist/research-WM6swPKf.js +0 -1
- package/dist/response-language-PoHoR-iU.js +0 -1
- package/dist/tag-management-DlV8h96A.js +0 -1
- package/dist/update-subtask-by-id-BRJxGaIi.js +0 -1
- package/dist/update-task-by-id-CLPjqWzq.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as e,i as t,n,r,t as i}from"./ai-services-unified-D0SWrwB5.js";import"./config-manager-Dn_JApjY.js";import"./git-utils-DllbRE35.js";import"./sentry-Dbx7-h6F.js";export{i as generateObjectService,n as generateTextService,r as logAiUsage,t as streamObjectService,e as streamTextService};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{A as e,C as t,D as n,Et as r,F as i,H as a,I as o,J as s,M as c,N as l,P as u,S as d,T as f,_ as p,a as m,b as h,d as g,ht as ee,j as _,l as v,o as te,p as y,s as ne,ut as b,v as x,yt as S}from"./config-manager-Dn_JApjY.js";import{n as C,t as w}from"./sentry-Dbx7-h6F.js";import{createRequire as T}from"node:module";import{promises as E}from"fs";import{join as D}from"path";import{homedir as O}from"os";import{execSync as k,spawn as A}from"child_process";import*as j from"ai";import{jsonrepair as M}from"jsonrepair";import{EnvHttpProxyAgent as re}from"undici";import{createAnthropic as N}from"@ai-sdk/anthropic";import{createPerplexity as P}from"@ai-sdk/perplexity";import{createGoogleGenerativeAI as ie}from"@ai-sdk/google";import{createOpenAI as ae}from"@ai-sdk/openai";import{createXai as oe}from"@ai-sdk/xai";import{createGroq as se}from"@ai-sdk/groq";import{createOpenRouter as ce}from"@openrouter/ai-sdk-provider";import{createOllama as le}from"ollama-ai-provider-v2";import{createAmazonBedrock as ue}from"@ai-sdk/amazon-bedrock";import{fromNodeProviderChain as de}from"@aws-sdk/credential-providers";import{createAzure as fe}from"@ai-sdk/azure";import{createVertex as pe}from"@ai-sdk/google-vertex";import{createClaudeCode as me}from"ai-sdk-provider-claude-code";import{createGeminiProvider as he}from"ai-sdk-provider-gemini-cli";import{APICallError as F,LoadAPIKeyError as ge,NoSuchModelError as I}from"@ai-sdk/provider";import{generateId as L}from"@ai-sdk/provider-utils";import{parse as _e}from"jsonc-parser";import{createCodexCli as ve}from"ai-sdk-provider-codex-cli";import{createOpenAICompatible as ye}from"@ai-sdk/openai-compatible";var be=Object.defineProperty,xe=e=>{let t={};for(var n in e)be(t,n,{get:e[n],enumerable:!0});return t},R=T(import.meta.url);let z=null;var B=class e{constructor(){this._providers=new Map,this._initialized=!1}static getInstance(){return z||=new e,z}initialize(){return this._initialized||=!0,this}registerProvider(e,t,n={}){if(!e||typeof e!=`string`)throw Error(`Provider name must be a non-empty string`);if(!t)throw Error(`Provider instance is required`);if(typeof t.generateText!=`function`||typeof t.streamText!=`function`||typeof t.generateObject!=`function`)throw Error(`Provider must implement BaseAIProvider interface`);return this._providers.set(e,{instance:t,options:n,registeredAt:new Date}),this}hasProvider(e){return this._providers.has(e)}getProvider(e){let t=this._providers.get(e);return t?t.instance:null}getAllProviders(){return new Map(this._providers)}unregisterProvider(e){return this._providers.has(e)?(this._providers.delete(e),!0):!1}reset(){this._providers.clear(),this._initialized=!1}};B.getInstance().initialize();var V=B;const{JSONParseError:Se,NoObjectGeneratedError:Ce,generateObject:we,generateText:Te,streamObject:Ee,streamText:De,zodSchema:Oe}=j,H=j.jsonSchema,ke=new Set([`minimum`,`maximum`,`exclusiveMinimum`,`exclusiveMaximum`]),Ae=[`additionalProperties`,`contains`,`if`,`then`,`else`,`not`,`propertyNames`],je=[`allOf`,`anyOf`,`oneOf`,`prefixItems`],Me=[`definitions`,`$defs`,`dependentSchemas`,`patternProperties`,`properties`],Ne=e=>e?Array.isArray(e)?e.includes(`integer`):e===`integer`:!1,U=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(U);let t={...e};if(Ne(t.type))for(let e of ke)e in t&&delete t[e];for(let e of Ae)t[e]&&(t[e]=U(t[e]));for(let e of je)Array.isArray(t[e])&&(t[e]=t[e].map(U));for(let e of Me)if(t[e]&&typeof t[e]==`object`){let n={};for(let[r,i]of Object.entries(t[e]))n[r]=U(i);t[e]=n}return t.items&&=U(t.items),t},W=e=>{if(!e||typeof e!=`object`)return e;if(Array.isArray(e))return e.map(W);let t={};for(let[n,r]of Object.entries(e))t[n]=W(r);let n=t.type===`object`,r=t.properties&&typeof t.properties==`object`&&!Array.isArray(t.properties),i=Object.prototype.hasOwnProperty.call(t,`additionalProperties`),a=r?Object.keys(t.properties):[],o=Array.isArray(t.required),s=o?new Set(t.required):new Set,c=o&&a.every(e=>s.has(e))&&t.required.length===a.length;return n&&r&&!i&&(t.additionalProperties=!1),n&&r&&!c&&(t.required=a),t},G=e=>{let t=Oe(e);if(!t||typeof t!=`object`||!t.jsonSchema)return t;let n=W(U(t.jsonSchema));return typeof H==`function`?H(n,{validate:t.validate}):{...t,jsonSchema:n}};var K=class e{constructor(){if(this.constructor===e)throw Error(`BaseAIProvider cannot be instantiated directly`);this.name=this.constructor.name,this._proxyAgent=null,this.needsExplicitJsonSchema=!1,this.supportsTemperature=!0}validateAuth(e){if(!e.apiKey)throw Error(`${this.name} API key is required`)}createProxyFetch(){this._projectRoot||=b();let e=this._projectRoot;if(a(null,e))return this._proxyAgent||=new re,(e,t={})=>fetch(e,{...t,dispatcher:this._proxyAgent})}validateParams(e){if(this.validateAuth(e),!e.modelId)throw Error(`${this.name} Model ID is required`);this.validateOptionalParams(e)}validateOptionalParams(e){if(e.temperature!==void 0&&(e.temperature<0||e.temperature>1))throw Error(`Temperature must be between 0 and 1`);if(e.maxTokens!==void 0){let t=Number(e.maxTokens);if(!Number.isFinite(t)||t<=0)throw Error(`maxTokens must be a finite number greater than 0`)}}validateMessages(e){if(!e||!Array.isArray(e)||e.length===0)throw Error(`Invalid or empty messages array provided`);for(let t of e)if(!t.role||!t.content)throw Error(`Invalid message format. Each message must have role and content`)}handleError(e,t){let n=t.message||`Unknown error occurred`;throw S(`error`,`${this.name} ${e} failed: ${n}`,{error:t}),Error(`${this.name} API error during ${e}: ${n}`)}getClient(e){throw Error(`getClient must be implemented by provider`)}isRequiredApiKey(){return!0}getRequiredApiKeyName(){throw Error(`getRequiredApiKeyName must be implemented by provider`)}prepareTokenParam(e,t){return t===void 0?{}:{maxOutputTokens:Math.floor(Number(t))}}async generateText(e){try{this.validateParams(e),this.validateMessages(e.messages),S(`debug`,`Generating ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.generateText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await Te({model:t(e.modelId),messages:e.messages,...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});S(`debug`,`${this.name} generateText completed successfully for model: ${e.modelId}`);let a=i.usage?.inputTokens??i.usage?.promptTokens??0,o=i.usage?.outputTokens??i.usage?.completionTokens??0,s=i.usage?.totalTokens??a+o;return{text:i.text,usage:{inputTokens:a,outputTokens:o,totalTokens:s}}}catch(e){this.handleError(`text generation`,e)}}async streamText(e){try{this.validateParams(e),this.validateMessages(e.messages),S(`debug`,`Streaming ${this.name} text with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.streamText`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=await De({model:t(e.modelId),messages:e.messages,...this.prepareTokenParam(e.modelId,e.maxTokens),...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r},...e.experimental_transform&&{experimental_transform:e.experimental_transform}});return S(`debug`,`${this.name} streamText initiated successfully for model: ${e.modelId}`),i}catch(e){this.handleError(`text streaming`,e)}}async streamObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object streaming`);S(`debug`,`Streaming ${this.name} object with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.streamObject`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=G(e.schema),a=await Ee({model:t(e.modelId),messages:e.messages,schema:i,mode:e.mode||`auto`,maxOutputTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});return S(`debug`,`${this.name} streamObject initiated successfully for model: ${e.modelId}`),a}catch(e){this.handleError(`object streaming`,e)}}async generateObject(e){try{if(this.validateParams(e),this.validateMessages(e.messages),!e.schema)throw Error(`Schema is required for object generation`);if(!e.objectName)throw Error(`Object name is required for object generation`);S(`debug`,`Generating ${this.name} object ('${e.objectName}') with model: ${e.modelId}`);let t=await this.getClient(e),n=e.commandName||`unknown`,r=w(`${this.name}.${e.modelId}.${n}.generateObject.${e.objectName}`,{command:n,outputType:e.outputType,tag:e.tag,projectHash:C(e.projectRoot),userId:e.userId,briefId:e.briefId}),i=G(e.schema),a=await we({model:t(e.modelId),messages:e.messages,schema:i,mode:this.needsExplicitJsonSchema?`json`:`auto`,schemaName:e.objectName,schemaDescription:`Generate a valid JSON object for ${e.objectName}`,maxTokens:e.maxTokens,...this.supportsTemperature&&e.temperature!==void 0?{temperature:e.temperature}:{},...r&&{experimental_telemetry:r}});S(`debug`,`${this.name} generateObject completed successfully for model: ${e.modelId}`);let o=a.usage?.inputTokens??a.usage?.promptTokens??0,s=a.usage?.outputTokens??a.usage?.completionTokens??0,c=a.usage?.totalTokens??o+s;return{object:a.object,usage:{inputTokens:o,outputTokens:s,totalTokens:c}}}catch(e){if(Ce.isInstance(e)&&e.cause instanceof Se&&e.cause.text){S(`warn`,`${this.name} generated malformed JSON, attempting to repair...`);try{let t=M(e.cause.text),n=JSON.parse(t);return S(`info`,`Successfully repaired ${this.name} JSON output`),{object:n,usage:{inputTokens:e.usage?.promptTokens||e.usage?.inputTokens||0,outputTokens:e.usage?.completionTokens||e.usage?.outputTokens||0,totalTokens:e.usage?.totalTokens||0}}}catch(e){S(`error`,`Failed to repair ${this.name} JSON: ${e.message}`)}}this.handleError(`object generation`,e)}}},Pe=class extends K{constructor(){super(),this.name=`Anthropic`}getRequiredApiKeyName(){return`ANTHROPIC_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return N({apiKey:t,...n&&{baseURL:n},headers:{"anthropic-beta":`output-128k-2025-02-19`},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Fe=class extends K{constructor(){super(),this.name=`Perplexity`}getRequiredApiKeyName(){return`PERPLEXITY_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return P({apiKey:t,baseURL:n||`https://api.perplexity.ai`,...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}async generateObject(e){return super.generateObject({...e,mode:`json`})}},Ie=class extends K{constructor(){super(),this.name=`Google`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ie({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Le=class extends K{constructor(){super(),this.name=`OpenAI`}getRequiredApiKeyName(){return`OPENAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.createProxyFetch();return ae({apiKey:t,...n&&{baseURL:n},...r&&{fetch:r}})}catch(e){this.handleError(`client initialization`,e)}}},Re=class extends K{constructor(){super(),this.name=`xAI`}getRequiredApiKeyName(){return`XAI_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return oe({apiKey:t,baseURL:n||`https://api.x.ai/v1`})}catch(e){this.handleError(`client initialization`,e)}}},ze=class extends K{constructor(){super(),this.name=`Groq`}getRequiredApiKeyName(){return`GROQ_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return se({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},Be=class extends K{constructor(){super(),this.name=`OpenRouter`}getRequiredApiKeyName(){return`OPENROUTER_API_KEY`}getClient(e){try{let{apiKey:t,baseURL:n}=e;return ce({apiKey:t,...n&&{baseURL:n}})}catch(e){this.handleError(`client initialization`,e)}}},Ve=class extends K{constructor(){super(),this.name=`Ollama`}validateAuth(e){}getClient(e){try{let{baseURL:t}=e;return le({...t&&{baseURL:t}})}catch(e){this.handleError(`client initialization`,e)}}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`OLLAMA_API_KEY`}},He=class extends K{constructor(){super(),this.name=`Bedrock`}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`AWS_ACCESS_KEY_ID`}validateAuth(e){}getClient(e){try{let e=de(),t=this.createProxyFetch();return ue({credentialProvider:e,...t&&{fetch:t}})}catch(e){this.handleError(`client initialization`,e)}}},Ue=class extends K{constructor(){super(),this.name=`Azure OpenAI`}getRequiredApiKeyName(){return`AZURE_OPENAI_API_KEY`}validateAuth(e){if(!e.apiKey)throw Error(`Azure API key is required`);if(!e.baseURL)throw Error(`Azure endpoint URL is required. Set it in .taskmasterconfig global.azureBaseURL or models.[role].baseURL`)}normalizeBaseURL(e){if(!e)return e;try{let t=new URL(e),n=t.pathname.replace(/\/+$/,``);return n.endsWith(`/openai`)||(n=`${n}/openai`),t.pathname=n,t.toString()}catch{let t=e.replace(/\/+$/,``);return t.endsWith(`/openai`)?t:`${t}/openai`}}getClient(e){try{let{apiKey:t,baseURL:n}=e,r=this.normalizeBaseURL(n),i=this.createProxyFetch();return fe({apiKey:t,baseURL:r,...i&&{fetch:i}})}catch(e){this.handleError(`client initialization`,e)}}},q=class extends Error{constructor(e){super(e),this.name=`VertexAuthError`,this.code=`vertex_auth_error`}},J=class extends Error{constructor(e){super(e),this.name=`VertexConfigError`,this.code=`vertex_config_error`}},We=class extends Error{constructor(e,t){super(e),this.name=`VertexApiError`,this.code=`vertex_api_error`,this.statusCode=t}},Ge=class extends K{constructor(){super(),this.name=`Google Vertex AI`}getRequiredApiKeyName(){return`GOOGLE_API_KEY`}isRequiredApiKey(){return!1}isAuthenticationRequired(){return!0}isValidCredential(e){return e?typeof e==`string`?e.trim().length>0:typeof e==`object`:!1}validateAuth(e){let{apiKey:t,projectId:n,location:r,credentials:i}=e,a=this.isValidCredential(t),o=this.isValidCredential(i);if(!a&&!o)throw new q(`Vertex AI requires authentication. Provide one of the following:
|
|
2
|
+
• GOOGLE_API_KEY environment variable (typical for API-based auth), OR
|
|
3
|
+
• GOOGLE_APPLICATION_CREDENTIALS pointing to a service account JSON file (recommended for production)`);if(!n||typeof n==`string`&&n.trim().length===0)throw new J(`Google Cloud project ID is required for Vertex AI. Set VERTEX_PROJECT_ID environment variable.`);if(!r||typeof r==`string`&&r.trim().length===0)throw new J(`Google Cloud location is required for Vertex AI. Set VERTEX_LOCATION environment variable (e.g., "us-central1").`)}getClient(e){try{let{apiKey:t,projectId:n,location:r,credentials:i,baseURL:a}=e,o=this.createProxyFetch(),s={};return t?s.googleAuthOptions={...i,apiKey:t}:i&&(s.googleAuthOptions=i),pe({...s,project:n,location:r,...a&&{baseURL:a},...o&&{fetch:o}})}catch(e){this.handleError(`client initialization`,e)}}handleError(e,t){if(S(`error`,`Vertex AI ${e} error:`,t),t.name===`VertexAuthError`||t.name===`VertexConfigError`||t.name===`VertexApiError`)throw t;if(t.response){let e=t.response.status,n=t.response.data?.error?.message||t.message;throw e===401||e===403?new q(`Authentication failed: ${n}`):e===400?new J(`Invalid request: ${n}`):new We(`API error (${e}): ${n}`,e)}throw Error(`Vertex AI ${e} failed: ${t.message}`)}};let Y=!1;var Ke=class extends K{constructor(){super(),this.name=`Claude Code`,this.supportedModels=l(`claude-code`),this.supportedModels.length===0&&S(`warn`,`No supported models found for claude-code provider. Check supported-models.json configuration.`),this.needsExplicitJsonSchema=!0,this.supportsTemperature=!1}getRequiredApiKeyName(){return`CLAUDE_CODE_API_KEY`}isRequiredApiKey(){return!1}validateAuth(e){if(process.env.NODE_ENV!==`test`&&!Y&&!process.env.CLAUDE_CODE_OAUTH_TOKEN)try{k(`claude --version`,{stdio:`pipe`,timeout:1e3})}catch{S(`warn`,`Claude Code CLI not detected. Install it with: npm install -g @anthropic-ai/claude-code`)}finally{Y=!0}}getClient(e={}){try{let t=v(e.commandName)||{},n=process.env.ANTHROPIC_API_KEY,r=process.env.CLAUDE_CODE_API_KEY;try{return r?process.env.ANTHROPIC_API_KEY=r:n&&delete process.env.ANTHROPIC_API_KEY,me({defaultSettings:{systemPrompt:{type:`preset`,preset:`claude_code`},settingSources:[`user`,`project`,`local`],...t}})}finally{n?process.env.ANTHROPIC_API_KEY=n:delete process.env.ANTHROPIC_API_KEY}}catch(e){let t=String(e?.message||``);if(e?.code===`ENOENT`||/claude/i.test(t)){let t=Error(`Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${e.message}`);t.cause=e,this.handleError(`Claude Code CLI initialization`,t)}else this.handleError(`client initialization`,e)}}getSupportedModels(){return this.supportedModels}isModelSupported(e){return e?this.supportedModels.includes(String(e).toLowerCase()):!1}},qe=class extends K{constructor(){super(),this.name=`Gemini CLI`,this.supportsTemperature=!1}validateAuth(e){}async getClient(e){try{let t={};return t=e.apiKey&&e.apiKey!==`gemini-cli-no-key-required`?{authType:`api-key`,apiKey:e.apiKey}:{authType:`oauth-personal`},e.baseURL&&(t.baseURL=e.baseURL),he(t)}catch(e){this.handleError(`client initialization`,e)}}getRequiredApiKeyName(){return`GEMINI_API_KEY`}isRequiredApiKey(){return!1}};function X({message:e,code:t,exitCode:n,stderr:r,stdout:i,promptExcerpt:a,isRetryable:o=!1}){return new F({message:e,isRetryable:o,url:`grok-cli://command`,requestBodyValues:a?{prompt:a}:void 0,data:{code:t,exitCode:n,stderr:r,stdout:i,promptExcerpt:a}})}function Z({message:e}){return new ge({message:e||`Authentication failed. Please ensure Grok CLI is properly configured with API key.`})}function Je({message:e,promptExcerpt:t,timeoutMs:n}){return new F({message:e,isRetryable:!0,url:`grok-cli://command`,requestBodyValues:t?{prompt:t}:void 0,data:{code:`TIMEOUT`,promptExcerpt:t,timeoutMs:n}})}function Ye({message:e}){return new F({message:e||`Grok CLI is not installed or not found in PATH. Please install with: npm install -g @vibe-kit/grok-cli`,isRetryable:!1,url:`grok-cli://installation`,requestBodyValues:void 0})}function Xe(e){let t=e.trim(),n=/```(?:json)?\s*([\s\S]*?)\s*```/i.exec(t);n&&(t=n[1]);let r=/^\s*(?:const|let|var)\s+\w+\s*=\s*([\s\S]*)/i.exec(t);r&&(t=r[1],t.trim().endsWith(`;`)&&(t=t.trim().slice(0,-1)));let i=t.indexOf(`{`),a=t.indexOf(`[`);if(i===-1&&a===-1)return e;let o=a===-1?i:i===-1?a:Math.min(i,a);t=t.slice(o);let s=e=>{let t=[];try{let n=_e(e,t,{allowTrailingComma:!0});if(t.length===0)return JSON.stringify(n,null,2)}catch{}},c=s(t);if(c!==void 0)return c;let l=t[0],u=l===`{`?`}`:`]`,d=[],f=0,p=!1,m=!1;for(let e=0;e<t.length;e++){let n=t[e];if(m){m=!1;continue}if(n===`\\`){m=!0;continue}if(n===`"`&&!p){p=!0;continue}if(n===`"`&&p){p=!1;continue}p||(n===l?f++:n===u&&(f--,f===0&&d.push(e+1)))}for(let e=d.length-1;e>=0;e--){let n=s(t.slice(0,d[e]));if(n!==void 0)return n}let h=Math.max(0,t.length-1e3);for(let e=t.length-1;e>h;e--){let n=s(t.slice(0,e));if(n!==void 0)return n}return e}function Ze(e){return e.map(e=>{let t=``;return typeof e.content==`string`?t=e.content:Array.isArray(e.content)?t=e.content.filter(e=>e.type===`text`).map(e=>e.text||``).join(`
|
|
4
|
+
`):e.content&&typeof e.content==`object`&&(t=e.content.text||JSON.stringify(e.content)),{role:e.role,content:t.trim()}})}function Qe(e){try{let t=e.trim().split(`
|
|
5
|
+
`).filter(e=>e.trim()),n=[];for(let e of t)try{let t=JSON.parse(e);n.push(t)}catch{continue}let r=n.filter(e=>e.role===`assistant`).pop();return r&&r.content?{text:r.content,usage:r.usage?{promptTokens:r.usage.prompt_tokens||0,completionTokens:r.usage.completion_tokens||0,totalTokens:r.usage.total_tokens||0}:void 0}:{text:e.trim(),usage:void 0}}catch{return{text:e.trim(),usage:void 0}}}function $e(e){return Ze(e).map(e=>{switch(e.role){case`system`:return`System: ${e.content}`;case`user`:return`User: ${e.content}`;case`assistant`:return`Assistant: ${e.content}`;default:return`${e.role}: ${e.content}`}}).join(`
|
|
6
|
+
|
|
7
|
+
`)}function et(e){return typeof e!=`string`&&(e=String(e)),`'`+e.replace(/'/g,`'\\''`)+`'`}var tt=class{specificationVersion=`v2`;defaultObjectGenerationMode=`json`;supportsImageUrls=!1;supportsStructuredOutputs=!1;supportedUrls={};modelId;settings;constructor(e){if(this.modelId=e.id,this.settings=e.settings??{},!this.modelId||typeof this.modelId!=`string`||this.modelId.trim()===``)throw new I({modelId:this.modelId,modelType:`languageModel`})}get provider(){return`grok-cli`}async checkGrokCliInstallation(){return new Promise(e=>{let t=A(`grok`,[`--version`],{stdio:`pipe`});t.on(`error`,()=>e(!1)),t.on(`exit`,t=>e(t===0))})}async getApiKey(){if(this.settings.apiKey)return this.settings.apiKey;if(process.env.GROK_CLI_API_KEY)return process.env.GROK_CLI_API_KEY;try{let e=D(O(),`.grok`,`user-settings.json`),t=await E.readFile(e,`utf8`);return JSON.parse(t).apiKey||null}catch{return null}}async executeGrokCli(e,t={}){let n=12e4;this.modelId.includes(`grok-4`)&&(n=6e5);let r=t.timeout??this.settings.timeout??n;return new Promise((n,i)=>{let a=A(`grok`,e,{stdio:`pipe`,cwd:this.settings.workingDirectory||process.cwd(),env:t.apiKey===void 0?process.env:{...process.env,GROK_CLI_API_KEY:t.apiKey}}),o=``,s=``,c;r>0&&(c=setTimeout(()=>{a.kill(`SIGTERM`),i(Je({message:`Grok CLI command timed out after ${r}ms`,timeoutMs:r,promptExcerpt:e.join(` `).substring(0,200)}))},r)),a.stdout?.on(`data`,e=>{let t=e.toString();o+=t}),a.stderr?.on(`data`,e=>{let t=e.toString();s+=t}),a.on(`error`,e=>{c&&clearTimeout(c),e.code===`ENOENT`?i(Ye({})):i(X({message:`Failed to execute Grok CLI: ${e.message}`,code:e.code,stderr:e.message,isRetryable:!1}))}),a.on(`exit`,e=>{c&&clearTimeout(c),n({stdout:o.trim(),stderr:s.trim(),exitCode:e||0})})})}generateAllWarnings(e,t){let n=[],r=[];if(e.temperature!==void 0&&r.push(`temperature`),e.topP!==void 0&&r.push(`topP`),e.topK!==void 0&&r.push(`topK`),e.presencePenalty!==void 0&&r.push(`presencePenalty`),e.frequencyPenalty!==void 0&&r.push(`frequencyPenalty`),e.stopSequences!==void 0&&e.stopSequences.length>0&&r.push(`stopSequences`),e.seed!==void 0&&r.push(`seed`),r.length>0)for(let e of r)n.push({type:`unsupported-setting`,setting:e,details:`Grok CLI does not support the ${e} parameter. It will be ignored.`});return(!this.modelId||this.modelId.trim()===``)&&n.push({type:`other`,message:`Model ID is empty or invalid`}),(!t||t.trim()===``)&&n.push({type:`other`,message:`Prompt is empty`}),n}async doGenerate(e){if(e.abortSignal?.aborted)throw e.abortSignal.reason||Error(`Request aborted`);if(!await this.checkGrokCliInstallation())throw Ye({});let t=await this.getApiKey();if(!t)throw Z({message:`Grok CLI API key not found. Set GROK_CLI_API_KEY environment variable or configure grok-cli.`});let n=$e(e.prompt),r=this.generateAllWarnings(e,n),i=[`--prompt`,et(n)];this.modelId&&this.modelId!==`default`&&i.push(`--model`,this.modelId),this.settings.baseURL&&i.push(`--base-url`,this.settings.baseURL),this.settings.workingDirectory&&i.push(`--directory`,this.settings.workingDirectory);try{let a=await this.executeGrokCli(i,{apiKey:t});if(a.exitCode!==0)throw a.stderr.toLowerCase().includes(`unauthorized`)||a.stderr.toLowerCase().includes(`authentication`)?Z({message:`Grok CLI authentication failed: ${a.stderr}`}):X({message:`Grok CLI failed with exit code ${a.exitCode}: ${a.stderr||`Unknown error`}`,exitCode:a.exitCode,stderr:a.stderr,stdout:a.stdout,promptExcerpt:n.substring(0,200),isRetryable:!1});let o=Qe(a.stdout),s=o.text||``;return(e=>!!e&&typeof e==`object`&&`mode`in e&&e.mode?.type===`object-json`)(e)&&s&&(s=Xe(s)),{content:[{type:`text`,text:s||``}],usage:o.usage?{inputTokens:o.usage.promptTokens,outputTokens:o.usage.completionTokens,totalTokens:o.usage.totalTokens}:{inputTokens:0,outputTokens:0,totalTokens:0},finishReason:`stop`,rawCall:{rawPrompt:n,rawSettings:i},warnings:r,response:{id:L(),timestamp:new Date,modelId:this.modelId},request:{body:n},providerMetadata:{"grok-cli":{exitCode:a.exitCode,...a.stderr&&{stderr:a.stderr}}}}}catch(e){throw e.name===`APICallError`||e.name===`LoadAPIKeyError`?e:X({message:`Grok CLI execution failed: ${e.message}`,code:e.code,promptExcerpt:n.substring(0,200),isRetryable:!1})}}async doStream(e){let t=$e(e.prompt),n=this.generateAllWarnings(e,t);return{stream:new ReadableStream({start:async t=>{let r;try{if(e.abortSignal?.aborted)throw e.abortSignal.reason||Error(`Request aborted`);e.abortSignal&&(r=()=>{t.enqueue({type:`error`,error:e.abortSignal?.reason||Error(`Request aborted`)}),t.close()},e.abortSignal.addEventListener(`abort`,r,{once:!0})),t.enqueue({type:`stream-start`,warnings:n});let i=await this.doGenerate(e);t.enqueue({type:`response-metadata`,id:i.response.id,timestamp:i.response.timestamp,modelId:i.response.modelId});let a=i.content||[],o=a.length>0&&a[0].type===`text`?a[0].text:``,s;o.length>0&&(s=L(),t.enqueue({type:`text-start`,id:s}));for(let n=0;n<o.length;n+=50){if(e.abortSignal?.aborted)throw e.abortSignal.reason||Error(`Request aborted`);let r=o.slice(n,n+50);t.enqueue({type:`text-delta`,id:s,delta:r}),await new Promise(e=>setTimeout(e,20))}s&&t.enqueue({type:`text-end`,id:s}),t.enqueue({type:`finish`,finishReason:i.finishReason,usage:i.usage,providerMetadata:i.providerMetadata}),t.close()}catch(e){t.enqueue({type:`error`,error:e}),t.close()}finally{e.abortSignal&&r&&e.abortSignal.removeEventListener(`abort`,r)}},cancel:()=>{}}),request:{body:t}}}};function nt(e={}){let t=(t,n={})=>new tt({id:t,settings:{...e.defaultSettings,...n}}),n=function(e,n){if(new.target)throw Error(`The Grok CLI model function cannot be called with the new keyword.`);return t(e,n)};return n.languageModel=t,n.chat=t,n.textEmbeddingModel=e=>{throw new I({modelId:e,modelType:`textEmbeddingModel`})},n.imageModel=e=>{throw new I({modelId:e,modelType:`imageModel`})},n}nt();var rt=class extends K{constructor(){super(),this.name=`Grok CLI`,this.needsExplicitJsonSchema=!0,this.supportsTemperature=!1}getRequiredApiKeyName(){return`GROK_CLI_API_KEY`}isRequiredApiKey(){return!1}validateAuth(e){}getClient(e){try{let{apiKey:t,baseURL:n,workingDirectory:r,timeout:i,commandName:a}=e,o=h(a);return nt({defaultSettings:{apiKey:t,baseURL:n,workingDirectory:r||o.workingDirectory,timeout:i||o.timeout,defaultModel:o.defaultModel}})}catch(e){this.handleError(`client initialization`,e)}}};const it={"gpt-5.1":[`none`,`low`,`medium`,`high`],"gpt-5.1-codex-max":[`none`,`low`,`medium`,`high`,`xhigh`],"gpt-5.2":[`none`,`low`,`medium`,`high`,`xhigh`],"gpt-5.3-codex":[`none`,`low`,`medium`,`high`,`xhigh`],"gpt-5.2-pro":[`medium`,`high`,`xhigh`],"gpt-5":[`none`,`low`,`medium`,`high`,`xhigh`]},at=[`none`,`low`,`medium`,`high`],ot=[`none`,`low`,`medium`,`high`,`xhigh`];var st=class extends K{constructor(){super(),this.name=`Codex CLI`,this.needsExplicitJsonSchema=!1,this.supportsTemperature=!1,this.supportedModels=l(`codex-cli`),this.supportedModels.length===0&&S(`warn`,`No supported models found for codex-cli provider. Check supported-models.json configuration.`),this._codexCliChecked=!1,this._codexCliAvailable=null}isRequiredApiKey(){return!1}getRequiredApiKeyName(){return`OPENAI_CODEX_API_KEY`}validateAuth(){if(process.env.NODE_ENV!==`test`&&!this._codexCliChecked)try{k(`codex --version`,{stdio:`pipe`,timeout:1e3}),this._codexCliAvailable=!0}catch{this._codexCliAvailable=!1,S(`warn`,`Codex CLI not detected. Install with: npm i -g @openai/codex or enable fallback with allowNpx.`)}finally{this._codexCliChecked=!0}}_getValidatedReasoningEffort(e,t){let n=it[e]||at,r=n.reduce((e,t)=>ot.indexOf(t)>ot.indexOf(e)?t:e,n[0]);return t?n.includes(t)?t:(S(`warn`,`Reasoning effort '${t}' not supported by ${e}. Using '${r}' instead.`),r):(S(`debug`,`No reasoning effort specified for ${e}. Using '${r}'.`),r)}getClient(e={}){try{let t=g(e.commandName)||{},n=this._getValidatedReasoningEffort(e.modelId,t.reasoningEffort);return ve({defaultSettings:{...t,reasoningEffort:n,...e.apiKey?{env:{...t.env||{},OPENAI_API_KEY:e.apiKey}}:{}}})}catch(e){let t=String(e?.message||``);if(e?.code===`ENOENT`||/codex/i.test(t)){let t=Error(`Codex CLI not available. Please install Codex CLI first. Original error: ${e.message}`);t.cause=e,this.handleError(`Codex CLI initialization`,t)}else this.handleError(`client initialization`,e)}}},Q=class extends K{constructor(e){if(super(),!e.name)throw Error(`Provider name is required`);if(!e.apiKeyEnvVar)throw Error(`API key environment variable name is required`);this.name=e.name,this.apiKeyEnvVar=e.apiKeyEnvVar,this.requiresApiKey=e.requiresApiKey!==!1,this.defaultBaseURL=e.defaultBaseURL,this.getBaseURLFromParams=e.getBaseURL,this.supportsStructuredOutputs=e.supportsStructuredOutputs}getRequiredApiKeyName(){return this.apiKeyEnvVar}isRequiredApiKey(){return this.requiresApiKey}validateAuth(e){if(this.requiresApiKey&&!e.apiKey)throw Error(`${this.name} API key is required`)}getBaseURL(e){return e.baseURL?e.baseURL:this.getBaseURLFromParams?this.getBaseURLFromParams(e):this.defaultBaseURL}getClient(e){try{let{apiKey:t}=e,n=this.createProxyFetch(),r=this.getBaseURL(e),i={name:this.name.toLowerCase().replace(/[^a-z0-9]/g,`-`)};return this.requiresApiKey&&t&&(i.apiKey=t),r&&(i.baseURL=r),this.supportsStructuredOutputs!==void 0&&(i.supportsStructuredOutputs=this.supportsStructuredOutputs),n&&(i.fetch=n),ye(i)}catch(e){this.handleError(`client initialization`,e)}}},ct=class extends Q{constructor(){super({name:`Z.ai`,apiKeyEnvVar:`ZAI_API_KEY`,requiresApiKey:!0,defaultBaseURL:`https://api.z.ai/api/paas/v4/`,supportsStructuredOutputs:!0})}prepareTokenParam(){return{}}findArrayPropertyInSchema(e){try{let t=e._zod.def;if(!(t?.type===`object`||t?.typeName===`ZodObject`))return null;let n=t.shape;if(typeof n==`function`&&(n=n()),!n||typeof n!=`object`)return null;for(let[e,t]of Object.entries(n)){let n=t._zod.def;if(n?.type===`array`||n?.typeName===`ZodArray`)return e}return null}catch(e){return console.warn(`Failed to introspect Zod schema:`,e.message),null}}async generateObject(e){let t=await super.generateObject(e);if(Array.isArray(t.object)){let n=this.findArrayPropertyInSchema(e.schema);return n?{...t,object:{[n]:t.object}}:(console.warn(`GLM returned a bare array for '${e.objectName}' but could not determine wrapper property from schema. Using objectName as fallback.`),{...t,object:{[e.objectName]:t.object}})}return t}},lt=class extends ct{constructor(){super(),this.name=`Z.ai (Coding Plan)`,this.defaultBaseURL=`https://api.z.ai/api/coding/paas/v4/`}},ut=class extends Q{constructor(){super({name:`LM Studio`,apiKeyEnvVar:`LMSTUDIO_API_KEY`,requiresApiKey:!1,defaultBaseURL:`http://localhost:1234/v1`,supportsStructuredOutputs:!0})}};const dt={anthropic:new Pe,perplexity:new Fe,google:new Ie,zai:new ct,"zai-coding":new lt,lmstudio:new ut,openai:new Le,xai:new Re,groq:new ze,openrouter:new Be,ollama:new Ve,"openai-compatible":new Q({name:`OpenAI Compatible`,apiKeyEnvVar:`OPENAI_COMPATIBLE_API_KEY`,requiresApiKey:!0}),bedrock:new He,azure:new Ue,vertex:new Ge,"claude-code":new Ke,"codex-cli":new st,"gemini-cli":new qe,"grok-cli":new rt};function ft(e){if(dt[e])return dt[e];let t=V.getInstance();return t.hasProvider(e)?(S(`debug`,`Provider "${e}" found in dynamic registry`),t.getProvider(e)):null}function pt(e,t){let n={inputCost:0,outputCost:0,currency:`USD`,isUnknown:!1};if(!s||!s[e])return S(`warn`,`Provider "${e}" not found in MODEL_MAP. Cannot determine cost for model ${t}.`),{...n,isUnknown:!0};let r=s[e].find(e=>e.id===t);if(!r)return S(`debug`,`Model "${t}" not found under provider "${e}". Assuming unknown cost.`),{...n,isUnknown:!0};if(r.cost_per_1m_tokens===null)return S(`debug`,`Cost data is null for model "${t}" under provider "${e}". Pricing unknown.`),{...n,isUnknown:!0};if(r.cost_per_1m_tokens===void 0)return S(`debug`,`Cost data not found for model "${t}" under provider "${e}". Pricing unknown.`),{...n,isUnknown:!0};let i=r.cost_per_1m_tokens;return{inputCost:i.input||0,outputCost:i.output||0,currency:i.currency||`USD`,isUnknown:!1}}function mt(e,t,n,r){let i=(e||0)/1e6*n+(t||0)/1e6*r;return parseFloat(i.toFixed(6))}function ht(e){let t={currentTag:`master`,availableTags:[`master`]};try{return e?{currentTag:ee(e)||`master`,availableTags:gt(e)}:t}catch(e){return y()&&S(`debug`,`Error getting tag information: ${e.message}`),t}}function gt(e){let t=[`master`];try{let n=R(`path`),r=R(`fs`),i=n.join(e,`.taskmaster`,`tasks`,`tasks.json`);if(!r.existsSync(i))return t;let a=JSON.parse(r.readFileSync(i,`utf8`));if(!a||typeof a!=`object`)return t;let o=Object.keys(a).filter(e=>_t(a[e]));return o.length>0?o:t}catch(e){return y()&&S(`debug`,`Could not read tasks file for available tags: ${e.message}`),t}}function _t(e){return e&&typeof e==`object`&&Array.isArray(e.tasks)}function vt(e){let t=e.message?.toLowerCase()||``;return t.includes(`rate limit`)||t.includes(`overloaded`)||t.includes(`service temporarily unavailable`)||t.includes(`timeout`)||t.includes(`network error`)||e.status===429||e.status>=500}function yt(e){try{if(e?.data?.error?.message)return e.data.error.message;if(e?.error?.message)return e.error.message;if(typeof e?.responseBody==`string`)try{let t=JSON.parse(e.responseBody);if(t?.error?.message)return t.error.message}catch{}return typeof e?.message==`string`&&e.message?e.message:typeof e==`string`?e:`An unknown AI service error occurred.`}catch{return`Failed to extract error message.`}}function bt(n,r){return{main:{provider:t(r),modelId:d(r)},research:{provider:_(r),modelId:e(r)},fallback:{provider:x(r),modelId:p(r)}}[n]||null}function xt(e,t){let n=o(e)||r(`VERTEX_PROJECT_ID`,t,e),a=i(e)||r(`VERTEX_LOCATION`,t,e)||`us-central1`,s=r(`GOOGLE_APPLICATION_CREDENTIALS`,t,e);S(`debug`,`Using Vertex AI configuration: Project ID=${n}, Location=${a}`);let c=s?{keyFile:s}:void 0;return{projectId:n,location:a,...c&&{credentials:c}}}function St(e,t,n=null){let i=ft(e);if(!i)throw Error(`Unknown provider '${e}' for API key resolution.`);let a=i.getRequiredApiKeyName();if(a===null)return null;let o=r(a,t,n);if(!i.isRequiredApiKey())return o||null;if(!o)throw Error(`Required API key ${a} for provider '${e}' is not set in environment, session, or .env file.`);return o}async function Ct(e,t,n,r,i,a){let o=0,s=t;for(;o<=2;)try{y()&&S(`info`,`Attempt ${o+1}/3 calling ${s} (Provider: ${r}, Model: ${i}, Role: ${a})`);let c=await e[t](n);return y()&&S(`info`,`${s} succeeded for role ${a} (Provider: ${r}) on attempt ${o+1}`),c}catch(e){if(S(`warn`,`Attempt ${o+1} failed for role ${a} (${s} / ${r}): ${e.message}`),vt(e)&&o<2){o++;let e=1e3*2**(o-1);S(`info`,`Something went wrong on the provider side. Retrying in ${e/1e3}s...`),await new Promise(t=>setTimeout(t,e))}else throw S(`error`,`Something went wrong on the provider side. Max retries reached for role ${a} (${s} / ${r}).`),e}throw Error(`Exhausted all retries for role ${a} (${s} / ${r})`)}async function $(e,t){let{role:r,session:i,projectRoot:a,systemPrompt:o,prompt:s,schema:l,objectName:d,commandName:p,outputType:h,experimental_transform:g,...ee}=t;y()&&S(`info`,`${e}Service called`,{role:r,commandName:p,outputType:h,projectRoot:a});let _=a||b(),v=u(_),x=i?.user?.id||i?.userId,C=i?.context?.briefId||i?.briefId,w;r===`main`?w=[`main`,`fallback`,`research`]:r===`research`?w=[`research`,`fallback`,`main`]:r===`fallback`?w=[`fallback`,`main`,`research`]:(S(`warn`,`Unknown initial role: ${r}. Defaulting to main -> fallback -> research sequence.`),w=[`main`,`fallback`,`research`]);let T=null,E=`AI service call failed for all configured roles.`;for(let t of w){let r,u,y,b,w,D,O,k=null;try{S(`debug`,`New AI service call with role: ${t}`);let E=bt(t,_);if(!E){S(`error`,`Unknown role encountered in _unifiedServiceRunner: ${t}`),T||=Error(`Unknown AI role specified: ${t}`);continue}if(r=E.provider,u=E.modelId,!r||!u){S(`warn`,`Skipping role '${t}': Provider or Model ID not configured.`),T||=Error(`Configuration missing for role '${t}'. Provider: ${r}, Model: ${u}`);continue}if(w=ft(r?.toLowerCase()),!w){S(`warn`,`Skipping role '${t}': Provider '${r}' not supported.`),T||=Error(`Unsupported provider configured: ${r}`);continue}D=te(t,_),r?.toLowerCase()===`azure`&&!D?(D=m(_),S(`debug`,`Using global Azure base URL: ${D}`)):r?.toLowerCase()===`ollama`&&!D?(D=f(_),S(`debug`,`Using global Ollama base URL: ${D}`)):r?.toLowerCase()===`bedrock`&&!D&&(D=ne(_),S(`debug`,`Using global Bedrock base URL: ${D}`)),b=n(t,_),y=St(r?.toLowerCase(),i,_);let A={};r?.toLowerCase()===`vertex`&&(A=xt(_,i));let j=[],M=`${o} \n\n Always respond in ${c(_)}.`;if(j.push({role:`system`,content:M.trim()}),s)j.push({role:`user`,content:s});else throw Error(`User prompt content is missing.`);let re={apiKey:y,modelId:u,maxTokens:b.maxTokens,temperature:b.temperature,messages:j,...D&&{baseURL:D},...(e===`generateObject`||e===`streamObject`)&&{schema:l,objectName:d},...p&&{commandName:p},...h&&{outputType:h},...a&&{projectRoot:a},...x&&{userId:x},...C&&{briefId:C},...g&&{experimental_transform:g},...A,...ee};if(O=await Ct(w,e,re,r,u,t),v&&O&&O.usage)try{k=await Ot({userId:v,commandName:p,providerName:r,modelId:u,inputTokens:O.usage.inputTokens,outputTokens:O.usage.outputTokens,outputType:h})}catch{}else v&&O&&!O.usage&&S(`warn`,`Cannot log telemetry for ${p} (${r}/${u}): AI result missing 'usage' data. (May be expected for streams)`);let N;e===`generateText`?N=O.text:e===`generateObject`?N=O.object:(e===`streamText`||e===`streamObject`||S(`error`,`Unknown serviceType in _unifiedServiceRunner: ${e}`),N=O);let P=ht(_);return{mainResult:N,telemetryData:k,tagInfo:P,providerName:r,modelId:u}}catch(n){let i=yt(n);if(S(`error`,`Service call failed for role ${t} (Provider: ${r||`unknown`}, Model: ${u||`unknown`}): ${i}`),T=n,E=i,e===`generateObject`){let e=i.toLowerCase();if(e.includes(`no endpoints found that support tool use`)||e.includes(`does not support tool_use`)||e.includes(`tool use is not supported`)||e.includes(`tools are not supported`)||e.includes(`function calling is not supported`)||e.includes(`tool use is not supported`)){let e=`Model '${u||`unknown`}' via provider '${r||`unknown`}' does not support the 'tool use' required by generateObjectService. Please configure a model that supports tool/function calling for the '${t}' role, or use generateTextService if structured output is not strictly required.`;throw S(`error`,`[Tool Support Error] ${e}`),Error(e)}}}}throw S(`error`,`All roles in the sequence [${w.join(`, `)}] failed.`),Error(E)}async function wt(e){return $(`generateText`,{outputType:`cli`,...e})}async function Tt(e){return $(`streamText`,{outputType:`cli`,...e})}async function Et(e){let t={outputType:`cli`,...e};if(!t.schema)throw Error(`streamObjectService requires a schema parameter`);return $(`streamObject`,t)}async function Dt(e){return $(`generateObject`,{objectName:`generated_object`,maxRetries:3,outputType:`cli`,...e})}async function Ot({userId:e,commandName:t,providerName:n,modelId:r,inputTokens:i,outputTokens:a,outputType:o}){try{let o=new Date().toISOString(),s=(i||0)+(a||0),{inputCost:c,outputCost:l,currency:u,isUnknown:d}=pt(n,r),f=mt(i,a,c,l),p={timestamp:o,userId:e,commandName:t,modelUsed:r,providerName:n,inputTokens:i||0,outputTokens:a||0,totalTokens:s,totalCost:f,currency:u,isUnknownCost:d};return y()&&S(`info`,`AI Usage Telemetry:`,p),p}catch(e){return S(`error`,`Failed to log AI usage telemetry: ${e.message}`,{error:e}),null}}export{Tt as a,xe as c,Et as i,R as l,wt as n,K as o,Ot as r,V as s,Dt as t};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import"./ai-services-unified-
|
|
1
|
+
import"./ai-services-unified-D0SWrwB5.js";import{An as e,B as t,Bt as n,E as r,Ht as i,Kt as a,Lt as o,Nt as s,Q as c,R as l,Rt as u,Tt as d,U as f,Ut as p,Vt as m,dt as h,f as g,hn as _,ln as ee,m as v,mn as te,p as y,t as b,ut as ne,yt as x}from"./config-manager-Dn_JApjY.js";import"./git-utils-DllbRE35.js";import"./sentry-Dbx7-h6F.js";import{$ as S,C,D as w,F as T,I as E,J as re,L as ie,M as ae,N as oe,O as se,P as ce,Q as le,S as ue,St as de,X as D,Y as fe,Z as pe,_ as me,_t as he,a as ge,at as O,b as _e,bt as ve,c as ye,ct as be,d as k,dt as xe,et as Se,f as Ce,g as we,h as Te,ht as Ee,i as De,it as Oe,j as ke,k as A,l as Ae,m as je,n as Me,nt as Ne,o as Pe,ot as Fe,p as j,r as Ie,rt as Le,s as Re,st as ze,t as Be,tt as Ve,u as He,ut as Ue,v as M,vt as We,w as Ge,wt as Ke,xt as qe,y as Je,yt as Ye}from"./dependency-manager-D_uegoOJ.js";import{t as Xe}from"./response-language-DeTA_0Bx.js";import{_ as Ze,a as Qe,c as $e,d as et,f as tt,g as nt,h as rt,i as it,l as N,m as at,n as ot,o as P,p as st,r as ct,s as F,t as I,u as L,v as R}from"./profiles-BVhvTqG7.js";import z from"chalk";import B from"fs";import V from"path";import H from"boxen";import{Command as lt}from"commander";import U from"inquirer";const W={AUTHENTICATION:`authentication`,VALIDATION:`validation`,NETWORK:`network`,API:`api`,FILE_SYSTEM:`file_system`,TASK:`task`,PERMISSION:`permission`,TIMEOUT:`timeout`,GENERIC:`generic`},ut=[/\b[A-Za-z0-9_-]{20,}\b/g,/sk-[A-Za-z0-9]{32,}/g,/api[_-]?key[:\s=]+[^\s]+/gi,/bearer\s+[^\s]+/gi,/token[:\s=]+[^\s]+/gi,/\/Users\/[^/]+/g,/C:\\Users\\[^\\]+/g,/\/home\/[^/]+/g,/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g,/https?:\/\/[^:]+:[^@]+@/g];function G(e){if(!e||typeof e!=`string`)return e;let t=e;for(let e of ut)t=t.replace(e,`***REDACTED***`);return t}function dt(e){if(!e)return W.GENERIC;let t=(e.message||``).toLowerCase(),n=(e.code||``).toLowerCase();return t.includes(`auth`)||t.includes(`unauthorized`)||t.includes(`forbidden`)||t.includes(`api key`)||t.includes(`token`)||n.includes(`auth`)?W.AUTHENTICATION:t.includes(`invalid`)||t.includes(`validation`)||t.includes(`required`)||t.includes(`must be`)||n.includes(`validation`)?W.VALIDATION:t.includes(`network`)||t.includes(`connection`)||t.includes(`econnrefused`)||t.includes(`enotfound`)||n.includes(`network`)||n.includes(`econnrefused`)||n.includes(`enotfound`)?W.NETWORK:t.includes(`timeout`)||t.includes(`timed out`)||n.includes(`timeout`)?W.TIMEOUT:t.includes(`api`)||t.includes(`rate limit`)||t.includes(`quota`)||n.includes(`api`)?W.API:t.includes(`enoent`)||t.includes(`eacces`)||t.includes(`file`)||t.includes(`directory`)||n.includes(`enoent`)||n.includes(`eacces`)?W.FILE_SYSTEM:t.includes(`permission`)||t.includes(`access denied`)||n.includes(`eperm`)?W.PERMISSION:t.includes(`task`)||t.includes(`subtask`)?W.TASK:W.GENERIC}function ft(e,t,n){let r=[],i=(t.message||``).toLowerCase();switch(e){case W.AUTHENTICATION:i.includes(`api key`)?(r.push(`Check that your API key is correctly set in the .env file`),r.push(`Verify the API key has not expired or been revoked`)):i.includes(`token`)?(r.push(`Your authentication token may have expired`),r.push(`Try running: tm auth refresh`)):(r.push(`Verify your credentials are correctly configured`),r.push(`Check the authentication status with: tm auth status`));break;case W.VALIDATION:i.includes(`brief id`)?(r.push(`Brief IDs are case-insensitive (e.g., "ham32" = "HAM-32")`),r.push(`Check the brief ID format: usually LETTERS-NUMBERS`)):i.includes(`task id`)||i.includes(`invalid id`)?(r.push(`Task IDs should be numbers (e.g., 1, 2, 3)`),r.push(`Subtask IDs use dot notation (e.g., 1.1, 2.3)`)):(r.push(`Check that all required parameters are provided`),r.push(`Verify parameter values match expected formats`));break;case W.NETWORK:i.includes(`econnrefused`)?(r.push(`Could not connect to the server`),r.push(`Check your internet connection`),r.push(`Verify the API endpoint URL is correct`)):i.includes(`enotfound`)?(r.push(`Could not resolve the server hostname`),r.push(`Check your internet connection`)):(r.push(`Check your network connection`),r.push(`Verify firewall settings are not blocking the request`));break;case W.TIMEOUT:r.push(`The operation took too long to complete`),r.push(`Try again with a simpler request`),r.push(`Check your network speed and stability`);break;case W.API:i.includes(`rate limit`)?(r.push(`You have exceeded the API rate limit`),r.push(`Wait a few minutes before trying again`)):i.includes(`quota`)?(r.push(`You have reached your API quota`),r.push(`Check your account usage and limits`)):(r.push(`The API returned an error`),r.push(`Try again in a few moments`));break;case W.FILE_SYSTEM:i.includes(`enoent`)?(r.push(`The specified file or directory does not exist`),r.push(`Check the file path and ensure it is correct`),n.includes(`tasks.json`)&&r.push(`Initialize the project with: tm init`)):i.includes(`eacces`)?(r.push(`Permission denied to access the file`),r.push(`Check file permissions or run with appropriate privileges`)):r.push(`Check that the file or directory exists and is accessible`);break;case W.PERMISSION:r.push(`You do not have permission to perform this operation`),r.push(`Check file/directory permissions`),r.push(`You may need elevated privileges (sudo)`);break;case W.TASK:i.includes(`not found`)?(r.push(`The specified task does not exist`),r.push(`Use: tm list to see all available tasks`)):i.includes(`dependency`)||i.includes(`circular`)?(r.push(`Task dependencies form a circular reference`),r.push(`Use: tm validate-dependencies to identify issues`)):(r.push(`Check that the task ID is correct`),r.push(`Use: tm show <id> to view task details`));break;default:r.push(`Check the error message for specific details`),n&&r.push(`Operation failed while: ${n}`)}return r.slice(0,2)}function pt(e,t={}){let{context:n=``,debug:r=!1,command:i=``}=t;typeof e==`string`&&(e=Error(e)),(!e||typeof e!=`object`)&&(e=Error(`An unknown error occurred`));let a=G(e.message||`Unknown error`),o=dt(e),s=ft(o,e,n);return{type:o,message:a,context:n||`Unknown operation`,hints:s,command:i||null,code:e.code||null,stack:r?G(e.stack):null}}function K(e,t={}){let n=pt(e,t),r=z.red.bold(`✗ Error
|
|
2
2
|
|
|
3
3
|
`);r+=z.white(n.message)+`
|
|
4
4
|
|
|
@@ -103,7 +103,7 @@ Subtask update was not completed. Review the messages above for details.`))}catc
|
|
|
103
103
|
To fix this issue:`)),console.log(` 1. Run task-master list --with-subtasks to see all available subtask IDs`),console.log(` 2. Use a valid subtask ID with the --id parameter in format "parentId.subtaskId"`)):e.message.includes(`API key`)&&console.log(z.yellow(`
|
|
104
104
|
This error is related to API keys. Check your environment variables.`)),y()&&console.error(e),process.exit(1)}}),n.command(`scope-up`).description(`Increase task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope up (required)`).option(`-s, --strength <level>`,`Complexity increase strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=q({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(z.red(`Error: --id parameter is required`)),console.log(z.yellow(`Usage example: task-master scope-up --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(z.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});A(e.strength)||(console.error(z.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),B.existsSync(n)||(console.error(z.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(z.blue(`Scoping up ${i.length} task(s): ${i.join(`, `)}`)),console.log(z.blue(`Strength level: ${e.strength}`)),e.prompt&&console.log(z.blue(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-up`,outputType:`cli`,research:e.research||!1},o=await se(n,i,e.strength,e.prompt||null,a,`text`);console.log(z.green(`✅ Successfully scoped up ${o.updatedTasks.length} task(s)`))}catch(e){console.error(z.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(z.yellow(`
|
|
105
105
|
To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),y()&&console.error(e),process.exit(1)}}),n.command(`scope-down`).description(`Decrease task complexity with AI assistance`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to scope down (required)`).option(`-s, --strength <level>`,`Complexity decrease strength: light, regular, heavy`,`regular`).option(`-p, --prompt <text>`,`Custom instructions for targeted scope adjustments`).option(`-r, --research`,`Use research AI for more informed adjustments`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{try{let t=q({tasksPath:e.file||!0,tag:e.tag}),n=t.getTasksPath(),r=t.getCurrentTag();await k(r),e.id||(console.error(z.red(`Error: --id parameter is required`)),console.log(z.yellow(`Usage example: task-master scope-down --id=1,2,3 --strength=regular`)),process.exit(1));let i=e.id.split(`,`).map(e=>{let t=parseInt(e.trim(),10);return(Number.isNaN(t)||t<=0)&&(console.error(z.red(`Error: Invalid task ID: ${e.trim()}`)),process.exit(1)),t});A(e.strength)||(console.error(z.red(`Error: Invalid strength level: ${e.strength}. Must be one of: light, regular, heavy`)),process.exit(1)),B.existsSync(n)||(console.error(z.red(`Error: Tasks file not found at path: ${n}`)),process.exit(1)),console.log(z.blue(`Scoping down ${i.length} task(s): ${i.join(`, `)}`)),console.log(z.blue(`Strength level: ${e.strength}`)),e.prompt&&console.log(z.blue(`Custom instructions: ${e.prompt}`));let a={projectRoot:t.getProjectRoot(),tag:r,commandName:`scope-down`,outputType:`cli`,research:e.research||!1},o=await w(n,i,e.strength,e.prompt||null,a,`text`);console.log(z.green(`✅ Successfully scoped down ${o.updatedTasks.length} task(s)`))}catch(e){console.error(z.red(`Error: ${e.message}`)),e.message.includes(`not found`)&&(console.log(z.yellow(`
|
|
106
|
-
To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),y()&&console.error(e),process.exit(1)}}),Fe(n),n.command(`expand`).description(`Expand a task into subtasks using AI`).option(`-i, --id <id>`,`ID of the task to expand`).option(`-a, --all`,`Expand all pending tasks based on complexity analysis`).option(`-n, --num <number>`,`Number of subtasks to generate (uses complexity analysis by default if available)`).option(`-r, --research`,`Enable research-backed generation (e.g., using Perplexity)`,!1).option(`-p, --prompt <text>`,`Additional context for subtask generation`).option(`-f, --force`,`Force expansion even if subtasks exist`,!1).option(`--file <file>`,`Path to the tasks file (relative to project root)`,a).option(`-cr, --complexity-report <file>`,`Path to the complexity report file (use this to specify the complexity report, not --file)`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.complexityReport&&(t.complexityReportPath=e.complexityReport);let r=q(t),i=r.getCurrentTag();if(await k(i),e.all){console.log(z.blue(`Expanding all pending tasks...`));try{await re(r.getTasksPath(),e.num,e.research,e.prompt,e.force,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()})}catch(e){console.error(z.red(`Error expanding all tasks: ${e.message}`)),process.exit(1)}}else if(e.id){e.id||(console.error(z.red(`Error: Task ID is required unless using --all.`)),process.exit(1)),console.log(z.blue(`Expanding task ${e.id}...`));try{await fe(r.getTasksPath(),e.id,e.num,e.research,e.prompt,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()},e.force)}catch(t){console.error(z.red(`Error expanding task ${e.id}: ${t.message}`)),process.exit(1)}}else console.error(z.red(`Error: You must specify either a task ID (--id) or --all.`)),n.help()}),n.command(`analyze-complexity`).description(`Analyze tasks and generate expansion recommendations${z.reset(``)}`).option(`-o, --output <file>`,`Output file path for the report`).option(`-m, --model <model>`,`LLM model to use for analysis (defaults to configured model)`).option(`-t, --threshold <number>`,`Minimum complexity score to recommend expansion (1-10)`,`5`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-r, --research`,`Use configured research model for research-backed complexity analysis`).option(`-i, --id <ids>`,`Comma-separated list of specific task IDs to analyze (e.g., "1,3,5")`).option(`--from <id>`,`Starting task ID in a range to analyze`).option(`--to <id>`,`Ending task ID in a range to analyze`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.output&&(t.complexityReportPath=e.output);let n=q(t);e.model,parseFloat(e.threshold);let r=e.research||!1,i=n.getCurrentTag();await k(i);let a=n.getComplexityReportPath();if(console.log(z.blue(`Analyzing task complexity from: ${n.getTasksPath()}`)),console.log(z.blue(`Output report will be saved to: ${a}`)),e.id)console.log(z.blue(`Analyzing specific task IDs: ${e.id}`));else if(e.from||e.to){let t=e.from?e.from:`first`,n=e.to?e.to:`last`;console.log(z.blue(`Analyzing tasks in range: ${t} to ${n}`))}r&&console.log(z.blue(`Using Perplexity AI for research-backed complexity analysis`)),await pe({...e,output:a,tag:i,projectRoot:n.getProjectRoot(),file:n.getTasksPath()})}),n.command(`research`).description(`Perform AI-powered research queries with project context`).argument(`[prompt]`,`Research prompt to investigate`).option(`--file <file>`,`Path to the tasks file`).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to include as context (e.g., "15,16.2")`).option(`-f, --files <paths>`,`Comma-separated file paths to include as context`).option(`-c, --context <text>`,`Additional custom context to include in the research prompt`).option(`-t, --tree`,`Include project file tree structure in the research context`).option(`-s, --save <file>`,`Save research results to the specified task/subtask(s)`).option(`-d, --detail <level>`,`Output detail level: low, medium, high`,`medium`).option(`--save-to <id>`,`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`).option(`--save-file`,`Save research results to .taskmaster/docs/research/ directory`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=q({tasksPath:t.file||!0,tag:t.tag});(!e||typeof e!=`string`||e.trim().length===0)&&(console.error(z.red(`Error: Research prompt is required and cannot be empty`)),m(),process.exit(1));let r=[`low`,`medium`,`high`];t.detail&&!r.includes(t.detail.toLowerCase())&&(console.error(z.red(`Error: Detail level must be one of: ${r.join(`, `)}`)),process.exit(1));let i=[];if(t.id)try{i=t.id.split(`,`).map(e=>{let t=e.trim();if(!/^\d+(\.\d+)?$/.test(t))throw Error(`Invalid task ID format: "${t}". Expected format: "15" or "15.2"`);return t})}catch(e){console.error(z.red(`Error parsing task IDs: ${e.message}`)),process.exit(1)}let a=[];if(t.files)try{a=t.files.split(`,`).map(e=>{let t=e.trim();if(t.length===0)throw Error(`Empty file path provided`);return t})}catch(e){console.error(z.red(`Error parsing file paths: ${e.message}`)),process.exit(1)}if(t.saveTo){let e=t.saveTo.trim();e.length===0&&(console.error(z.red(`Error: Save-to ID cannot be empty`)),process.exit(1)),/^\d+(\.\d+)?$/.test(e)||(console.error(z.red(`Error: Save-to ID must be in format "15" for task or "15.2" for subtask`)),process.exit(1))}if(t.save){let e=t.save.trim();e.length===0&&(console.error(z.red(`Error: Save target cannot be empty`)),process.exit(1)),(e.includes(`..`)||e.startsWith(`/`))&&(console.error(z.red(`Error: Save path must be relative and cannot contain ".."`)),process.exit(1))}let o=n.getCurrentTag();if(await k(o),i.length>0)try{let e=d(n.getTasksPath(),n.getProjectRoot(),o);(!e||!e.tasks)&&(console.error(z.red(`Error: No valid tasks found in ${n.getTasksPath()} for tag '${o}'`)),process.exit(1))}catch(e){console.error(z.red(`Error reading tasks file: ${e.message}`)),process.exit(1)}if(a.length>0)for(let e of a){let t=V.isAbsolute(e)?e:V.join(n.getProjectRoot(),e);B.existsSync(t)||(console.error(z.red(`Error: File not found: ${e}`)),process.exit(1))}let s={prompt:e.trim(),taskIds:i,filePaths:a,customContext:t.context?t.context.trim():null,includeProjectTree:!!t.tree,saveTarget:t.save?t.save.trim():null,saveToId:t.saveTo?t.saveTo.trim():null,allowFollowUp:!0,detailLevel:t.detail?t.detail.toLowerCase():`medium`,tasksPath:n.getTasksPath(),projectRoot:n.getProjectRoot()};console.log(z.blue(`Researching: "${s.prompt}"`)),s.taskIds.length>0&&console.log(z.gray(`Task context: ${s.taskIds.join(`, `)}`)),s.filePaths.length>0&&console.log(z.gray(`File context: ${s.filePaths.join(`, `)}`)),s.customContext&&console.log(z.gray(`Custom context: ${s.customContext.substring(0,50)}${s.customContext.length>50?`...`:``}`)),s.includeProjectTree&&console.log(z.gray(`Including project file tree`)),console.log(z.gray(`Detail level: ${s.detailLevel}`));try{let{performResearch:e}=await import(`./research-
|
|
106
|
+
To fix this issue:`)),console.log(` 1. Run task-master list to see all available task IDs`),console.log(` 2. Use valid task IDs with the --id parameter`)),y()&&console.error(e),process.exit(1)}}),Fe(n),n.command(`expand`).description(`Expand a task into subtasks using AI`).option(`-i, --id <id>`,`ID of the task to expand`).option(`-a, --all`,`Expand all pending tasks based on complexity analysis`).option(`-n, --num <number>`,`Number of subtasks to generate (uses complexity analysis by default if available)`).option(`-r, --research`,`Enable research-backed generation (e.g., using Perplexity)`,!1).option(`-p, --prompt <text>`,`Additional context for subtask generation`).option(`-f, --force`,`Force expansion even if subtasks exist`,!1).option(`--file <file>`,`Path to the tasks file (relative to project root)`,a).option(`-cr, --complexity-report <file>`,`Path to the complexity report file (use this to specify the complexity report, not --file)`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.complexityReport&&(t.complexityReportPath=e.complexityReport);let r=q(t),i=r.getCurrentTag();if(await k(i),e.all){console.log(z.blue(`Expanding all pending tasks...`));try{await re(r.getTasksPath(),e.num,e.research,e.prompt,e.force,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()})}catch(e){console.error(z.red(`Error expanding all tasks: ${e.message}`)),process.exit(1)}}else if(e.id){e.id||(console.error(z.red(`Error: Task ID is required unless using --all.`)),process.exit(1)),console.log(z.blue(`Expanding task ${e.id}...`));try{await fe(r.getTasksPath(),e.id,e.num,e.research,e.prompt,{projectRoot:r.getProjectRoot(),tag:i,complexityReportPath:r.getComplexityReportPath()},e.force)}catch(t){console.error(z.red(`Error expanding task ${e.id}: ${t.message}`)),process.exit(1)}}else console.error(z.red(`Error: You must specify either a task ID (--id) or --all.`)),n.help()}),n.command(`analyze-complexity`).description(`Analyze tasks and generate expansion recommendations${z.reset(``)}`).option(`-o, --output <file>`,`Output file path for the report`).option(`-m, --model <model>`,`LLM model to use for analysis (defaults to configured model)`).option(`-t, --threshold <number>`,`Minimum complexity score to recommend expansion (1-10)`,`5`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-r, --research`,`Use configured research model for research-backed complexity analysis`).option(`-i, --id <ids>`,`Comma-separated list of specific task IDs to analyze (e.g., "1,3,5")`).option(`--from <id>`,`Starting task ID in a range to analyze`).option(`--to <id>`,`Ending task ID in a range to analyze`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async e=>{let t={tasksPath:e.file||!0,tag:e.tag};e.output&&(t.complexityReportPath=e.output);let n=q(t);e.model,parseFloat(e.threshold);let r=e.research||!1,i=n.getCurrentTag();await k(i);let a=n.getComplexityReportPath();if(console.log(z.blue(`Analyzing task complexity from: ${n.getTasksPath()}`)),console.log(z.blue(`Output report will be saved to: ${a}`)),e.id)console.log(z.blue(`Analyzing specific task IDs: ${e.id}`));else if(e.from||e.to){let t=e.from?e.from:`first`,n=e.to?e.to:`last`;console.log(z.blue(`Analyzing tasks in range: ${t} to ${n}`))}r&&console.log(z.blue(`Using Perplexity AI for research-backed complexity analysis`)),await pe({...e,output:a,tag:i,projectRoot:n.getProjectRoot(),file:n.getTasksPath()})}),n.command(`research`).description(`Perform AI-powered research queries with project context`).argument(`[prompt]`,`Research prompt to investigate`).option(`--file <file>`,`Path to the tasks file`).option(`-i, --id <ids>`,`Comma-separated task/subtask IDs to include as context (e.g., "15,16.2")`).option(`-f, --files <paths>`,`Comma-separated file paths to include as context`).option(`-c, --context <text>`,`Additional custom context to include in the research prompt`).option(`-t, --tree`,`Include project file tree structure in the research context`).option(`-s, --save <file>`,`Save research results to the specified task/subtask(s)`).option(`-d, --detail <level>`,`Output detail level: low, medium, high`,`medium`).option(`--save-to <id>`,`Automatically save research results to specified task/subtask ID (e.g., "15" or "15.2")`).option(`--save-file`,`Save research results to .taskmaster/docs/research/ directory`).option(`--tag <tag>`,`Specify tag context for task operations`).action(async(e,t)=>{let n=q({tasksPath:t.file||!0,tag:t.tag});(!e||typeof e!=`string`||e.trim().length===0)&&(console.error(z.red(`Error: Research prompt is required and cannot be empty`)),m(),process.exit(1));let r=[`low`,`medium`,`high`];t.detail&&!r.includes(t.detail.toLowerCase())&&(console.error(z.red(`Error: Detail level must be one of: ${r.join(`, `)}`)),process.exit(1));let i=[];if(t.id)try{i=t.id.split(`,`).map(e=>{let t=e.trim();if(!/^\d+(\.\d+)?$/.test(t))throw Error(`Invalid task ID format: "${t}". Expected format: "15" or "15.2"`);return t})}catch(e){console.error(z.red(`Error parsing task IDs: ${e.message}`)),process.exit(1)}let a=[];if(t.files)try{a=t.files.split(`,`).map(e=>{let t=e.trim();if(t.length===0)throw Error(`Empty file path provided`);return t})}catch(e){console.error(z.red(`Error parsing file paths: ${e.message}`)),process.exit(1)}if(t.saveTo){let e=t.saveTo.trim();e.length===0&&(console.error(z.red(`Error: Save-to ID cannot be empty`)),process.exit(1)),/^\d+(\.\d+)?$/.test(e)||(console.error(z.red(`Error: Save-to ID must be in format "15" for task or "15.2" for subtask`)),process.exit(1))}if(t.save){let e=t.save.trim();e.length===0&&(console.error(z.red(`Error: Save target cannot be empty`)),process.exit(1)),(e.includes(`..`)||e.startsWith(`/`))&&(console.error(z.red(`Error: Save path must be relative and cannot contain ".."`)),process.exit(1))}let o=n.getCurrentTag();if(await k(o),i.length>0)try{let e=d(n.getTasksPath(),n.getProjectRoot(),o);(!e||!e.tasks)&&(console.error(z.red(`Error: No valid tasks found in ${n.getTasksPath()} for tag '${o}'`)),process.exit(1))}catch(e){console.error(z.red(`Error reading tasks file: ${e.message}`)),process.exit(1)}if(a.length>0)for(let e of a){let t=V.isAbsolute(e)?e:V.join(n.getProjectRoot(),e);B.existsSync(t)||(console.error(z.red(`Error: File not found: ${e}`)),process.exit(1))}let s={prompt:e.trim(),taskIds:i,filePaths:a,customContext:t.context?t.context.trim():null,includeProjectTree:!!t.tree,saveTarget:t.save?t.save.trim():null,saveToId:t.saveTo?t.saveTo.trim():null,allowFollowUp:!0,detailLevel:t.detail?t.detail.toLowerCase():`medium`,tasksPath:n.getTasksPath(),projectRoot:n.getProjectRoot()};console.log(z.blue(`Researching: "${s.prompt}"`)),s.taskIds.length>0&&console.log(z.gray(`Task context: ${s.taskIds.join(`, `)}`)),s.filePaths.length>0&&console.log(z.gray(`File context: ${s.filePaths.join(`, `)}`)),s.customContext&&console.log(z.gray(`Custom context: ${s.customContext.substring(0,50)}${s.customContext.length>50?`...`:``}`)),s.includeProjectTree&&console.log(z.gray(`Including project file tree`)),console.log(z.gray(`Detail level: ${s.detailLevel}`));try{let{performResearch:e}=await import(`./research-CubqvgZX.js`),n={taskIds:s.taskIds,filePaths:s.filePaths,customContext:s.customContext||``,includeProjectTree:s.includeProjectTree,detailLevel:s.detailLevel,projectRoot:s.projectRoot,saveToFile:!!t.saveFile,tag:o},r=await e(s.prompt,n,{commandName:`research`,outputType:`cli`,tag:o},`text`,s.allowFollowUp);if(s.saveToId&&!r.interactiveSaveOccurred)try{let e=s.saveToId.includes(`.`),t=`## Research Query: ${s.prompt}
|
|
107
107
|
|
|
108
108
|
**Detail Level:** ${r.detailLevel}
|
|
109
109
|
**Context Size:** ${r.contextSize} characters
|
|
@@ -111,7 +111,7 @@ To fix this issue:`)),console.log(` 1. Run task-master list to see all availabl
|
|
|
111
111
|
|
|
112
112
|
### Results
|
|
113
113
|
|
|
114
|
-
${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-
|
|
114
|
+
${r.result}`;if(e){let{updateSubtaskById:e}=await import(`./update-subtask-by-id-D56bbaA6.js`);await e(s.tasksPath,s.saveToId,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`),console.log(z.green(`✅ Research saved to subtask ${s.saveToId}`))}else{let e=(await import(`./update-task-by-id-rlGR5O_g.js`)).default,n=parseInt(s.saveToId,10);await e(s.tasksPath,n,t,!1,{commandName:`research-save`,outputType:`cli`,projectRoot:s.projectRoot,tag:o},`text`,!0),console.log(z.green(`✅ Research saved to task ${s.saveToId}`))}}catch(e){console.log(z.red(`❌ Error saving to task/subtask: ${e.message}`))}if(s.saveTarget){let e=`# Research Query: ${s.prompt}
|
|
115
115
|
|
|
116
116
|
**Detail Level:** ${r.detailLevel}
|
|
117
117
|
**Context Size:** ${r.contextSize} characters
|
|
@@ -306,14 +306,14 @@ Or specify profiles directly:
|
|
|
306
306
|
`));for(let e of t)console.log(` • ${e.displayName} ${z.gray(`(${e.markerPath})`)}`);console.log(``),e=t.map(e=>e.profileName)}else e=await F(i);if(!e||e.length===0){console.log(z.yellow(`No profiles selected. Exiting.`));return}console.log(z.blue(`Installing ${e.length} selected profile(s)...`));let{allSuccessfulProfiles:t,totalSuccess:r,totalFailed:a}=I(await P(e,i,n.mode));console.log(z.green(`\n✓ Successfully installed ${t.length} profile(s)`)),r>0&&console.log(z.gray(` ${r} files processed, ${a} failed`));return}(!t||t.length===0)&&(console.error(`Please specify at least one rule profile (e.g., windsurf, roo).`),process.exit(1));let a=t.flatMap(e=>e.split(`,`).map(e=>e.trim())).filter(Boolean);if(e===N.REMOVE){let e=!0;if(n.force||(e=$e(i,a)?await _t(a,Qe(i)):await gt(a)),!e){console.log(z.yellow(`Aborted: No rules were removed.`));return}}let o=[],s=[];for(let t of a){if(!rt(t)){console.warn(`Rule profile for "${t}" not found. Valid profiles: ${R.join(`, `)}. Skipping.`);continue}let a=at(t);if(e===N.ADD){console.log(z.blue(`Adding rules for profile: ${t}...`));let e=st(i,a,{mode:await r(n.mode)});console.log(z.blue(`Completed adding rules for profile: ${t}`)),s.push({profileName:t,success:e.success,failed:e.failed}),console.log(z.green(it(t,e)))}else if(e===N.REMOVE){console.log(z.blue(`Removing rules for profile: ${t}...`));let e=nt(i,a);o.push(e),console.log(z.green(ct(t,e)))}else console.error(`Unknown action. Use "${N.ADD}" or "${N.REMOVE}".`),process.exit(1)}if(e===N.ADD&&s.length>0){let{allSuccessfulProfiles:e,totalSuccess:t,totalFailed:n}=I(s);e.length>0&&(console.log(z.green(`\nSuccessfully processed profiles: ${e.join(`, `)}`)),t>0?console.log(z.green(`Total: ${t} files processed, ${n} failed.`)):console.log(z.green(`Total: ${e.length} profile(s) set up successfully.`)))}if(e===N.REMOVE&&o.length>0){let{successfulRemovals:e,skippedRemovals:t,failedRemovals:n,removalsWithNotices:r}=ot(o);e.length>0&&console.log(z.green(`\nSuccessfully removed profiles for: ${e.join(`, `)}`)),t.length>0&&console.log(z.yellow(`Skipped (default or protected): ${t.join(`, `)}`)),n.length>0&&(console.log(z.red(`
|
|
307
307
|
Errors occurred:`)),n.forEach(e=>{console.log(z.red(` ${e.profileName}: ${e.error}`))})),r.length>0&&(console.log(z.cyan(`
|
|
308
308
|
Notices:`)),r.forEach(e=>{console.log(z.cyan(` ${e.profileName}: ${e.notice}`))}));let i=o.length,a=e.length,s=t.length,c=n.length;console.log(z.blue(`\nTotal: ${i} profile(s) processed - ${a} removed, ${s} skipped, ${c} failed.`))}}),n.command(`migrate`).description(`Migrate existing project to use the new .taskmaster directory structure`).option(`-f, --force`,`Force migration even if .taskmaster directory already exists`).option(`--backup`,`Create backup of old files before migration (default: false)`,!1).option(`--cleanup`,`Remove old files after successful migration (default: true)`,!0).option(`-y, --yes`,`Skip confirmation prompts`).option(`--dry-run`,`Show what would be migrated without actually moving files`).action(async e=>{try{await ie(e)}catch(e){console.error(z.red(`Error during migration:`),e.message),process.exit(1)}}),n.command(`sync-readme`).description(`Sync the current task list to README.md in the project root`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--with-subtasks`,`Include subtasks in the README output`).option(`-s, --status <status>`,`Show only tasks matching this status (e.g., pending, done)`).option(`-t, --tag <tag>`,`Tag to use for the task list (default: master)`).action(async e=>{let t=q({tasksPath:e.file||!0,tag:e.tag}),n=e.withSubtasks||!1,r=e.status||null,i=t.getCurrentTag();console.log(z.blue(`📝 Syncing tasks to README.md${n?` (with subtasks)`:``}${r?` (status: ${r})`:``}...`)),await syncTasksToReadme(t.getProjectRoot(),{withSubtasks:n,status:r,tasksPath:t.getTasksPath(),tag:i})||(console.error(z.red(`❌ Failed to sync tasks to README.md`)),process.exit(1))}),n.command(`add-tag`).description(`[DEPRECATED] Create a new tag context for organizing tasks (use "tm tags add" instead)`).argument(`[tagName]`,`Name of the new tag to create (optional when using --from-branch)`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`--copy-from-current`,`Copy tasks from the current tag to the new tag`).option(`--copy-from <tag>`,`Copy tasks from the specified tag to the new tag`).option(`--from-branch`,`Create tag name from current git branch (ignores tagName argument)`).option(`-d, --description <text>`,`Optional description for the tag`).action(async(e,t)=>{console.warn(z.yellow(`⚠ Warning: "tm add-tag" is deprecated. Use "tm tags add" instead.`)),console.log(z.gray(` This command will be removed in a future version.
|
|
309
|
-
`));try{let n=q({tasksPath:t.file||!0}),r=n.getTasksPath();B.existsSync(r)||(console.error(z.red(`Error: Tasks file not found at path: ${r}`)),console.log(z.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)),process.exit(1)),!e&&!t.fromBranch&&(console.error(z.red(`Error: Either tagName argument or --from-branch option is required.`)),console.log(z.yellow(`Usage examples:`)),console.log(z.cyan(` task-master add-tag my-tag`)),console.log(z.cyan(` task-master add-tag --from-branch`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`add-tag`,outputType:`cli`};if(t.fromBranch){let{createTagFromBranch:e}=await import(`./tag-management-
|
|
309
|
+
`));try{let n=q({tasksPath:t.file||!0}),r=n.getTasksPath();B.existsSync(r)||(console.error(z.red(`Error: Tasks file not found at path: ${r}`)),console.log(z.yellow(`Hint: Run task-master init or task-master parse-prd to create tasks.json first`)),process.exit(1)),!e&&!t.fromBranch&&(console.error(z.red(`Error: Either tagName argument or --from-branch option is required.`)),console.log(z.yellow(`Usage examples:`)),console.log(z.cyan(` task-master add-tag my-tag`)),console.log(z.cyan(` task-master add-tag --from-branch`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`add-tag`,outputType:`cli`};if(t.fromBranch){let{createTagFromBranch:e}=await import(`./tag-management-ByKA_1s5.js`),r=await import(`./git-utils-PBP1PRVP.js`);await r.isGitRepository(i.projectRoot)||(console.error(z.red(`Error: Not in a git repository. Cannot use --from-branch option.`)),process.exit(1));let a=await r.getCurrentBranch(i.projectRoot);a||(console.error(z.red(`Error: Could not determine current git branch.`)),process.exit(1));let o={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description||`Tag created from git branch "${a}"`};await e(n.getTasksPath(),a,o,i,`text`)}else{let r={copyFromCurrent:t.copyFromCurrent||!1,copyFromTag:t.copyFrom,description:t.description};await be(n.getTasksPath(),e,r,i,`text`)}if(t.autoSwitch){let{useTag:r}=await import(`./tag-management-ByKA_1s5.js`),a=t.fromBranch?(await import(`./git-utils-PBP1PRVP.js`)).sanitizeBranchNameForTag(await(await import(`./git-utils-PBP1PRVP.js`)).getCurrentBranch(projectRoot)):e;await r(n.getTasksPath(),a,{},i,`text`)}}catch(e){console.error(z.red(`Error creating tag: ${e.message}`)),u(),process.exit(1)}}).on(`error`,function(e){console.error(z.red(`Error: ${e.message}`)),u(),process.exit(1)}),n.command(`delete-tag`).description(`[DEPRECATED] Delete an existing tag and all its tasks (use "tm tags remove" instead)`).argument(`<tagName>`,`Name of the tag to delete`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-y, --yes`,`Skip confirmation prompts`).action(async(e,t)=>{console.warn(z.yellow(`⚠ Warning: "tm delete-tag" is deprecated. Use "tm tags remove" instead.`)),console.log(z.gray(` This command will be removed in a future version.
|
|
310
310
|
`));try{let n=q({tasksPath:t.file||!0}),r=n.getTasksPath();B.existsSync(r)||(console.error(z.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={yes:t.yes||!1},a={projectRoot:n.getProjectRoot(),commandName:`delete-tag`,outputType:`cli`};await Ue(n.getTasksPath(),e,i,a,`text`)}catch(e){console.error(z.red(`Error deleting tag: ${e.message}`)),f(),process.exit(1)}}).on(`error`,function(e){console.error(z.red(`Error: ${e.message}`)),f(),process.exit(1)}),n.command(`use-tag`).description(`[DEPRECATED] Switch to a different tag context (use "tm tags use" instead)`).argument(`<tagName>`,`Name of the tag to switch to`).option(`-f, --file <file>`,`Path to the tasks file`,a).action(async(e,t)=>{console.warn(z.yellow(`⚠ Warning: "tm use-tag" is deprecated. Use "tm tags use" instead.`)),console.log(z.gray(` This command will be removed in a future version.
|
|
311
311
|
`));try{let n=q({tasksPath:t.file||!0}),r=n.getTasksPath();B.existsSync(r)||(console.error(z.red(`Error: Tasks file not found at path: ${r}`)),process.exit(1));let i={projectRoot:n.getProjectRoot(),commandName:`use-tag`,outputType:`cli`};await Ee(n.getTasksPath(),e,{},i,`text`)}catch(e){console.error(z.red(`Error switching tag: ${e.message}`)),p(),process.exit(1)}}).on(`error`,function(e){console.error(z.red(`Error: ${e.message}`)),p(),process.exit(1)}),n.command(`rename-tag`).description(`[DEPRECATED] Rename an existing tag (use "tm tags rename" instead)`).argument(`<oldName>`,`Current name of the tag`).argument(`<newName>`,`New name for the tag`).option(`-f, --file <file>`,`Path to the tasks file`,a).action(async(e,t,n)=>{console.warn(z.yellow(`⚠ Warning: "tm rename-tag" is deprecated. Use "tm tags rename" instead.`)),console.log(z.gray(` This command will be removed in a future version.
|
|
312
312
|
`));try{let r=q({tasksPath:n.file||!0}),i=r.getTasksPath();B.existsSync(i)||(console.error(z.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1));let a={projectRoot:r.getProjectRoot(),commandName:`rename-tag`,outputType:`cli`};await xe(r.getTasksPath(),e,t,{},a,`text`)}catch(e){console.error(z.red(`Error renaming tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(z.red(`Error: ${e.message}`)),process.exit(1)}),n.command(`copy-tag`).description(`[DEPRECATED] Copy an existing tag to create a new tag with the same tasks (use "tm tags copy" instead)`).argument(`<sourceName>`,`Name of the source tag to copy from`).argument(`<targetName>`,`Name of the new tag to create`).option(`-f, --file <file>`,`Path to the tasks file`,a).option(`-d, --description <text>`,`Optional description for the new tag`).action(async(e,t,n)=>{console.warn(z.yellow(`⚠ Warning: "tm copy-tag" is deprecated. Use "tm tags copy" instead.`)),console.log(z.gray(` This command will be removed in a future version.
|
|
313
313
|
`));try{let r=q({tasksPath:n.file||!0}),i=r.getTasksPath();B.existsSync(i)||(console.error(z.red(`Error: Tasks file not found at path: ${i}`)),process.exit(1)),await ze(i,e,t,{description:n.description},{projectRoot:r.getProjectRoot(),commandName:`copy-tag`,outputType:`cli`},`text`)}catch(e){console.error(z.red(`Error copying tag: ${e.message}`)),process.exit(1)}}).on(`error`,function(e){console.error(z.red(`Error: ${e.message}`)),process.exit(1)}),n.command(`tui`).alias(`repl`).description(`Launch the interactive TUI/REPL mode`).action(async()=>{await Q()}),n}async function bt(){return null}async function Q(){let e=await import(`react`),t=await bt();if(!t){console.log(z.yellow(`TUI mode coming soon!`)),console.log(z.dim(`Showing help instead...
|
|
314
314
|
`)),J()?X():j();return}let{render:n,Shell:r}=t,i=`master`,a=`local`,o,s={isAuthenticated:!1},c=process.cwd();try{let e=q({});i=e.getCurrentTag(),c=e.getProjectRoot()||process.cwd();let t=_.getInstance(),n=t.getContext(),r=t.getStoredContext();r&&r.email&&(s={isAuthenticated:!0,email:r.email,userId:r.userId}),n&&n.briefId&&(a=`api`,o={id:n.briefId,name:n.briefName||i})}catch{}let l=process.stdin.isTTY&&typeof process.stdin.setRawMode==`function`;console.clear();let u={showBanner:!0,showSplash:l,initialTag:i,storageType:a,brief:o,authState:s,isInteractive:l,projectRoot:c,onExit:()=>{console.log(z.dim(`
|
|
315
315
|
Goodbye! 👋`)),process.exit(0)}},d=n(e.createElement(r,u));l||setTimeout(()=>{d.unmount(),console.log(z.dim(`
|
|
316
|
-
💡 Run in an interactive terminal for full REPL mode.`)),process.exit(0)},200)}function $(){let e=new lt().name(`task-master`).description(`AI-driven development task management`).version(`0.43.
|
|
316
|
+
💡 Run in an interactive terminal for full REPL mode.`)),process.exit(0)},200)}function $(){let e=new lt().name(`task-master`).description(`AI-driven development task management`).version(`0.43.8`).helpOption(`-h, --help`,`Display help`).addHelpCommand(!1),t=e.helpInformation.bind(e);return e.helpInformation=function(){return this.parent&&this.parent!==e?t():(J()?X():j(),``)},Z(e),e}async function xt(e=process.argv){try{if(e.length<=2){await Q();return}let t=e.includes(`init`),n=e.includes(`tui`)||e.includes(`repl`),r=e.includes(`--no-banner`);process.stdout.isTTY&&!t&&!n&&!r&&Re();let i=process.env.TASKMASTER_SKIP_AUTO_UPDATE===`1`||process.env.CI||process.env.NODE_ENV===`test`,a=Se(),o=i?{currentVersion:a,latestVersion:a,needsUpdate:!1}:await ve(a);if(o.needsUpdate&&(Ye(o.currentVersion,o.latestVersion,o.highlights),await We(o.latestVersion))){he(e);return}let s=$(),c=e.filter(e=>e!==`--no-banner`);await s.parseAsync(c);try{let e=q({}),t=e.getTasksPath(),n=e.getStatePath();if(t&&B.existsSync(t)){let e=B.readFileSync(t,`utf8`),r=JSON.parse(e);if(r&&r.master){let e={migrationNoticeShown:!1};if(n&&B.existsSync(n)){let t=B.readFileSync(n,`utf8`);e=JSON.parse(t)||e}e.migrationNoticeShown||(me({_migrationHappened:!0}),e.migrationNoticeShown=!0,n&&B.writeFileSync(n,JSON.stringify(e,null,2)))}}}catch{}}catch(e){e instanceof b?console.error(H(z.red.bold(`Configuration Update Required!`)+`
|
|
317
317
|
|
|
318
318
|
`+z.white(`Taskmaster now uses a `)+z.yellow.bold(`configuration file`)+z.white(` in your project for AI model choices and settings.
|
|
319
319
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as e,B as t,C as n,Cn as r,D as i,E as a,F as o,G as s,H as c,I as l,J as u,K as d,L as f,M as p,N as m,O as h,P as g,R as _,S as v,T as y,U as b,V as x,W as S,_ as C,a as w,b as T,bn as E,c as D,d as O,f as k,g as A,h as j,i as M,j as N,k as P,l as F,m as I,n as L,o as R,p as z,q as B,r as V,s as H,t as U,u as W,v as G,w as K,x as q,xn as J,y as Y,z as X}from"./config-manager-
|
|
1
|
+
import{A as e,B as t,C as n,Cn as r,D as i,E as a,F as o,G as s,H as c,I as l,J as u,K as d,L as f,M as p,N as m,O as h,P as g,R as _,S as v,T as y,U as b,V as x,W as S,_ as C,a as w,b as T,bn as E,c as D,d as O,f as k,g as A,h as j,i as M,j as N,k as P,l as F,m as I,n as L,o as R,p as z,q as B,r as V,s as H,t as U,u as W,v as G,w as K,x as q,xn as J,y as Y,z as X}from"./config-manager-Dn_JApjY.js";import"./git-utils-DllbRE35.js";export{E as ALL_PROVIDERS,J as CUSTOM_PROVIDERS,U as ConfigurationError,u as MODEL_MAP,r as VALIDATED_PROVIDERS,L as getAllProviders,V as getAnonymousTelemetryEnabled,M as getAvailableModels,w as getAzureBaseURL,R as getBaseUrlForRole,H as getBedrockBaseURL,D as getClaudeCodeSettings,F as getClaudeCodeSettingsForCommand,W as getCodexCliSettings,O as getCodexCliSettingsForCommand,k as getConfig,z as getDebugFlag,I as getDefaultNumTasks,j as getDefaultPriority,A as getDefaultSubtasks,C as getFallbackModelId,G as getFallbackProvider,Y as getGrokCliSettings,T as getGrokCliSettingsForCommand,q as getLogLevel,v as getMainModelId,n as getMainProvider,K as getMcpApiKeyStatus,y as getOllamaBaseURL,a as getOperatingMode,i as getParametersForRole,h as getProjectName,P as getProxyEnabled,e as getResearchModelId,N as getResearchProvider,p as getResponseLanguage,m as getSupportedModelsForProvider,g as getUserId,o as getVertexLocation,l as getVertexProjectId,f as hasCodebaseAnalysis,_ as isApiKeySet,X as isCodebaseAnalysisEnabled,t as isConfigFilePresent,x as isConfigWarningSuppressed,c as isProxyEnabled,b as setSuppressConfigWarnings,S as validateClaudeCodeSettings,s as validateCodexCliSettings,d as validateProvider,B as writeConfig};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import{t as e}from"./git-utils-DllbRE35.js";import t,{join as n,resolve as r}from"node:path";import i from"chalk";import{createClient as a,isAuthError as o}from"@supabase/supabase-js";import s from"fs";import c,{join as l}from"path";import u from"fs/promises";import{Writer as d}from"steno";import f from"crypto";import p from"os";import m,{appendFile as h,mkdir as ee,readFile as te}from"node:fs/promises";import ne from"fs-extra";import{simpleGit as re}from"simple-git";import ie,{constants as ae,existsSync as g,readFileSync as oe,readdirSync as se,realpathSync as ce}from"node:fs";import le from"proper-lockfile";import{spawn as ue,spawnSync as de}from"node:child_process";import fe from"node:os";import{z as _}from"zod";import{exec as pe,execSync as me}from"child_process";import{promisify as he}from"util";import"node:crypto";import{format as ge,formatDistanceToNow as _e}from"date-fns";import{fileURLToPath as ve}from"url";import ye from"dotenv";const be=600*1e3,xe=3,Se=[`add-dependency`,`remove-dependency`,`validate-dependencies`,`fix-dependencies`,`clear-subtasks`,`models`,`generate`];function Ce(e){return Se.includes(e)}function we(e){let{hasValidSession:t,briefName:n,storageType:r,commandName:i}=e;return!Ce(i)||!t||r!==`api`?{isBlocked:!1,commandName:i}:{isBlocked:!0,briefName:n||`remote brief`,commandName:i}}const v={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`,NOT_FOUND:`NOT_FOUND`,NO_BRIEF_SELECTED:`NO_BRIEF_SELECTED`};var y=class e extends Error{code;context;cause;timestamp;constructor(t,n=v.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:v.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=v.INTERNAL_ERROR,r={}){return new e(t,n,r,this)}};let b=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 Te=class e{config;static DEFAULT_CONFIG={level:b.SILENT,silent:!1,prefix:``,timestamp:!1,colors:!0,mcpMode:!1,logCallback:void 0};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 b&&(n.level=b[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.logCallback&&(this.config.silent=!0)}shouldLog(e){return this.config.logCallback?e<=this.config.level: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?i.gray(`[${e}] `):`[${e}] `}if(this.config.prefix&&(r+=this.config.colors?i.cyan(`[${this.config.prefix}] `):`[${this.config.prefix}] `),this.config.colors)switch(e){case b.ERROR:t=i.red(t);break;case b.WARN:t=i.yellow(t);break;case b.INFO:break;case b.DEBUG:t=i.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}isLogObject(e){return typeof e==`object`&&!!e&&`info`in e&&`warn`in e&&`error`in e&&`debug`in e}output(e,t,n,...r){let i=this.formatMessage(e,n,...r);if(this.config.logCallback){if(this.isLogObject(this.config.logCallback)){let e=t.toLowerCase();e in this.config.logCallback&&this.config.logCallback[e](i)}else this.config.logCallback(t.toLowerCase(),i);return}switch(e){case b.ERROR:console.error(i);break;case b.WARN:console.warn(i);break;default:console.log(i);break}}error(e,...t){this.shouldLog(b.ERROR)&&this.output(b.ERROR,`ERROR`,e,...t)}warn(e,...t){this.shouldLog(b.WARN)&&this.output(b.WARN,`WARN`,e,...t)}info(e,...t){this.shouldLog(b.INFO)&&this.output(b.INFO,`INFO`,e,...t)}debug(e,...t){this.shouldLog(b.DEBUG)&&this.output(b.DEBUG,`DEBUG`,e,...t)}log(e,...t){if(this.config.logCallback){let n=t.length>0?[e,...t].join(` `):e;this.isLogObject(this.config.logCallback)?this.config.logCallback.info(n):this.config.logCallback(`log`,n);return}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.logCallback&&(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 Ee=null;const De=new Map;function Oe(e){return new Te(e)}function x(e,t){return e?(De.has(e)||De.set(e,Oe({prefix:e,...t})),De.get(e)):(Ee||=Oe(t),Ee)}const ke=c.join(process.env.HOME||process.env.USERPROFILE||`~`,`.taskmaster`,`session.json`);var Ae=class{storage=new Map;persistPath;logger=x(`SupabaseSessionStorage`);writer;initPromise;constructor(e=ke){this.persistPath=e,this.writer=new d(e),this.initPromise=this.load()}async load(){try{let e=c.dirname(this.persistPath);if(await u.mkdir(e,{recursive:!0,mode:448}),s.existsSync(this.persistPath)){let e=JSON.parse(await u.readFile(this.persistPath,`utf8`));Object.entries(e).forEach(([e,t])=>this.storage.set(e,t)),this.logger.debug(`Loaded session from disk`,{keys:Array.from(this.storage.keys())})}}catch(e){this.logger.error(`Failed to load session:`,e)}}async persist(){try{let e=Object.fromEntries(this.storage),t=JSON.stringify(e,null,2);await this.writer.write(t+`
|
|
2
|
-
`),this.logger.debug(`Persisted session to disk (steno)`)}catch(e){this.logger.error(`Failed to persist session:`,e)}}async getItem(e){await this.initPromise;let t=this.storage.get(e)??null;return this.logger.debug(`getItem called`,{key:e,hasValue:!!t}),t}async setItem(e,t){await this.initPromise,this.logger.debug(`setItem called`,{key:e}),this.storage.set(e,t),await this.persist()}async removeItem(e){await this.initPromise,this.logger.debug(`removeItem called`,{key:e}),this.storage.delete(e),await this.persist()}async clear(){await this.initPromise,this.logger.debug(`clear called`),this.storage.clear(),await this.persist()}},S=class extends Error{mfaChallenge;constructor(e,t,n,r){super(e),this.code=t,this.cause=n,this.name=`AuthenticationError`,this.mfaChallenge=r,n&&n instanceof Error&&(this.stack=`${this.stack}\nCaused by: ${n.stack}`)}};function C(e){return o(e)}const je={refresh_token_not_found:`Your session has expired. Please log in again with: task-master login`,refresh_token_already_used:`Your session has expired (token was already used). Please log in again with: task-master login`,invalid_refresh_token:`Your session has expired (invalid token). Please log in again with: task-master login`,session_expired:`Your session has expired. Please log in again with: task-master login`,user_not_found:`User account not found. Please log in again with: task-master login`,invalid_credentials:`Invalid credentials. Please log in again with: task-master login`},Me=[`refresh_token_not_found`,`refresh_token_already_used`];function w(e){return C(e)?Me.includes(e.code||``):!1}function Ne(e,t){let n=e.code,r=n&&je[n]||`${t}: ${e.message}`,i=`REFRESH_FAILED`;return n===`refresh_token_not_found`||n===`refresh_token_already_used`||n===`invalid_refresh_token`||n===`session_expired`||n===`user_not_found`?i=`NOT_AUTHENTICATED`:n===`invalid_credentials`&&(i=`INVALID_CREDENTIALS`),new S(r,i,e)}function Pe(){let{publicKey:e,privateKey:t}=f.generateKeyPairSync(`rsa`,{modulusLength:2048,publicKeyEncoding:{type:`spki`,format:`pem`},privateKeyEncoding:{type:`pkcs8`,format:`pem`}});return{publicKey:e,privateKey:t}}function Fe(e,t){try{let n=Buffer.from(e.encrypted_key,`base64`),r=Buffer.from(e.encrypted_data,`base64`),i=Buffer.from(e.iv,`base64`),a=Buffer.from(e.auth_tag,`base64`),o=f.privateDecrypt({key:t,padding:f.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:`sha256`},n),s=f.createDecipheriv(`aes-256-gcm`,o,i);s.setAuthTag(a);let c=Buffer.concat([s.update(r),s.final()]);return JSON.parse(c.toString(`utf8`))}catch(e){throw new S(`Token decryption failed: ${e instanceof Error?e.message:`Unknown error`}`,`DECRYPTION_FAILED`,e)}}var Ie=class e{static instance=null;client=null;sessionStorage;logger=x(`SupabaseAuthClient`);constructor(){this.sessionStorage=new Ae}static getInstance(){return e.instance||=new e,e.instance}static resetInstance(){e.instance&&(e.instance.client=null),e.instance=null}getClient(){if(!this.client){let e=process.env.TM_SUPABASE_URL||process.env.TM_PUBLIC_SUPABASE_URL||`https://tryhamster.com`,t=process.env.TM_SUPABASE_ANON_KEY||process.env.TM_PUBLIC_SUPABASE_ANON_KEY||`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im5zdHhhdGRwbnNmYWxja3hhd3R6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDg3MzU3NTYsImV4cCI6MjA2NDMxMTc1Nn0.GF897_2zXRxl4pkeQ89-7xF4TkJfJuYPWKhv1bTbv9k`;if(!e||!t)throw new S(`Supabase configuration missing. Please set TM_SUPABASE_URL and TM_SUPABASE_ANON_KEY (runtime) or TM_PUBLIC_SUPABASE_URL and TM_PUBLIC_SUPABASE_ANON_KEY (build-time) environment variables.`,`CONFIG_MISSING`);this.client=a(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?(w(n)||this.logger.warn(`Failed to restore session:`,n),null):(t&&this.logger.info(`Session restored successfully`),t)}catch(e){return w(e)?this.logger.debug(`Session not available (expected during MFA flow)`):C(e)?this.logger.warn(`Session expired or invalid`):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 S(`Failed to initiate PKCE flow: ${n.message}`,`PKCE_INIT_FAILED`);if(!t?.url)throw new S(`No authorization URL returned`,`INVALID_RESPONSE`);return{url:t.url,codeVerifier:``}}catch(e){throw e instanceof S?e:new S(`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 S(`Failed to exchange code: ${r.message}`,`CODE_EXCHANGE_FAILED`);if(!n?.session)throw new S(`No session returned from code exchange`,`INVALID_RESPONSE`);return this.logger.info(`Successfully exchanged code for session`),n.session}catch(e){throw e instanceof S?e:new S(`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?(w(n)||this.logger.warn(`Failed to get session:`,n),null):t}catch(e){return w(e)?this.logger.debug(`Session not available (expected during MFA flow)`):C(e)?this.logger.warn(`Session expired or invalid`):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),Ne(n,`Failed to refresh session`);return t&&this.logger.info(`Successfully refreshed session`),t}catch(e){throw e instanceof S?e:C(e)?Ne(e,`Session refresh failed`):new S(`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:`local`});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 S(`Failed to set session: ${n.message}`,`SESSION_SET_FAILED`);this.logger.info(`Session set successfully`)}catch(e){throw e instanceof S?e:new S(`Failed to set session: ${e.message}`,`SESSION_SET_FAILED`)}}async handleRecoverableError(e,t,n){return!t&&w(e)?(this.logger.debug(`MFA-expected error during token verification, clearing stale session and retrying`),await this.sessionStorage.clear(),n()):null}async verifyOneTimeCode(e,t=!1){let n=this.getClient(),r=()=>this.verifyOneTimeCode(e,!0);try{this.logger.info(`Verifying authentication token...`);let{data:i,error:a}=await n.auth.verifyOtp({token_hash:e,type:`magiclink`});if(a){let e=await this.handleRecoverableError(a,t,r);if(e)return e;throw this.logger.error(`Failed to verify token:`,a),Ne(a,`Failed to verify token`)}if(!i?.session)throw new S(`No session returned from token verification`,`INVALID_RESPONSE`);return this.logger.info(`Successfully verified authentication token`),i.session}catch(e){if(e instanceof S)throw e;if(C(e)){let n=await this.handleRecoverableError(e,t,r);if(n)return n;throw Ne(e,`Token verification failed`)}throw new S(`Token verification failed: ${e.message}`,`CODE_AUTH_FAILED`)}}async checkMFARequired(){let e=this.getClient();try{let{data:{session:t},error:n}=await e.auth.getSession();if(n||!t)return this.logger.warn(`No session available to check MFA`),{required:!1};let{data:r,error:i}=await e.auth.mfa.getAuthenticatorAssuranceLevel();if(i)return this.logger.warn(`Failed to get AAL:`,i),{required:!1};if(r?.currentLevel===`aal2`)return this.logger.info(`Session already at AAL2, MFA not required`),{required:!1};let{data:a,error:o}=await e.auth.mfa.listFactors();if(o)return this.logger.warn(`Failed to list MFA factors:`,o),{required:!1};let s=a?.totp?.filter(e=>e.status===`verified`);if(!s||s.length===0)return this.logger.info(`No verified MFA factors found`),{required:!1};let c=s[0];return this.logger.info(`MFA verification required`,{factorId:c.id,factorType:c.factor_type}),{required:!0,factorId:c.id,factorType:c.factor_type}}catch(e){return this.logger.error(`Error checking MFA requirement:`,e),{required:!1}}}async verifyMFA(e,t){let n=this.getClient();try{this.logger.info(`Verifying MFA code...`);let{data:r,error:i}=await n.auth.mfa.challenge({factorId:e});if(i||!r)throw new S(`Failed to create MFA challenge: ${i?.message||`Unknown error`}`,`MFA_VERIFICATION_FAILED`);let{data:a,error:o}=await n.auth.mfa.verify({factorId:e,challengeId:r.id,code:t});if(o)throw this.logger.error(`MFA verification failed:`,o),new S(`Invalid MFA code: ${o.message}`,`INVALID_MFA_CODE`);if(!a)throw new S(`No data returned from MFA verification`,`INVALID_RESPONSE`);let{data:{session:s},error:c}=await n.auth.refreshSession();if(c||!s)throw new S(`Failed to refresh session after MFA: ${c?.message||`No session returned`}`,`REFRESH_FAILED`);return this.logger.info(`Successfully verified MFA, session upgraded to AAL2`),s}catch(e){throw e instanceof S?e:new S(`MFA verification failed: ${e.message}`,`MFA_VERIFICATION_FAILED`)}}};const Le=c.join(process.env.HOME||process.env.USERPROFILE||`~`,`.taskmaster`,`context.json`);var Re=class e{static instance=null;logger=x(`ContextStore`);contextPath;constructor(e=Le){this.contextPath=e}static getInstance(t){return e.instance||=new e(t),e.instance}static resetInstance(){e.instance=null}getContext(){try{if(!s.existsSync(this.contextPath))return null;let e=JSON.parse(s.readFileSync(this.contextPath,`utf8`));return this.logger.debug(`Loaded context from disk`),e}catch(e){return this.logger.error(`Failed to read context:`,e),null}}saveContext(e){try{let t={...this.getContext()||{},...e,lastUpdated:new Date().toISOString()},n=c.dirname(this.contextPath);s.existsSync(n)||s.mkdirSync(n,{recursive:!0,mode:448});let r=`${this.contextPath}.tmp`;s.writeFileSync(r,JSON.stringify(t,null,2),{mode:384}),s.renameSync(r,this.contextPath),this.logger.debug(`Saved context to disk`)}catch(e){throw new S(`Failed to save context: ${e.message}`,`SAVE_FAILED`,e)}}updateUserContext(e){let t=this.getContext(),n={...t?.selectedContext||{},...e,updatedAt:new Date().toISOString()};this.saveContext({...t,selectedContext:n})}getUserContext(){return this.getContext()?.selectedContext||null}clearUserContext(){let e=this.getContext();if(e){let{selectedContext:t,...n}=e;this.saveContext(n)}}clearContext(){try{s.existsSync(this.contextPath)&&(s.unlinkSync(this.contextPath),this.logger.debug(`Cleared context from disk`))}catch(e){throw new S(`Failed to clear context: ${e.message}`,`CLEAR_FAILED`,e)}}hasContext(){return this.getContext()!==null}getContextPath(){return this.contextPath}},ze=`@hhsw2015/task-master-ai`,Be=`0.43.6`;const Ve=[`anthropic`,`openai`,`google`,`zai`,`zai-coding`,`perplexity`,`xai`,`groq`,`mistral`,`azure`,`openrouter`,`bedrock`,`ollama`],T={AZURE:`azure`,VERTEX:`vertex`,BEDROCK:`bedrock`,OPENROUTER:`openrouter`,OLLAMA:`ollama`,LMSTUDIO:`lmstudio`,OPENAI_COMPATIBLE:`openai-compatible`,CLAUDE_CODE:`claude-code`,MCP:`mcp`,GEMINI_CLI:`gemini-cli`,GROK_CLI:`grok-cli`,CODEX_CLI:`codex-cli`},He=Object.values(T),Ue=[...new Set([...Ve,...He])],We=`.taskmaster/tasks/tasks.json`,Ge=[`.taskmaster`,`.taskmaster/config.json`,We,`.taskmasterconfig`],Ke=`.git,.svn,.hg,.fossil,.github,.gitlab,.circleci,.travis.yml,.jenkins,.buildkite,.vscode,.idea,.project,.devcontainer,package-lock.json,yarn.lock,pnpm-lock.yaml,bun.lockb,bun.lock,deno.lock,deno.json,deno.jsonc,package.json,lerna.json,nx.json,turbo.json,rush.json,pnpm-workspace.yaml,Cargo.toml,Cargo.lock,go.mod,go.sum,go.work,pyproject.toml,setup.py,setup.cfg,poetry.lock,Pipfile,Pipfile.lock,uv.lock,Gemfile,Gemfile.lock,composer.json,composer.lock,build.gradle,build.gradle.kts,settings.gradle,settings.gradle.kts,pom.xml,build.sbt,project.clj,deps.edn,mix.exs,rebar.config,pubspec.yaml,Package.swift,CMakeLists.txt,Makefile,meson.build,BUILD.bazel,WORKSPACE,flake.nix,shell.nix,default.nix,Dockerfile,docker-compose.yml,docker-compose.yaml,Containerfile,kubernetes.yml,kubernetes.yaml,helm/Chart.yaml`.split(`,`),qe=[`tasks/tasks.json`,`tasks.json`,...Ke,`requirements.txt`];[...Ge,...qe];const Je=Be||`unknown`,Ye=[`pending`,`in-progress`,`done`,`deferred`,`cancelled`,`blocked`,`review`],Xe=[`done`,`completed`,`cancelled`];function Ze(e){return Xe.includes(e)}const Qe=[`text`,`json`,`compact`],$e={done:`✓`,completed:`✓`,"in-progress":`►`,blocked:`⭕`,pending:`○`,deferred:`⏸`,cancelled:`✗`,review:`👁`};function et(){return process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`https://tryhamster.com`}function tt(){return{baseUrl:et(),configDir:c.join(p.homedir(),`.taskmaster`),configFile:c.join(p.homedir(),`.taskmaster`,`auth.json`)}}function nt(e){return{...tt(),...e}}new Proxy({},{get(e,t){return tt()[t]}});var rt=class{logger=x(`OAuthService`);contextStore;supabaseClient;configOverrides;authorizationUrl=null;keyPair=null;get baseUrl(){return nt(this.configOverrides).baseUrl}constructor(e,t,n={}){this.contextStore=e,this.supabaseClient=t,this.configOverrides=n}async authenticate(e={}){let{openBrowser:t,timeout:n=3e5,onAuthUrl:r,onWaitingForAuth:i,onSuccess:a,onError:o}=e;try{return await this.authenticateWithBackendPKCE({openBrowser:t,timeout:n,onAuthUrl:r,onWaitingForAuth:i,onSuccess:a})}catch(e){let t=e instanceof S?e:new S(`OAuth authentication failed: ${e.message}`,`OAUTH_FAILED`,e);throw o&&t.code!==`MFA_REQUIRED`&&o(t),t}}async authenticateWithBackendPKCE(e){let{openBrowser:t,timeout:n=3e5,onAuthUrl:r,onWaitingForAuth:i,onSuccess:a}=e;this.keyPair=Pe(),this.logger.debug(`Generated RSA keypair for E2E encryption`);let o=await this.startBackendFlow();if(!o.success||!o.flow_id)throw new S(o.message||`Failed to start authentication flow`,`START_FLOW_FAILED`);let{flow_id:s,verification_url:c,poll_interval:l=2}=o;if(this.authorizationUrl=c||null,r&&c&&r(c),t&&c)try{await t(c),this.logger.debug(`Browser opened successfully with URL:`,c)}catch(e){this.logger.warn(`Failed to open browser automatically:`,e)}i&&i();let u=await this.pollForCompletion(s,l*1e3,n);u.refreshToken||this.logger.warn(`No refresh token received from server - session refresh will not work`);let d={access_token:u.token,refresh_token:u.refreshToken??``,expires_in:u.expiresAt?Math.floor((new Date(u.expiresAt).getTime()-Date.now())/1e3):3600,token_type:`bearer`,user:{id:u.userId,email:u.email,app_metadata:{},user_metadata:{},aud:`authenticated`,created_at:``}};return await this.supabaseClient.setSession(d),this.contextStore.saveContext({userId:u.userId,email:u.email}),await this.checkAndThrowIfMFARequired(),a&&a(u),u}async startBackendFlow(){let e=`${this.baseUrl}/api/auth/cli/start`;if(!this.keyPair)throw new S(`Keypair not generated before starting flow`,`INTERNAL_ERROR`);try{let t=await fetch(e,{method:`POST`,headers:{"Content-Type":`application/json`,"User-Agent":`TaskMasterCLI/${this.getCliVersion()}`},body:JSON.stringify({name:`Task Master CLI`,version:this.getCliVersion(),device:p.hostname(),user:p.userInfo().username,platform:p.platform(),public_key:this.keyPair.publicKey})});if(!t.ok)throw new S((await t.json().catch(()=>({}))).message||`HTTP ${t.status}`,`START_FLOW_FAILED`);return await t.json()}catch(e){throw e instanceof S?e:(this.logger.warn(`Failed to reach backend for PKCE flow:`,e),new S(`Unable to reach authentication server`,`BACKEND_UNREACHABLE`,e))}}async pollForCompletion(e,t,n){let r=`${this.baseUrl}/api/auth/cli/status?flow_id=${e}`,i=Date.now();if(!this.keyPair)throw new S(`Keypair not available for decryption`,`INTERNAL_ERROR`);for(;Date.now()-i<n;){try{let e=await fetch(r,{method:`GET`,headers:{"User-Agent":`TaskMasterCLI/${this.getCliVersion()}`}});if(!e.ok){let t=await e.json().catch(()=>({}));throw e.status===404?new S(`Authentication flow expired or not found`,`FLOW_NOT_FOUND`):new S(t.message||`HTTP ${e.status}`,`POLL_FAILED`)}let t=await e.json();if(!t.success)throw new S(t.message||`Failed to check status`,`POLL_FAILED`);switch(t.status){case`complete`:{if(!t.encrypted_tokens)throw new S(`Server returned no encrypted tokens`,`MISSING_TOKENS`);let e=Fe(t.encrypted_tokens,this.keyPair.privateKey);return this.logger.debug(`Successfully decrypted authentication tokens`),{token:e.access_token,refreshToken:e.refresh_token,userId:e.user_id,email:e.email,expiresAt:e.expires_in?new Date(Date.now()+e.expires_in*1e3).toISOString():void 0,tokenType:`standard`,savedAt:new Date().toISOString()}}case`failed`:throw new S(t.error_description||t.error||`Authentication failed`,`OAUTH_FAILED`);case`expired`:throw new S(`Authentication flow expired`,`AUTH_TIMEOUT`);case`pending`:case`authenticating`:this.logger.debug(`Flow status: ${t.status}, continuing to poll`);break;default:this.logger.warn(`Unknown flow status: ${t.status}`)}}catch(e){if(e instanceof S)throw e;this.logger.debug(`Poll request failed, will retry:`,e)}await new Promise(e=>setTimeout(e,t))}throw new S(`Authentication timeout`,`AUTH_TIMEOUT`)}getCliVersion(){return Je}getAuthorizationUrl(){return this.authorizationUrl}async checkAndThrowIfMFARequired(){let e=await this.supabaseClient.checkMFARequired();if(e.required)throw!e.factorId||!e.factorType?(this.logger.error(`MFA required but factor information is incomplete`,{mfaCheck:e}),new S(`MFA is required but the server returned incomplete factor configuration. Please contact support or try re-enrolling MFA.`,`MFA_REQUIRED_INCOMPLETE`)):(this.logger.info(`MFA verification required after OAuth login`,{factorId:e.factorId,factorType:e.factorType}),new S(`MFA verification required. Please provide your authentication code.`,`MFA_REQUIRED`,void 0,{factorId:e.factorId,factorType:e.factorType}))}},it=class{logger=x(`OrganizationService`);constructor(e){this.supabaseClient=e}async getOrganizations(){try{let{data:e,error:t}=await this.supabaseClient.from(`user_accounts`).select(`
|
|
2
|
+
`),this.logger.debug(`Persisted session to disk (steno)`)}catch(e){this.logger.error(`Failed to persist session:`,e)}}async getItem(e){await this.initPromise;let t=this.storage.get(e)??null;return this.logger.debug(`getItem called`,{key:e,hasValue:!!t}),t}async setItem(e,t){await this.initPromise,this.logger.debug(`setItem called`,{key:e}),this.storage.set(e,t),await this.persist()}async removeItem(e){await this.initPromise,this.logger.debug(`removeItem called`,{key:e}),this.storage.delete(e),await this.persist()}async clear(){await this.initPromise,this.logger.debug(`clear called`),this.storage.clear(),await this.persist()}},S=class extends Error{mfaChallenge;constructor(e,t,n,r){super(e),this.code=t,this.cause=n,this.name=`AuthenticationError`,this.mfaChallenge=r,n&&n instanceof Error&&(this.stack=`${this.stack}\nCaused by: ${n.stack}`)}};function C(e){return o(e)}const je={refresh_token_not_found:`Your session has expired. Please log in again with: task-master login`,refresh_token_already_used:`Your session has expired (token was already used). Please log in again with: task-master login`,invalid_refresh_token:`Your session has expired (invalid token). Please log in again with: task-master login`,session_expired:`Your session has expired. Please log in again with: task-master login`,user_not_found:`User account not found. Please log in again with: task-master login`,invalid_credentials:`Invalid credentials. Please log in again with: task-master login`},Me=[`refresh_token_not_found`,`refresh_token_already_used`];function w(e){return C(e)?Me.includes(e.code||``):!1}function Ne(e,t){let n=e.code,r=n&&je[n]||`${t}: ${e.message}`,i=`REFRESH_FAILED`;return n===`refresh_token_not_found`||n===`refresh_token_already_used`||n===`invalid_refresh_token`||n===`session_expired`||n===`user_not_found`?i=`NOT_AUTHENTICATED`:n===`invalid_credentials`&&(i=`INVALID_CREDENTIALS`),new S(r,i,e)}function Pe(){let{publicKey:e,privateKey:t}=f.generateKeyPairSync(`rsa`,{modulusLength:2048,publicKeyEncoding:{type:`spki`,format:`pem`},privateKeyEncoding:{type:`pkcs8`,format:`pem`}});return{publicKey:e,privateKey:t}}function Fe(e,t){try{let n=Buffer.from(e.encrypted_key,`base64`),r=Buffer.from(e.encrypted_data,`base64`),i=Buffer.from(e.iv,`base64`),a=Buffer.from(e.auth_tag,`base64`),o=f.privateDecrypt({key:t,padding:f.constants.RSA_PKCS1_OAEP_PADDING,oaepHash:`sha256`},n),s=f.createDecipheriv(`aes-256-gcm`,o,i);s.setAuthTag(a);let c=Buffer.concat([s.update(r),s.final()]);return JSON.parse(c.toString(`utf8`))}catch(e){throw new S(`Token decryption failed: ${e instanceof Error?e.message:`Unknown error`}`,`DECRYPTION_FAILED`,e)}}var Ie=class e{static instance=null;client=null;sessionStorage;logger=x(`SupabaseAuthClient`);constructor(){this.sessionStorage=new Ae}static getInstance(){return e.instance||=new e,e.instance}static resetInstance(){e.instance&&(e.instance.client=null),e.instance=null}getClient(){if(!this.client){let e=process.env.TM_SUPABASE_URL||process.env.TM_PUBLIC_SUPABASE_URL||`https://tryhamster.com`,t=process.env.TM_SUPABASE_ANON_KEY||process.env.TM_PUBLIC_SUPABASE_ANON_KEY||`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im5zdHhhdGRwbnNmYWxja3hhd3R6Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDg3MzU3NTYsImV4cCI6MjA2NDMxMTc1Nn0.GF897_2zXRxl4pkeQ89-7xF4TkJfJuYPWKhv1bTbv9k`;if(!e||!t)throw new S(`Supabase configuration missing. Please set TM_SUPABASE_URL and TM_SUPABASE_ANON_KEY (runtime) or TM_PUBLIC_SUPABASE_URL and TM_PUBLIC_SUPABASE_ANON_KEY (build-time) environment variables.`,`CONFIG_MISSING`);this.client=a(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?(w(n)||this.logger.warn(`Failed to restore session:`,n),null):(t&&this.logger.info(`Session restored successfully`),t)}catch(e){return w(e)?this.logger.debug(`Session not available (expected during MFA flow)`):C(e)?this.logger.warn(`Session expired or invalid`):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 S(`Failed to initiate PKCE flow: ${n.message}`,`PKCE_INIT_FAILED`);if(!t?.url)throw new S(`No authorization URL returned`,`INVALID_RESPONSE`);return{url:t.url,codeVerifier:``}}catch(e){throw e instanceof S?e:new S(`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 S(`Failed to exchange code: ${r.message}`,`CODE_EXCHANGE_FAILED`);if(!n?.session)throw new S(`No session returned from code exchange`,`INVALID_RESPONSE`);return this.logger.info(`Successfully exchanged code for session`),n.session}catch(e){throw e instanceof S?e:new S(`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?(w(n)||this.logger.warn(`Failed to get session:`,n),null):t}catch(e){return w(e)?this.logger.debug(`Session not available (expected during MFA flow)`):C(e)?this.logger.warn(`Session expired or invalid`):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),Ne(n,`Failed to refresh session`);return t&&this.logger.info(`Successfully refreshed session`),t}catch(e){throw e instanceof S?e:C(e)?Ne(e,`Session refresh failed`):new S(`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:`local`});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 S(`Failed to set session: ${n.message}`,`SESSION_SET_FAILED`);this.logger.info(`Session set successfully`)}catch(e){throw e instanceof S?e:new S(`Failed to set session: ${e.message}`,`SESSION_SET_FAILED`)}}async handleRecoverableError(e,t,n){return!t&&w(e)?(this.logger.debug(`MFA-expected error during token verification, clearing stale session and retrying`),await this.sessionStorage.clear(),n()):null}async verifyOneTimeCode(e,t=!1){let n=this.getClient(),r=()=>this.verifyOneTimeCode(e,!0);try{this.logger.info(`Verifying authentication token...`);let{data:i,error:a}=await n.auth.verifyOtp({token_hash:e,type:`magiclink`});if(a){let e=await this.handleRecoverableError(a,t,r);if(e)return e;throw this.logger.error(`Failed to verify token:`,a),Ne(a,`Failed to verify token`)}if(!i?.session)throw new S(`No session returned from token verification`,`INVALID_RESPONSE`);return this.logger.info(`Successfully verified authentication token`),i.session}catch(e){if(e instanceof S)throw e;if(C(e)){let n=await this.handleRecoverableError(e,t,r);if(n)return n;throw Ne(e,`Token verification failed`)}throw new S(`Token verification failed: ${e.message}`,`CODE_AUTH_FAILED`)}}async checkMFARequired(){let e=this.getClient();try{let{data:{session:t},error:n}=await e.auth.getSession();if(n||!t)return this.logger.warn(`No session available to check MFA`),{required:!1};let{data:r,error:i}=await e.auth.mfa.getAuthenticatorAssuranceLevel();if(i)return this.logger.warn(`Failed to get AAL:`,i),{required:!1};if(r?.currentLevel===`aal2`)return this.logger.info(`Session already at AAL2, MFA not required`),{required:!1};let{data:a,error:o}=await e.auth.mfa.listFactors();if(o)return this.logger.warn(`Failed to list MFA factors:`,o),{required:!1};let s=a?.totp?.filter(e=>e.status===`verified`);if(!s||s.length===0)return this.logger.info(`No verified MFA factors found`),{required:!1};let c=s[0];return this.logger.info(`MFA verification required`,{factorId:c.id,factorType:c.factor_type}),{required:!0,factorId:c.id,factorType:c.factor_type}}catch(e){return this.logger.error(`Error checking MFA requirement:`,e),{required:!1}}}async verifyMFA(e,t){let n=this.getClient();try{this.logger.info(`Verifying MFA code...`);let{data:r,error:i}=await n.auth.mfa.challenge({factorId:e});if(i||!r)throw new S(`Failed to create MFA challenge: ${i?.message||`Unknown error`}`,`MFA_VERIFICATION_FAILED`);let{data:a,error:o}=await n.auth.mfa.verify({factorId:e,challengeId:r.id,code:t});if(o)throw this.logger.error(`MFA verification failed:`,o),new S(`Invalid MFA code: ${o.message}`,`INVALID_MFA_CODE`);if(!a)throw new S(`No data returned from MFA verification`,`INVALID_RESPONSE`);let{data:{session:s},error:c}=await n.auth.refreshSession();if(c||!s)throw new S(`Failed to refresh session after MFA: ${c?.message||`No session returned`}`,`REFRESH_FAILED`);return this.logger.info(`Successfully verified MFA, session upgraded to AAL2`),s}catch(e){throw e instanceof S?e:new S(`MFA verification failed: ${e.message}`,`MFA_VERIFICATION_FAILED`)}}};const Le=c.join(process.env.HOME||process.env.USERPROFILE||`~`,`.taskmaster`,`context.json`);var Re=class e{static instance=null;logger=x(`ContextStore`);contextPath;constructor(e=Le){this.contextPath=e}static getInstance(t){return e.instance||=new e(t),e.instance}static resetInstance(){e.instance=null}getContext(){try{if(!s.existsSync(this.contextPath))return null;let e=JSON.parse(s.readFileSync(this.contextPath,`utf8`));return this.logger.debug(`Loaded context from disk`),e}catch(e){return this.logger.error(`Failed to read context:`,e),null}}saveContext(e){try{let t={...this.getContext()||{},...e,lastUpdated:new Date().toISOString()},n=c.dirname(this.contextPath);s.existsSync(n)||s.mkdirSync(n,{recursive:!0,mode:448});let r=`${this.contextPath}.tmp`;s.writeFileSync(r,JSON.stringify(t,null,2),{mode:384}),s.renameSync(r,this.contextPath),this.logger.debug(`Saved context to disk`)}catch(e){throw new S(`Failed to save context: ${e.message}`,`SAVE_FAILED`,e)}}updateUserContext(e){let t=this.getContext(),n={...t?.selectedContext||{},...e,updatedAt:new Date().toISOString()};this.saveContext({...t,selectedContext:n})}getUserContext(){return this.getContext()?.selectedContext||null}clearUserContext(){let e=this.getContext();if(e){let{selectedContext:t,...n}=e;this.saveContext(n)}}clearContext(){try{s.existsSync(this.contextPath)&&(s.unlinkSync(this.contextPath),this.logger.debug(`Cleared context from disk`))}catch(e){throw new S(`Failed to clear context: ${e.message}`,`CLEAR_FAILED`,e)}}hasContext(){return this.getContext()!==null}getContextPath(){return this.contextPath}},ze=`@hhsw2015/task-master-ai`,Be=`0.43.8`;const Ve=[`anthropic`,`openai`,`google`,`zai`,`zai-coding`,`perplexity`,`xai`,`groq`,`mistral`,`azure`,`openrouter`,`bedrock`,`ollama`],T={AZURE:`azure`,VERTEX:`vertex`,BEDROCK:`bedrock`,OPENROUTER:`openrouter`,OLLAMA:`ollama`,LMSTUDIO:`lmstudio`,OPENAI_COMPATIBLE:`openai-compatible`,CLAUDE_CODE:`claude-code`,MCP:`mcp`,GEMINI_CLI:`gemini-cli`,GROK_CLI:`grok-cli`,CODEX_CLI:`codex-cli`},He=Object.values(T),Ue=[...new Set([...Ve,...He])],We=`.taskmaster/tasks/tasks.json`,Ge=[`.taskmaster`,`.taskmaster/config.json`,We,`.taskmasterconfig`],Ke=`.git,.svn,.hg,.fossil,.github,.gitlab,.circleci,.travis.yml,.jenkins,.buildkite,.vscode,.idea,.project,.devcontainer,package-lock.json,yarn.lock,pnpm-lock.yaml,bun.lockb,bun.lock,deno.lock,deno.json,deno.jsonc,package.json,lerna.json,nx.json,turbo.json,rush.json,pnpm-workspace.yaml,Cargo.toml,Cargo.lock,go.mod,go.sum,go.work,pyproject.toml,setup.py,setup.cfg,poetry.lock,Pipfile,Pipfile.lock,uv.lock,Gemfile,Gemfile.lock,composer.json,composer.lock,build.gradle,build.gradle.kts,settings.gradle,settings.gradle.kts,pom.xml,build.sbt,project.clj,deps.edn,mix.exs,rebar.config,pubspec.yaml,Package.swift,CMakeLists.txt,Makefile,meson.build,BUILD.bazel,WORKSPACE,flake.nix,shell.nix,default.nix,Dockerfile,docker-compose.yml,docker-compose.yaml,Containerfile,kubernetes.yml,kubernetes.yaml,helm/Chart.yaml`.split(`,`),qe=[`tasks/tasks.json`,`tasks.json`,...Ke,`requirements.txt`];[...Ge,...qe];const Je=Be||`unknown`,Ye=[`pending`,`in-progress`,`done`,`deferred`,`cancelled`,`blocked`,`review`],Xe=[`done`,`completed`,`cancelled`];function Ze(e){return Xe.includes(e)}const Qe=[`text`,`json`,`compact`],$e={done:`✓`,completed:`✓`,"in-progress":`►`,blocked:`⭕`,pending:`○`,deferred:`⏸`,cancelled:`✗`,review:`👁`};function et(){return process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`https://tryhamster.com`}function tt(){return{baseUrl:et(),configDir:c.join(p.homedir(),`.taskmaster`),configFile:c.join(p.homedir(),`.taskmaster`,`auth.json`)}}function nt(e){return{...tt(),...e}}new Proxy({},{get(e,t){return tt()[t]}});var rt=class{logger=x(`OAuthService`);contextStore;supabaseClient;configOverrides;authorizationUrl=null;keyPair=null;get baseUrl(){return nt(this.configOverrides).baseUrl}constructor(e,t,n={}){this.contextStore=e,this.supabaseClient=t,this.configOverrides=n}async authenticate(e={}){let{openBrowser:t,timeout:n=3e5,onAuthUrl:r,onWaitingForAuth:i,onSuccess:a,onError:o}=e;try{return await this.authenticateWithBackendPKCE({openBrowser:t,timeout:n,onAuthUrl:r,onWaitingForAuth:i,onSuccess:a})}catch(e){let t=e instanceof S?e:new S(`OAuth authentication failed: ${e.message}`,`OAUTH_FAILED`,e);throw o&&t.code!==`MFA_REQUIRED`&&o(t),t}}async authenticateWithBackendPKCE(e){let{openBrowser:t,timeout:n=3e5,onAuthUrl:r,onWaitingForAuth:i,onSuccess:a}=e;this.keyPair=Pe(),this.logger.debug(`Generated RSA keypair for E2E encryption`);let o=await this.startBackendFlow();if(!o.success||!o.flow_id)throw new S(o.message||`Failed to start authentication flow`,`START_FLOW_FAILED`);let{flow_id:s,verification_url:c,poll_interval:l=2}=o;if(this.authorizationUrl=c||null,r&&c&&r(c),t&&c)try{await t(c),this.logger.debug(`Browser opened successfully with URL:`,c)}catch(e){this.logger.warn(`Failed to open browser automatically:`,e)}i&&i();let u=await this.pollForCompletion(s,l*1e3,n);u.refreshToken||this.logger.warn(`No refresh token received from server - session refresh will not work`);let d={access_token:u.token,refresh_token:u.refreshToken??``,expires_in:u.expiresAt?Math.floor((new Date(u.expiresAt).getTime()-Date.now())/1e3):3600,token_type:`bearer`,user:{id:u.userId,email:u.email,app_metadata:{},user_metadata:{},aud:`authenticated`,created_at:``}};return await this.supabaseClient.setSession(d),this.contextStore.saveContext({userId:u.userId,email:u.email}),await this.checkAndThrowIfMFARequired(),a&&a(u),u}async startBackendFlow(){let e=`${this.baseUrl}/api/auth/cli/start`;if(!this.keyPair)throw new S(`Keypair not generated before starting flow`,`INTERNAL_ERROR`);try{let t=await fetch(e,{method:`POST`,headers:{"Content-Type":`application/json`,"User-Agent":`TaskMasterCLI/${this.getCliVersion()}`},body:JSON.stringify({name:`Task Master CLI`,version:this.getCliVersion(),device:p.hostname(),user:p.userInfo().username,platform:p.platform(),public_key:this.keyPair.publicKey})});if(!t.ok)throw new S((await t.json().catch(()=>({}))).message||`HTTP ${t.status}`,`START_FLOW_FAILED`);return await t.json()}catch(e){throw e instanceof S?e:(this.logger.warn(`Failed to reach backend for PKCE flow:`,e),new S(`Unable to reach authentication server`,`BACKEND_UNREACHABLE`,e))}}async pollForCompletion(e,t,n){let r=`${this.baseUrl}/api/auth/cli/status?flow_id=${e}`,i=Date.now();if(!this.keyPair)throw new S(`Keypair not available for decryption`,`INTERNAL_ERROR`);for(;Date.now()-i<n;){try{let e=await fetch(r,{method:`GET`,headers:{"User-Agent":`TaskMasterCLI/${this.getCliVersion()}`}});if(!e.ok){let t=await e.json().catch(()=>({}));throw e.status===404?new S(`Authentication flow expired or not found`,`FLOW_NOT_FOUND`):new S(t.message||`HTTP ${e.status}`,`POLL_FAILED`)}let t=await e.json();if(!t.success)throw new S(t.message||`Failed to check status`,`POLL_FAILED`);switch(t.status){case`complete`:{if(!t.encrypted_tokens)throw new S(`Server returned no encrypted tokens`,`MISSING_TOKENS`);let e=Fe(t.encrypted_tokens,this.keyPair.privateKey);return this.logger.debug(`Successfully decrypted authentication tokens`),{token:e.access_token,refreshToken:e.refresh_token,userId:e.user_id,email:e.email,expiresAt:e.expires_in?new Date(Date.now()+e.expires_in*1e3).toISOString():void 0,tokenType:`standard`,savedAt:new Date().toISOString()}}case`failed`:throw new S(t.error_description||t.error||`Authentication failed`,`OAUTH_FAILED`);case`expired`:throw new S(`Authentication flow expired`,`AUTH_TIMEOUT`);case`pending`:case`authenticating`:this.logger.debug(`Flow status: ${t.status}, continuing to poll`);break;default:this.logger.warn(`Unknown flow status: ${t.status}`)}}catch(e){if(e instanceof S)throw e;this.logger.debug(`Poll request failed, will retry:`,e)}await new Promise(e=>setTimeout(e,t))}throw new S(`Authentication timeout`,`AUTH_TIMEOUT`)}getCliVersion(){return Je}getAuthorizationUrl(){return this.authorizationUrl}async checkAndThrowIfMFARequired(){let e=await this.supabaseClient.checkMFARequired();if(e.required)throw!e.factorId||!e.factorType?(this.logger.error(`MFA required but factor information is incomplete`,{mfaCheck:e}),new S(`MFA is required but the server returned incomplete factor configuration. Please contact support or try re-enrolling MFA.`,`MFA_REQUIRED_INCOMPLETE`)):(this.logger.info(`MFA verification required after OAuth login`,{factorId:e.factorId,factorType:e.factorType}),new S(`MFA verification required. Please provide your authentication code.`,`MFA_REQUIRED`,void 0,{factorId:e.factorId,factorType:e.factorType}))}},it=class{logger=x(`OrganizationService`);constructor(e){this.supabaseClient=e}async getOrganizations(){try{let{data:e,error:t}=await this.supabaseClient.from(`user_accounts`).select(`
|
|
3
3
|
id,
|
|
4
4
|
name,
|
|
5
5
|
slug
|