@hhsw2015/task-master-ai 0.43.22 → 0.43.23
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-DYnwtn3B.js +1 -0
- package/dist/{ai-services-unified-C8J7Phtj.js → ai-services-unified-DtbZ97I9.js} +1 -1
- package/dist/{commands-Dy7jrPwm.js → commands-DQQiVMX6.js} +4 -4
- package/dist/{config-manager-BShVbTKv.js → config-manager-BuZz09-s.js} +27 -26
- package/dist/{config-manager-BXmWyJ0Q.js → config-manager-CWpKNiYl.js} +1 -1
- package/dist/{dependency-manager-DwuytYCA.js → dependency-manager-n41vxXSd.js} +4 -4
- package/dist/mcp-server.js +2 -2
- package/dist/{profiles-B02F8eQH.js → profiles-Cboh56FD.js} +2 -2
- package/dist/research-BKRDZpbK.js +1 -0
- package/dist/{response-language-D5YyjQUa.js → response-language-C7cKb2Ko.js} +1 -1
- package/dist/response-language-Ck21x8Tz.js +1 -0
- package/dist/{sentry-Kc9f9Kgq.js → sentry-BO485gI2.js} +1 -1
- package/dist/tag-management-D95A287N.js +1 -0
- package/dist/{task-manager-DWe0kRWf.js → task-manager-DWiOU-Qz.js} +1 -1
- package/dist/task-master.js +1 -1
- package/dist/update-subtask-by-id-DXTuaE1V.js +1 -0
- package/dist/update-task-by-id-Dshn8T-y.js +1 -0
- package/dist/{utils-B86D4uiR.js → utils-C0PQr5j9.js} +1 -1
- package/package.json +1 -1
- package/dist/ai-services-unified-D8U4gub7.js +0 -1
- package/dist/research-CtyiGvG0.js +0 -1
- package/dist/response-language-C2l7xfTI.js +0 -1
- package/dist/tag-management-Uth1KJyf.js +0 -1
- package/dist/update-subtask-by-id-BZB0AG2e.js +0 -1
- package/dist/update-task-by-id-TVSsRUFk.js +0 -1
|
@@ -241,7 +241,15 @@ Use Taskmaster as the source of truth and execute one task at a time with Codex
|
|
|
241
241
|
2. CSV is runtime ledger, not task source.
|
|
242
242
|
3. Execute only current task; do not auto-pick next inside one Codex call.
|
|
243
243
|
4. Return concise implementation summary and test evidence.
|
|
244
|
-
`,on
|
|
244
|
+
`,on=`# SPEC
|
|
245
|
+
|
|
246
|
+
Frozen goal for this longrun session. It will be refreshed from Taskmaster tasks when run starts.
|
|
247
|
+
`,sn=`# PROGRESS
|
|
248
|
+
|
|
249
|
+
Decision log and audit trail for this longrun session.
|
|
250
|
+
|
|
251
|
+
## Entries
|
|
252
|
+
`,cn=`https://raw.githubusercontent.com/lili-luo/aicoding-cookbook/refs/heads/main/skills/codex/taskmaster/SKILL.md`,ln=`<!-- TM-INTEGRATION-START -->`,un=`<!-- TM-INTEGRATION-END -->`,dn=`${ln}
|
|
245
253
|
## Taskmaster Integration Addendum
|
|
246
254
|
|
|
247
255
|
This addendum defines how this upstream skill is integrated with Task Master CLI:
|
|
@@ -259,9 +267,9 @@ This addendum defines how this upstream skill is integrated with Task Master CLI
|
|
|
259
267
|
6. Runner is the only status writer and parses machine-readable result:
|
|
260
268
|
- success => done
|
|
261
269
|
- retry exhausted => blocked
|
|
262
|
-
${
|
|
270
|
+
${un}`;function F(){return new Date().toISOString()}function fn(e){return e.split(t.sep).join(`/`)}function pn(e){return e.replace(/[^a-zA-Z0-9._-]/g,`_`)}function I(e){let t=e.replace(/\r?\n/g,` `).trim();return/[",]/.test(t)?`"${t.replace(/"/g,`""`)}"`:t}var mn=class{constructor(e,t){this.projectRoot=e,this.tasksDomain=t}resolvePaths(e={}){let n=this.resolveMode(e.mode),r=e.sessionDir?t.resolve(this.projectRoot,e.sessionDir):t.join(this.projectRoot,`.codex-tasks`,`taskmaster-longrun`),i=e.agentsPath?t.resolve(this.projectRoot,e.agentsPath):this.resolveDefaultAgentsPath(),a=e.skillPath?t.resolve(this.projectRoot,e.skillPath):t.join(this.projectRoot,`.codex`,`skills`,`taskmaster-longrun`,`SKILL.md`);return{agentsPath:i,skillAgentsPath:t.join(t.dirname(a),`AGENTS.md`),skillPath:a,skillAssetsDir:t.join(t.dirname(a),`assets`),sessionDir:r,specPath:t.join(r,`SPEC.md`),progressPath:t.join(r,`PROGRESS.md`),todoCsvPath:n===`lite`?t.join(this.projectRoot,`TODO.csv`):t.join(r,`TODO.csv`),mapPath:t.join(r,`taskmaster-map.json`),checkpointPath:t.join(r,`checkpoint.json`),ledgerPath:t.join(r,`ledger.jsonl`),logsDir:t.join(r,`logs`)}}async initAssets(e={}){let n=this.resolvePaths(e),r=this.resolveMode(e.mode);await b(t.dirname(n.skillPath),{recursive:!0}),await b(n.sessionDir,{recursive:!0}),await b(n.logsDir,{recursive:!0}),await this.ensureCodexTasksGitignore();let i={paths:n,created:[],updated:[],skipped:[]};if(await this.ensureAgentsHook(n.agentsPath,i,e.agentsMode??`append`),await this.ensureUpstreamAgentsTemplate(n.skillAgentsPath,i),await this.ensureSkillTemplate(n.skillPath,i),await this.ensureSkillAssetTemplates(n.skillAssetsDir,i),r===`full`){let e=await this.getSkillAssetTemplate(n.skillAssetsDir,`SPEC_TEMPLATE.md`,on),t=await this.getSkillAssetTemplate(n.skillAssetsDir,`PROGRESS_TEMPLATE.md`,sn);await this.ensureSpecTemplate(n.specPath,i,e),await this.ensureProgressTemplate(n.progressPath,i,t)}return i}async run(e={}){let t=e.callbacks,n=this.resolveMode(e.mode),r=(await this.initAssets({...e,mode:n})).paths,i=await this.loadCheckpoint(r.checkpointPath),a=Math.max(0,e.maxRetries??3),o=0;for(await this.syncTodoAndMap(e.tag,i,r,n);;){let s=await this.tasksDomain.getNext(e.tag);if(!s||e.maxTasks&&o>=e.maxTasks)break;let c=String(s.id),l=(i.attempts[c]??0)+1;i.attempts[c]=l,i.lastTaskId=c,await this.tasksDomain.updateStatus(c,`in-progress`,e.tag),t?.onTaskStart?.(s,l);let u=await this.executeCodex(s,l,r,e);o++;let d=this.resolveExecutionOutcome(u);if(d.success)await this.tasksDomain.updateStatus(c,`done`,e.tag),i.doneTaskIds=this.pushUnique(i.doneTaskIds,c),i.blockedTaskIds=i.blockedTaskIds.filter(e=>e!==c),await this.appendLedger(r.ledgerPath,{timestamp:F(),taskId:c,title:s.title,attempt:l,status:`DONE`,exitCode:u.exitCode,durationMs:u.durationMs,logFile:u.logFile,notes:d.note}),t?.onTaskEnd?.({taskId:c,title:s.title,attempt:l,status:`DONE`,exitCode:u.exitCode,durationMs:u.durationMs,logFile:u.logFile});else{let f=l>a;f?(await this.tasksDomain.updateStatus(c,`blocked`,e.tag),i.blockedTaskIds=this.pushUnique(i.blockedTaskIds,c)):await this.tasksDomain.updateStatus(c,`pending`,e.tag);let p=f?`max retries reached: ${a}`:`will retry`;if(await this.appendLedger(r.ledgerPath,{timestamp:F(),taskId:c,title:s.title,attempt:l,status:f?`BLOCKED`:`FAILED`,exitCode:u.exitCode,durationMs:u.durationMs,logFile:u.logFile,notes:this.combineNotes(d.note,p)}),t?.onTaskEnd?.({taskId:c,title:s.title,attempt:l,status:f?`BLOCKED`:`FAILED`,exitCode:u.exitCode,durationMs:u.durationMs,logFile:u.logFile}),!e.continueOnFailure)return await this.saveCheckpoint(r.checkpointPath,i),await this.syncTodoAndMap(e.tag,i,r,n),{completedTaskIds:i.doneTaskIds,blockedTaskIds:i.blockedTaskIds,attempts:i.attempts,totalRuns:o,finalStatus:`error`,errorMessage:`Task ${c} failed and continueOnFailure=false`}}await this.saveCheckpoint(r.checkpointPath,i),await this.syncTodoAndMap(e.tag,i,r,n)}return await this.saveCheckpoint(r.checkpointPath,i),await this.syncTodoAndMap(e.tag,i,r,n),{completedTaskIds:i.doneTaskIds,blockedTaskIds:i.blockedTaskIds,attempts:i.attempts,totalRuns:o,finalStatus:i.blockedTaskIds.length>0?`partial`:`all_complete`}}async executeCodex(e,n,r,i){let a=this.composePrompt(e,r),o=i.executor||`codex`,s=this.buildExecutorArgs(a,i),c=t.join(r.logsDir,`${pn(String(e.id))}-attempt-${n}.log`),l=Date.now(),u=this.resolveTimeoutMs(i.execIdleTimeoutMs,12e5),d=this.resolveTimeoutMs(i.execHardTimeoutMs??i.execTimeoutMs,null);return new Promise(t=>{let n=ee(c,{flags:`a`}),r=ce(o,s,{cwd:this.projectRoot,stdio:[`ignore`,`pipe`,`pipe`]}),a=!1,f=null,p=null,m=``,h=null,g=null,_=null,te=null,ne=e=>{r.killed||r.exitCode!==null||r.signalCode||(n.write(`\n[runner-${e}] terminating executor process\n`),r.kill(`SIGTERM`),g=setTimeout(()=>{r.killed||r.exitCode!==null||r.signalCode||(n.write(`
|
|
263
271
|
[runner-force-kill] process did not exit after SIGTERM
|
|
264
|
-
`),r.kill(`SIGKILL`))},5e3))},re=(t,n)=>{a=!0,f=t,p=n,i.callbacks?.onWarning?.(`Executor ${t} timeout after ${n}ms for task ${e.id}`),ne(`${t}-timeout`)},v=()=>{u&&(_&&clearTimeout(_),_=setTimeout(()=>{re(`idle`,u)},u))};v(),d&&(te=setTimeout(()=>{re(`hard`,d)},d));let y=e=>{if(v(),m=this.appendOutputBuffer(m,e),h)return;let t=this.extractTaskResult(m);t&&(h=t,i.callbacks?.onInfo?.(`Parsed ${nn} status=${t.status} validation=${t.validation}`),n.write(`\n[runner-result-detected] status=${t.status} validation=${t.validation}\n`),(i.terminateOnResult??!0)&&setTimeout(()=>{ne(`result-received`)},1500))};r.stdout?.on(`data`,e=>{let t=e.toString(`utf-8`);process.stdout.write(t),i.callbacks?.onStdout?.(t),n.write(t),y(t)}),r.stderr?.on(`data`,e=>{let t=e.toString(`utf-8`);process.stderr.write(t),i.callbacks?.onStderr?.(t),n.write(t),y(t)}),r.on(`error`,e=>{n.write(`\n[executor-error] ${e.message}\n`)}),r.on(`close`,(e,r)=>{_&&clearTimeout(_),te&&clearTimeout(te),g&&clearTimeout(g),n.end(),t({exitCode:e,signal:r,durationMs:Date.now()-l,logFile:c,timedOut:a,timeoutMs:p,timeoutKind:f,parsedResult:h})})})}buildExecutorArgs(e,t){let n=[`exec`];return(t.fullAuto??!0)&&n.push(`--full-auto`),(t.skipGitRepoCheck??!0)&&n.push(`--skip-git-repo-check`),t.model&&n.push(`-m`,t.model),t.reasoningEffort&&n.push(`--config`,`model_reasoning_effort=\"${t.reasoningEffort}\"`),n.push(e),n}resolveExecutionOutcome(e){if(e.parsedResult){let t=e.parsedResult;return t.status===`done`&&t.validation!==`fail`?{success:!0,note:this.combineNotes(`parsed_result status=${t.status} validation=${t.validation}`,t.summary?`summary: ${t.summary}`:void 0)}:{success:!1,note:this.combineNotes(`parsed_result status=${t.status} validation=${t.validation}`,t.summary?`summary: ${t.summary}`:void 0)}}return e.timedOut?{success:!1,note:`executor ${e.timeoutKind||`unknown`} timeout after ${typeof e.timeoutMs==`number`?`${e.timeoutMs}ms`:`unknown duration`}`}:e.exitCode===0?{success:!0,note:`exit_code_fallback success (missing TM_RESULT)`}:{success:!1,note:`executor failed exitCode=${String(e.exitCode)} signal=${String(e.signal)}`}}combineNotes(...e){let t=e.map(e=>e?.trim()).filter(e=>!!e);if(t.length!==0)return t.join(` | `)}appendOutputBuffer(e,t){let n=`${e}${t}`;return n.length<=rn?n:n.slice(-rn)}resolveTimeoutMs(e,t){return typeof e==`number`&&Number.isFinite(e)?e<=0?null:Math.max(1e3,Math.trunc(e)):t}extractTaskResult(e){let t=e.split(/\r?\n/);for(let e=t.length-1;e>=0;e--){let n=t[e],r=n.indexOf(nn);if(r===-1)continue;let i=n.slice(r+10).trim(),a=i.indexOf(`{`),o=i.lastIndexOf(`}`);if(a===-1||o===-1||o<a)continue;let s=i.slice(a,o+1);try{let e=JSON.parse(s),t=e.status?.toLowerCase();if(t!==`done`&&t!==`failed`)continue;let n=e.validation?.toLowerCase();return{status:t,validation:n===`pass`||n===`fail`||n===`unknown`?n:`unknown`,summary:typeof e.summary==`string`?e.summary.trim():``,raw:s}}catch{continue}}return null}composePrompt(e,n){let r=
|
|
272
|
+
`),r.kill(`SIGKILL`))},5e3))},re=(t,n)=>{a=!0,f=t,p=n,i.callbacks?.onWarning?.(`Executor ${t} timeout after ${n}ms for task ${e.id}`),ne(`${t}-timeout`)},v=()=>{u&&(_&&clearTimeout(_),_=setTimeout(()=>{re(`idle`,u)},u))};v(),d&&(te=setTimeout(()=>{re(`hard`,d)},d));let y=e=>{if(v(),m=this.appendOutputBuffer(m,e),h)return;let t=this.extractTaskResult(m);t&&(h=t,i.callbacks?.onInfo?.(`Parsed ${nn} status=${t.status} validation=${t.validation}`),n.write(`\n[runner-result-detected] status=${t.status} validation=${t.validation}\n`),(i.terminateOnResult??!0)&&setTimeout(()=>{ne(`result-received`)},1500))};r.stdout?.on(`data`,e=>{let t=e.toString(`utf-8`);process.stdout.write(t),i.callbacks?.onStdout?.(t),n.write(t),y(t)}),r.stderr?.on(`data`,e=>{let t=e.toString(`utf-8`);process.stderr.write(t),i.callbacks?.onStderr?.(t),n.write(t),y(t)}),r.on(`error`,e=>{n.write(`\n[executor-error] ${e.message}\n`)}),r.on(`close`,(e,r)=>{_&&clearTimeout(_),te&&clearTimeout(te),g&&clearTimeout(g),n.end(),t({exitCode:e,signal:r,durationMs:Date.now()-l,logFile:c,timedOut:a,timeoutMs:p,timeoutKind:f,parsedResult:h})})})}buildExecutorArgs(e,t){let n=[`exec`];return(t.fullAuto??!0)&&n.push(`--full-auto`),(t.skipGitRepoCheck??!0)&&n.push(`--skip-git-repo-check`),t.model&&n.push(`-m`,t.model),t.reasoningEffort&&n.push(`--config`,`model_reasoning_effort=\"${t.reasoningEffort}\"`),n.push(e),n}resolveExecutionOutcome(e){if(e.parsedResult){let t=e.parsedResult;return t.status===`done`&&t.validation!==`fail`?{success:!0,note:this.combineNotes(`parsed_result status=${t.status} validation=${t.validation}`,t.summary?`summary: ${t.summary}`:void 0)}:{success:!1,note:this.combineNotes(`parsed_result status=${t.status} validation=${t.validation}`,t.summary?`summary: ${t.summary}`:void 0)}}return e.timedOut?{success:!1,note:`executor ${e.timeoutKind||`unknown`} timeout after ${typeof e.timeoutMs==`number`?`${e.timeoutMs}ms`:`unknown duration`}`}:e.exitCode===0?{success:!0,note:`exit_code_fallback success (missing TM_RESULT)`}:{success:!1,note:`executor failed exitCode=${String(e.exitCode)} signal=${String(e.signal)}`}}combineNotes(...e){let t=e.map(e=>e?.trim()).filter(e=>!!e);if(t.length!==0)return t.join(` | `)}appendOutputBuffer(e,t){let n=`${e}${t}`;return n.length<=rn?n:n.slice(-rn)}resolveTimeoutMs(e,t){return typeof e==`number`&&Number.isFinite(e)?e<=0?null:Math.max(1e3,Math.trunc(e)):t}extractTaskResult(e){let t=e.split(/\r?\n/);for(let e=t.length-1;e>=0;e--){let n=t[e],r=n.indexOf(nn);if(r===-1)continue;let i=n.slice(r+10).trim(),a=i.indexOf(`{`),o=i.lastIndexOf(`}`);if(a===-1||o===-1||o<a)continue;let s=i.slice(a,o+1);try{let e=JSON.parse(s),t=e.status?.toLowerCase();if(t!==`done`&&t!==`failed`)continue;let n=e.validation?.toLowerCase();return{status:t,validation:n===`pass`||n===`fail`||n===`unknown`?n:`unknown`,summary:typeof e.summary==`string`?e.summary.trim():``,raw:s}}catch{continue}}return null}composePrompt(e,n){let r=fn(t.relative(this.projectRoot,n.agentsPath)),i=fn(t.relative(this.projectRoot,n.skillAgentsPath)),a=fn(t.relative(this.projectRoot,n.skillPath)),o=e.dependencies?.length?e.dependencies.join(`, `):`none`;return`@${r}\n@${i}\n@${a}
|
|
265
273
|
|
|
266
274
|
请只实现当前 Taskmaster 任务,不要继续下一个任务。
|
|
267
275
|
|
|
@@ -276,32 +284,25 @@ ${nn} {"status":"done|failed","validation":"pass|fail|unknown","summary":"<简
|
|
|
276
284
|
描述: ${e.description||``}
|
|
277
285
|
实现细节: ${e.details||``}
|
|
278
286
|
测试策略: ${e.testStrategy||``}
|
|
279
|
-
依赖: ${o}`}async ensureAgentsHook(e,n,r){let i=`${en}\n## Taskmaster Longrun Hook\nWhen implementation starts, load AGENTS first, then load @.codex/skills/taskmaster-longrun/SKILL.md, then execute one Taskmaster task per Codex run.\n${tn}`;if(!await this.fileExists(e)){await S(e,`${i}\n`,`utf-8`),n.created.push(t.relative(this.projectRoot,e));return}let a=await x(e,`utf-8`),o=a.includes(en),s=a.includes(tn);if(o&&s){n.skipped.push(t.relative(this.projectRoot,e));return}if(o!==s)throw Error(`Invalid AGENTS hook markers in ${t.relative(this.projectRoot,e)}`);if(r===`skip`){n.skipped.push(t.relative(this.projectRoot,e));return}if(r===`fail`)throw Error(`AGENTS hook missing in ${t.relative(this.projectRoot,e)}. Re-run with agentsMode=append to auto-insert.`);await S(e,`${a.trimEnd()}\n\n${i}\n`,`utf-8`),n.updated.push(t.relative(this.projectRoot,e))}async ensureSkillTemplate(e,n){let r=await this.safeRead(e);if(!r){let r=await this.loadRemoteTemplate(
|
|
287
|
+
依赖: ${o}`}async ensureAgentsHook(e,n,r){let i=`${en}\n## Taskmaster Longrun Hook\nWhen implementation starts, load AGENTS first, then load @.codex/skills/taskmaster-longrun/SKILL.md, then execute one Taskmaster task per Codex run.\n${tn}`;if(!await this.fileExists(e)){await S(e,`${i}\n`,`utf-8`),n.created.push(t.relative(this.projectRoot,e));return}let a=await x(e,`utf-8`),o=a.includes(en),s=a.includes(tn);if(o&&s){n.skipped.push(t.relative(this.projectRoot,e));return}if(o!==s)throw Error(`Invalid AGENTS hook markers in ${t.relative(this.projectRoot,e)}`);if(r===`skip`){n.skipped.push(t.relative(this.projectRoot,e));return}if(r===`fail`)throw Error(`AGENTS hook missing in ${t.relative(this.projectRoot,e)}. Re-run with agentsMode=append to auto-insert.`);await S(e,`${a.trimEnd()}\n\n${i}\n`,`utf-8`),n.updated.push(t.relative(this.projectRoot,e))}async ensureSkillTemplate(e,n){let r=await this.safeRead(e);if(!r){let r=await this.loadRemoteTemplate(cn,an);await S(e,this.mergeSkillWithIntegrationAddon(r),`utf-8`),n.created.push(t.relative(this.projectRoot,e));return}if(this.looksLikeUpstreamTaskmasterSkill(r)&&this.hasSkillIntegrationAddon(r)){n.skipped.push(t.relative(this.projectRoot,e));return}let i=await this.loadRemoteTemplate(cn,an);await S(e,this.mergeSkillWithIntegrationAddon(i),`utf-8`),n.updated.push(t.relative(this.projectRoot,e))}async ensureUpstreamAgentsTemplate(e,n){let r=await this.safeRead(e);if(r&&this.looksLikeUpstreamAgents(r)){n.skipped.push(t.relative(this.projectRoot,e));return}await S(e,await this.loadRemoteTemplate(`https://raw.githubusercontent.com/lili-luo/aicoding-cookbook/refs/heads/main/skills/codex/AGENTS.md`,`# Global Agent Rules
|
|
280
288
|
|
|
281
289
|
## Language
|
|
282
290
|
|
|
283
291
|
Default to Chinese in user-facing replies unless the user explicitly requests another language.
|
|
284
|
-
`),`utf-8`),r?n.updated.push(t.relative(this.projectRoot,e)):n.created.push(t.relative(this.projectRoot,e))}async
|
|
285
|
-
|
|
286
|
-
Frozen goal for this longrun session. It will be refreshed from Taskmaster tasks when run starts.
|
|
287
|
-
`,`utf-8`),n.created.push(t.relative(this.projectRoot,e))}async ensureProgressTemplate(e,n){if(await this.fileExists(e)){n.skipped.push(t.relative(this.projectRoot,e));return}await S(e,`# PROGRESS
|
|
288
|
-
|
|
289
|
-
Decision log and audit trail for this longrun session.
|
|
290
|
-
|
|
291
|
-
## Entries
|
|
292
|
-
`,`utf-8`),n.created.push(t.relative(this.projectRoot,e))}hasYamlFrontmatter(e){return/^---\s*\n[\s\S]*?\n---\s*\n?/.test(e)}looksLikeUpstreamTaskmasterSkill(e){return this.hasYamlFrontmatter(e)&&e.includes(`name: taskmaster`)&&e.includes(`Taskmaster — Unified Task Protocol`)}hasSkillIntegrationAddon(e){return e.includes(sn)&&e.includes(cn)}mergeSkillWithIntegrationAddon(e){return`${this.removeMarkedBlock(e,sn,cn).trimEnd()}\n\n${ln}\n`}removeMarkedBlock(e,t,n){let r=e.indexOf(t),i=e.indexOf(n);if(r===-1||i===-1||i<r)return e;let a=i+n.length,o=e.slice(0,r).trimEnd(),s=e.slice(a).trimStart();return o?s?`${o}\n\n${s}`:`${o}\n`:s}looksLikeUpstreamAgents(e){return e.includes(`# Global Agent Rules`)}resolveMode(e){return e===`lite`||e===`full`?e:`full`}async safeRead(e){return await this.fileExists(e)?x(e,`utf-8`):null}async loadRemoteTemplate(e,t){if(process.env.TM_DISABLE_REMOTE_SKILL_FETCH===`1`||process.env.NODE_ENV===`test`)return t;try{let n=await fetch(e,{headers:{"User-Agent":`task-master-ai/skill-run`}});if(!n.ok)return t;let r=await n.text();return r.trim().length>0?r:t}catch{return t}}async ensureCodexTasksGitignore(){let e=t.join(this.projectRoot,`.codex-tasks`),n=t.join(e,`.gitignore`);if(await b(e,{recursive:!0}),!await this.fileExists(n)){await S(n,`*
|
|
292
|
+
`),`utf-8`),r?n.updated.push(t.relative(this.projectRoot,e)):n.created.push(t.relative(this.projectRoot,e))}async ensureSkillAssetTemplates(e,n){await b(e,{recursive:!0}),await this.ensureSkillAssetTemplate(t.join(e,`SPEC_TEMPLATE.md`),`https://raw.githubusercontent.com/lili-luo/aicoding-cookbook/refs/heads/main/skills/codex/taskmaster/assets/SPEC_TEMPLATE.md`,on,n),await this.ensureSkillAssetTemplate(t.join(e,`PROGRESS_TEMPLATE.md`),`https://raw.githubusercontent.com/lili-luo/aicoding-cookbook/refs/heads/main/skills/codex/taskmaster/assets/PROGRESS_TEMPLATE.md`,sn,n),await this.ensureSkillAssetTemplate(t.join(e,`todo_template.csv`),`https://raw.githubusercontent.com/lili-luo/aicoding-cookbook/refs/heads/main/skills/codex/taskmaster/assets/todo_template.csv`,`id,task,status,acceptance_criteria,validation_command,completed_at,retry_count,notes
|
|
293
|
+
`,n)}async ensureSkillAssetTemplate(e,n,r,i){if(await this.fileExists(e)){i.skipped.push(t.relative(this.projectRoot,e));return}await S(e,await this.loadRemoteTemplate(n,r),`utf-8`),i.created.push(t.relative(this.projectRoot,e))}async getSkillAssetTemplate(e,n,r){let i=t.join(e,n),a=await this.safeRead(i);return!a||a.trim().length===0?r:a}async ensureSpecTemplate(e,n,r){if(await this.fileExists(e)){n.skipped.push(t.relative(this.projectRoot,e));return}await S(e,r,`utf-8`),n.created.push(t.relative(this.projectRoot,e))}async ensureProgressTemplate(e,n,r){if(await this.fileExists(e)){n.skipped.push(t.relative(this.projectRoot,e));return}await S(e,r,`utf-8`),n.created.push(t.relative(this.projectRoot,e))}hasYamlFrontmatter(e){return/^---\s*\n[\s\S]*?\n---\s*\n?/.test(e)}looksLikeUpstreamTaskmasterSkill(e){return this.hasYamlFrontmatter(e)&&e.includes(`name: taskmaster`)&&e.includes(`Taskmaster — Unified Task Protocol`)}hasSkillIntegrationAddon(e){return e.includes(ln)&&e.includes(un)}mergeSkillWithIntegrationAddon(e){return`${this.removeMarkedBlock(e,ln,un).trimEnd()}\n\n${dn}\n`}removeMarkedBlock(e,t,n){let r=e.indexOf(t),i=e.indexOf(n);if(r===-1||i===-1||i<r)return e;let a=i+n.length,o=e.slice(0,r).trimEnd(),s=e.slice(a).trimStart();return o?s?`${o}\n\n${s}`:`${o}\n`:s}looksLikeUpstreamAgents(e){return e.includes(`# Global Agent Rules`)}resolveMode(e){return e===`lite`||e===`full`?e:`full`}async safeRead(e){return await this.fileExists(e)?x(e,`utf-8`):null}async loadRemoteTemplate(e,t){if(process.env.TM_DISABLE_REMOTE_SKILL_FETCH===`1`||process.env.NODE_ENV===`test`)return t;try{let n=await fetch(e,{headers:{"User-Agent":`task-master-ai/skill-run`}});if(!n.ok)return t;let r=await n.text();return r.trim().length>0?r:t}catch{return t}}async ensureCodexTasksGitignore(){let e=t.join(this.projectRoot,`.codex-tasks`),n=t.join(e,`.gitignore`);if(await b(e,{recursive:!0}),!await this.fileExists(n)){await S(n,`*
|
|
293
294
|
!.gitignore
|
|
294
295
|
`,`utf-8`);return}let r=await x(n,`utf-8`);r.includes(`*`)||await y(n,`
|
|
295
296
|
*
|
|
296
297
|
`,`utf-8`),r.includes(`!.gitignore`)||await y(n,`!.gitignore
|
|
297
298
|
`,`utf-8`)}async syncTodoAndMap(e,t,n,r){let i=await this.tasksDomain.list({tag:e}),a=[],o=[],s=1;for(let e of i.tasks){a.push(this.toCsvRow(e,String(e.id),t,e.dependencies||[])),o.push({rowId:s,taskId:String(e.id),title:e.title,dependencies:e.dependencies||[]}),s++;for(let n of e.subtasks||[]){let r=`${e.id}.${n.id}`,i=(n.dependencies||[]).map(t=>{let n=String(t);return n.includes(`.`)?n:`${e.id}.${n}`});a.push(this.toCsvRow(n,r,t,i)),o.push({rowId:s,taskId:r,title:n.title||`Subtask ${n.id}`,dependencies:i}),s++}}if(await S(n.todoCsvPath,r===`lite`?this.renderLiteCsv(a):this.renderCsv(a),`utf-8`),r===`full`){let e={generatedAt:F(),rows:o};await S(n.mapPath,JSON.stringify(e,null,2),`utf-8`)}}toCsvRow(e,t,n,r){let i=this.mapStatus(e.status||`pending`,n,t);return{taskId:t,title:e.title||`Task ${t}`,status:i,acceptanceCriteria:e.testStrategy||``,validationCommand:`echo SKIP`,completedAt:i===`DONE`?F():``,retryCount:n.attempts[t]??0,notes:n.blockedTaskIds.includes(t)?`blocked by retry limit`:``,dependencies:r}}mapStatus(e,t,n){return t.doneTaskIds.includes(n)?`DONE`:t.blockedTaskIds.includes(n)?`FAILED`:e===`done`||e===`completed`?`DONE`:e===`in-progress`?`IN_PROGRESS`:e===`blocked`||e===`cancelled`||e===`deferred`?`FAILED`:`TODO`}renderCsv(e){return`id,task,status,acceptance_criteria,validation_command,completed_at,retry_count,notes\n${e.map((e,t)=>[t+1,I(`[${e.taskId}] ${e.title}`),e.status,I(e.acceptanceCriteria),I(e.validationCommand),I(e.completedAt),e.retryCount,I(e.notes)].join(`,`)).join(`
|
|
298
299
|
`)}\n`}renderLiteCsv(e){return`id,task,status,completed_at,notes\n${e.map((e,t)=>[t+1,I(`[${e.taskId}] ${e.title}`),this.mapStatusLite(e.status),I(e.completedAt),I(e.notes)].join(`,`)).join(`
|
|
299
|
-
`)}\n`}mapStatusLite(e){return e===`DONE`?`DONE`:`TODO`}async appendLedger(e,t){await y(e,`${JSON.stringify(t)}\n`,`utf-8`)}async loadCheckpoint(e){if(!await this.fileExists(e))return{updatedAt:F(),attempts:{},doneTaskIds:[],blockedTaskIds:[]};let t=await x(e,`utf-8`),n=JSON.parse(t);return{updatedAt:n.updatedAt||F(),attempts:n.attempts||{},doneTaskIds:n.doneTaskIds||[],blockedTaskIds:n.blockedTaskIds||[],lastTaskId:n.lastTaskId}}async saveCheckpoint(e,t){t.updatedAt=F(),await S(e,JSON.stringify(t,null,2),`utf-8`)}async fileExists(e){try{return await ie(e),!0}catch{return!1}}pushUnique(e,t){return e.includes(t)?e:[...e,t]}resolveDefaultAgentsPath(){let e=t.join(this.projectRoot,`AGENTS.md`);if(g(e))return e;let n=t.join(this.projectRoot,`agent.md`);return g(n)?n:e}},pn=class{service=null;tasksDomain=null;projectRoot;constructor(e){this.projectRoot=e.getProjectRoot()}setTasksDomain(e){this.tasksDomain=e,this.service=new fn(this.projectRoot,this.tasksDomain)}async initAssets(e={}){return this.getService().initAssets(e)}async run(e={}){return this.getService().run(e)}getService(){if(!this.tasksDomain)throw Error(`SkillRunDomain is not initialized with TasksDomain`);return this.service||=new fn(this.projectRoot,this.tasksDomain),this.service}},mn=class{async findBrief(e,t){return e.find(e=>this.matches(e,t))}matches(e,t){let n=e.document?.title||``;return!!(n.toLowerCase()===t.toLowerCase()||n.toLowerCase().includes(t.toLowerCase())||e.id===t||e.id.toLowerCase()===t.toLowerCase()||e.id.slice(-8).toLowerCase()===t.toLowerCase())}async getTagsWithStats(e,t,n,r){let i=await Promise.all(e.map(async e=>{try{let r=await n.getTasks(e.id,{}),i={},a=0,o={totalSubtasks:0,subtasksByStatus:{}};return r.forEach(e=>{let t=e.status||`pending`;i[t]=(i[t]||0)+1,t===`done`&&a++,e.subtasks&&e.subtasks.length>0&&(o.totalSubtasks+=e.subtasks.length,e.subtasks.forEach(e=>{let t=e.status||`pending`;o.subtasksByStatus[t]=(o.subtasksByStatus[t]||0)+1}))}),{name:e.document?.title||e.document?.document_name||e.id,isCurrent:t===e.id,taskCount:r.length,completedTasks:a,statusBreakdown:i,subtaskCounts:o.totalSubtasks>0?o:void 0,created:e.createdAt,description:e.document?.description,status:e.status,briefId:e.id,updatedAt:e.updatedAt}}catch(n){return console.warn(`Failed to get tasks for brief ${e.id}:`,n),{name:e.document?.title||e.document?.document_name||e.id,isCurrent:t===e.id,taskCount:0,completedTasks:0,statusBreakdown:{},created:e.createdAt,description:e.document?.description,status:e.status,briefId:e.id,updatedAt:e.updatedAt}}})),a={delivering:1,aligned:2,refining:3,draft:4,delivered:5,done:6,archived:7},o=i.sort((e,t)=>{let n=(e.status||``).toLowerCase(),r=(t.status||``).toLowerCase(),i=a[n]??999,o=a[r]??999;if(i!==o)return i-o;let s=e.updatedAt?new Date(e.updatedAt).getTime():0;return(t.updatedAt?new Date(t.updatedAt).getTime():0)-s}),s=e.find(e=>e.id===t);return{tags:o,currentTag:s&&(s.document?.title||s.document?.document_name)||null,totalTags:o.length}}validateBriefFound(e,t){if(!e)throw new T(`Brief "${t}" not found in organization`,w.NOT_FOUND)}},hn=class{static parse(e){let t=e?.trim()??``;if(!t)return{orgSlug:null,briefId:null};let n=this.parseAsUrl(t),r=n?n.pathname:t.includes(`/`)?t:null;return r?this.parsePathComponents(r,n):{orgSlug:null,briefId:t}}static extractOrgSlug(e){return this.parse(e).orgSlug}static extractBriefId(e){return this.parse(e).briefId||e.trim()}static parseAsUrl(e){try{return new URL(e)}catch{}try{return new URL(`https://${e}`)}catch{}return null}static parsePathComponents(e,t){let n=e.split(`/`).filter(Boolean),r=n.lastIndexOf(`briefs`),i=null,a=null;if(r>0&&(i=n[r-1]||null),t){let e=t.searchParams.get(`id`)||t.searchParams.get(`briefId`);e&&(a=e)}return!a&&r>=0&&n.length>r+1&&(a=n[r+1]),!a&&n.length>0&&!(r>=0&&r===n.length-1)&&(a=n[n.length-1]),{orgSlug:i,briefId:a}}static validate(e,t={}){if(t.requireOrg&&!e.orgSlug)throw new T(`Organization slug could not be extracted from input`,w.VALIDATION_ERROR);if(t.requireBrief&&!e.briefId)throw new T(`Brief identifier could not be extracted from input`,w.VALIDATION_ERROR)}},gn=class{briefService;authManager;constructor(){this.briefService=new mn,this.authManager=M.getInstance()}async resolveBrief(e,t){let n=hn.parse(e),r=n.briefId||e.trim(),i=t;if(!i&&n.orgSlug)try{let e=(await this.authManager.getOrganizations()).find(e=>e.slug?.toLowerCase()===n.orgSlug?.toLowerCase()||e.name.toLowerCase()===n.orgSlug?.toLowerCase());e&&(i=e.id)}catch{}if(i||=this.authManager.getContext()?.orgId,!i)throw new T(`No organization selected. Run "tm context org" first.`,w.CONFIG_ERROR);let a=await this.authManager.getBriefs(i),o=await this.briefService.findBrief(a,r);return this.briefService.validateBriefFound(o,r),o}async switchBrief(e){let t=await this.resolveBrief(e);await this.authManager.updateContext({briefId:t.id,briefName:t.document?.title||`Brief ${t.id.slice(-8)}`,briefStatus:t.status,briefUpdatedAt:t.updatedAt})}async getBriefsWithStats(e,t){let n=this.authManager.getContext();if(!n?.orgId)throw new T(`No organization context available`,w.MISSING_CONFIGURATION,{operation:`getBriefsWithStats`,userMessage:`No organization selected. Please authenticate first using: tm auth login`});let r=await this.authManager.getBriefs(n.orgId);return this.briefService.getTagsWithStats(r,n.briefId,e,t)}},_n=class{repository;projectId;apiClient;authManager;logger=D(`TaskExpansionService`);constructor(e,t,n,r){this.repository=e,this.projectId=t,this.apiClient=n,this.authManager=r}async expandTask(e,t){try{let n=this.authManager.ensureBriefSelected(`expandTask`),r=await this.repository.getTask(this.projectId,e);if(!r)throw new T(`Task ${e} not found`,w.TASK_NOT_FOUND,{operation:`expandTask`,taskId:e,userMessage:`Task ${e} isn't available in the current project.`});let i=await this.repository.getBrief(n.briefId),a={briefContext:{title:i?.name||n.briefName||n.briefId,description:i?.description||void 0,status:i?.status||`active`},allTasks:await this.repository.getTasks(this.projectId),existingSubtasks:r.subtasks||[],enrichedContext:t?.additionalContext},o=new URLSearchParams;if(t?.numSubtasks!==void 0&&o.set(`numSubtasks`,t.numSubtasks.toString()),t?.useResearch!==void 0&&o.set(`useResearch`,t.useResearch.toString()),t?.force!==void 0&&o.set(`force`,t.force.toString()),!r.databaseId)throw new T(`Task ${e} is missing a database ID. Task expansion requires tasks to be synced with the remote database.`,w.VALIDATION_ERROR,{operation:`expandTask`,taskId:e,userMessage:`This task has not been synced with the remote database. Please ensure the task is saved remotely before attempting expansion.`});if(!C.uuid().safeParse(r.databaseId).success)throw new T(`Task ${e} has an invalid database ID format: ${r.databaseId}`,w.VALIDATION_ERROR,{operation:`expandTask`,taskId:e,databaseId:r.databaseId,userMessage:`The task database ID is not in valid UUID format. This may indicate data corruption.`});let s=r.databaseId,c=`/ai/api/v1/tasks/${s}/subtasks/generate${o.toString()?`?${o.toString()}`:``}`,l=await this.apiClient.post(c,a),u=`${process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`http://localhost:8080`}/home/hamster/briefs/${n.briefId}/task/${s}`;return this.logger.info(`✓ Task expansion queued for ${e}`),this.logger.info(` Job ID: ${l.jobId}`),this.logger.info(` ${l.message}`),this.logger.info(` View task: ${u}`),{...l,taskLink:u}}catch(n){throw n instanceof T?n.withContext({operation:`expandTask`,taskId:e,numSubtasks:t?.numSubtasks,useResearch:t?.useResearch}):new T(n instanceof Error?n.message:String(n),w.STORAGE_ERROR,{operation:`expandTask`,taskId:e,numSubtasks:t?.numSubtasks,useResearch:t?.useResearch},n)}}},vn=class{repository;projectId;apiClient;authManager;logger=D(`TaskRetrievalService`);constructor(e,t,n,r){this.repository=e,this.projectId=t,this.apiClient=n,this.authManager=r}async getTask(e){try{this.authManager.ensureBriefSelected(`getTask`);let t=await this.repository.getTask(this.projectId,e);if(!t)throw new T(`Task ${e} not found`,w.TASK_NOT_FOUND,{operation:`getTask`,taskId:e,userMessage:`Task ${e} isn't available in the current project.`});try{let e=`/ai/api/v1/tasks/${t.id}`,n=await this.apiClient.get(e);n.document?.content&&(t.details=n.document.content)}catch(t){this.logger.debug(`Could not fetch document content for task ${e}: ${t}`)}return this.logger.info(`✓ Retrieved task ${e}`),t.details&&this.logger.debug(` Document content available (${t.details.length} chars)`),t}catch(t){throw t instanceof T?t.withContext({operation:`getTask`,taskId:e}):new T(t instanceof Error?t.message:String(t),w.STORAGE_ERROR,{operation:`getTask`,taskId:e},t)}}},yn=class{static mapDatabaseTasksToTasks(e,t){if(!e||e.length===0)return[];let n=t instanceof Map?t:this.groupDependenciesByTaskId(t),r=e.filter(e=>!e.parent_task_id),i=this.groupSubtasksByParentId(e);return r.map(e=>this.mapDatabaseTaskToTask(e,i.get(e.id)||[],n))}static mapDatabaseTaskToTask(e,t,n){let r=t.map((t,r)=>{let i=this.extractImplementationMetadata(t.metadata);return{id:t.display_id||String(r+1),parentId:e.id,title:t.title,description:t.description||``,status:this.mapStatus(t.status),priority:this.mapPriority(t.priority),dependencies:n.get(t.id)||[],details:this.extractMetadataField(t.metadata,`details`,``),testStrategy:this.extractMetadataField(t.metadata,`testStrategy`,``),createdAt:t.created_at,updatedAt:t.updated_at,assignee:t.assignee_id||void 0,complexity:t.complexity??void 0,databaseId:t.id,...this.filterUndefined(i)}}),i=this.extractImplementationMetadata(e.metadata);return{id:e.display_id||e.id,databaseId:e.id,title:e.title,description:e.description||``,status:this.mapStatus(e.status),priority:this.mapPriority(e.priority),dependencies:n.get(e.id)||[],details:this.extractMetadataField(e.metadata,`details`,``),testStrategy:this.extractMetadataField(e.metadata,`testStrategy`,``),subtasks:r,createdAt:e.created_at,updatedAt:e.updated_at,assignee:e.assignee_id||void 0,complexity:e.complexity??void 0,effort:e.estimated_hours||void 0,actualEffort:e.actual_hours||void 0,...this.filterUndefined(i)}}static groupDependenciesByTaskId(e){let t=new Map;if(e)for(let n of e){let e=t.get(n.task_id)||[],r=typeof n.depends_on_task==`object`?n.depends_on_task?.display_id:n.depends_on_task_id;r&&e.push(r),t.set(n.task_id,e)}return t}static groupSubtasksByParentId(e){let t=new Map;for(let n of e)if(n.parent_task_id){let e=t.get(n.parent_task_id)||[];e.push(n),t.set(n.parent_task_id,e)}for(let e of t.values())e.sort((e,t)=>e.subtask_position-t.subtask_position);return t}static mapStatus(e){switch(e){case`todo`:return`pending`;case`in_progress`:return`in-progress`;case`done`:return`done`;default:return`pending`}}static mapPriority(e){switch(e){case`urgent`:return`critical`;default:return e}}static extractMetadataField(e,t,n){if(!e||typeof e!=`object`)return n;let r=e[t];if(r===void 0)return n;let i=typeof n,a=typeof r;return i===a?r:(console.warn(`Type mismatch in metadata field "${t}": expected ${i}, got ${a}. Using default value.`),n)}static extractOptionalString(e,t){if(!e||typeof e!=`object`)return;let n=e[t];return typeof n==`string`?n:void 0}static extractStringArray(e,t){if(!e||typeof e!=`object`)return;let n=e[t];if(!Array.isArray(n))return;let r=n.filter(e=>typeof e==`string`);return r.length>0?r:void 0}static extractRelevantFiles(e){if(!e||typeof e!=`object`)return;let t=e.relevantFiles;if(!Array.isArray(t))return;let n=t.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.path==`string`&&typeof t.description==`string`&&(t.action===`create`||t.action===`modify`||t.action===`reference`)});return n.length>0?n:void 0}static extractExistingInfrastructure(e){if(!e||typeof e!=`object`)return;let t=e.existingInfrastructure;if(!Array.isArray(t))return;let n=t.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.location==`string`&&typeof t.usage==`string`});return n.length>0?n:void 0}static extractScopeBoundaries(e){if(!e||typeof e!=`object`)return;let t=e.scopeBoundaries;if(!t||typeof t!=`object`)return;let n=t,r={};return typeof n.included==`string`&&(r.included=n.included),typeof n.excluded==`string`&&(r.excluded=n.excluded),r.included||r.excluded?r:void 0}static extractCategory(e){if(!e||typeof e!=`object`)return;let t=e.category;return[`research`,`design`,`development`,`testing`,`documentation`,`review`].includes(t)?t:void 0}static extractImplementationMetadata(e){return{relevantFiles:this.extractRelevantFiles(e),codebasePatterns:this.extractStringArray(e,`codebasePatterns`),existingInfrastructure:this.extractExistingInfrastructure(e),scopeBoundaries:this.extractScopeBoundaries(e),implementationApproach:this.extractOptionalString(e,`implementationApproach`),technicalConstraints:this.extractStringArray(e,`technicalConstraints`),acceptanceCriteria:this.extractStringArray(e,`acceptanceCriteria`),skills:this.extractStringArray(e,`skills`),category:this.extractCategory(e)}}static filterUndefined(e){return Object.fromEntries(Object.entries(e).filter(([e,t])=>t!==void 0))}},bn=class{constructor(e){this.supabase=e}async fetchDependenciesWithDisplayIds(e){if(!e||e.length===0)return new Map;let{data:t,error:n}=await this.supabase.from(`task_dependencies`).select(`
|
|
300
|
+
`)}\n`}mapStatusLite(e){return e===`DONE`?`DONE`:`TODO`}async appendLedger(e,t){await y(e,`${JSON.stringify(t)}\n`,`utf-8`)}async loadCheckpoint(e){if(!await this.fileExists(e))return{updatedAt:F(),attempts:{},doneTaskIds:[],blockedTaskIds:[]};let t=await x(e,`utf-8`),n=JSON.parse(t);return{updatedAt:n.updatedAt||F(),attempts:n.attempts||{},doneTaskIds:n.doneTaskIds||[],blockedTaskIds:n.blockedTaskIds||[],lastTaskId:n.lastTaskId}}async saveCheckpoint(e,t){t.updatedAt=F(),await S(e,JSON.stringify(t,null,2),`utf-8`)}async fileExists(e){try{return await ie(e),!0}catch{return!1}}pushUnique(e,t){return e.includes(t)?e:[...e,t]}resolveDefaultAgentsPath(){let e=t.join(this.projectRoot,`AGENTS.md`);if(g(e))return e;let n=t.join(this.projectRoot,`agent.md`);return g(n)?n:e}},hn=class{service=null;tasksDomain=null;projectRoot;constructor(e){this.projectRoot=e.getProjectRoot()}setTasksDomain(e){this.tasksDomain=e,this.service=new mn(this.projectRoot,this.tasksDomain)}async initAssets(e={}){return this.getService().initAssets(e)}async run(e={}){return this.getService().run(e)}getService(){if(!this.tasksDomain)throw Error(`SkillRunDomain is not initialized with TasksDomain`);return this.service||=new mn(this.projectRoot,this.tasksDomain),this.service}},gn=class{async findBrief(e,t){return e.find(e=>this.matches(e,t))}matches(e,t){let n=e.document?.title||``;return!!(n.toLowerCase()===t.toLowerCase()||n.toLowerCase().includes(t.toLowerCase())||e.id===t||e.id.toLowerCase()===t.toLowerCase()||e.id.slice(-8).toLowerCase()===t.toLowerCase())}async getTagsWithStats(e,t,n,r){let i=await Promise.all(e.map(async e=>{try{let r=await n.getTasks(e.id,{}),i={},a=0,o={totalSubtasks:0,subtasksByStatus:{}};return r.forEach(e=>{let t=e.status||`pending`;i[t]=(i[t]||0)+1,t===`done`&&a++,e.subtasks&&e.subtasks.length>0&&(o.totalSubtasks+=e.subtasks.length,e.subtasks.forEach(e=>{let t=e.status||`pending`;o.subtasksByStatus[t]=(o.subtasksByStatus[t]||0)+1}))}),{name:e.document?.title||e.document?.document_name||e.id,isCurrent:t===e.id,taskCount:r.length,completedTasks:a,statusBreakdown:i,subtaskCounts:o.totalSubtasks>0?o:void 0,created:e.createdAt,description:e.document?.description,status:e.status,briefId:e.id,updatedAt:e.updatedAt}}catch(n){return console.warn(`Failed to get tasks for brief ${e.id}:`,n),{name:e.document?.title||e.document?.document_name||e.id,isCurrent:t===e.id,taskCount:0,completedTasks:0,statusBreakdown:{},created:e.createdAt,description:e.document?.description,status:e.status,briefId:e.id,updatedAt:e.updatedAt}}})),a={delivering:1,aligned:2,refining:3,draft:4,delivered:5,done:6,archived:7},o=i.sort((e,t)=>{let n=(e.status||``).toLowerCase(),r=(t.status||``).toLowerCase(),i=a[n]??999,o=a[r]??999;if(i!==o)return i-o;let s=e.updatedAt?new Date(e.updatedAt).getTime():0;return(t.updatedAt?new Date(t.updatedAt).getTime():0)-s}),s=e.find(e=>e.id===t);return{tags:o,currentTag:s&&(s.document?.title||s.document?.document_name)||null,totalTags:o.length}}validateBriefFound(e,t){if(!e)throw new T(`Brief "${t}" not found in organization`,w.NOT_FOUND)}},_n=class{static parse(e){let t=e?.trim()??``;if(!t)return{orgSlug:null,briefId:null};let n=this.parseAsUrl(t),r=n?n.pathname:t.includes(`/`)?t:null;return r?this.parsePathComponents(r,n):{orgSlug:null,briefId:t}}static extractOrgSlug(e){return this.parse(e).orgSlug}static extractBriefId(e){return this.parse(e).briefId||e.trim()}static parseAsUrl(e){try{return new URL(e)}catch{}try{return new URL(`https://${e}`)}catch{}return null}static parsePathComponents(e,t){let n=e.split(`/`).filter(Boolean),r=n.lastIndexOf(`briefs`),i=null,a=null;if(r>0&&(i=n[r-1]||null),t){let e=t.searchParams.get(`id`)||t.searchParams.get(`briefId`);e&&(a=e)}return!a&&r>=0&&n.length>r+1&&(a=n[r+1]),!a&&n.length>0&&!(r>=0&&r===n.length-1)&&(a=n[n.length-1]),{orgSlug:i,briefId:a}}static validate(e,t={}){if(t.requireOrg&&!e.orgSlug)throw new T(`Organization slug could not be extracted from input`,w.VALIDATION_ERROR);if(t.requireBrief&&!e.briefId)throw new T(`Brief identifier could not be extracted from input`,w.VALIDATION_ERROR)}},vn=class{briefService;authManager;constructor(){this.briefService=new gn,this.authManager=M.getInstance()}async resolveBrief(e,t){let n=_n.parse(e),r=n.briefId||e.trim(),i=t;if(!i&&n.orgSlug)try{let e=(await this.authManager.getOrganizations()).find(e=>e.slug?.toLowerCase()===n.orgSlug?.toLowerCase()||e.name.toLowerCase()===n.orgSlug?.toLowerCase());e&&(i=e.id)}catch{}if(i||=this.authManager.getContext()?.orgId,!i)throw new T(`No organization selected. Run "tm context org" first.`,w.CONFIG_ERROR);let a=await this.authManager.getBriefs(i),o=await this.briefService.findBrief(a,r);return this.briefService.validateBriefFound(o,r),o}async switchBrief(e){let t=await this.resolveBrief(e);await this.authManager.updateContext({briefId:t.id,briefName:t.document?.title||`Brief ${t.id.slice(-8)}`,briefStatus:t.status,briefUpdatedAt:t.updatedAt})}async getBriefsWithStats(e,t){let n=this.authManager.getContext();if(!n?.orgId)throw new T(`No organization context available`,w.MISSING_CONFIGURATION,{operation:`getBriefsWithStats`,userMessage:`No organization selected. Please authenticate first using: tm auth login`});let r=await this.authManager.getBriefs(n.orgId);return this.briefService.getTagsWithStats(r,n.briefId,e,t)}},yn=class{repository;projectId;apiClient;authManager;logger=D(`TaskExpansionService`);constructor(e,t,n,r){this.repository=e,this.projectId=t,this.apiClient=n,this.authManager=r}async expandTask(e,t){try{let n=this.authManager.ensureBriefSelected(`expandTask`),r=await this.repository.getTask(this.projectId,e);if(!r)throw new T(`Task ${e} not found`,w.TASK_NOT_FOUND,{operation:`expandTask`,taskId:e,userMessage:`Task ${e} isn't available in the current project.`});let i=await this.repository.getBrief(n.briefId),a={briefContext:{title:i?.name||n.briefName||n.briefId,description:i?.description||void 0,status:i?.status||`active`},allTasks:await this.repository.getTasks(this.projectId),existingSubtasks:r.subtasks||[],enrichedContext:t?.additionalContext},o=new URLSearchParams;if(t?.numSubtasks!==void 0&&o.set(`numSubtasks`,t.numSubtasks.toString()),t?.useResearch!==void 0&&o.set(`useResearch`,t.useResearch.toString()),t?.force!==void 0&&o.set(`force`,t.force.toString()),!r.databaseId)throw new T(`Task ${e} is missing a database ID. Task expansion requires tasks to be synced with the remote database.`,w.VALIDATION_ERROR,{operation:`expandTask`,taskId:e,userMessage:`This task has not been synced with the remote database. Please ensure the task is saved remotely before attempting expansion.`});if(!C.uuid().safeParse(r.databaseId).success)throw new T(`Task ${e} has an invalid database ID format: ${r.databaseId}`,w.VALIDATION_ERROR,{operation:`expandTask`,taskId:e,databaseId:r.databaseId,userMessage:`The task database ID is not in valid UUID format. This may indicate data corruption.`});let s=r.databaseId,c=`/ai/api/v1/tasks/${s}/subtasks/generate${o.toString()?`?${o.toString()}`:``}`,l=await this.apiClient.post(c,a),u=`${process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`http://localhost:8080`}/home/hamster/briefs/${n.briefId}/task/${s}`;return this.logger.info(`✓ Task expansion queued for ${e}`),this.logger.info(` Job ID: ${l.jobId}`),this.logger.info(` ${l.message}`),this.logger.info(` View task: ${u}`),{...l,taskLink:u}}catch(n){throw n instanceof T?n.withContext({operation:`expandTask`,taskId:e,numSubtasks:t?.numSubtasks,useResearch:t?.useResearch}):new T(n instanceof Error?n.message:String(n),w.STORAGE_ERROR,{operation:`expandTask`,taskId:e,numSubtasks:t?.numSubtasks,useResearch:t?.useResearch},n)}}},bn=class{repository;projectId;apiClient;authManager;logger=D(`TaskRetrievalService`);constructor(e,t,n,r){this.repository=e,this.projectId=t,this.apiClient=n,this.authManager=r}async getTask(e){try{this.authManager.ensureBriefSelected(`getTask`);let t=await this.repository.getTask(this.projectId,e);if(!t)throw new T(`Task ${e} not found`,w.TASK_NOT_FOUND,{operation:`getTask`,taskId:e,userMessage:`Task ${e} isn't available in the current project.`});try{let e=`/ai/api/v1/tasks/${t.id}`,n=await this.apiClient.get(e);n.document?.content&&(t.details=n.document.content)}catch(t){this.logger.debug(`Could not fetch document content for task ${e}: ${t}`)}return this.logger.info(`✓ Retrieved task ${e}`),t.details&&this.logger.debug(` Document content available (${t.details.length} chars)`),t}catch(t){throw t instanceof T?t.withContext({operation:`getTask`,taskId:e}):new T(t instanceof Error?t.message:String(t),w.STORAGE_ERROR,{operation:`getTask`,taskId:e},t)}}},xn=class{static mapDatabaseTasksToTasks(e,t){if(!e||e.length===0)return[];let n=t instanceof Map?t:this.groupDependenciesByTaskId(t),r=e.filter(e=>!e.parent_task_id),i=this.groupSubtasksByParentId(e);return r.map(e=>this.mapDatabaseTaskToTask(e,i.get(e.id)||[],n))}static mapDatabaseTaskToTask(e,t,n){let r=t.map((t,r)=>{let i=this.extractImplementationMetadata(t.metadata);return{id:t.display_id||String(r+1),parentId:e.id,title:t.title,description:t.description||``,status:this.mapStatus(t.status),priority:this.mapPriority(t.priority),dependencies:n.get(t.id)||[],details:this.extractMetadataField(t.metadata,`details`,``),testStrategy:this.extractMetadataField(t.metadata,`testStrategy`,``),createdAt:t.created_at,updatedAt:t.updated_at,assignee:t.assignee_id||void 0,complexity:t.complexity??void 0,databaseId:t.id,...this.filterUndefined(i)}}),i=this.extractImplementationMetadata(e.metadata);return{id:e.display_id||e.id,databaseId:e.id,title:e.title,description:e.description||``,status:this.mapStatus(e.status),priority:this.mapPriority(e.priority),dependencies:n.get(e.id)||[],details:this.extractMetadataField(e.metadata,`details`,``),testStrategy:this.extractMetadataField(e.metadata,`testStrategy`,``),subtasks:r,createdAt:e.created_at,updatedAt:e.updated_at,assignee:e.assignee_id||void 0,complexity:e.complexity??void 0,effort:e.estimated_hours||void 0,actualEffort:e.actual_hours||void 0,...this.filterUndefined(i)}}static groupDependenciesByTaskId(e){let t=new Map;if(e)for(let n of e){let e=t.get(n.task_id)||[],r=typeof n.depends_on_task==`object`?n.depends_on_task?.display_id:n.depends_on_task_id;r&&e.push(r),t.set(n.task_id,e)}return t}static groupSubtasksByParentId(e){let t=new Map;for(let n of e)if(n.parent_task_id){let e=t.get(n.parent_task_id)||[];e.push(n),t.set(n.parent_task_id,e)}for(let e of t.values())e.sort((e,t)=>e.subtask_position-t.subtask_position);return t}static mapStatus(e){switch(e){case`todo`:return`pending`;case`in_progress`:return`in-progress`;case`done`:return`done`;default:return`pending`}}static mapPriority(e){switch(e){case`urgent`:return`critical`;default:return e}}static extractMetadataField(e,t,n){if(!e||typeof e!=`object`)return n;let r=e[t];if(r===void 0)return n;let i=typeof n,a=typeof r;return i===a?r:(console.warn(`Type mismatch in metadata field "${t}": expected ${i}, got ${a}. Using default value.`),n)}static extractOptionalString(e,t){if(!e||typeof e!=`object`)return;let n=e[t];return typeof n==`string`?n:void 0}static extractStringArray(e,t){if(!e||typeof e!=`object`)return;let n=e[t];if(!Array.isArray(n))return;let r=n.filter(e=>typeof e==`string`);return r.length>0?r:void 0}static extractRelevantFiles(e){if(!e||typeof e!=`object`)return;let t=e.relevantFiles;if(!Array.isArray(t))return;let n=t.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.path==`string`&&typeof t.description==`string`&&(t.action===`create`||t.action===`modify`||t.action===`reference`)});return n.length>0?n:void 0}static extractExistingInfrastructure(e){if(!e||typeof e!=`object`)return;let t=e.existingInfrastructure;if(!Array.isArray(t))return;let n=t.filter(e=>{if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.name==`string`&&typeof t.location==`string`&&typeof t.usage==`string`});return n.length>0?n:void 0}static extractScopeBoundaries(e){if(!e||typeof e!=`object`)return;let t=e.scopeBoundaries;if(!t||typeof t!=`object`)return;let n=t,r={};return typeof n.included==`string`&&(r.included=n.included),typeof n.excluded==`string`&&(r.excluded=n.excluded),r.included||r.excluded?r:void 0}static extractCategory(e){if(!e||typeof e!=`object`)return;let t=e.category;return[`research`,`design`,`development`,`testing`,`documentation`,`review`].includes(t)?t:void 0}static extractImplementationMetadata(e){return{relevantFiles:this.extractRelevantFiles(e),codebasePatterns:this.extractStringArray(e,`codebasePatterns`),existingInfrastructure:this.extractExistingInfrastructure(e),scopeBoundaries:this.extractScopeBoundaries(e),implementationApproach:this.extractOptionalString(e,`implementationApproach`),technicalConstraints:this.extractStringArray(e,`technicalConstraints`),acceptanceCriteria:this.extractStringArray(e,`acceptanceCriteria`),skills:this.extractStringArray(e,`skills`),category:this.extractCategory(e)}}static filterUndefined(e){return Object.fromEntries(Object.entries(e).filter(([e,t])=>t!==void 0))}},Sn=class{constructor(e){this.supabase=e}async fetchDependenciesWithDisplayIds(e){if(!e||e.length===0)return new Map;let{data:t,error:n}=await this.supabase.from(`task_dependencies`).select(`
|
|
300
301
|
task_id,
|
|
301
302
|
depends_on_task:tasks!task_dependencies_depends_on_task_id_fkey (
|
|
302
303
|
display_id
|
|
303
304
|
)
|
|
304
|
-
`).in(`task_id`,e);if(n)throw Error(`Failed to fetch task dependencies: ${n.message}`);return this.processDependencyData(t)}processDependencyData(e){let t=new Map;if(!e)return t;for(let n of e){if(!n.task_id)continue;let e=t.get(n.task_id)||[],r=n.depends_on_task?.display_id;r&&e.push(r),t.set(n.task_id,e)}return t}};const
|
|
305
|
+
`).in(`task_id`,e);if(n)throw Error(`Failed to fetch task dependencies: ${n.message}`);return this.processDependencyData(t)}processDependencyData(e){let t=new Map;if(!e)return t;for(let n of e){if(!n.task_id)continue;let e=t.get(n.task_id)||[],r=n.depends_on_task?.display_id;r&&e.push(r),t.set(n.task_id,e)}return t}};const Cn=C.enum([`pending`,`in-progress`,`done`,`review`,`deferred`,`cancelled`,`blocked`]),wn=C.object({title:C.string().min(1).optional(),description:C.string().optional(),status:Cn.optional(),priority:C.enum([`low`,`medium`,`high`,`critical`]).optional(),details:C.string().optional(),testStrategy:C.string().optional()}).partial();var Tn=class{dependencyFetcher;authManager;constructor(e){this.supabase=e,this.dependencyFetcher=new Sn(e),this.authManager=M.getInstance()}getBriefIdOrThrow(){let e=this.authManager.getContext();if(!e?.briefId)throw Error(`No brief selected. Please select a brief first using: tm context brief`);return e.briefId}async getTasks(e,t){let n=this.getBriefIdOrThrow(),r=this.supabase.from(`tasks`).select(`
|
|
305
306
|
*,
|
|
306
307
|
document:document_id (
|
|
307
308
|
id,
|
|
@@ -309,26 +310,26 @@ Decision log and audit trail for this longrun session.
|
|
|
309
310
|
title,
|
|
310
311
|
description
|
|
311
312
|
)
|
|
312
|
-
`).eq(`brief_id`,n);if(t?.status){let e=this.mapStatusToDatabase(t.status);r=r.eq(`status`,e)}t?.excludeSubtasks&&(r=r.is(`parent_task_id`,null));let{data:i,error:a}=await r.order(`position`,{ascending:!0}).order(`subtask_position`,{ascending:!0}).order(`created_at`,{ascending:!0});if(a)throw Error(`Failed to fetch tasks: ${a.message}`);if(!i||i.length===0)return[];let o=i.map(e=>e.id),s=await this.dependencyFetcher.fetchDependenciesWithDisplayIds(o);return
|
|
313
|
+
`).eq(`brief_id`,n);if(t?.status){let e=this.mapStatusToDatabase(t.status);r=r.eq(`status`,e)}t?.excludeSubtasks&&(r=r.is(`parent_task_id`,null));let{data:i,error:a}=await r.order(`position`,{ascending:!0}).order(`subtask_position`,{ascending:!0}).order(`created_at`,{ascending:!0});if(a)throw Error(`Failed to fetch tasks: ${a.message}`);if(!i||i.length===0)return[];let o=i.map(e=>e.id),s=await this.dependencyFetcher.fetchDependenciesWithDisplayIds(o);return xn.mapDatabaseTasksToTasks(i,s)}async getTask(e,t){let n=this.getBriefIdOrThrow(),{data:r,error:i}=await this.supabase.from(`tasks`).select(`*`).eq(`brief_id`,n).eq(`display_id`,t.toUpperCase()).single();if(i){if(i.code===`PGRST116`)return null;throw Error(`Failed to fetch task: ${i.message}`)}let{data:a}=await this.supabase.from(`tasks`).select(`*`).eq(`parent_task_id`,r.id).order(`subtask_position`,{ascending:!0}),o=[r.id,...a?.map(e=>e.id)||[]],s=await this.dependencyFetcher.fetchDependenciesWithDisplayIds(o);return xn.mapDatabaseTaskToTask(r,a||[],s)}async getBrief(e){let{data:t,error:n}=await this.supabase.from(`brief`).select(`
|
|
313
314
|
*,
|
|
314
315
|
document:document_id (
|
|
315
316
|
id,
|
|
316
317
|
title,
|
|
317
318
|
description
|
|
318
319
|
)
|
|
319
|
-
`).eq(`id`,e).single();if(n){if(n.code===`PGRST116`)return null;throw Error(`Failed to fetch brief: ${n.message}`)}if(!t)return null;let r=t.document;return{id:t.id,accountId:t.account_id,createdAt:t.created_at,name:r?.title||void 0,description:r?.description||void 0,status:t.status||void 0}}async updateTask(e,t,n){let r=this.getBriefIdOrThrow();try{Sn.parse(n)}catch(e){if(e instanceof C.ZodError){let t=e.issues.map(e=>`${e.path.join(`.`)}: ${e.message}`).join(`, `);throw Error(`Invalid task update data: ${t}`)}throw e}let i={};n.title!==void 0&&(i.title=n.title),n.description!==void 0&&(i.description=n.description),n.status!==void 0&&(i.status=this.mapStatusToDatabase(n.status)),n.priority!==void 0&&(i.priority=this.mapPriorityToDatabase(n.priority));let{data:a,error:o}=await this.supabase.from(`tasks`).select(`metadata`).eq(`brief_id`,r).eq(`display_id`,t.toUpperCase()).single();if(o)throw Error(`Failed to load existing task metadata: ${o.message}`);let s={...a?.metadata??{}};n.details!==void 0&&(s.details=n.details),n.testStrategy!==void 0&&(s.testStrategy=n.testStrategy),Object.keys(s).length>0&&(i.metadata=s);let{error:c}=await this.supabase.from(`tasks`).update(i).eq(`brief_id`,r).eq(`display_id`,t.toUpperCase());if(c)throw Error(`Failed to update task: ${c.message}`);let l=await this.getTask(e,t);if(!l)throw Error(`Failed to retrieve updated task ${t}`);return l}mapStatusToDatabase(e){switch(e){case`pending`:return`todo`;case`in-progress`:case`in_progress`:return`in_progress`;case`done`:return`done`;default:throw Error(`Invalid task status: ${e}. Valid statuses are: pending, in-progress, done`)}}mapPriorityToDatabase(e){switch(e){case`critical`:return`urgent`;case`low`:case`medium`:case`high`:return e;default:throw Error(`Invalid task priority: ${e}. Valid priorities are: low, medium, high, critical`)}}},wn=class{constructor(e){this.options=e}async request(e,t={}){let{baseUrl:n,authManager:r,accountId:i}=this.options,a=await r.supabaseClient.getSession();if(!a)throw new T(`Not authenticated`,w.AUTHENTICATION_ERROR,{operation:`api-request`,endpoint:e});let o=`${n}${e}`,s={"Content-Type":`application/json`,Authorization:`Bearer ${a.access_token}`,...i?{"x-account-id":i}:{},...t.headers};try{let n=await fetch(o,{...t,headers:s});return n.ok||await this.handleErrorResponse(n,e),await n.json()}catch(t){throw t instanceof T?t:new T(t instanceof Error?t.message:String(t),w.API_ERROR,{operation:`api-request`,endpoint:e},t)}}async handleErrorResponse(e,t){let n;try{let t=await e.json();n=t.message||t.error||`Unknown API error`}catch{n=await e.text()||e.statusText}throw new T(n,w.API_ERROR,{operation:`api-request`,endpoint:t,statusCode:e.status})}async get(e){return this.request(e,{method:`GET`})}async post(e,t){return this.request(e,{method:`POST`,body:t?JSON.stringify(t):void 0})}async patch(e,t){return this.request(e,{method:`PATCH`,body:t?JSON.stringify(t):void 0})}async put(e,t){return this.request(e,{method:`PUT`,body:t?JSON.stringify(t):void 0})}async delete(e){return this.request(e,{method:`DELETE`})}},Tn=class{repository;projectId;enableRetry;maxRetries;initialized=!1;tagsCache=new Map;apiClient;expansionService;retrievalService;logger=D(`ApiStorage`);constructor(e){if(this.validateConfig(e),e.repository)this.repository=e.repository;else if(e.supabaseClient)this.repository=new Cn(e.supabaseClient);else throw new T(`Either repository or supabaseClient must be provided`,w.MISSING_CONFIGURATION);this.projectId=e.projectId,this.enableRetry=e.enableRetry??!0,this.maxRetries=e.maxRetries??3}validateConfig(e){if(!e.projectId)throw new T(`Project ID is required for API storage`,w.MISSING_CONFIGURATION);if(!e.repository&&!e.supabaseClient)throw new T(`Either repository or supabaseClient must be provided`,w.MISSING_CONFIGURATION)}async initialize(){if(!this.initialized)try{await this.loadTagsIntoCache(),this.initialized=!0}catch(e){throw new T(`Failed to initialize API storage`,w.STORAGE_ERROR,{operation:`initialize`},e)}}getStorageType(){return`api`}getCurrentBriefName(){return M.getInstance().getContext()?.briefName||null}async getTagsWithStats(){await this.ensureInitialized();try{return await new gn().getBriefsWithStats(this.repository,this.projectId)}catch(e){throw new T(`Failed to get tags with stats from API`,w.STORAGE_ERROR,{operation:`getTagsWithStats`},e)}}async loadTagsIntoCache(){try{let e=M.getInstance().getContext();if(e?.briefId){let t={name:e.briefId,tasks:[],metadata:{briefId:e.briefId,briefName:e.briefName,organizationId:e.orgId}};this.tagsCache.clear(),this.tagsCache.set(e.briefId,t)}}catch{console.debug(`No brief selected, starting with empty cache`)}}async loadTasks(e,t){await this.ensureInitialized();try{let e=M.getInstance().ensureBriefSelected(`loadTasks`),n=await this.retryOperation(()=>this.repository.getTasks(this.projectId,t)),r=this.tagsCache.get(e.briefId);return r&&(r.tasks=n.map(e=>e.id)),n}catch(t){this.wrapError(t,`Failed to load tasks from API`,{operation:`loadTasks`,tag:e,context:`brief-based loading`})}}async saveTasks(e,t){await this.ensureInitialized();try{if(t){let n=this.tagsCache.get(t)||{name:t,tasks:[],metadata:{}};n.tasks=e.map(e=>e.id),this.tagsCache.has(t)?await this.repository.updateTag(this.projectId,t,n):await this.repository.createTag(this.projectId,n),this.tagsCache.set(t,n)}await this.retryOperation(()=>this.repository.bulkCreateTasks(this.projectId,e))}catch(n){throw new T(`Failed to save tasks to API`,w.STORAGE_ERROR,{operation:`saveTasks`,tag:t,taskCount:e.length},n)}}async loadTask(e,t){await this.ensureInitialized();try{let t=this.getRetrievalService();return await this.retryOperation(()=>t.getTask(e))}catch(n){this.wrapError(n,`Failed to load task from API`,{operation:`loadTask`,taskId:e,tag:t})}}async saveTask(e,t){await this.ensureInitialized();try{if(await this.repository.getTask(this.projectId,e.id)?await this.retryOperation(()=>this.repository.updateTask(this.projectId,e.id,e)):await this.retryOperation(()=>this.repository.createTask(this.projectId,e)),t){let n=this.tagsCache.get(t);n&&!n.tasks.includes(e.id)&&(n.tasks.push(e.id),await this.repository.updateTag(this.projectId,t,n))}}catch(n){throw new T(`Failed to save task to API`,w.STORAGE_ERROR,{operation:`saveTask`,taskId:e.id,tag:t},n)}}async deleteTask(e,t){await this.ensureInitialized();try{if(await this.retryOperation(()=>this.repository.deleteTask(this.projectId,e)),t){let n=this.tagsCache.get(t);n&&(n.tasks=n.tasks.filter(t=>t!==e),await this.repository.updateTag(this.projectId,t,n))}}catch(n){throw new T(`Failed to delete task from API`,w.STORAGE_ERROR,{operation:`deleteTask`,taskId:e,tag:t},n)}}async listTags(){await this.ensureInitialized();try{let e=M.getInstance().getContext();return e?.briefId?(await this.loadTagsIntoCache(),[e.briefId]):[]}catch(e){throw new T(`Failed to list tags from API`,w.STORAGE_ERROR,{operation:`listTags`},e)}}async loadMetadata(e){await this.ensureInitialized();try{return e?this.tagsCache.get(e)?.metadata||null:(await this.repository.getTag(this.projectId,`_system`))?.metadata||null}catch(t){throw new T(`Failed to load metadata from API`,w.STORAGE_ERROR,{operation:`loadMetadata`,tag:e},t)}}async saveMetadata(e,t){await this.ensureInitialized();try{if(t){let n=this.tagsCache.get(t)||{name:t,tasks:[],metadata:{}};n.metadata=e,this.tagsCache.has(t)?await this.repository.updateTag(this.projectId,t,n):await this.repository.createTag(this.projectId,n),this.tagsCache.set(t,n)}else{let t={name:`_system`,tasks:[],metadata:e};await this.repository.getTag(this.projectId,`_system`)?await this.repository.updateTag(this.projectId,`_system`,t):await this.repository.createTag(this.projectId,t)}}catch(e){throw new T(`Failed to save metadata to API`,w.STORAGE_ERROR,{operation:`saveMetadata`,tag:t},e)}}async exists(){try{return await this.initialize(),!0}catch{return!1}}async appendTasks(e,t){await this.ensureInitialized();try{if(await this.retryOperation(()=>this.repository.bulkCreateTasks(this.projectId,e)),t){let n=this.tagsCache.get(t)||{name:t,tasks:[],metadata:{}},r=e.map(e=>e.id);n.tasks=[...new Set([...n.tasks,...r])],this.tagsCache.has(t)?await this.repository.updateTag(this.projectId,t,n):await this.repository.createTag(this.projectId,n),this.tagsCache.set(t,n)}}catch(n){throw new T(`Failed to append tasks to API`,w.STORAGE_ERROR,{operation:`appendTasks`,tag:t,taskCount:e.length},n)}}async updateTask(e,t,n){await this.ensureInitialized();try{await this.retryOperation(()=>this.repository.updateTask(this.projectId,e,t))}catch(t){throw new T(`Failed to update task via API`,w.STORAGE_ERROR,{operation:`updateTask`,taskId:e,tag:n},t)}}async updateTaskWithPrompt(e,t,n,r){await this.ensureInitialized();let i=r?.mode??`append`;try{let n=await this.getApiClient().patch(`/ai/api/v1/tasks/${e}/prompt`,{prompt:t,mode:i});if(!n.success)throw Error(n.message||`Update failed for task ${e}. The server did not provide details.`);this.logger.info(`Successfully updated task ${n.task.displayId||n.task.id} using AI prompt (mode: ${i})`),this.logger.info(` Title: ${n.task.title}`),this.logger.info(` Status: ${n.task.status}`),n.message&&this.logger.info(` ${n.message}`)}catch(r){throw r instanceof T?r.withContext({operation:`updateTaskWithPrompt`,taskId:e,tag:n,promptLength:t.length,mode:i}):new T(r instanceof Error?r.message:String(r),w.STORAGE_ERROR,{operation:`updateTaskWithPrompt`,taskId:e,tag:n,promptLength:t.length,mode:i},r)}}async expandTaskWithPrompt(e,t,n){return await this.ensureInitialized(),await this.getExpansionService().expandTask(e,n)}async updateTaskStatus(e,t,n){await this.ensureInitialized();try{M.getInstance().ensureBriefSelected(`updateTaskStatus`);let n=await this.retryOperation(()=>this.repository.getTask(this.projectId,e));if(!n)throw Error(`Task ${e} not found`);let r=n.status;return r===t||await this.retryOperation(()=>this.repository.updateTask(this.projectId,e,{status:t,updatedAt:new Date().toISOString()})),{success:!0,oldStatus:r,newStatus:t,taskId:e}}catch(r){this.wrapError(r,`Failed to update task status via API`,{operation:`updateTaskStatus`,taskId:e,newStatus:t,tag:n})}}async getAllTags(){return this.listTags()}async createTag(e,t){throw new T(`Tag creation is not supported with API storage. Please create briefs through Hamster Studio.`,w.NOT_IMPLEMENTED,{storageType:`api`,operation:`createTag`,tagName:e})}async deleteTag(e){await this.ensureInitialized();try{await this.retryOperation(()=>this.repository.deleteTag(this.projectId,e)),this.tagsCache.delete(e)}catch(t){throw new T(`Failed to delete tag via API`,w.STORAGE_ERROR,{operation:`deleteTag`,tag:e},t)}}async renameTag(e,t){await this.ensureInitialized();try{let n=this.tagsCache.get(e);if(!n)throw Error(`Tag ${e} not found`);let r={...n,name:t};await this.repository.createTag(this.projectId,r),await this.repository.deleteTag(this.projectId,e),this.tagsCache.delete(e),this.tagsCache.set(t,r)}catch(n){throw new T(`Failed to rename tag via API`,w.STORAGE_ERROR,{operation:`renameTag`,oldTag:e,newTag:t},n)}}async copyTag(e,t){await this.ensureInitialized();try{let n=this.tagsCache.get(e);if(!n)throw Error(`Source tag ${e} not found`);let r={...n,name:t};await this.repository.createTag(this.projectId,r),this.tagsCache.set(t,r)}catch(n){throw new T(`Failed to copy tag via API`,w.STORAGE_ERROR,{operation:`copyTag`,sourceTag:e,targetTag:t},n)}}async getStats(){await this.ensureInitialized();try{let e=await this.repository.getTasks(this.projectId),t=await this.repository.getTags(this.projectId),n=t.map(e=>({tag:e.name,taskCount:e.tasks.length,lastModified:new Date().toISOString()}));return{totalTasks:e.length,totalTags:t.length,storageSize:0,lastModified:new Date().toISOString(),tagStats:n}}catch(e){throw new T(`Failed to get stats from API`,w.STORAGE_ERROR,{operation:`getStats`},e)}}async backup(){await this.ensureInitialized();try{return await this.repository.getTasks(this.projectId),await this.repository.getTags(this.projectId),`backup-${this.projectId}-${Date.now()}`}catch(e){throw new T(`Failed to create backup via API`,w.STORAGE_ERROR,{operation:`backup`},e)}}async restore(e){throw await this.ensureInitialized(),new T(`Restore not implemented for API storage`,w.NOT_IMPLEMENTED,{operation:`restore`,backupId:e})}async clear(){await this.ensureInitialized();try{let e=await this.repository.getTasks(this.projectId);e.length>0&&await this.repository.bulkDeleteTasks(this.projectId,e.map(e=>e.id));let t=await this.repository.getTags(this.projectId);for(let e of t)await this.repository.deleteTag(this.projectId,e.name);this.tagsCache.clear()}catch(e){throw new T(`Failed to clear data via API`,w.STORAGE_ERROR,{operation:`clear`},e)}}async close(){this.initialized=!1,this.tagsCache.clear()}async watch(e,t){await this.ensureInitialized();let n=M.getInstance(),r=n.getContext();if(!r?.briefId)throw new T(`No brief context found for watching. Please connect to a brief first.`,w.NO_BRIEF_SELECTED,{operation:`watch`});let i=n.supabaseClient.getClient(),a=`tasks-watch-${r.briefId}-${Date.now()}`,o=t?.debounceMs??300,s,c=!1,l=i.channel(a).on(`postgres_changes`,{event:`*`,schema:`public`,table:`tasks`,filter:`brief_id=eq.${r.briefId}`},()=>{c||(s&&clearTimeout(s),s=setTimeout(()=>{c||e({type:`change`,timestamp:new Date})},o))}).subscribe((t,n)=>{(t===`CHANNEL_ERROR`||t===`TIMED_OUT`||t===`CLOSED`||n)&&e({type:`error`,timestamp:new Date,error:n||Error(`Channel subscription ${t.toLowerCase()}`)})});return{unsubscribe:()=>{c=!0,s&&clearTimeout(s),l.unsubscribe()}}}async ensureInitialized(){this.initialized||await this.initialize()}getApiClient(){if(!this.apiClient){let e=process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN;if(!e)throw new T(`API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable.`,w.MISSING_CONFIGURATION,{operation:`getApiClient`});let t=M.getInstance().ensureBriefSelected(`getApiClient`);this.apiClient=new wn({baseUrl:e,authManager:M.getInstance(),accountId:t.orgId})}return this.apiClient}getExpansionService(){if(!this.expansionService){let e=this.getApiClient(),t=M.getInstance();this.expansionService=new _n(this.repository,this.projectId,e,t)}return this.expansionService}getRetrievalService(){if(!this.retrievalService){let e=this.getApiClient(),t=M.getInstance();this.retrievalService=new vn(this.repository,this.projectId,e,t)}return this.retrievalService}async retryOperation(e,t=1){try{return await e()}catch(n){if(this.enableRetry&&t<this.maxRetries){let n=2**t*1e3;return await new Promise(e=>setTimeout(e,n)),this.retryOperation(e,t+1)}throw n}}wrapError(e,t,n){throw e instanceof T&&e.is(w.NO_BRIEF_SELECTED)?e:new T(t,w.STORAGE_ERROR,n,e)}},En=class e{static async createFromStorageConfig(t,n){return e.create({storage:t,projectPath:n},n)}static async create(t,n){let r=t.storage?.type||`auto`,i=D(`StorageFactory`);switch(r){case`file`:return i.debug(`📁 Using local file storage`),e.createFileStorage(n,t);case`api`:if(!e.isHamsterAvailable(t)){let e=[];t.storage?.apiEndpoint||e.push(`apiEndpoint`),t.storage?.apiAccessToken||e.push(`apiAccessToken`);let n=M.getInstance();if(!await n.hasValidSession())throw new T(`API storage not fully configured (${e.join(`, `)||`credentials missing`}). Run: tm auth login, or set the missing field(s).`,w.MISSING_CONFIGURATION,{storageType:`api`,missing:e});let r=await n.getAccessToken();if(r){let e={...t.storage,type:`api`,apiAccessToken:r,apiEndpoint:t.storage?.apiEndpoint||process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`https://tryhamster.com/api`};if(!e.apiEndpoint)throw new T(`API endpoint could not be determined.`,w.MISSING_CONFIGURATION,{storageType:`api`});t.storage=e}}return i.info(`☁️ Using API storage`),e.createApiStorage(t);case`auto`:let a=M.getInstance();if(e.isHamsterAvailable(t))return i.info(`☁️ Using API storage (configured)`),e.createApiStorage(t);if(await a.hasValidSession()){let r=await a.getAccessToken();if(!a.getContext()?.briefId)return i.debug(`📁 User authenticated but no brief selected, using file storage`),e.createFileStorage(n,t);if(r)return t.storage={...t.storage,type:`api`,apiAccessToken:r,apiEndpoint:t.storage?.apiEndpoint||process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`https://tryhamster.com/api`},i.info(`☁️ Using API storage (authenticated)`),e.createApiStorage(t)}return i.debug(`📁 Using local file storage`),e.createFileStorage(n,t);default:throw new T(`Unknown storage type: ${r}`,w.INVALID_INPUT,{storageType:r})}}static createFileStorage(e,t){return new Mt(t.storage?.basePath||e)}static createApiStorage(e){return new Tn({supabaseClient:Pe.getInstance().getClient(),projectId:e.projectPath||``,enableRetry:e.retry?.retryOnNetworkError,maxRetries:e.retry?.retryAttempts})}static detectOptimalStorage(e){return e.storage?.apiEndpoint&&e.storage?.apiAccessToken?`api`:`file`}static validateStorageConfig(e){let t=[],n=e.storage?.type;if(!n)return t.push(`Storage type is not specified`),{isValid:!1,errors:t};switch(n){case`api`:e.storage?.apiEndpoint||t.push(`API endpoint is required for API storage`),e.storage?.apiAccessToken||t.push(`API access token is required for API storage`);break;case`file`:break;case`auto`:break;default:t.push(`Unknown storage type: ${n}`)}return{isValid:t.length===0,errors:t}}static isHamsterAvailable(e){return!!(e.storage?.apiEndpoint&&e.storage?.apiAccessToken)}static async createWithFallback(t,n){if(e.isHamsterAvailable(t))try{let n=e.createApiStorage(t);return await n.initialize(),n}catch(e){D(`StorageFactory`).warn(`Failed to initialize API storage, falling back to file storage:`,e)}return e.createFileStorage(n,t)}},Dn=class e{id;title;description;status;priority;dependencies;details;testStrategy;subtasks;createdAt;updatedAt;effort;actualEffort;tags;assignee;complexity;recommendedSubtasks;expansionPrompt;complexityReasoning;metadata;constructor(e){this.validate(e),this.id=String(e.id),this.title=e.title,this.description=e.description,this.status=e.status,this.priority=e.priority,this.dependencies=(e.dependencies||[]).map(e=>String(e)),this.details=e.details,this.testStrategy=e.testStrategy,this.subtasks=(e.subtasks||[]).map(e=>({...e,id:String(e.id),parentId:String(e.parentId)})),this.createdAt=e.createdAt,this.updatedAt=e.updatedAt,this.effort=e.effort,this.actualEffort=e.actualEffort,this.tags=e.tags,this.assignee=e.assignee,this.complexity=e.complexity,this.recommendedSubtasks=e.recommendedSubtasks,this.expansionPrompt=e.expansionPrompt,this.complexityReasoning=e.complexityReasoning,this.metadata=e.metadata}validate(e){if(e.id===void 0||e.id===null||typeof e.id!=`string`&&typeof e.id!=`number`)throw new T(`Task ID is required and must be a string or number`,w.VALIDATION_ERROR);if(!e.title||e.title.trim().length===0)throw new T(`Task title is required`,w.VALIDATION_ERROR);if(!e.description||e.description.trim().length===0)throw new T(`Task description is required`,w.VALIDATION_ERROR);if(!this.isValidStatus(e.status))throw new T(`Invalid task status: ${e.status}`,w.VALIDATION_ERROR);if(!this.isValidPriority(e.priority))throw new T(`Invalid task priority: ${e.priority}`,w.VALIDATION_ERROR)}isValidStatus(e){return[`pending`,`in-progress`,`done`,`deferred`,`cancelled`,`blocked`,`review`].includes(e)}isValidPriority(e){return[`low`,`medium`,`high`,`critical`].includes(e)}canComplete(){return this.status===`done`||this.status===`cancelled`||this.status===`blocked`?!1:this.subtasks.every(e=>e.status===`done`||e.status===`cancelled`)}markAsComplete(){if(!this.canComplete())throw new T(`Task cannot be marked as complete`,w.TASK_STATUS_ERROR,{taskId:this.id,currentStatus:this.status,hasIncompleteSubtasks:this.subtasks.some(e=>e.status!==`done`&&e.status!==`cancelled`)});this.status=`done`,this.updatedAt=new Date().toISOString()}hasDependencies(){return this.dependencies.length>0}hasSubtasks(){return this.subtasks.length>0}addSubtask(e){let t=this.subtasks.length+1;this.subtasks.push({...e,id:t,parentId:this.id}),this.updatedAt=new Date().toISOString()}updateStatus(e){if(!this.isValidStatus(e))throw new T(`Invalid status: ${e}`,w.VALIDATION_ERROR);if(this.status===`done`&&e===`pending`)throw new T(`Cannot move completed task back to pending`,w.TASK_STATUS_ERROR);this.status=e,this.updatedAt=new Date().toISOString()}toJSON(){return{id:this.id,title:this.title,description:this.description,status:this.status,priority:this.priority,dependencies:this.dependencies,details:this.details,testStrategy:this.testStrategy,subtasks:this.subtasks,createdAt:this.createdAt,updatedAt:this.updatedAt,effort:this.effort,actualEffort:this.actualEffort,tags:this.tags,assignee:this.assignee,complexity:this.complexity,recommendedSubtasks:this.recommendedSubtasks,expansionPrompt:this.expansionPrompt,complexityReasoning:this.complexityReasoning,metadata:this.metadata}}static fromObject(t){return new e(t)}static fromArray(t){return t.map(t=>new e(t))}},On=class{configManager;storage;initialized=!1;logger=D(`TaskService`);constructor(e){this.configManager=e,this.storage=null}async initialize(){if(this.initialized)return;let e=this.configManager.getStorageConfig(),t=this.configManager.getProjectRoot();this.storage=await En.createFromStorageConfig(e,t),await this.storage.initialize(),this.initialized=!0}async getTaskList(e={}){let t=this.configManager.getActiveTag(),n=e.tag||t;try{let t=e.filter?.status&&!e.filter.priority&&!e.filter.tags&&!e.filter.assignee&&!e.filter.search&&e.filter.hasSubtasks===void 0,r={};if(t){let t=Array.isArray(e.filter.status)?e.filter.status:[e.filter.status];t.length===1&&(r.status=t[0])}e.includeSubtasks===!1&&(r.excludeSubtasks=!0);let i=await this.storage.loadTasks(n,r),a={};e.includeSubtasks===!1&&(a.excludeSubtasks=!0);let o=r.status===void 0?i:await this.storage.loadTasks(n,a),s=Dn.fromArray(i),c=s;(e.filter&&!t||e.filter?.status&&Array.isArray(e.filter.status)&&e.filter.status.length>1)&&(c=this.applyFilters(s,e.filter));let l=c.map(e=>e.toJSON()),u=this.getStorageType(),d=u===`api`&&this.storage.getCurrentBriefName()||n;return{tasks:l,total:o.length,filtered:c.length,tag:d,storageType:u}}catch(t){throw t instanceof T?t:(this.logger.error(`Failed to get task list`,t),new T(`Failed to get task list`,w.INTERNAL_ERROR,{operation:`getTaskList`,tag:n,hasFilter:!!e.filter},t))}}async getTask(e,t){let n=t||this.getActiveTag();try{return await this.storage.loadTask(String(e),n)}catch(t){throw t instanceof T?t:new T(`Failed to get task ${e}`,w.STORAGE_ERROR,{operation:`getTask`,resource:`task`,taskId:String(e),tag:n},t)}}async getTasksByStatus(e,t){let n=Array.isArray(e)?e:[e];return(await this.getTaskList({tag:t,filter:{status:n}})).tasks}async getTaskStats(e){let t=await this.getTaskList({tag:e,includeSubtasks:!0}),n={total:t.total,byStatus:{},withSubtasks:0,blocked:0,storageType:t.storageType};return[`pending`,`in-progress`,`done`,`deferred`,`cancelled`,`blocked`,`review`].forEach(e=>{n.byStatus[e]=0}),t.tasks.forEach(e=>{n.byStatus[e.status]++,e.subtasks&&e.subtasks.length>0&&n.withSubtasks++,e.status===`blocked`&&n.blocked++}),n}async getNextTask(e){let t=(await this.getTaskList({tag:e,filter:{status:[`pending`,`in-progress`,`done`]}})).tasks,n={critical:4,high:3,medium:2,low:1},r=(e,t)=>typeof t==`string`&&t.includes(`.`)?t:`${e}.${t}`,i=new Set;t.forEach(e=>{e.status===`done`&&i.add(String(e.id)),Array.isArray(e.subtasks)&&e.subtasks.forEach(t=>{t.status===`done`&&i.add(`${e.id}.${t.id}`)})});let a=[];if(t.filter(e=>e.status===`in-progress`&&Array.isArray(e.subtasks)).forEach(e=>{e.subtasks.forEach(t=>{let n=(t.status||`pending`).toLowerCase();if(n!==`pending`&&n!==`in-progress`)return;let o=t.dependencies?.map(t=>r(String(e.id),t))??[];(o.length===0||o.every(e=>i.has(String(e))))&&a.push({id:`${e.id}.${t.id}`,title:t.title||`Subtask ${t.id}`,status:t.status||`pending`,priority:t.priority||e.priority||`medium`,dependencies:o,parentId:String(e.id),description:t.description,details:t.details,testStrategy:t.testStrategy,subtasks:[]})})}),a.length>0)return a.sort((e,t)=>{let r=n[e.priority]??2,i=n[t.priority]??2;if(i!==r)return i-r;if(e.dependencies.length!==t.dependencies.length)return e.dependencies.length-t.dependencies.length;let[a,o]=String(e.id).split(`.`).map(Number),[s,c]=String(t.id).split(`.`).map(Number);return a===s?o-c:a-s}),a[0];let o=t.filter(e=>{let t=(e.status||`pending`).toLowerCase();return t!==`pending`&&t!==`in-progress`?!1:(e.dependencies??[]).every(e=>i.has(String(e)))});return o.length===0?null:o.sort((e,t)=>{let r=n[e.priority]??2,i=n[t.priority]??2;if(i!==r)return i-r;let a=(e.dependencies??[]).length,o=(t.dependencies??[]).length;return a===o?Number(e.id)-Number(t.id):a-o})[0]}applyFilters(e,t){return e.filter(e=>{if(t.status&&!(Array.isArray(t.status)?t.status:[t.status]).includes(e.status)||t.priority&&!(Array.isArray(t.priority)?t.priority:[t.priority]).includes(e.priority)||t.tags&&t.tags.length>0&&(!e.tags||!t.tags.some(t=>e.tags?.includes(t)))||t.assignee&&e.assignee!==t.assignee)return!1;if(t.search){let n=t.search.toLowerCase(),r=e.title.toLowerCase().includes(n),i=e.description.toLowerCase().includes(n),a=e.details.toLowerCase().includes(n);if(!r&&!i&&!a)return!1}return!(t.hasSubtasks!==void 0&&e.subtasks.length>0!==t.hasSubtasks)})}getStorageType(){return this.storage.getStorageType()}getStorage(){return this.storage}getActiveTag(){if(this.initialized&&this.getStorageType()===`api`){let e=this.storage.getCurrentBriefName();if(e)return e}return this.configManager.getActiveTag()}async setActiveTag(e){await this.configManager.setActiveTag(e)}async updateTask(e,t,n){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();let r=n||this.getActiveTag(),i=String(e);try{await this.storage.updateTask(i,t,r)}catch(t){throw t instanceof T?t:new T(`Failed to update task ${e}`,w.STORAGE_ERROR,{operation:`updateTask`,resource:`task`,taskId:i,tag:r},t)}}async updateTaskWithPrompt(e,t,n,r){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();let i=n||this.getActiveTag(),a=String(e);try{await this.storage.updateTaskWithPrompt(a,t,i,r)}catch(n){throw n instanceof T?n:new T(`Failed to update task ${e} with prompt`,w.STORAGE_ERROR,{operation:`updateTaskWithPrompt`,resource:`task`,taskId:a,tag:i,promptLength:t.length},n)}}async expandTaskWithPrompt(e,t,n){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();let r=t||this.getActiveTag(),i=String(e);try{return await this.storage.expandTaskWithPrompt(i,r,n)}catch(t){throw t instanceof T?t:new T(`Failed to expand task ${e}`,w.STORAGE_ERROR,{operation:`expandTaskWithPrompt`,resource:`task`,taskId:i,tag:r,numSubtasks:n?.numSubtasks},t)}}async updateTaskStatus(e,t,n){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);let r=n||this.getActiveTag(),i=String(e);try{return await this.storage.updateTaskStatus(i,t,r)}catch(e){throw e instanceof T?e:new T(`Failed to update task status for ${i}`,w.STORAGE_ERROR,{operation:`updateTaskStatus`,resource:`task`,taskId:i,newStatus:t,tag:r},e)}}async getTagsWithStats(){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();try{return await this.storage.getTagsWithStats()}catch(e){throw e instanceof T?e:new T(`Failed to get tags with stats`,w.STORAGE_ERROR,{operation:`getTagsWithStats`,resource:`tags`},e)}}async close(){this.storage&&await this.storage.close(),this.initialized=!1}},kn=class{constructor(e,t=process.cwd()){this.taskService=e,this.projectRoot=t}async startTask(e,t={}){try{let{parentId:n,subtaskId:r}=this.parseTaskId(e);if(!t.force){let t=await this.checkInProgressConflicts(e);if(!t.canProceed)return{task:null,found:!1,started:!1,error:`Conflicting tasks in progress: ${t.conflictingTasks.map(e=>`#${e.id}: ${e.title}`).join(`, `)}`}}let i=await this.taskService.getTask(n);if(!i)return{task:null,found:!1,started:!1,error:`Task ${n} not found`};let a;r&&i.subtasks&&(a=i.subtasks.find(e=>String(e.id)===r));let o=this.normalizeExecutor(t.executor);if(!t.dryRun&&o===`codex`){let e=Zt(this.projectRoot);if(!e.success)return{task:i,found:!0,started:!1,subtaskId:r,subtask:a,error:this.formatCodexPreflightError(e.errors)}}if(t.updateStatus&&!t.dryRun)try{await this.taskService.updateTaskStatus(n,`in-progress`)}catch(e){console.warn(`Could not update task status: ${e instanceof Error?e.message:String(e)}`)}let s=!1,c=`Task ready to execute`,l;return t.dryRun?(s=!0,c=`Dry run - task would be executed`,l=await this.prepareExecutionCommand(i,a,o)):(l=await this.prepareExecutionCommand(i,a,o),s=!!l,c=l?`Command prepared: ${l.executable} ${l.args.join(` `)}`:`Failed to prepare execution command`),{task:i,found:!0,started:s,subtaskId:r,subtask:a,executionOutput:c,command:l||void 0}}catch(e){return{task:null,found:!1,started:!1,error:e instanceof Error?e.message:String(e)}}}formatCodexPreflightError(e){return`Codex execution blocked by permission preflight checks:\n${e.map(e=>`- ${e}`).join(`
|
|
320
|
-
`)}`}async checkInProgressConflicts(e){let t=(await this.taskService.getTaskList()).tasks.filter(e=>e.status===`in-progress`);if(t.find(t=>t.id===e))return{canProceed:!0,conflictingTasks:[]};let n=e.includes(`.`);if(n){let n=e.split(`.`)[0];if(t.find(e=>e.id===n))return{canProceed:!0,conflictingTasks:[]}}let r=t.filter(t=>{if(t.id===e)return!1;if(n){let n=e.split(`.`)[0];if(t.id===n)return!1}if(t.id.toString().includes(`.`)){let r=t.id.toString().split(`.`)[0];if(n&&r===e.split(`.`)[0])return!1}return!0});return r.length>0?{canProceed:!1,conflictingTasks:r,reason:`Other tasks are already in progress`}:{canProceed:!0,conflictingTasks:[]}}async getNextAvailableTask(){return(await this.taskService.getNextTask())?.id||null}parseTaskId(e){if(e.includes(`.`)){let[t,n]=e.split(`.`);return{parentId:t,subtaskId:n}}return{parentId:e}}async canStartTask(e,t=!1){return t?!0:(await this.checkInProgressConflicts(e)).canProceed}async prepareExecutionCommand(e,t,n=`claude`){try{let r=this.formatTaskPrompt(e,t);return{executable:n,args:this.getExecutionArgs(n,r),cwd:this.projectRoot}}catch(e){return console.warn(`Failed to prepare execution command: ${e instanceof Error?e.message:String(e)}`),null}}normalizeExecutor(e){if(!e)return`claude`;let t=e.toLowerCase();return t===`claude`||t===`codex`?t:(console.warn(`Unknown executor "${e}", defaulting to "claude". Supported executors: claude, codex.`),`claude`)}getExecutionArgs(e,t){return[t]}formatTaskPrompt(e,t){let n=t||e,r=t?`Subtask`:`Task`,i=`${r} #${t?`${e.id}.${t.id}`:e.id}: ${n.title}\n\n`;return n.description&&(i+=`Description:\n${n.description}\n\n`),n.details&&(i+=`Implementation Details:\n${n.details}\n\n`),n.testStrategy&&(i+=`Test Strategy:\n${n.testStrategy}\n\n`),e.dependencies&&e.dependencies.length>0&&(i+=`Dependencies: ${e.dependencies.join(`, `)}\n\n`),i+=`Please help me implement this ${r.toLowerCase()}.`,i}async getTaskWithSubtask(e){let{parentId:t,subtaskId:n}=this.parseTaskId(e),r=await this.taskService.getTask(t);return r?n&&r.subtasks?{task:r,subtask:r.subtasks.find(e=>String(e.id)===n),subtaskId:n}:{task:r}:{task:null}}};const
|
|
320
|
+
`).eq(`id`,e).single();if(n){if(n.code===`PGRST116`)return null;throw Error(`Failed to fetch brief: ${n.message}`)}if(!t)return null;let r=t.document;return{id:t.id,accountId:t.account_id,createdAt:t.created_at,name:r?.title||void 0,description:r?.description||void 0,status:t.status||void 0}}async updateTask(e,t,n){let r=this.getBriefIdOrThrow();try{wn.parse(n)}catch(e){if(e instanceof C.ZodError){let t=e.issues.map(e=>`${e.path.join(`.`)}: ${e.message}`).join(`, `);throw Error(`Invalid task update data: ${t}`)}throw e}let i={};n.title!==void 0&&(i.title=n.title),n.description!==void 0&&(i.description=n.description),n.status!==void 0&&(i.status=this.mapStatusToDatabase(n.status)),n.priority!==void 0&&(i.priority=this.mapPriorityToDatabase(n.priority));let{data:a,error:o}=await this.supabase.from(`tasks`).select(`metadata`).eq(`brief_id`,r).eq(`display_id`,t.toUpperCase()).single();if(o)throw Error(`Failed to load existing task metadata: ${o.message}`);let s={...a?.metadata??{}};n.details!==void 0&&(s.details=n.details),n.testStrategy!==void 0&&(s.testStrategy=n.testStrategy),Object.keys(s).length>0&&(i.metadata=s);let{error:c}=await this.supabase.from(`tasks`).update(i).eq(`brief_id`,r).eq(`display_id`,t.toUpperCase());if(c)throw Error(`Failed to update task: ${c.message}`);let l=await this.getTask(e,t);if(!l)throw Error(`Failed to retrieve updated task ${t}`);return l}mapStatusToDatabase(e){switch(e){case`pending`:return`todo`;case`in-progress`:case`in_progress`:return`in_progress`;case`done`:return`done`;default:throw Error(`Invalid task status: ${e}. Valid statuses are: pending, in-progress, done`)}}mapPriorityToDatabase(e){switch(e){case`critical`:return`urgent`;case`low`:case`medium`:case`high`:return e;default:throw Error(`Invalid task priority: ${e}. Valid priorities are: low, medium, high, critical`)}}},En=class{constructor(e){this.options=e}async request(e,t={}){let{baseUrl:n,authManager:r,accountId:i}=this.options,a=await r.supabaseClient.getSession();if(!a)throw new T(`Not authenticated`,w.AUTHENTICATION_ERROR,{operation:`api-request`,endpoint:e});let o=`${n}${e}`,s={"Content-Type":`application/json`,Authorization:`Bearer ${a.access_token}`,...i?{"x-account-id":i}:{},...t.headers};try{let n=await fetch(o,{...t,headers:s});return n.ok||await this.handleErrorResponse(n,e),await n.json()}catch(t){throw t instanceof T?t:new T(t instanceof Error?t.message:String(t),w.API_ERROR,{operation:`api-request`,endpoint:e},t)}}async handleErrorResponse(e,t){let n;try{let t=await e.json();n=t.message||t.error||`Unknown API error`}catch{n=await e.text()||e.statusText}throw new T(n,w.API_ERROR,{operation:`api-request`,endpoint:t,statusCode:e.status})}async get(e){return this.request(e,{method:`GET`})}async post(e,t){return this.request(e,{method:`POST`,body:t?JSON.stringify(t):void 0})}async patch(e,t){return this.request(e,{method:`PATCH`,body:t?JSON.stringify(t):void 0})}async put(e,t){return this.request(e,{method:`PUT`,body:t?JSON.stringify(t):void 0})}async delete(e){return this.request(e,{method:`DELETE`})}},Dn=class{repository;projectId;enableRetry;maxRetries;initialized=!1;tagsCache=new Map;apiClient;expansionService;retrievalService;logger=D(`ApiStorage`);constructor(e){if(this.validateConfig(e),e.repository)this.repository=e.repository;else if(e.supabaseClient)this.repository=new Tn(e.supabaseClient);else throw new T(`Either repository or supabaseClient must be provided`,w.MISSING_CONFIGURATION);this.projectId=e.projectId,this.enableRetry=e.enableRetry??!0,this.maxRetries=e.maxRetries??3}validateConfig(e){if(!e.projectId)throw new T(`Project ID is required for API storage`,w.MISSING_CONFIGURATION);if(!e.repository&&!e.supabaseClient)throw new T(`Either repository or supabaseClient must be provided`,w.MISSING_CONFIGURATION)}async initialize(){if(!this.initialized)try{await this.loadTagsIntoCache(),this.initialized=!0}catch(e){throw new T(`Failed to initialize API storage`,w.STORAGE_ERROR,{operation:`initialize`},e)}}getStorageType(){return`api`}getCurrentBriefName(){return M.getInstance().getContext()?.briefName||null}async getTagsWithStats(){await this.ensureInitialized();try{return await new vn().getBriefsWithStats(this.repository,this.projectId)}catch(e){throw new T(`Failed to get tags with stats from API`,w.STORAGE_ERROR,{operation:`getTagsWithStats`},e)}}async loadTagsIntoCache(){try{let e=M.getInstance().getContext();if(e?.briefId){let t={name:e.briefId,tasks:[],metadata:{briefId:e.briefId,briefName:e.briefName,organizationId:e.orgId}};this.tagsCache.clear(),this.tagsCache.set(e.briefId,t)}}catch{console.debug(`No brief selected, starting with empty cache`)}}async loadTasks(e,t){await this.ensureInitialized();try{let e=M.getInstance().ensureBriefSelected(`loadTasks`),n=await this.retryOperation(()=>this.repository.getTasks(this.projectId,t)),r=this.tagsCache.get(e.briefId);return r&&(r.tasks=n.map(e=>e.id)),n}catch(t){this.wrapError(t,`Failed to load tasks from API`,{operation:`loadTasks`,tag:e,context:`brief-based loading`})}}async saveTasks(e,t){await this.ensureInitialized();try{if(t){let n=this.tagsCache.get(t)||{name:t,tasks:[],metadata:{}};n.tasks=e.map(e=>e.id),this.tagsCache.has(t)?await this.repository.updateTag(this.projectId,t,n):await this.repository.createTag(this.projectId,n),this.tagsCache.set(t,n)}await this.retryOperation(()=>this.repository.bulkCreateTasks(this.projectId,e))}catch(n){throw new T(`Failed to save tasks to API`,w.STORAGE_ERROR,{operation:`saveTasks`,tag:t,taskCount:e.length},n)}}async loadTask(e,t){await this.ensureInitialized();try{let t=this.getRetrievalService();return await this.retryOperation(()=>t.getTask(e))}catch(n){this.wrapError(n,`Failed to load task from API`,{operation:`loadTask`,taskId:e,tag:t})}}async saveTask(e,t){await this.ensureInitialized();try{if(await this.repository.getTask(this.projectId,e.id)?await this.retryOperation(()=>this.repository.updateTask(this.projectId,e.id,e)):await this.retryOperation(()=>this.repository.createTask(this.projectId,e)),t){let n=this.tagsCache.get(t);n&&!n.tasks.includes(e.id)&&(n.tasks.push(e.id),await this.repository.updateTag(this.projectId,t,n))}}catch(n){throw new T(`Failed to save task to API`,w.STORAGE_ERROR,{operation:`saveTask`,taskId:e.id,tag:t},n)}}async deleteTask(e,t){await this.ensureInitialized();try{if(await this.retryOperation(()=>this.repository.deleteTask(this.projectId,e)),t){let n=this.tagsCache.get(t);n&&(n.tasks=n.tasks.filter(t=>t!==e),await this.repository.updateTag(this.projectId,t,n))}}catch(n){throw new T(`Failed to delete task from API`,w.STORAGE_ERROR,{operation:`deleteTask`,taskId:e,tag:t},n)}}async listTags(){await this.ensureInitialized();try{let e=M.getInstance().getContext();return e?.briefId?(await this.loadTagsIntoCache(),[e.briefId]):[]}catch(e){throw new T(`Failed to list tags from API`,w.STORAGE_ERROR,{operation:`listTags`},e)}}async loadMetadata(e){await this.ensureInitialized();try{return e?this.tagsCache.get(e)?.metadata||null:(await this.repository.getTag(this.projectId,`_system`))?.metadata||null}catch(t){throw new T(`Failed to load metadata from API`,w.STORAGE_ERROR,{operation:`loadMetadata`,tag:e},t)}}async saveMetadata(e,t){await this.ensureInitialized();try{if(t){let n=this.tagsCache.get(t)||{name:t,tasks:[],metadata:{}};n.metadata=e,this.tagsCache.has(t)?await this.repository.updateTag(this.projectId,t,n):await this.repository.createTag(this.projectId,n),this.tagsCache.set(t,n)}else{let t={name:`_system`,tasks:[],metadata:e};await this.repository.getTag(this.projectId,`_system`)?await this.repository.updateTag(this.projectId,`_system`,t):await this.repository.createTag(this.projectId,t)}}catch(e){throw new T(`Failed to save metadata to API`,w.STORAGE_ERROR,{operation:`saveMetadata`,tag:t},e)}}async exists(){try{return await this.initialize(),!0}catch{return!1}}async appendTasks(e,t){await this.ensureInitialized();try{if(await this.retryOperation(()=>this.repository.bulkCreateTasks(this.projectId,e)),t){let n=this.tagsCache.get(t)||{name:t,tasks:[],metadata:{}},r=e.map(e=>e.id);n.tasks=[...new Set([...n.tasks,...r])],this.tagsCache.has(t)?await this.repository.updateTag(this.projectId,t,n):await this.repository.createTag(this.projectId,n),this.tagsCache.set(t,n)}}catch(n){throw new T(`Failed to append tasks to API`,w.STORAGE_ERROR,{operation:`appendTasks`,tag:t,taskCount:e.length},n)}}async updateTask(e,t,n){await this.ensureInitialized();try{await this.retryOperation(()=>this.repository.updateTask(this.projectId,e,t))}catch(t){throw new T(`Failed to update task via API`,w.STORAGE_ERROR,{operation:`updateTask`,taskId:e,tag:n},t)}}async updateTaskWithPrompt(e,t,n,r){await this.ensureInitialized();let i=r?.mode??`append`;try{let n=await this.getApiClient().patch(`/ai/api/v1/tasks/${e}/prompt`,{prompt:t,mode:i});if(!n.success)throw Error(n.message||`Update failed for task ${e}. The server did not provide details.`);this.logger.info(`Successfully updated task ${n.task.displayId||n.task.id} using AI prompt (mode: ${i})`),this.logger.info(` Title: ${n.task.title}`),this.logger.info(` Status: ${n.task.status}`),n.message&&this.logger.info(` ${n.message}`)}catch(r){throw r instanceof T?r.withContext({operation:`updateTaskWithPrompt`,taskId:e,tag:n,promptLength:t.length,mode:i}):new T(r instanceof Error?r.message:String(r),w.STORAGE_ERROR,{operation:`updateTaskWithPrompt`,taskId:e,tag:n,promptLength:t.length,mode:i},r)}}async expandTaskWithPrompt(e,t,n){return await this.ensureInitialized(),await this.getExpansionService().expandTask(e,n)}async updateTaskStatus(e,t,n){await this.ensureInitialized();try{M.getInstance().ensureBriefSelected(`updateTaskStatus`);let n=await this.retryOperation(()=>this.repository.getTask(this.projectId,e));if(!n)throw Error(`Task ${e} not found`);let r=n.status;return r===t||await this.retryOperation(()=>this.repository.updateTask(this.projectId,e,{status:t,updatedAt:new Date().toISOString()})),{success:!0,oldStatus:r,newStatus:t,taskId:e}}catch(r){this.wrapError(r,`Failed to update task status via API`,{operation:`updateTaskStatus`,taskId:e,newStatus:t,tag:n})}}async getAllTags(){return this.listTags()}async createTag(e,t){throw new T(`Tag creation is not supported with API storage. Please create briefs through Hamster Studio.`,w.NOT_IMPLEMENTED,{storageType:`api`,operation:`createTag`,tagName:e})}async deleteTag(e){await this.ensureInitialized();try{await this.retryOperation(()=>this.repository.deleteTag(this.projectId,e)),this.tagsCache.delete(e)}catch(t){throw new T(`Failed to delete tag via API`,w.STORAGE_ERROR,{operation:`deleteTag`,tag:e},t)}}async renameTag(e,t){await this.ensureInitialized();try{let n=this.tagsCache.get(e);if(!n)throw Error(`Tag ${e} not found`);let r={...n,name:t};await this.repository.createTag(this.projectId,r),await this.repository.deleteTag(this.projectId,e),this.tagsCache.delete(e),this.tagsCache.set(t,r)}catch(n){throw new T(`Failed to rename tag via API`,w.STORAGE_ERROR,{operation:`renameTag`,oldTag:e,newTag:t},n)}}async copyTag(e,t){await this.ensureInitialized();try{let n=this.tagsCache.get(e);if(!n)throw Error(`Source tag ${e} not found`);let r={...n,name:t};await this.repository.createTag(this.projectId,r),this.tagsCache.set(t,r)}catch(n){throw new T(`Failed to copy tag via API`,w.STORAGE_ERROR,{operation:`copyTag`,sourceTag:e,targetTag:t},n)}}async getStats(){await this.ensureInitialized();try{let e=await this.repository.getTasks(this.projectId),t=await this.repository.getTags(this.projectId),n=t.map(e=>({tag:e.name,taskCount:e.tasks.length,lastModified:new Date().toISOString()}));return{totalTasks:e.length,totalTags:t.length,storageSize:0,lastModified:new Date().toISOString(),tagStats:n}}catch(e){throw new T(`Failed to get stats from API`,w.STORAGE_ERROR,{operation:`getStats`},e)}}async backup(){await this.ensureInitialized();try{return await this.repository.getTasks(this.projectId),await this.repository.getTags(this.projectId),`backup-${this.projectId}-${Date.now()}`}catch(e){throw new T(`Failed to create backup via API`,w.STORAGE_ERROR,{operation:`backup`},e)}}async restore(e){throw await this.ensureInitialized(),new T(`Restore not implemented for API storage`,w.NOT_IMPLEMENTED,{operation:`restore`,backupId:e})}async clear(){await this.ensureInitialized();try{let e=await this.repository.getTasks(this.projectId);e.length>0&&await this.repository.bulkDeleteTasks(this.projectId,e.map(e=>e.id));let t=await this.repository.getTags(this.projectId);for(let e of t)await this.repository.deleteTag(this.projectId,e.name);this.tagsCache.clear()}catch(e){throw new T(`Failed to clear data via API`,w.STORAGE_ERROR,{operation:`clear`},e)}}async close(){this.initialized=!1,this.tagsCache.clear()}async watch(e,t){await this.ensureInitialized();let n=M.getInstance(),r=n.getContext();if(!r?.briefId)throw new T(`No brief context found for watching. Please connect to a brief first.`,w.NO_BRIEF_SELECTED,{operation:`watch`});let i=n.supabaseClient.getClient(),a=`tasks-watch-${r.briefId}-${Date.now()}`,o=t?.debounceMs??300,s,c=!1,l=i.channel(a).on(`postgres_changes`,{event:`*`,schema:`public`,table:`tasks`,filter:`brief_id=eq.${r.briefId}`},()=>{c||(s&&clearTimeout(s),s=setTimeout(()=>{c||e({type:`change`,timestamp:new Date})},o))}).subscribe((t,n)=>{(t===`CHANNEL_ERROR`||t===`TIMED_OUT`||t===`CLOSED`||n)&&e({type:`error`,timestamp:new Date,error:n||Error(`Channel subscription ${t.toLowerCase()}`)})});return{unsubscribe:()=>{c=!0,s&&clearTimeout(s),l.unsubscribe()}}}async ensureInitialized(){this.initialized||await this.initialize()}getApiClient(){if(!this.apiClient){let e=process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN;if(!e)throw new T(`API endpoint not configured. Please set TM_PUBLIC_BASE_DOMAIN environment variable.`,w.MISSING_CONFIGURATION,{operation:`getApiClient`});let t=M.getInstance().ensureBriefSelected(`getApiClient`);this.apiClient=new En({baseUrl:e,authManager:M.getInstance(),accountId:t.orgId})}return this.apiClient}getExpansionService(){if(!this.expansionService){let e=this.getApiClient(),t=M.getInstance();this.expansionService=new yn(this.repository,this.projectId,e,t)}return this.expansionService}getRetrievalService(){if(!this.retrievalService){let e=this.getApiClient(),t=M.getInstance();this.retrievalService=new bn(this.repository,this.projectId,e,t)}return this.retrievalService}async retryOperation(e,t=1){try{return await e()}catch(n){if(this.enableRetry&&t<this.maxRetries){let n=2**t*1e3;return await new Promise(e=>setTimeout(e,n)),this.retryOperation(e,t+1)}throw n}}wrapError(e,t,n){throw e instanceof T&&e.is(w.NO_BRIEF_SELECTED)?e:new T(t,w.STORAGE_ERROR,n,e)}},On=class e{static async createFromStorageConfig(t,n){return e.create({storage:t,projectPath:n},n)}static async create(t,n){let r=t.storage?.type||`auto`,i=D(`StorageFactory`);switch(r){case`file`:return i.debug(`📁 Using local file storage`),e.createFileStorage(n,t);case`api`:if(!e.isHamsterAvailable(t)){let e=[];t.storage?.apiEndpoint||e.push(`apiEndpoint`),t.storage?.apiAccessToken||e.push(`apiAccessToken`);let n=M.getInstance();if(!await n.hasValidSession())throw new T(`API storage not fully configured (${e.join(`, `)||`credentials missing`}). Run: tm auth login, or set the missing field(s).`,w.MISSING_CONFIGURATION,{storageType:`api`,missing:e});let r=await n.getAccessToken();if(r){let e={...t.storage,type:`api`,apiAccessToken:r,apiEndpoint:t.storage?.apiEndpoint||process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`https://tryhamster.com/api`};if(!e.apiEndpoint)throw new T(`API endpoint could not be determined.`,w.MISSING_CONFIGURATION,{storageType:`api`});t.storage=e}}return i.info(`☁️ Using API storage`),e.createApiStorage(t);case`auto`:let a=M.getInstance();if(e.isHamsterAvailable(t))return i.info(`☁️ Using API storage (configured)`),e.createApiStorage(t);if(await a.hasValidSession()){let r=await a.getAccessToken();if(!a.getContext()?.briefId)return i.debug(`📁 User authenticated but no brief selected, using file storage`),e.createFileStorage(n,t);if(r)return t.storage={...t.storage,type:`api`,apiAccessToken:r,apiEndpoint:t.storage?.apiEndpoint||process.env.TM_BASE_DOMAIN||process.env.TM_PUBLIC_BASE_DOMAIN||`https://tryhamster.com/api`},i.info(`☁️ Using API storage (authenticated)`),e.createApiStorage(t)}return i.debug(`📁 Using local file storage`),e.createFileStorage(n,t);default:throw new T(`Unknown storage type: ${r}`,w.INVALID_INPUT,{storageType:r})}}static createFileStorage(e,t){return new Mt(t.storage?.basePath||e)}static createApiStorage(e){return new Dn({supabaseClient:Pe.getInstance().getClient(),projectId:e.projectPath||``,enableRetry:e.retry?.retryOnNetworkError,maxRetries:e.retry?.retryAttempts})}static detectOptimalStorage(e){return e.storage?.apiEndpoint&&e.storage?.apiAccessToken?`api`:`file`}static validateStorageConfig(e){let t=[],n=e.storage?.type;if(!n)return t.push(`Storage type is not specified`),{isValid:!1,errors:t};switch(n){case`api`:e.storage?.apiEndpoint||t.push(`API endpoint is required for API storage`),e.storage?.apiAccessToken||t.push(`API access token is required for API storage`);break;case`file`:break;case`auto`:break;default:t.push(`Unknown storage type: ${n}`)}return{isValid:t.length===0,errors:t}}static isHamsterAvailable(e){return!!(e.storage?.apiEndpoint&&e.storage?.apiAccessToken)}static async createWithFallback(t,n){if(e.isHamsterAvailable(t))try{let n=e.createApiStorage(t);return await n.initialize(),n}catch(e){D(`StorageFactory`).warn(`Failed to initialize API storage, falling back to file storage:`,e)}return e.createFileStorage(n,t)}},kn=class e{id;title;description;status;priority;dependencies;details;testStrategy;subtasks;createdAt;updatedAt;effort;actualEffort;tags;assignee;complexity;recommendedSubtasks;expansionPrompt;complexityReasoning;metadata;constructor(e){this.validate(e),this.id=String(e.id),this.title=e.title,this.description=e.description,this.status=e.status,this.priority=e.priority,this.dependencies=(e.dependencies||[]).map(e=>String(e)),this.details=e.details,this.testStrategy=e.testStrategy,this.subtasks=(e.subtasks||[]).map(e=>({...e,id:String(e.id),parentId:String(e.parentId)})),this.createdAt=e.createdAt,this.updatedAt=e.updatedAt,this.effort=e.effort,this.actualEffort=e.actualEffort,this.tags=e.tags,this.assignee=e.assignee,this.complexity=e.complexity,this.recommendedSubtasks=e.recommendedSubtasks,this.expansionPrompt=e.expansionPrompt,this.complexityReasoning=e.complexityReasoning,this.metadata=e.metadata}validate(e){if(e.id===void 0||e.id===null||typeof e.id!=`string`&&typeof e.id!=`number`)throw new T(`Task ID is required and must be a string or number`,w.VALIDATION_ERROR);if(!e.title||e.title.trim().length===0)throw new T(`Task title is required`,w.VALIDATION_ERROR);if(!e.description||e.description.trim().length===0)throw new T(`Task description is required`,w.VALIDATION_ERROR);if(!this.isValidStatus(e.status))throw new T(`Invalid task status: ${e.status}`,w.VALIDATION_ERROR);if(!this.isValidPriority(e.priority))throw new T(`Invalid task priority: ${e.priority}`,w.VALIDATION_ERROR)}isValidStatus(e){return[`pending`,`in-progress`,`done`,`deferred`,`cancelled`,`blocked`,`review`].includes(e)}isValidPriority(e){return[`low`,`medium`,`high`,`critical`].includes(e)}canComplete(){return this.status===`done`||this.status===`cancelled`||this.status===`blocked`?!1:this.subtasks.every(e=>e.status===`done`||e.status===`cancelled`)}markAsComplete(){if(!this.canComplete())throw new T(`Task cannot be marked as complete`,w.TASK_STATUS_ERROR,{taskId:this.id,currentStatus:this.status,hasIncompleteSubtasks:this.subtasks.some(e=>e.status!==`done`&&e.status!==`cancelled`)});this.status=`done`,this.updatedAt=new Date().toISOString()}hasDependencies(){return this.dependencies.length>0}hasSubtasks(){return this.subtasks.length>0}addSubtask(e){let t=this.subtasks.length+1;this.subtasks.push({...e,id:t,parentId:this.id}),this.updatedAt=new Date().toISOString()}updateStatus(e){if(!this.isValidStatus(e))throw new T(`Invalid status: ${e}`,w.VALIDATION_ERROR);if(this.status===`done`&&e===`pending`)throw new T(`Cannot move completed task back to pending`,w.TASK_STATUS_ERROR);this.status=e,this.updatedAt=new Date().toISOString()}toJSON(){return{id:this.id,title:this.title,description:this.description,status:this.status,priority:this.priority,dependencies:this.dependencies,details:this.details,testStrategy:this.testStrategy,subtasks:this.subtasks,createdAt:this.createdAt,updatedAt:this.updatedAt,effort:this.effort,actualEffort:this.actualEffort,tags:this.tags,assignee:this.assignee,complexity:this.complexity,recommendedSubtasks:this.recommendedSubtasks,expansionPrompt:this.expansionPrompt,complexityReasoning:this.complexityReasoning,metadata:this.metadata}}static fromObject(t){return new e(t)}static fromArray(t){return t.map(t=>new e(t))}},An=class{configManager;storage;initialized=!1;logger=D(`TaskService`);constructor(e){this.configManager=e,this.storage=null}async initialize(){if(this.initialized)return;let e=this.configManager.getStorageConfig(),t=this.configManager.getProjectRoot();this.storage=await On.createFromStorageConfig(e,t),await this.storage.initialize(),this.initialized=!0}async getTaskList(e={}){let t=this.configManager.getActiveTag(),n=e.tag||t;try{let t=e.filter?.status&&!e.filter.priority&&!e.filter.tags&&!e.filter.assignee&&!e.filter.search&&e.filter.hasSubtasks===void 0,r={};if(t){let t=Array.isArray(e.filter.status)?e.filter.status:[e.filter.status];t.length===1&&(r.status=t[0])}e.includeSubtasks===!1&&(r.excludeSubtasks=!0);let i=await this.storage.loadTasks(n,r),a={};e.includeSubtasks===!1&&(a.excludeSubtasks=!0);let o=r.status===void 0?i:await this.storage.loadTasks(n,a),s=kn.fromArray(i),c=s;(e.filter&&!t||e.filter?.status&&Array.isArray(e.filter.status)&&e.filter.status.length>1)&&(c=this.applyFilters(s,e.filter));let l=c.map(e=>e.toJSON()),u=this.getStorageType(),d=u===`api`&&this.storage.getCurrentBriefName()||n;return{tasks:l,total:o.length,filtered:c.length,tag:d,storageType:u}}catch(t){throw t instanceof T?t:(this.logger.error(`Failed to get task list`,t),new T(`Failed to get task list`,w.INTERNAL_ERROR,{operation:`getTaskList`,tag:n,hasFilter:!!e.filter},t))}}async getTask(e,t){let n=t||this.getActiveTag();try{return await this.storage.loadTask(String(e),n)}catch(t){throw t instanceof T?t:new T(`Failed to get task ${e}`,w.STORAGE_ERROR,{operation:`getTask`,resource:`task`,taskId:String(e),tag:n},t)}}async getTasksByStatus(e,t){let n=Array.isArray(e)?e:[e];return(await this.getTaskList({tag:t,filter:{status:n}})).tasks}async getTaskStats(e){let t=await this.getTaskList({tag:e,includeSubtasks:!0}),n={total:t.total,byStatus:{},withSubtasks:0,blocked:0,storageType:t.storageType};return[`pending`,`in-progress`,`done`,`deferred`,`cancelled`,`blocked`,`review`].forEach(e=>{n.byStatus[e]=0}),t.tasks.forEach(e=>{n.byStatus[e.status]++,e.subtasks&&e.subtasks.length>0&&n.withSubtasks++,e.status===`blocked`&&n.blocked++}),n}async getNextTask(e){let t=(await this.getTaskList({tag:e,filter:{status:[`pending`,`in-progress`,`done`]}})).tasks,n={critical:4,high:3,medium:2,low:1},r=(e,t)=>typeof t==`string`&&t.includes(`.`)?t:`${e}.${t}`,i=new Set;t.forEach(e=>{e.status===`done`&&i.add(String(e.id)),Array.isArray(e.subtasks)&&e.subtasks.forEach(t=>{t.status===`done`&&i.add(`${e.id}.${t.id}`)})});let a=[];if(t.filter(e=>e.status===`in-progress`&&Array.isArray(e.subtasks)).forEach(e=>{e.subtasks.forEach(t=>{let n=(t.status||`pending`).toLowerCase();if(n!==`pending`&&n!==`in-progress`)return;let o=t.dependencies?.map(t=>r(String(e.id),t))??[];(o.length===0||o.every(e=>i.has(String(e))))&&a.push({id:`${e.id}.${t.id}`,title:t.title||`Subtask ${t.id}`,status:t.status||`pending`,priority:t.priority||e.priority||`medium`,dependencies:o,parentId:String(e.id),description:t.description,details:t.details,testStrategy:t.testStrategy,subtasks:[]})})}),a.length>0)return a.sort((e,t)=>{let r=n[e.priority]??2,i=n[t.priority]??2;if(i!==r)return i-r;if(e.dependencies.length!==t.dependencies.length)return e.dependencies.length-t.dependencies.length;let[a,o]=String(e.id).split(`.`).map(Number),[s,c]=String(t.id).split(`.`).map(Number);return a===s?o-c:a-s}),a[0];let o=t.filter(e=>{let t=(e.status||`pending`).toLowerCase();return t!==`pending`&&t!==`in-progress`?!1:(e.dependencies??[]).every(e=>i.has(String(e)))});return o.length===0?null:o.sort((e,t)=>{let r=n[e.priority]??2,i=n[t.priority]??2;if(i!==r)return i-r;let a=(e.dependencies??[]).length,o=(t.dependencies??[]).length;return a===o?Number(e.id)-Number(t.id):a-o})[0]}applyFilters(e,t){return e.filter(e=>{if(t.status&&!(Array.isArray(t.status)?t.status:[t.status]).includes(e.status)||t.priority&&!(Array.isArray(t.priority)?t.priority:[t.priority]).includes(e.priority)||t.tags&&t.tags.length>0&&(!e.tags||!t.tags.some(t=>e.tags?.includes(t)))||t.assignee&&e.assignee!==t.assignee)return!1;if(t.search){let n=t.search.toLowerCase(),r=e.title.toLowerCase().includes(n),i=e.description.toLowerCase().includes(n),a=e.details.toLowerCase().includes(n);if(!r&&!i&&!a)return!1}return!(t.hasSubtasks!==void 0&&e.subtasks.length>0!==t.hasSubtasks)})}getStorageType(){return this.storage.getStorageType()}getStorage(){return this.storage}getActiveTag(){if(this.initialized&&this.getStorageType()===`api`){let e=this.storage.getCurrentBriefName();if(e)return e}return this.configManager.getActiveTag()}async setActiveTag(e){await this.configManager.setActiveTag(e)}async updateTask(e,t,n){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();let r=n||this.getActiveTag(),i=String(e);try{await this.storage.updateTask(i,t,r)}catch(t){throw t instanceof T?t:new T(`Failed to update task ${e}`,w.STORAGE_ERROR,{operation:`updateTask`,resource:`task`,taskId:i,tag:r},t)}}async updateTaskWithPrompt(e,t,n,r){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();let i=n||this.getActiveTag(),a=String(e);try{await this.storage.updateTaskWithPrompt(a,t,i,r)}catch(n){throw n instanceof T?n:new T(`Failed to update task ${e} with prompt`,w.STORAGE_ERROR,{operation:`updateTaskWithPrompt`,resource:`task`,taskId:a,tag:i,promptLength:t.length},n)}}async expandTaskWithPrompt(e,t,n){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();let r=t||this.getActiveTag(),i=String(e);try{return await this.storage.expandTaskWithPrompt(i,r,n)}catch(t){throw t instanceof T?t:new T(`Failed to expand task ${e}`,w.STORAGE_ERROR,{operation:`expandTaskWithPrompt`,resource:`task`,taskId:i,tag:r,numSubtasks:n?.numSubtasks},t)}}async updateTaskStatus(e,t,n){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);let r=n||this.getActiveTag(),i=String(e);try{return await this.storage.updateTaskStatus(i,t,r)}catch(e){throw e instanceof T?e:new T(`Failed to update task status for ${i}`,w.STORAGE_ERROR,{operation:`updateTaskStatus`,resource:`task`,taskId:i,newStatus:t,tag:r},e)}}async getTagsWithStats(){if(!this.storage)throw new T(`Storage not initialized`,w.STORAGE_ERROR);this.initialized||await this.initialize();try{return await this.storage.getTagsWithStats()}catch(e){throw e instanceof T?e:new T(`Failed to get tags with stats`,w.STORAGE_ERROR,{operation:`getTagsWithStats`,resource:`tags`},e)}}async close(){this.storage&&await this.storage.close(),this.initialized=!1}},jn=class{constructor(e,t=process.cwd()){this.taskService=e,this.projectRoot=t}async startTask(e,t={}){try{let{parentId:n,subtaskId:r}=this.parseTaskId(e);if(!t.force){let t=await this.checkInProgressConflicts(e);if(!t.canProceed)return{task:null,found:!1,started:!1,error:`Conflicting tasks in progress: ${t.conflictingTasks.map(e=>`#${e.id}: ${e.title}`).join(`, `)}`}}let i=await this.taskService.getTask(n);if(!i)return{task:null,found:!1,started:!1,error:`Task ${n} not found`};let a;r&&i.subtasks&&(a=i.subtasks.find(e=>String(e.id)===r));let o=this.normalizeExecutor(t.executor);if(!t.dryRun&&o===`codex`){let e=Zt(this.projectRoot);if(!e.success)return{task:i,found:!0,started:!1,subtaskId:r,subtask:a,error:this.formatCodexPreflightError(e.errors)}}if(t.updateStatus&&!t.dryRun)try{await this.taskService.updateTaskStatus(n,`in-progress`)}catch(e){console.warn(`Could not update task status: ${e instanceof Error?e.message:String(e)}`)}let s=!1,c=`Task ready to execute`,l;return t.dryRun?(s=!0,c=`Dry run - task would be executed`,l=await this.prepareExecutionCommand(i,a,o)):(l=await this.prepareExecutionCommand(i,a,o),s=!!l,c=l?`Command prepared: ${l.executable} ${l.args.join(` `)}`:`Failed to prepare execution command`),{task:i,found:!0,started:s,subtaskId:r,subtask:a,executionOutput:c,command:l||void 0}}catch(e){return{task:null,found:!1,started:!1,error:e instanceof Error?e.message:String(e)}}}formatCodexPreflightError(e){return`Codex execution blocked by permission preflight checks:\n${e.map(e=>`- ${e}`).join(`
|
|
321
|
+
`)}`}async checkInProgressConflicts(e){let t=(await this.taskService.getTaskList()).tasks.filter(e=>e.status===`in-progress`);if(t.find(t=>t.id===e))return{canProceed:!0,conflictingTasks:[]};let n=e.includes(`.`);if(n){let n=e.split(`.`)[0];if(t.find(e=>e.id===n))return{canProceed:!0,conflictingTasks:[]}}let r=t.filter(t=>{if(t.id===e)return!1;if(n){let n=e.split(`.`)[0];if(t.id===n)return!1}if(t.id.toString().includes(`.`)){let r=t.id.toString().split(`.`)[0];if(n&&r===e.split(`.`)[0])return!1}return!0});return r.length>0?{canProceed:!1,conflictingTasks:r,reason:`Other tasks are already in progress`}:{canProceed:!0,conflictingTasks:[]}}async getNextAvailableTask(){return(await this.taskService.getNextTask())?.id||null}parseTaskId(e){if(e.includes(`.`)){let[t,n]=e.split(`.`);return{parentId:t,subtaskId:n}}return{parentId:e}}async canStartTask(e,t=!1){return t?!0:(await this.checkInProgressConflicts(e)).canProceed}async prepareExecutionCommand(e,t,n=`claude`){try{let r=this.formatTaskPrompt(e,t);return{executable:n,args:this.getExecutionArgs(n,r),cwd:this.projectRoot}}catch(e){return console.warn(`Failed to prepare execution command: ${e instanceof Error?e.message:String(e)}`),null}}normalizeExecutor(e){if(!e)return`claude`;let t=e.toLowerCase();return t===`claude`||t===`codex`?t:(console.warn(`Unknown executor "${e}", defaulting to "claude". Supported executors: claude, codex.`),`claude`)}getExecutionArgs(e,t){return[t]}formatTaskPrompt(e,t){let n=t||e,r=t?`Subtask`:`Task`,i=`${r} #${t?`${e.id}.${t.id}`:e.id}: ${n.title}\n\n`;return n.description&&(i+=`Description:\n${n.description}\n\n`),n.details&&(i+=`Implementation Details:\n${n.details}\n\n`),n.testStrategy&&(i+=`Test Strategy:\n${n.testStrategy}\n\n`),e.dependencies&&e.dependencies.length>0&&(i+=`Dependencies: ${e.dependencies.join(`, `)}\n\n`),i+=`Please help me implement this ${r.toLowerCase()}.`,i}async getTaskWithSubtask(e){let{parentId:t,subtaskId:n}=this.parseTaskId(e),r=await this.taskService.getTask(t);return r?n&&r.subtasks?{task:r,subtask:r.subtasks.find(e=>String(e.id)===n),subtaskId:n}:{task:r}:{task:null}}};const Mn=D(`TaskLoader`);var Nn=class{taskService;constructor(e){if(!e)throw Error(`taskService is required for TaskLoaderService`);this.taskService=e}async loadAndValidateTask(e){Mn.info(`Loading task ${e}...`);let t=await this.loadTask(e);if(!t)return{success:!1,errorType:`task_not_found`,errorMessage:`Task with ID "${e}" not found`,suggestion:`Use "task-master list" to see available tasks or verify the task ID is correct.`};let n=this.validateTaskStatus(t);if(!n.success)return n;let r=this.validateSubtasksExist(t);if(!r.success)return r;let i=this.validateSubtaskStructure(t);if(!i.success)return i;let a=this.validateDependencies(t);return a.success?(Mn.info(`Task ${e} validated successfully`),{success:!0,task:t}):a}async loadTask(e){try{return await this.taskService.getTask(e)}catch(t){return Mn.error(`Failed to load task ${e}:`,t),null}}validateTaskStatus(e){return et(e.status)?{success:!1,errorType:`task_completed`,errorMessage:`Task "${e.title}" is already ${e.status}`,suggestion:`Autopilot can only execute tasks that are pending or in-progress. Use a different task.`}:{success:!0}}validateSubtasksExist(e){return!e.subtasks||e.subtasks.length===0?{success:!1,errorType:`no_subtasks`,errorMessage:`Task "${e.title}" has no subtasks`,suggestion:this.buildExpansionSuggestion(e)}:{success:!0}}buildExpansionSuggestion(e){let t=[`Autopilot requires tasks to be broken down into subtasks for execution.`];return t.push(`
|
|
321
322
|
Expand this task using:`),t.push(` task-master expand --id=${e.id}`),e.complexity||e.recommendedSubtasks?(t.push(`
|
|
322
323
|
This task has complexity analysis available. Consider reviewing it first:`),t.push(` task-master show ${e.id}`)):(t.push(`
|
|
323
324
|
Or analyze task complexity first to determine optimal subtask count:`),t.push(` task-master analyze-complexity --from=${e.id}`)),t.join(`
|
|
324
325
|
`)}validateSubtaskStructure(e){for(let t of e.subtasks){if(!t.title||!t.description)return{success:!1,errorType:`invalid_structure`,errorMessage:`Subtask ${e.id}.${t.id} is missing required fields`,suggestion:`Subtasks must have title and description. Re-expand the task or manually fix the subtask structure.`};if(t.dependencies&&!Array.isArray(t.dependencies))return{success:!1,errorType:`invalid_structure`,errorMessage:`Subtask ${e.id}.${t.id} has invalid dependencies format`,suggestion:`Dependencies must be an array. Fix the task structure manually.`}}return{success:!0}}validateDependencies(e){let t=[],n=new Set(e.subtasks.map(e=>String(e.id)));for(let r of e.subtasks){let i=`${e.id}.${r.id}`;if(r.dependencies&&r.dependencies.length>0)for(let e of r.dependencies){let r=String(e);n.has(r)||t.push({subtaskId:i,issueType:`missing`,message:`References non-existent subtask ${r}`,dependencyRef:r})}let a=this.detectCircularDependency(r,e.subtasks,new Set);a&&t.push({subtaskId:i,issueType:`circular`,message:`Circular dependency detected: ${a.join(` -> `)}`})}return t.length>0?{success:!1,errorType:t[0].issueType===`circular`?`circular_dependencies`:`missing_dependencies`,errorMessage:`Task "${e.title}" has dependency issues`,suggestion:`Fix dependency issues manually or re-expand the task:
|
|
325
326
|
`+t.map(e=>` - ${e.subtaskId}: ${e.message}`).join(`
|
|
326
|
-
`),dependencyIssues:t}:{success:!0}}detectCircularDependency(e,t,n){let r=String(e.id);if(n.has(r))return[r];if(n.add(r),e.dependencies&&e.dependencies.length>0)for(let i of e.dependencies){let e=String(i),a=t.find(t=>String(t.id)===e);if(a){let e=this.detectCircularDependency(a,t,new Set(n));if(e)return[r,...e]}}return null}getExecutionOrder(e){let t=[],n=new Set;for(;t.length<e.subtasks.length;){let r=!1;for(let i of e.subtasks){let e=String(i.id);if(!n.has(e)&&(!i.dependencies||i.dependencies.length===0||i.dependencies.every(e=>n.has(String(e))))){t.push(i),n.add(e),r=!0;break}}if(!r&&t.length<e.subtasks.length){
|
|
327
|
-
`).filter(e=>e.length>0).map(e=>e.trim())}catch{return[]}}async function
|
|
328
|
-
`).filter(e=>e.length>0&&!e.includes(`HEAD`)).map(e=>e.replace(/^[^/]+\//,``).trim());return Array.from(new Set(n))}catch{return[]}}async function
|
|
329
|
-
`).filter(Boolean);if(t.length>0){let n=t.includes(`origin`)?`origin`:t[0];try{let{stdout:t}=await L(`git remote show ${n}`,{cwd:e,maxBuffer:10*1024*1024}),r=t.match(/HEAD branch:\s+([^\s]+)/);if(r)return r[1].trim()}catch{}try{let{stdout:t}=await L(`git symbolic-ref refs/remotes/${n}/HEAD`,{cwd:e});return t.replace(`refs/remotes/${n}/`,``).trim()}catch{}}throw Error(`default-branch-not-found`)}catch{let t=[`main`,`master`],n=await
|
|
327
|
+
`),dependencyIssues:t}:{success:!0}}detectCircularDependency(e,t,n){let r=String(e.id);if(n.has(r))return[r];if(n.add(r),e.dependencies&&e.dependencies.length>0)for(let i of e.dependencies){let e=String(i),a=t.find(t=>String(t.id)===e);if(a){let e=this.detectCircularDependency(a,t,new Set(n));if(e)return[r,...e]}}return null}getExecutionOrder(e){let t=[],n=new Set;for(;t.length<e.subtasks.length;){let r=!1;for(let i of e.subtasks){let e=String(i.id);if(!n.has(e)&&(!i.dependencies||i.dependencies.length===0||i.dependencies.every(e=>n.has(String(e))))){t.push(i),n.add(e),r=!0;break}}if(!r&&t.length<e.subtasks.length){Mn.warn(`Could not determine complete execution order for task ${e.id}`);for(let r of e.subtasks)n.has(String(r.id))||t.push(r);break}}return t}async cleanup(){}};const L=pe(de);async function Pn(e){if(!e)throw Error(`projectRoot is required for isGitRepository`);try{return await L(`git rev-parse --git-dir`,{cwd:e}),!0}catch{return!1}}async function Fn(e){if(!e)throw Error(`projectRoot is required for getLocalBranches`);try{let{stdout:t}=await L(`git branch --format="%(refname:short)"`,{cwd:e,maxBuffer:10*1024*1024});return t.trim().split(`
|
|
328
|
+
`).filter(e=>e.length>0).map(e=>e.trim())}catch{return[]}}async function In(e){if(!e)throw Error(`projectRoot is required for getRemoteBranches`);try{let{stdout:t}=await L(`git branch -r --format="%(refname:short)"`,{cwd:e,maxBuffer:10*1024*1024}),n=t.trim().split(`
|
|
329
|
+
`).filter(e=>e.length>0&&!e.includes(`HEAD`)).map(e=>e.replace(/^[^/]+\//,``).trim());return Array.from(new Set(n))}catch{return[]}}async function Ln(e){try{return await L(`gh auth status`,e?{cwd:e}:{}),!0}catch{return!1}}async function Rn(e){if(!e)throw Error(`projectRoot is required for getGitHubRepoInfo`);try{let{stdout:t}=await L(`gh repo view --json name,owner,defaultBranchRef`,{cwd:e});return JSON.parse(t)}catch{return null}}async function zn(e){if(!e)throw Error(`projectRoot is required for getDefaultBranch`);try{if(await Ln(e)){let t=await Rn(e);if(t&&t.defaultBranchRef)return t.defaultBranchRef.name}let t=(await L(`git remote`,{cwd:e})).stdout.trim().split(`
|
|
330
|
+
`).filter(Boolean);if(t.length>0){let n=t.includes(`origin`)?`origin`:t[0];try{let{stdout:t}=await L(`git remote show ${n}`,{cwd:e,maxBuffer:10*1024*1024}),r=t.match(/HEAD branch:\s+([^\s]+)/);if(r)return r[1].trim()}catch{}try{let{stdout:t}=await L(`git symbolic-ref refs/remotes/${n}/HEAD`,{cwd:e});return t.replace(`refs/remotes/${n}/`,``).trim()}catch{}}throw Error(`default-branch-not-found`)}catch{let t=[`main`,`master`],n=await Fn(e),r=await In(e);for(let e of t)if(n.includes(e)||r.includes(e))return e;return null}}const Bn=D(`PreflightChecker`);var Vn=class{projectRoot;constructor(e){if(!e)throw Error(`projectRoot is required for PreflightChecker`);this.projectRoot=e}async detectTestCommand(){try{let e=_(l(this.projectRoot,`package.json`),`utf-8`),t=JSON.parse(e);if(!t.scripts||!t.scripts.test)return{success:!1,message:`No test script found in package.json. Please add a "test" script.`};let n=t.scripts.test;return{success:!0,value:n,message:`Test command: ${n}`}}catch(e){return e.code===`ENOENT`?{success:!1,message:`package.json not found in project root`}:{success:!1,message:`Failed to read package.json: ${e.message}`}}}async checkGitWorkingTree(){try{return await Pn(this.projectRoot)?fe(`git status --porcelain`,{cwd:this.projectRoot,encoding:`utf-8`,timeout:5e3}).trim().length>0?{success:!1,value:`dirty`,message:`Working tree has uncommitted or untracked changes. Please commit or stash them.`}:{success:!0,value:`clean`,message:`Working tree is clean`}:{success:!1,message:`Not a git repository. Initialize git first.`}}catch(e){return{success:!1,message:`Git check failed: ${e.message}`}}}detectProjectTypes(){let e=[];return g(l(this.projectRoot,`package.json`))&&e.push(`node`),(g(l(this.projectRoot,`requirements.txt`))||g(l(this.projectRoot,`setup.py`))||g(l(this.projectRoot,`pyproject.toml`)))&&e.push(`python`),(g(l(this.projectRoot,`pom.xml`))||g(l(this.projectRoot,`build.gradle`)))&&e.push(`java`),g(l(this.projectRoot,`go.mod`))&&e.push(`go`),g(l(this.projectRoot,`Cargo.toml`))&&e.push(`rust`),g(l(this.projectRoot,`composer.json`))&&e.push(`php`),g(l(this.projectRoot,`Gemfile`))&&e.push(`ruby`),te(this.projectRoot).some(e=>e.endsWith(`.csproj`)||e.endsWith(`.sln`))&&e.push(`dotnet`),e}getToolsForProjectType(e){return{node:[{command:`node`,args:[`--version`]},{command:`npm`,args:[`--version`]}],python:[{command:`python3`,args:[`--version`]},{command:`pip3`,args:[`--version`]}],java:[{command:`java`,args:[`--version`]}],go:[{command:`go`,args:[`version`]}],rust:[{command:`cargo`,args:[`--version`]}],php:[{command:`php`,args:[`--version`]},{command:`composer`,args:[`--version`]}],ruby:[{command:`ruby`,args:[`--version`]},{command:`bundle`,args:[`--version`]}],dotnet:[{command:`dotnet`,args:[`--version`]}]}[e]||[]}async validateRequiredTools(){let e=[];e.push(this.checkTool(`git`,[`--version`])),e.push(await this.checkGhCli());let t=this.detectProjectTypes();t.length===0?Bn.warn(`No recognized project type detected`):Bn.info(`Detected project types: ${t.join(`, `)}`);for(let n of t){let t=this.getToolsForProjectType(n);for(let n of t)e.push(this.checkTool(n.command,n.args))}let n=e.every(e=>e.available),r=e.filter(e=>!e.available).map(e=>e.name);return n?{success:!0,value:e,message:`All required tools are available`}:{success:!1,value:e,message:`Missing required tools: ${r.join(`, `)}`}}checkTool(e,t){try{let n=fe(`${e} ${t.join(` `)}`,{cwd:this.projectRoot,encoding:`utf-8`,stdio:`pipe`,timeout:5e3}).trim().split(`
|
|
330
331
|
`)[0];return{name:e,available:!0,version:n,message:`${e} ${n}`}}catch{return{name:e,available:!1,message:`${e} not found`}}}async checkGhCli(){try{return{name:`gh`,available:!0,version:fe(`gh --version`,{cwd:this.projectRoot,encoding:`utf-8`,stdio:`pipe`,timeout:5e3}).trim().split(`
|
|
331
|
-
`)[0],message:await
|
|
332
|
+
`)[0],message:await Ln(this.projectRoot)?`GitHub CLI installed (authenticated)`:`GitHub CLI installed (not authenticated)`}}catch{return{name:`gh`,available:!1,message:`GitHub CLI not found`}}}async detectDefaultBranch(){try{let e=await zn(this.projectRoot);return e?{success:!0,value:e,message:`Default branch: ${e}`}:{success:!1,message:`Could not determine default branch. Make sure remote is configured.`}}catch(e){return{success:!1,message:`Failed to detect default branch: ${e.message}`}}}async runAllChecks(){Bn.info(`Running preflight checks...`);let e=await this.detectTestCommand(),t=await this.checkGitWorkingTree(),n=await this.validateRequiredTools(),r=await this.detectDefaultBranch(),i=e.success&&t.success&&n.success&&r.success,a=[],o=[];e.success?a.push(`Test command`):o.push(`Test command`),t.success?a.push(`Git working tree`):o.push(`Git working tree`),n.success?a.push(`Required tools`):o.push(`Required tools`),r.success?a.push(`Default branch`):o.push(`Default branch`);let s=a.length+o.length,c=i?`All preflight checks passed (${a.length}/${s})`:`Preflight checks failed: ${o.join(`, `)} (${a.length}/${s} passed)`;return Bn.info(c),{success:i,testCommand:e,gitWorkingTree:t,requiredTools:n,defaultBranch:r,summary:c}}};const Hn=[`master`];var Un=class{constructor(e){this.storage=e}validateTagName(e,t=`Tag name`){if(!e||typeof e!=`string`)throw new T(`${t} is required and must be a string`,w.VALIDATION_ERROR);if(e.length>50)throw new T(`${t} must be 50 characters or less`,w.VALIDATION_ERROR,{tagName:e,maxLength:50});if(!/^[a-zA-Z0-9_-]+$/.test(e))throw new T(`${t} can only contain letters, numbers, hyphens, and underscores`,w.VALIDATION_ERROR,{tagName:e});if(Hn.includes(e.toLowerCase()))throw new T(`"${e}" is a reserved tag name`,w.VALIDATION_ERROR,{tagName:e,reserved:!0})}checkTagMutationSupport(e){if(this.storage.getStorageType()===`api`)throw new T(`${e} is not supported with API storage. Use the web interface at Hamster Studio.`,w.NOT_IMPLEMENTED,{storageType:`api`,operation:e})}async createTag(e,t={}){this.validateTagName(e);let n=await this.storage.getAllTags();if(n.includes(e))throw new T(`Tag "${e}" already exists`,w.VALIDATION_ERROR,{tagName:e});if(t.copyFromTag&&!n.includes(t.copyFromTag))throw new T(`Cannot copy from missing tag "${t.copyFromTag}"`,w.NOT_FOUND,{tagName:t.copyFromTag});this.checkTagMutationSupport(`Tag creation`);let r;return t.copyFromTag?r=t.copyFromTag:t.copyFromCurrent&&(r=(await this.storage.getTagsWithStats()).currentTag||void 0),await this.storage.createTag(e,{copyFrom:r,description:t.description}),{name:e,taskCount:0,completedTasks:0,isCurrent:!1,statusBreakdown:{},description:t.description||`Tag created on ${new Date().toLocaleDateString()}`}}async deleteTag(e,t={}){if(this.validateTagName(e),e===`master`)throw new T(`Cannot delete the "master" tag`,w.VALIDATION_ERROR,{tagName:e,protected:!0});if(this.checkTagMutationSupport(`Tag deletion`),!(await this.storage.getAllTags()).includes(e))throw new T(`Tag "${e}" does not exist`,w.NOT_FOUND,{tagName:e});await this.storage.deleteTag(e)}async renameTag(e,t){if(this.validateTagName(e,`Old tag name`),this.validateTagName(t,`New tag name`),e===`master`)throw new T(`Cannot rename the "master" tag`,w.VALIDATION_ERROR,{tagName:e,protected:!0});this.checkTagMutationSupport(`Tag renaming`);let n=await this.storage.getAllTags();if(!n.includes(e))throw new T(`Tag "${e}" does not exist`,w.NOT_FOUND,{tagName:e});if(n.includes(t))throw new T(`Tag "${t}" already exists`,w.VALIDATION_ERROR,{tagName:t});await this.storage.renameTag(e,t)}async copyTag(e,t,n={}){this.validateTagName(e,`Source tag name`),this.validateTagName(t,`Target tag name`),this.checkTagMutationSupport(`Tag copying`);let r=await this.storage.getAllTags();if(!r.includes(e))throw new T(`Source tag "${e}" does not exist`,w.NOT_FOUND,{tagName:e});if(r.includes(t))throw new T(`Target tag "${t}" already exists`,w.VALIDATION_ERROR,{tagName:t});await this.storage.copyTag(e,t)}async getTagsWithStats(){return await this.storage.getTagsWithStats()}},Wn=class{constructor(e,t,n){this.storage=e,this.projectPath=t,this.configManager=n}async generateTaskFiles(e={}){let n=e.tag||this.configManager.getActiveTag(),r=e.outputDir||t.join(this.projectPath,`.taskmaster`,`tasks`);try{await v.mkdir(r,{recursive:!0});let e=await this.storage.loadTasks(n);if(e.length===0)return{success:!0,count:0,directory:r,orphanedFilesRemoved:0};let i=await this.cleanupOrphanedFiles(r,e,n),a={},o=await Promise.allSettled(e.map(async i=>{let a=this.formatTaskContent(i,e),o=this.getTaskFileName(i.id,n),s=t.join(r,o);return await v.writeFile(s,a,`utf-8`),i.id})),s=0;for(let t=0;t<o.length;t++){let n=o[t];if(n.status===`fulfilled`)s++;else{let r=String(e[t].id);a[r]=n.reason?.message||`Unknown error`}}return{success:Object.keys(a).length===0,count:s,directory:r,orphanedFilesRemoved:i,...Object.keys(a).length>0&&{fileErrors:a}}}catch(e){return{success:!1,count:0,directory:r,orphanedFilesRemoved:0,error:e.message}}}getTaskFileName(e,t){let n=String(e).padStart(3,`0`);return t===`master`?`task_${n}.md`:`task_${n}_${t}.md`}escapeRegExp(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}async cleanupOrphanedFiles(e,n,r){let i=0;try{let a=await v.readdir(e),o=n.map(e=>String(e.id)),s=/^task_(\d+)\.md$/,c=RegExp(`^task_(\\d+)_${this.escapeRegExp(r)}\\.md$`),l=[];for(let e of a){let t=null,n=null;if(r===`master`?(t=e.match(s),t&&(n=t[1])):(t=e.match(c),t&&(n=t[1])),n!==null){let t=String(parseInt(n,10));o.includes(t)||l.push(e)}}await Promise.all(l.map(async n=>{let r=t.join(e,n);await v.unlink(r)})),i=l.length}catch{}return i}formatTaskContent(e,t){let n=`# Task ID: ${e.id}\n\n`;if(n+=`**Title:** ${e.title}\n\n`,n+=`**Status:** ${e.status||`pending`}\n\n`,e.dependencies&&e.dependencies.length>0){let r=this.formatDependenciesWithStatus(e.dependencies,t);n+=`**Dependencies:** ${r}\n\n`}else n+=`**Dependencies:** None
|
|
332
333
|
|
|
333
334
|
`;if(n+=`**Priority:** ${e.priority||`medium`}\n\n`,n+=`**Description:** ${e.description||``}\n\n`,n+=`**Details:**
|
|
334
335
|
|
|
@@ -340,6 +341,6 @@ Or analyze task complexity first to determine optimal subtask count:`),t.push(`
|
|
|
340
341
|
|
|
341
342
|
`)}formatSubtaskContent(e,t){let n=`\n### ${t.id}.${e.id}. ${e.title}\n\n`;if(n+=`**Status:** ${e.status||`pending`} \n`,e.dependencies&&e.dependencies.length>0){let r=e.dependencies.map(e=>{let n=String(e);return n.includes(`.`)?n:`${t.id}.${n}`}).join(`, `);n+=`**Dependencies:** ${r} \n`}else n+=`**Dependencies:** None
|
|
342
343
|
`;return n+=`
|
|
343
|
-
`,e.description&&(n+=`${e.description}\n`),e.details&&(n+=`\n**Details:**\n\n${e.details}\n`),n}formatDependenciesWithStatus(e,t){return e.map(e=>{let n=t.find(t=>String(t.id)===String(e));return n?`${e}${this.getStatusSymbol(n.status)}`:String(e)}).join(`, `)}getStatusSymbol(e){switch(e){case`done`:return` ✓`;case`in-progress`:return` ⧖`;case`blocked`:return` ⛔`;case`cancelled`:return` ✗`;case`deferred`:return` ⏸`;default:return``}}},
|
|
344
|
-
`),this.logger.debug(`Saved workflow state (${t.length} bytes)`)}catch(e){throw Error(`Failed to save workflow state: ${e.message}`)}}async createBackup(){try{if(!await this.exists())return;let e=await this.load();await v.mkdir(this.backupDir,{recursive:!0});let n=new Date().toISOString().replace(/[:.]/g,`-`),r=t.join(this.backupDir,`workflow-state-${n}.json`),i={timestamp:new Date().toISOString(),state:e};await v.writeFile(r,JSON.stringify(i,null,2),`utf-8`),await this.pruneBackups()}catch(e){throw Error(`Failed to create backup: ${e.message}`)}}async delete(){try{await v.unlink(this.statePath)}catch(e){if(e.code!==`ENOENT`)throw Error(`Failed to delete workflow state: ${e.message}`)}}async listBackups(){try{return(await v.readdir(this.backupDir)).filter(e=>e.startsWith(`workflow-state-`)&&e.endsWith(`.json`)).sort().reverse()}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to list backups: ${e.message}`)}}async restoreBackup(e){try{let n=t.join(this.backupDir,e),r=await v.readFile(n,`utf-8`),i=JSON.parse(r);await this.save(i.state)}catch(e){throw Error(`Failed to restore backup: ${e.message}`)}}async pruneBackups(){try{let e=await this.listBackups();if(e.length>this.maxBackups){let n=e.slice(this.maxBackups);for(let e of n)await v.unlink(t.join(this.backupDir,e))}}catch(e){this.logger.warn(`Failed to prune backups: ${e.message}`)}}getStatePath(){return this.statePath}getBackupDir(){return this.backupDir}getSessionDir(){return this.sessionDir}getProjectRoot(){return this.projectRoot}getActivityLogPath(){return t.join(this.sessionDir,`activity.jsonl`)}},
|
|
345
|
-
`;await ae.appendFile(e,r,`utf-8`)}const qn=[`workflow:started`,`workflow:completed`,`workflow:error`,`workflow:resumed`,`phase:entered`,`phase:exited`,`tdd:feature-already-implemented`,`tdd:red:started`,`tdd:red:completed`,`tdd:green:started`,`tdd:green:completed`,`tdd:commit:started`,`tdd:commit:completed`,`subtask:started`,`subtask:completed`,`subtask:failed`,`test:run`,`test:passed`,`test:failed`,`git:branch:created`,`git:commit:created`,`error:occurred`,`state:persisted`,`progress:updated`,`adapter:configured`];var Jn=class{activityLogPath;orchestrator;logger=D(`WorkflowActivityLogger`);listenerMap=new Map;isActive=!1;constructor(e,t){this.orchestrator=e,this.activityLogPath=t}start(){if(this.isActive){this.logger.warn(`Activity logger is already active`);return}qn.forEach(e=>{let t=e=>this.logEvent(e);this.listenerMap.set(e,t),this.orchestrator.on(e,t)}),this.isActive=!0,this.logger.debug(`Activity logger started, logging to: ${this.activityLogPath}`)}stop(){this.isActive&&(this.listenerMap.forEach((e,t)=>{this.orchestrator.off(t,e)}),this.listenerMap.clear(),this.isActive=!1,this.logger.debug(`Activity logger stopped and listeners removed`))}async logEvent(e){if(this.isActive)try{let t=e.timestamp instanceof Date?e.timestamp.toISOString():new Date(e.timestamp).toISOString(),n={type:e.type,phase:e.phase,tddPhase:e.tddPhase,subtaskId:e.subtaskId,eventTimestamp:t,...e.data||{}};await Kn(this.activityLogPath,n)}catch(t){this.logger.error(`Failed to log activity event ${e.type}: ${t.message}`)}}getActivityLogPath(){return this.activityLogPath}isLogging(){return this.isActive}},Yn=class{projectRoot;stateManager;taskStatusUpdater;tag;logger=D(`WorkflowService`);orchestrator;activityLogger;constructor(e){typeof e==`string`?this.projectRoot=e:(this.projectRoot=e.projectRoot,this.taskStatusUpdater=e.taskStatusUpdater,this.tag=e.tag),this.stateManager=new Wn(this.projectRoot)}async updateTaskStatus(e,t,n){if(this.taskStatusUpdater)try{await this.taskStatusUpdater.updateStatus(e,t,n??this.tag)}catch(t){let n=t instanceof Error?t.message:String(t);this.logger.warn(`Failed to update task ${e} status: ${n}`)}}async hasWorkflow(){return await this.stateManager.exists()}async startWorkflow(e){let{taskId:t,taskTitle:n,subtasks:r,maxAttempts:i=3,force:a,tag:o,orgSlug:s}=e;if(await this.hasWorkflow()&&!a)throw Error(`Workflow already exists. Use force=true to override or resume existing workflow.`);let c=new _t(this.projectRoot);await c.ensureGitRepository(),await c.ensureCleanWorkingTree();let l=r.map(e=>({id:e.id,title:e.title,status:e.status===`done`?`completed`:`pending`,attempts:0,maxAttempts:e.maxAttempts||i})),u=l.findIndex(e=>e.status!==`completed`);if(u===-1)throw Error(`All subtasks for task ${t} are already completed. Nothing to do.`);this.orchestrator=new Gn({taskId:t,subtasks:l,currentSubtaskIndex:u,tag:o,errors:[],metadata:{startedAt:new Date().toISOString(),taskTitle:n,resumedFromSubtask:u>0?l[u].id:void 0}}),this.orchestrator.enableAutoPersist(async e=>{await this.stateManager.save(e)}),this.activityLogger=new Jn(this.orchestrator,this.stateManager.getActivityLogPath()),this.activityLogger.start(),await this.orchestrator.transition({type:`PREFLIGHT_COMPLETE`});let d=this.generateBranchName(t,n,o,s);return await c.getCurrentBranch()!==d&&await c.createAndCheckoutBranch(d),await this.orchestrator.transition({type:`BRANCH_CREATED`,branchName:d}),await this.updateTaskStatus(t,`in-progress`,o),this.getStatus()}async resumeWorkflow(){let e=await this.stateManager.load();if(this.orchestrator=new Gn(e.context),!this.orchestrator.canResumeFromState(e))throw Error(`Invalid workflow state. State may be corrupted. Consider starting a new workflow.`);return this.orchestrator.restoreState(e),this.orchestrator.enableAutoPersist(async e=>{await this.stateManager.save(e)}),this.activityLogger=new Jn(this.orchestrator,this.stateManager.getActivityLogPath()),this.activityLogger.start(),this.getStatus()}getStatus(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getContext(),t=this.orchestrator.getProgress(),n=this.orchestrator.getCurrentSubtask();return{taskId:e.taskId,phase:this.orchestrator.getCurrentPhase(),tddPhase:this.orchestrator.getCurrentTDDPhase(),branchName:e.branchName,currentSubtask:n?{id:n.id,title:n.title,attempts:n.attempts,maxAttempts:n.maxAttempts||3}:void 0,progress:t}}getContext(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);return this.orchestrator.getContext()}getNextAction(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getCurrentPhase(),t=this.orchestrator.getCurrentTDDPhase(),n=this.orchestrator.getCurrentSubtask();if(e===`COMPLETE`)return{action:`workflow_complete`,description:`All subtasks completed`,nextSteps:`All subtasks completed! Review the entire implementation and merge your branch when ready.`,phase:e};if(e===`FINALIZE`)return{action:`finalize_workflow`,description:`Finalize and complete the workflow`,nextSteps:`All subtasks are complete! Use autopilot_finalize to verify no uncommitted changes remain and mark the workflow as complete.`,phase:e};if(e!==`SUBTASK_LOOP`||!t||!n)return{action:`unknown`,description:`Workflow is not in active state`,nextSteps:`Use autopilot_status to check workflow state.`,phase:e};let r={phase:e,tddPhase:t,subtask:{id:n.id,title:n.title}};switch(t){case`RED`:return{...r,action:`generate_test`,description:`Generate failing test for current subtask`,nextSteps:`Write failing tests for subtask ${n.id}: "${n.title}". Create test file(s) that validate the expected behavior. Run tests and use autopilot_complete_phase with results. Note: If all tests pass (0 failures), the feature is already implemented and the subtask will be auto-completed.`};case`GREEN`:return{...r,action:`implement_code`,description:`Implement feature to make tests pass`,nextSteps:`Implement code to make tests pass for subtask ${n.id}: "${n.title}". Write the minimal code needed to pass all tests (GREEN phase), then use autopilot_complete_phase with test results.`};case`COMMIT`:return{...r,action:`commit_changes`,description:`Commit RED-GREEN cycle changes`,nextSteps:`Review and commit your changes for subtask ${n.id}: "${n.title}". Use autopilot_commit to create the commit and advance to the next subtask.`};default:return{...r,action:`unknown`,description:`Unknown TDD phase`,nextSteps:`Use autopilot_status to check workflow state.`}}}async completePhase(e){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let t=this.orchestrator.getCurrentTDDPhase();if(!t)throw Error(`Not in active TDD phase`);switch(t){case`RED`:await this.orchestrator.transition({type:`RED_PHASE_COMPLETE`,testResults:e});break;case`GREEN`:await this.orchestrator.transition({type:`GREEN_PHASE_COMPLETE`,testResults:e});break;case`COMMIT`:throw Error(`Cannot complete COMMIT phase with test results. Use commit() instead.`);default:throw Error(`Unknown TDD phase: ${t}`)}return this.getStatus()}async commit(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getCurrentTDDPhase();if(e!==`COMMIT`)throw Error(`Cannot commit in ${e} phase. Complete RED and GREEN phases first.`);let t=this.orchestrator.getCurrentSubtask()?.id;await this.orchestrator.transition({type:`COMMIT_COMPLETE`});let n=this.orchestrator.getProgress();if(n.current<n.total?await this.orchestrator.transition({type:`SUBTASK_COMPLETE`}):await this.orchestrator.transition({type:`ALL_SUBTASKS_COMPLETE`}),t){let e=this.orchestrator.getContext();await this.updateTaskStatus(t,`done`,e.tag)}return this.getStatus()}async finalizeWorkflow(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getCurrentPhase();if(e!==`FINALIZE`)throw Error(`Cannot finalize workflow in ${e} phase. Complete all subtasks first.`);let t=await new _t(this.projectRoot).getStatusSummary();if(!t.isClean)throw Error(`Cannot finalize workflow: working tree has uncommitted changes.\nStaged: ${t.staged}, Modified: ${t.modified}, Deleted: ${t.deleted}, Untracked: ${t.untracked}\nPlease commit all changes before finalizing the workflow.`);let n=this.orchestrator.getContext(),r=n.taskId;await this.orchestrator.transition({type:`FINALIZE_COMPLETE`});let i=this.getStatus();return await this.updateTaskStatus(r,`done`,n.tag),await this.stateManager.delete(),this.orchestrator=void 0,i}async abortWorkflow(){this.orchestrator&&await this.orchestrator.transition({type:`ABORT`}),await this.stateManager.delete(),this.orchestrator=void 0}generateBranchName(e,t,n,r){let i=t.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).substring(0,50),a=e.replace(/\./g,`-`),o=r||n;return`${o?`tm/${o}`:`tm`}/task-${a}-${i}`}},Xn=class{workflowService=null;projectRoot;configManager;tasksDomain=null;constructor(e){this.configManager=e,this.projectRoot=e.getProjectRoot()}setTasksDomain(e){this.tasksDomain=e}getWorkflowService(){if(!this.workflowService){let e=this.configManager.getActiveTag(),t=this.tasksDomain?{updateStatus:async(e,t,n)=>{await this.tasksDomain.updateStatus(e,t,n)}}:void 0;this.workflowService=new Yn({projectRoot:this.projectRoot,taskStatusUpdater:t,tag:e})}return this.workflowService}resetWorkflowService(){this.workflowService=null}async start(e){return this.resetWorkflowService(),this.getWorkflowService().startWorkflow(e)}async resume(){return this.resetWorkflowService(),this.getWorkflowService().resumeWorkflow()}getStatus(){return this.getWorkflowService().getStatus()}getContext(){return this.getWorkflowService().getContext()}getNextAction(){return this.getWorkflowService().getNextAction()}async completePhase(e){return this.getWorkflowService().completePhase(e)}async commit(){return this.getWorkflowService().commit()}async finalize(){let e=await this.getWorkflowService().finalizeWorkflow();return this.resetWorkflowService(),e}async abort(){await this.getWorkflowService().abortWorkflow(),this.resetWorkflowService()}async hasWorkflow(){return this.getWorkflowService().hasWorkflow()}},Zn=class e{_projectPath;_configManager;_logger;_tasks;_auth;_workflow;_git;_config;_integration;_loop;_skillRun;get tasks(){return this._tasks}get auth(){return this._auth}get workflow(){return this._workflow}get git(){return this._git}get config(){return this._config}get integration(){return this._integration}get loop(){return this._loop}get skillRun(){return this._skillRun}get logger(){return this._logger}static async create(t){let n=new e(t);return await n.initialize(),n}_options;constructor(e){if(!e.projectPath)throw new T(`Project path is required`,w.MISSING_CONFIGURATION);if(!t.isAbsolute(e.projectPath))throw new T(`Project path must be an absolute path, received: "${e.projectPath}"`,w.INVALID_INPUT);this._projectPath=t.resolve(e.projectPath),this._options=e}async initialize(){try{this._logger=Ee(this._options.loggerConfig),this._configManager=await gt.create(this._projectPath),this._options.configuration&&await this._configManager.updateConfig(this._options.configuration),this._auth=new N,this._tasks=new Un(this._configManager,this._auth),this._workflow=new Xn(this._configManager),this._git=new Tt(this._projectPath),this._config=new lt(this._configManager),this._integration=new Pt(this._configManager),this._loop=new $t(this._configManager),this._skillRun=new pn(this._configManager),await this._tasks.initialize(),this._workflow.setTasksDomain(this._tasks),this._skillRun.setTasksDomain(this._tasks),this._logger.info(`TmCore initialized successfully`)}catch(e){throw this._logger&&this._logger.error(`Failed to initialize TmCore:`,e),new T(`Failed to initialize TmCore`,w.INTERNAL_ERROR,{operation:`initialize`},e)}}get projectPath(){return this._projectPath}async close(){this._tasks&&await this._tasks.close()}};async function Qn(e){return Zn.create(e)}function $n(e,n){try{return m.existsSync(t.join(e,n))}catch{return!1}}function R(e,t){return t.some(t=>$n(e,t))}function er(e=process.cwd()){let n=t.resolve(e),r=t.parse(n).root,i=0,a=null;if(R(n,Ve)||R(n,He))return n;let o=t.dirname(n);for(i=1;i<50;){let e=R(o,Ve),n=R(o,He);if(e&&(n||i===1))return o;if(n&&!e){a=o;break}if(o===r)break;let s=t.dirname(o);if(s===o)break;o=s,i++}for(n=a||t.resolve(e),i=0;i<50;){if(R(n,Ue))return n;if(n===r)break;let e=t.dirname(n);if(e===n)break;n=e,i++}return t.resolve(e)}function tr(e){if(!e)return``;let n=String(e).split(t.sep),r=n.findIndex(e=>e===`.taskmaster`);return r===-1?String(e):n.slice(0,r).join(t.sep)||t.sep}function nr(e){let t=e?r(process.cwd(),e):er();return{projectRoot:t,tasksPath:n(t,Be)}}function rr(e){return he(typeof e==`string`?new Date(e):e,{addSuffix:!0})}function ir(e){return me(e,`hh:mm:ss a`)}function ar(e){if(!e)return e;let t=e.trim();if(/^\d+(\.\d+)?$/.test(t))return t;let n=t.match(/^([a-zA-Z]{3})-?(\d+)$/);return n?`${n[1].toUpperCase()}-${n[2]}`:t}const or=/^\d+$/,sr=/^\d+\.\d+$/,cr=/^[a-zA-Z]{3}-?\d+$/;function lr(e){if(!e)return!1;let t=e.trim();return!!(or.test(t)||sr.test(t)||cr.test(t))}function ur(e){if(!e)return!1;let t=e.trim();return!!(or.test(t)||cr.test(t))}const dr=C.string().trim().refine(lr,{message:`Invalid task ID format. Expected: numeric ("1", "1.2") or prefixed with hyphen ("HAM-1")`}),fr=C.string().trim().refine(lr,{message:`Invalid task ID format. Expected: numeric ("1") or prefixed with hyphen ("HAM-1")`}).refine(ur,{message:`Subtask IDs are not allowed. Please provide a main task ID (e.g., "1", "HAM-1")`}),pr=dr.transform(ar),mr=fr.transform(ar),hr=dr,gr=fr,_r=/^(\d+(\.\d+)*|[A-Za-z]+-?\d+)$/;function vr(e){return _r.test(e)}C.string().min(1,`Task ID cannot be empty`).refine(vr,{message:`Invalid task ID format. Expected numeric (e.g., '15'), subtask (e.g., '15.2'), or display ID (e.g., 'HAM-123')`});const yr=C.string().min(1,`Task ID(s) cannot be empty`).refine(e=>{let t=e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0);return t.length>0&&t.every(vr)},{message:`Invalid task ID format. Expected numeric (e.g., '15'), subtask (e.g., '15.2'), or display ID (e.g., 'HAM-123'). Multiple IDs should be comma-separated.`});function br(e){let t=e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0);if(t.length===0)throw Error(`No valid task IDs provided`);let n=t.filter(e=>!vr(e));if(n.length>0)throw Error(`Invalid task ID format: ${n.join(`, `)}. Expected numeric (e.g., '15'), subtask (e.g., '15.2'), or display ID (e.g., 'HAM-123')`);return t.map(ar)}const xr=D(`TaskFilters`),Sr=[`pending`,`in-progress`,`review`];function Cr(e){let t=new Map(e.map(e=>[String(e.id),[]])),n=[];for(let r of e)for(let e of r.dependencies??[]){let i=String(e),a=t.get(i);a?a.push(String(r.id)):n.push({taskId:String(r.id),depId:i})}return{blocksMap:t,invalidDependencies:n}}function wr(e){let t=new Set(e.filter(e=>et(e.status)).map(e=>String(e.id)));return e.filter(e=>(Qe.includes(e.status)||xr.warn(`Task ${e.id} has unexpected status "${e.status}". Valid statuses are: ${Qe.join(`, `)}`),Sr.includes(e.status)?(e.dependencies??[]).every(e=>t.has(String(e))):!1))}function Tr(e){return e.filter(e=>e.blocks.length>0)}const Er=[{type:`task_count`,threshold:10,message:`Your tasks are growing! Upgrade to Hamster Studio (Multiplayer) for coordinated team action, AI context sharing, and faster shipping.`,promptType:`upgrade_suggestion`,showOnce:!1,cooldownDays:7,priority:80},{type:`tags_used`,threshold:3,message:`Organize by tags? Hamster briefs let you group and collaborate on tagged tasks with your team.`,promptType:`educational_notice`,showOnce:!1,cooldownDays:14,priority:70},{type:`list_count`,threshold:5,message:`Managing multiple projects? Create Hamster briefs to organize work across your team.`,promptType:`educational_notice`,showOnce:!1,cooldownDays:14,priority:50},{type:`dependencies_complex`,threshold:5,message:`Your tasks have complex dependencies. Hamster visualizes these relationships and tracks blockers automatically.`,promptType:`educational_notice`,showOnce:!1,cooldownDays:14,priority:60},{type:`days_active`,threshold:7,message:`Ready to collaborate? Export your tasks to Hamster Studio and start shipping faster with your team.`,promptType:`upgrade_suggestion`,showOnce:!0,priority:90},{type:`export_attempt`,threshold:1,message:`Export to Hamster Studio to enable coordinated team action, AI context sharing, and alignment in hours.`,promptType:`critical_choice`,showOnce:!1,cooldownDays:1,priority:100},{type:`no_connection`,threshold:1,message:`Connect to Hamster Studio to sync your tasks across devices and collaborate with your team.`,promptType:`upgrade_suggestion`,showOnce:!1,cooldownDays:3,priority:75},{type:`parse_prd`,threshold:1,message:`Export your PRD to Hamster for dynamic task generation and team collaboration.`,promptType:`critical_choice`,showOnce:!1,cooldownDays:1,priority:95}],Dr=`1.0.0`,Or=`upgradePrompts`;var kr=class{logger=D(`PromptStateManager`);runtimeStateManager;cachedState=null;constructor(e){this.runtimeStateManager=new ht(e)}async getState(){return this.cachedState||=await this.loadState(),this.cachedState}async loadState(){try{await this.runtimeStateManager.loadState();let e=this.runtimeStateManager.getState().metadata?.[Or];if(e&&typeof e==`object`)return this.validateAndMigrate(e)}catch(e){this.logger.warn(`Failed to load prompt state, using defaults:`,e)}return this.createDefaultState()}createDefaultState(){return{triggers:{},metrics:{totalTaskCount:0,tagCount:0,listCommandCount:0,tasksWithDependencies:0},lastUpdated:new Date().toISOString(),version:Dr}}validateAndMigrate(e){return{triggers:e.triggers||{},metrics:{totalTaskCount:e.metrics?.totalTaskCount||0,tagCount:e.metrics?.tagCount||0,listCommandCount:e.metrics?.listCommandCount||0,tasksWithDependencies:e.metrics?.tasksWithDependencies||0,firstActivityAt:e.metrics?.firstActivityAt,lastActivityAt:e.metrics?.lastActivityAt},lastUpdated:e.lastUpdated||new Date().toISOString(),version:Dr}}async saveState(){if(this.cachedState)try{this.cachedState.lastUpdated=new Date().toISOString(),await this.runtimeStateManager.updateMetadata({[Or]:this.cachedState})}catch(e){throw this.logger.error(`Failed to save prompt state:`,e),e}}async getTriggerState(e){return(await this.getState()).triggers[e]||null}async recordPromptShown(e){let t=await this.getState(),n=new Date().toISOString(),r=t.triggers[e];t.triggers[e]={firstShownAt:r?.firstShownAt||n,lastShownAt:n,showCount:(r?.showCount||0)+1,dismissed:r?.dismissed||!1},await this.saveState()}async recordPromptAction(e,t){let n=await this.getState(),r=new Date().toISOString(),i=n.triggers[e]||{showCount:1,dismissed:!1};n.triggers[e]={...i,action:t,actionAt:r,dismissed:t===`dismissed`},await this.saveState()}async updateMetrics(e){let t=await this.getState(),n=new Date().toISOString();t.metrics.firstActivityAt||(t.metrics.firstActivityAt=n),t.metrics.lastActivityAt=n,Object.assign(t.metrics,e),await this.saveState()}async incrementMetric(e,t=1){let n=await this.getState();n.metrics[e]=(n.metrics[e]||0)+t,n.metrics.firstActivityAt||(n.metrics.firstActivityAt=new Date().toISOString()),n.metrics.lastActivityAt=new Date().toISOString(),await this.saveState()}async getMetrics(){return(await this.getState()).metrics}async isWithinCooldown(e,t){let n=await this.getTriggerState(e);if(!n?.lastShownAt)return!1;let r=new Date(n.lastShownAt),i=t*24*60*60*1e3;return Date.now()-r.getTime()<i}async isDismissed(e){return(await this.getTriggerState(e))?.dismissed||!1}async getDaysActive(){let e=await this.getState();if(!e.metrics.firstActivityAt)return 0;let t=new Date(e.metrics.firstActivityAt),n=Date.now();return Math.floor((n-t.getTime())/(1440*60*1e3))}async reset(){this.cachedState=this.createDefaultState(),await this.saveState()}async resetTrigger(e){let t=await this.getState();delete t.triggers[e],await this.saveState()}},Ar=class{stateManager;config;constructor(e,t){this.stateManager=e,this.config=t||{enabled:!0,triggers:Er,defaultCooldownDays:7,respectDismissed:!0}}async evaluate(e={}){if(!this.config.enabled)return{shouldShow:!1,reason:`Prompts are disabled`};let t=await this.stateManager.getMetrics(),n=await this.stateManager.getDaysActive(),r=[...this.config.triggers].sort((e,t)=>t.priority-e.priority);for(let i of r){let r=await this.evaluateTrigger(i,t,n,e);if(r.shouldShow)return r}return{shouldShow:!1,reason:`No trigger conditions met`}}async evaluateTriggerType(e,t={}){let n=this.config.triggers.find(t=>t.type===e);if(!n)return{shouldShow:!1,reason:`Unknown trigger type: ${e}`};let r=await this.stateManager.getMetrics(),i=await this.stateManager.getDaysActive();return this.evaluateTrigger(n,r,i,t)}async evaluateTrigger(e,t,n,r){if(this.config.respectDismissed&&await this.stateManager.isDismissed(e.type))return{shouldShow:!1,trigger:e,reason:`Prompt was dismissed by user`};let i=e.cooldownDays??this.config.defaultCooldownDays;if(await this.stateManager.isWithinCooldown(e.type,i))return{shouldShow:!1,trigger:e,reason:`Within cooldown period (${i} days)`};if(e.showOnce){let t=await this.stateManager.getTriggerState(e.type);if(t&&t.showCount>0)return{shouldShow:!1,trigger:e,reason:`Prompt already shown (showOnce=true)`}}let a=this.evaluateThreshold(e,t,n,r);return a.met?{shouldShow:!0,trigger:e,reason:a.reason}:{shouldShow:!1,trigger:e,reason:a.reason}}evaluateThreshold(e,t,n,r){switch(e.type){case`task_count`:let i=t.totalTaskCount>=e.threshold;return{met:i,reason:i?`Task count ${t.totalTaskCount} >= ${e.threshold}`:`Task count ${t.totalTaskCount} < ${e.threshold}`};case`tags_used`:let a=t.tagCount>=e.threshold;return{met:a,reason:a?`Tag count ${t.tagCount} >= ${e.threshold}`:`Tag count ${t.tagCount} < ${e.threshold}`};case`list_count`:let o=t.listCommandCount>=e.threshold;return{met:o,reason:o?`List count ${t.listCommandCount} >= ${e.threshold}`:`List count ${t.listCommandCount} < ${e.threshold}`};case`dependencies_complex`:let s=t.tasksWithDependencies>=e.threshold;return{met:s,reason:s?`Tasks with dependencies ${t.tasksWithDependencies} >= ${e.threshold}`:`Tasks with dependencies ${t.tasksWithDependencies} < ${e.threshold}`};case`days_active`:let c=n>=e.threshold;return{met:c,reason:c?`Days active ${n} >= ${e.threshold}`:`Days active ${n} < ${e.threshold}`};case`export_attempt`:let l=r.currentCommand===`export`;return{met:l,reason:l?`User is attempting export`:`Not an export command`};case`no_connection`:let u=!r.isAuthenticated||!r.hasBriefConnected;return{met:u,reason:u?`No Hamster connection detected`:`User is connected to Hamster`};case`parse_prd`:let d=r.currentCommand===`parse-prd`;return{met:d,reason:d?`User is parsing a PRD`:`Not a parse-prd command`};default:return{met:!1,reason:`Unknown trigger type: ${e.type}`}}}getTriggers(){return this.config.triggers}getTrigger(e){return this.config.triggers.find(t=>t.type===e)}isEnabled(){return this.config.enabled}},jr=class{logger=D(`PromptService`);stateManager;evaluator;constructor(e,t){this.stateManager=new kr(e),this.evaluator=new Ar(this.stateManager,t)}async evaluatePrompts(e={}){try{return await this.evaluator.evaluate(e)}catch(e){return this.logger.error(`Error evaluating prompts:`,e),{shouldShow:!1,reason:`Evaluation error: ${e.message}`}}}async evaluateTrigger(e,t={}){try{return await this.evaluator.evaluateTriggerType(e,t)}catch(t){return this.logger.error(`Error evaluating trigger ${e}:`,t),{shouldShow:!1,reason:`Evaluation error: ${t.message}`}}}async recordPromptShown(e){try{await this.stateManager.recordPromptShown(e),this.logger.debug(`Recorded prompt shown: ${e}`)}catch(e){this.logger.error(`Error recording prompt shown:`,e)}}async recordAction(e,t){try{await this.stateManager.recordPromptAction(e,t),this.logger.debug(`Recorded prompt action: ${e} -> ${t}`)}catch(e){this.logger.error(`Error recording prompt action:`,e)}}async updateMetrics(e){try{await this.stateManager.updateMetrics(e)}catch(e){this.logger.error(`Error updating metrics:`,e)}}async incrementMetric(e,t=1){try{await this.stateManager.incrementMetric(e,t)}catch(t){this.logger.error(`Error incrementing metric ${e}:`,t)}}async getMetrics(){return this.stateManager.getMetrics()}async dismissPrompt(e){await this.recordAction(e,`dismissed`)}isEnabled(){return this.evaluator.isEnabled()}getPromptMessage(e){return this.evaluator.getTrigger(e)?.message||null}async reset(){await this.stateManager.reset()}async resetTrigger(e){await this.stateManager.resetTrigger(e)}async syncMetrics(e){let t={};e.taskCount!==void 0&&(t.totalTaskCount=e.taskCount),e.tagCount!==void 0&&(t.tagCount=e.tagCount),e.tasksWithDependencies!==void 0&&(t.tasksWithDependencies=e.tasksWithDependencies),Object.keys(t).length>0&&await this.updateMetrics(t)}static buildContext(e){return{currentCommand:e.command,isAuthenticated:e.isAuthenticated,hasBriefConnected:e.hasBriefConnected,custom:e.custom}}};const Mr=[`add-task`,`analyze-complexity`,`expand-task`,`parse-prd`,`research`,`research-save`,`update-subtask`,`update-task`,`update-tasks`],Nr=`.taskmaster`,Pr=`.taskmaster/tasks`,Fr=`.taskmaster/docs`,Ir=`.taskmaster/reports`,Lr=`.taskmaster/templates`,Rr=`.taskmaster/config.json`,zr=`.taskmaster/state.json`,z=`.taskmasterconfig`,Br=`.taskmaster/reports/task-complexity-report.json`,Vr=`.taskmaster/docs/prd.txt`,Hr=`.taskmaster/templates/example_prd.txt`,Ur=`.taskmaster/tasks/tasks.json`,Wr=`tasks/tasks.json`,Gr=`.env.example`,Kr=`.gitignore`;let qr=!1;const Jr={maxRetries:5,retryDelay:100,staleLockAge:1e4};function Yr(e){if(typeof SharedArrayBuffer<`u`&&typeof Atomics<`u`&&typeof Atomics.wait==`function`)try{let t=new SharedArrayBuffer(4),n=new Int32Array(t);Atomics.wait(n,0,0,e);return}catch{}let t=Date.now()+e;for(;Date.now()<t;);}function Xr(e,t,n={}){let{createIfMissing:r=!1}=n,i=c.dirname(e);if(s.existsSync(i)||s.mkdirSync(i,{recursive:!0}),r)try{s.writeFileSync(e,`{}`,{flag:`wx`})}catch(e){if(e.code!==`EEXIST`)throw e}let a=`${e}.lock`,{maxRetries:o,retryDelay:l,staleLockAge:u}=Jr,d=!1;for(let e=0;e<o;e++)try{let e=JSON.stringify({pid:process.pid,timestamp:Date.now()});s.writeFileSync(a,e,{flag:`wx`}),d=!0;break}catch(t){if(t.code===`EEXIST`){try{let e=s.statSync(a);if(Date.now()-e.mtimeMs>u){let e=`${a}.stale.${process.pid}.${Date.now()}`;try{s.renameSync(a,e);try{s.unlinkSync(e)}catch{}continue}catch{}}}catch(e){if(e.code===`ENOENT`)continue;throw e}e<o-1&&Yr(l*2**e)}else throw t}if(!d)throw Error(`Failed to acquire lock on ${e} after ${o} attempts`);try{return t()}finally{try{s.unlinkSync(a)}catch(t){U(`warn`,`Failed to release lock for ${e}: ${t.message}`)}}}function B(e,t=null,n=null){if(t?.env?.[e])return t.env[e];if(n){let t=c.join(n,`.env`);if(s.existsSync(t))try{let n=s.readFileSync(t,`utf-8`),r=_e.parse(n);if(r&&r[e])return r[e]}catch(e){U(`warn`,`Could not read or parse ${t}: ${e.message}`)}}if(process.env[e])return process.env[e]}function V(e=process.cwd(),t=[`package.json`,`pyproject.toml`,`.git`,z]){let n=c.resolve(e),r=c.parse(n).root;for(;n!==r;){if(t.some(e=>{let t=c.join(n,e);return s.existsSync(t)}))return n;n=c.dirname(n)}return t.some(e=>{let t=c.join(r,e);return s.existsSync(t)})?r:null}const H={debug:0,info:1,warn:2,error:3,success:1};function Zr(){qr=!0}function Qr(){qr=!1}function $r(){return qr}function U(e,...t){if($r())return;let n=`info`;try{n=ta()||`info`}catch{n=`info`}let r={debug:i.gray(`[DEBUG]`),info:i.blue(`[INFO]`),warn:i.yellow(`[WARN]`),error:i.red(`[ERROR]`),success:i.green(`[SUCCESS]`)},a=H.hasOwnProperty(e)?e:`info`;if(H[a]>=(H[n]??H.info)){let e=r[a]||``,n=t.map(e=>typeof e==`object`?JSON.stringify(e):e).join(` `);console.log(`${e} ${n}`)}}function ei(e){if(!e||typeof e!=`object`)return!1;for(let t in e)if(e.hasOwnProperty(t)&&typeof e[t]==`object`&&Array.isArray(e[t].tasks))return!0;return!1}function W(e){Array.isArray(e)&&e.forEach(e=>{if(e.id!==void 0){let t=parseInt(e.id,10);!isNaN(t)&&t>0&&(e.id=t)}Array.isArray(e.subtasks)&&e.subtasks.forEach(e=>{if(e.id!==void 0)if(typeof e.id==`string`&&e.id.includes(`.`)){let t=e.id.split(`.`);e.id=parseInt(t[t.length-1],10)}else{let t=parseInt(e.id,10);!isNaN(t)&&t>0&&(e.id=t)}})})}function ti(t,n=null,r=null){let i=!1;try{i=$()}catch{}if(i&&console.log(`readJSON called with: ${t}, projectRoot: ${n}, tag: ${r}`),!t)return null;let a;try{a=JSON.parse(s.readFileSync(t,`utf8`)),i&&console.log(`Successfully read JSON from ${t}`)}catch(e){return i&&console.log(`Failed to read JSON from ${t}: ${e.message}`),null}if(!t.includes(`tasks.json`)||!a)return i&&console.log(`File is not tasks.json or data is null, returning as-is`),a;if(Array.isArray(a.tasks)&&!a._rawTaggedData&&!ei(a)){i&&console.log(`File is in legacy format, performing migration...`),W(a.tasks);let r={master:{tasks:a.tasks,metadata:a.metadata||{created:new Date().toISOString(),updated:new Date().toISOString(),description:`Tasks for master context`}}};try{if(oi(t,r),i&&console.log(`Successfully migrated legacy format to tagged format`),ni(t),n)try{e(n,t)}catch{}ai(t)}catch(e){i&&console.log(`Error writing migrated data: ${e.message}`)}a=r}if(typeof a==`object`&&!a.tasks){for(let e in i&&console.log(`File is in tagged format, resolving tag...`),a)if(a.hasOwnProperty(e)&&typeof a[e]==`object`&&a[e].tasks)try{Si(a[e],{description:`Tasks for ${e} context`,skipUpdate:!0})}catch(t){i&&console.log(`Failed to ensure metadata for tag ${e}: ${t.message}`)}let o=JSON.parse(JSON.stringify(a));for(let e in o)o[e]&&Array.isArray(o[e].tasks)&&W(o[e].tasks);if(n)try{e(n,t)}catch{}try{let e=`master`;try{if(r)e=r;else if(n)e=yi({projectRoot:n});else{let n=V(c.dirname(t));n&&(e=yi({projectRoot:n}))}}catch(e){i&&console.log(`Tag resolution failed, using master: ${e.message}`)}i&&console.log(`Resolved tag: ${e}`);let s=a[e];if(s&&s.tasks){W(s.tasks);let t={...s,tag:e,_rawTaggedData:o};return i&&console.log(`Returning data for tag '${e}' with ${s.tasks.length} tasks`),t}else{let t=a.master;return t&&t.tasks?(W(t.tasks),i&&console.log(`Tag '${e}' not found, falling back to master with ${t.tasks.length} tasks`),{...t,tag:`master`,_rawTaggedData:o}):(i&&console.log(`No valid tag data found, returning empty structure`),{tasks:[],tag:`master`,_rawTaggedData:o})}}catch(e){i&&console.log(`Error during tag resolution: ${e.message}`);let t=a.master;return t&&t.tasks?(W(t.tasks),{...t,_rawTaggedData:o}):{tasks:[],_rawTaggedData:o}}}return i&&console.log(`File format not recognized, returning as-is`),a}function ni(e){try{let t=V(c.dirname(e))||c.dirname(e),n=c.join(t,`.taskmaster`,`config.json`);s.existsSync(n)&&ri(n);let r=c.join(t,`.taskmaster`,`state.json`);s.existsSync(r)||ii(r),$()&&U(`debug`,`Complete tag migration performed for project: ${t}`)}catch(e){$()&&U(`warn`,`Error during complete tag migration: ${e.message}`)}}function ri(e){try{let t=s.readFileSync(e,`utf8`),n=JSON.parse(t);if(!n)return;let r=!1;n.global||={},n.global.defaultTag||(n.global.defaultTag=`master`,r=!0),r&&(s.writeFileSync(e,JSON.stringify(n,null,2),`utf8`),process.env.TASKMASTER_DEBUG===`true`&&console.log(`[DEBUG] Updated config.json with tagged task system settings`))}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error migrating config.json: ${e.message}`)}}function ii(e){try{let t={currentTag:`master`,lastSwitched:new Date().toISOString(),branchTagMapping:{},migrationNoticeShown:!1};s.writeFileSync(e,JSON.stringify(t,null,2),`utf8`),process.env.TASKMASTER_DEBUG===`true`&&console.log(`[DEBUG] Created initial state.json for tagged task system`)}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error creating state.json: ${e.message}`)}}function ai(e){try{let t=c.dirname(c.dirname(e)),n=c.join(t,`.taskmaster`,`state.json`);s.existsSync(n)||ii(n);try{let e=s.readFileSync(n,`utf8`),t=JSON.parse(e)||{};t.migrationNoticeShown===void 0&&(t.migrationNoticeShown=!1,s.writeFileSync(n,JSON.stringify(t,null,2),`utf8`))}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error updating state for migration notice: ${e.message}`)}}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error marking migration for notice: ${e.message}`)}}function oi(e,t,n=null,r=null){let i=process.env.TASKMASTER_DEBUG===`true`;try{Xr(e,()=>{let a=t;if(t&&!t._rawTaggedData&&n&&Array.isArray(t.tasks)&&!ei(t)){let o=r||vi(n);i&&console.log(`writeJSON: Detected resolved tag data missing _rawTaggedData. Re-reading raw data to prevent data loss for tag '${o}'.`);let c={};try{c=JSON.parse(s.readFileSync(e,`utf8`))}catch(e){i&&console.log(`writeJSON: Could not read existing file, starting fresh: ${e.message}`)}a={...c,[o]:{metadata:{...c[o]?.metadata||{},...t.metadata||{}},tasks:t.tasks}}}else if(t&&t._rawTaggedData&&n){let o=r||vi(n),c;try{c=JSON.parse(s.readFileSync(e,`utf8`))}catch(e){c=t._rawTaggedData,i&&console.log(`writeJSON: Using _rawTaggedData as fallback: ${e.message}`)}let{_rawTaggedData:l,tag:u,...d}=t;a={...c,[o]:d},i&&console.log(`writeJSON: Merging resolved data back into tag '${o}'`)}let o=a;if(o&&typeof o==`object`){let{_rawTaggedData:e,tag:t,...n}=o;if(o=n,typeof o==`object`&&!Array.isArray(o)){let e={};for(let[t,n]of Object.entries(o))if(n&&typeof n==`object`&&Array.isArray(n.tasks)){let{created:r,description:i,...a}=n;a.metadata||={},r&&!a.metadata.created&&(a.metadata.created=r),i&&!a.metadata.description&&(a.metadata.description=i),e[t]=a}else e[t]=n;o=e}}let c=`${e}.tmp.${process.pid}`;try{s.writeFileSync(c,JSON.stringify(o,null,2),`utf8`),s.renameSync(c,e)}catch(e){try{s.existsSync(c)&&s.unlinkSync(c)}catch{}throw e}i&&console.log(`writeJSON: Successfully wrote to ${e}`)},{createIfMissing:!0})}catch(t){throw U(`error`,`Error writing JSON file ${e}:`,t.message),i&&U(`error`,`Full error details:`,t),t}}function si(e=null){let t=!1;try{t=$()}catch{t=!1}try{let n;if(e)n=e;else{let e=c.join(process.cwd(),Br),t=c.join(process.cwd(),`scripts/task-complexity-report.json`);n=s.existsSync(e)?e:t}if(!s.existsSync(n))return t&&U(`debug`,`Complexity report not found at ${n}`),null;let r=ti(n);return t&&U(`debug`,`Successfully read complexity report from ${n}`),r}catch(e){return t&&U(`error`,`Error reading complexity report: ${e.message}`),null}}function ci(e,t){return!e||!e.complexityAnalysis||!Array.isArray(e.complexityAnalysis)?null:e.complexityAnalysis.find(e=>e.taskId===t)}function li(e,t){let n;n=e.isSubtask?e.parentTask.id:e.parentId?e.parentId:e.id;let r=ci(t,n);r&&(e.complexityScore=r.complexityScore)}function ui(e,t){if(!t||!e||!Array.isArray(e))return!1;if(typeof t==`string`&&t.includes(`.`)){let[n,r]=t.split(`.`).map(e=>parseInt(e,10)),i=e.find(e=>e.id===n);return!i||!i.subtasks?!1:i.subtasks.some(e=>e.id===r)}let n=parseInt(t,10);return e.some(e=>e.id===n)}function di(e){return typeof e==`string`&&e.includes(`.`)?e:typeof e==`number`?e.toString():e}function fi(e,t,n=null,r=null){if(!t||!e||!Array.isArray(e))return{task:null,originalSubtaskCount:null};if(typeof t==`string`&&t.includes(`.`)){let[r,i]=t.split(`.`).map(e=>parseInt(e,10)),a=e.find(e=>e.id===r);if(!a||!a.subtasks)return{task:null,originalSubtaskCount:null,originalSubtasks:null};let o=a.subtasks.find(e=>e.id===i);return o&&(o.parentTask={id:a.id,title:a.title,status:a.status},o.isSubtask=!0),o&&n&&li(o,n),{task:o||null,originalSubtaskCount:null,originalSubtasks:null}}let i=null,a=null,o=null,s=parseInt(t,10),c=e.find(e=>e.id===s)||null;if(!c)return{task:null,originalSubtaskCount:null,originalSubtasks:null};if(i=c,r&&c.subtasks&&Array.isArray(c.subtasks)){o=[...c.subtasks],a=c.subtasks.length;let e={...c};e.subtasks=c.subtasks.filter(e=>e.status&&e.status.toLowerCase()===r.toLowerCase()),i=e}return i&&n&&li(i,n),{task:i,originalSubtaskCount:a,originalSubtasks:o}}function pi(e,t){return!e||e.length<=t?e:`${e.slice(0,t-3)}...`}function mi(e){return Array.isArray(e)?e.length===0:typeof e==`object`&&e?Object.keys(e).length===0:!1}function hi(e,t,n=new Set,r=new Set,i=[]){n.add(e),r.add(e),i.push(e);let a=[],o=t.get(e)||[];for(let e of o)if(n.has(e)){if(r.has(e)){let t=i.indexOf(e);i.slice(t),a.push(e)}}else{let o=hi(e,t,n,r,[...i]);a.push(...o)}return r.delete(e),a}function gi(e,t,n={}){let{maxDepth:r=50,includeSelf:i=!1,direction:a=`forward`,logger:o=null}=n,s=new Set,c=new Set;function l(e){if(typeof e==`string`){if(e.includes(`.`))return e;let t=parseInt(e,10);return isNaN(t)?e:t}return e}function u(e,n=0){if(n>=r){let t=`Maximum recursion depth (${r}) reached for task ${e}`;o&&typeof o.warn==`function`?o.warn(t):U!==void 0&&U.warn?U.warn(t):console.warn(t);return}if(c.has(e))return;c.add(e);let a=t.find(t=>t.id===e);!a||!Array.isArray(a.dependencies)||a.dependencies.forEach(t=>{let r=l(t);r==null||!i&&r===e||(s.add(r),u(r,n+1))})}function d(e,n=0){if(n>=r){let t=`Maximum recursion depth (${r}) reached for task ${e}`;o&&typeof o.warn==`function`?o.warn(t):U!==void 0&&U.warn?U.warn(t):console.warn(t);return}c.has(e)||(c.add(e),t.forEach(t=>{if(t.dependencies&&Array.isArray(t.dependencies)&&t.dependencies.some(t=>l(t)===e)){if(t.id==null||!i&&t.id===e)return;s.add(t.id),d(t.id,n+1)}}))}let f=a===`reverse`?d:u;return e.forEach(e=>{e&&e.id&&f(e.id)}),Array.from(s)}function _i(e,t){if(!e||e.length===0)return null;let n={timestamp:new Date().toISOString(),userId:e[0].userId,commandName:t,modelUsed:`Multiple`,providerName:`Multiple`,inputTokens:0,outputTokens:0,totalTokens:0,totalCost:0,currency:e[0].currency||`USD`},r=new Set,i=new Set,a=new Set;return e.forEach(e=>{n.inputTokens+=e.inputTokens||0,n.outputTokens+=e.outputTokens||0,n.totalCost+=e.totalCost||0,r.add(e.modelUsed),i.add(e.providerName),a.add(e.currency||`USD`)}),n.totalTokens=n.inputTokens+n.outputTokens,n.totalCost=parseFloat(n.totalCost.toFixed(6)),r.size===1&&(n.modelUsed=[...r][0]),i.size===1&&(n.providerName=[...i][0]),a.size>1?n.currency=`Multiple`:a.size===1&&(n.currency=[...a][0]),n}function vi(e){if(!e)throw Error(`projectRoot is required for getCurrentTag`);try{let t=c.join(e,`.taskmaster`,`state.json`);if(s.existsSync(t)){let e=s.readFileSync(t,`utf8`),n=JSON.parse(e);if(n&&n.currentTag)return n.currentTag}}catch{}try{let t=c.join(e,`.taskmaster`,`config.json`);if(s.existsSync(t)){let e=s.readFileSync(t,`utf8`),n=JSON.parse(e);if(n&&n.global&&n.global.defaultTag)return n.global.defaultTag}}catch{}return`master`}function yi(e={}){let{projectRoot:t,tag:n}=e;if(!t)throw Error(`projectRoot is required for resolveTag`);return n||vi(t)}function bi(e,t){return!e||!t?[]:e[t]&&e[t].tasks&&Array.isArray(e[t].tasks)?e[t].tasks:[]}function xi(e){let t=[];for(let n of e)if(t.push({...n,searchableId:n.id.toString(),isSubtask:!1}),n.subtasks&&n.subtasks.length>0)for(let e of n.subtasks)t.push({...e,searchableId:`${n.id}.${e.id}`,isSubtask:!0,parentId:n.id,parentTitle:n.title,title:`${e.title} (subtask of: ${n.title})`,description:`${e.description} [Parent: ${n.description}]`});return t}function Si(e,t={}){if(!e||typeof e!=`object`)throw Error(`tagObj must be a valid object`);let n=new Date().toISOString();return e.metadata?(e.metadata.created||(e.metadata.created=n),t.skipUpdate||(e.metadata.updated=n),t.description&&!e.metadata.description&&(e.metadata.description=t.description)):e.metadata={created:n,updated:n,...t.description?{description:t.description}:{}},e}function Ci(){return{info:(e,...t)=>U(`info`,e,...t),warn:(e,...t)=>U(`warn`,e,...t),error:(e,...t)=>U(`error`,e,...t),debug:(e,...t)=>U(`debug`,e,...t),success:(e,...t)=>U(`success`,e,...t)}}function G(e=null){return e||Ci()}function K(e){return tr(e)}function q(e=process.cwd()){return er(e)}function wi(e=null,t=null,n=null){let r=G(n),i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i);if(e){let t=c.isAbsolute(e)?e:c.resolve(a,e);if(s.existsSync(t))return r.info?.(`Using explicit tasks path: ${t}`),t;r.warn?.(`Explicit tasks path not found: ${t}, trying fallbacks`)}let o=[c.join(a,Ur),c.join(a,Wr)];for(let e of o)if(s.existsSync(e))return r.info?.(`Found tasks file at: ${e}`),e.includes(`tasks/tasks.json`)&&!e.includes(`.taskmaster`)?r.warn?.(`⚠️ DEPRECATION WARNING: Found tasks.json in legacy location '${e}'. Please migrate to the new .taskmaster directory structure. Run 'task-master migrate' to automatically migrate your project.`):e.endsWith(`tasks.json`)&&!e.includes(`.taskmaster`)&&!e.includes(`tasks/`)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found tasks.json in legacy root location '${e}'. Please migrate to the new .taskmaster directory structure. Run 'task-master migrate' to automatically migrate your project.`),e;return r.warn?.(`No tasks.json found in project: ${a}`),null}function Ti(e=null,t=null,n=null){let r=G(n);if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);if(s.existsSync(n))return r.info?.(`Using explicit PRD path: ${n}`),n;r.warn?.(`Explicit PRD path not found: ${n}, trying fallbacks`)}let i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i),o=[Fr,`scripts/`,``],l=[`PRD.md`,`prd.md`,`PRD.txt`,`prd.txt`];for(let e of o)for(let t of l){let n=c.join(a,e,t);if(s.existsSync(n))return r.info?.(`Found PRD document at: ${n}`),(e===`scripts/`||e===``)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found PRD file in legacy location '${n}'. Please migrate to .taskmaster/docs/ directory. Run 'task-master migrate' to automatically migrate your project.`),n}return r.warn?.(`No PRD document found in project: ${a}`),null}function Ei(e=null,t=null,n=null){let r=G(n);if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);if(s.existsSync(n))return r.info?.(`Using explicit complexity report path: ${n}`),n;r.warn?.(`Explicit complexity report path not found: ${n}, trying fallbacks`)}let i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i),o=[Ir,`scripts/`,``],l=[`task-complexity-report`,`task-complexity`,`complexity-report`].map(e=>t?.tag&&t?.tag!==`master`?`${e}_${t.tag}.json`:`${e}.json`);for(let e of o)for(let t of l){let n=c.join(a,e,t);if(s.existsSync(n))return r.info?.(`Found complexity report at: ${n}`),(e===`scripts/`||e===``)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found complexity report in legacy location '${n}'. Please migrate to .taskmaster/reports/ directory. Run 'task-master migrate' to automatically migrate your project.`),n}return r.warn?.(`No complexity report found in project: ${a}`),null}function Di(e=null,t=null,n=null){let r=G(n),i=t?.tag;if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);return r.info?.(`Using explicit complexity report output path: ${n}`),n}let a=K(t?.projectRoot||q()||process.cwd()),o=`task-complexity-report.json`;i&&i!==`master`&&(o=`task-complexity-report_${i}.json`);let l=c.join(a,`.taskmaster/reports`,o);r.info?.(`Using tag-aware complexity report output path: ${l}`);let u=c.dirname(l);return s.existsSync(u)||(r.info?.(`Creating reports directory: ${u}`),s.mkdirSync(u,{recursive:!0})),l}function Oi(e=null,t=null,n=null){let r=G(n);if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);if(s.existsSync(n))return r.info?.(`Using explicit config path: ${n}`),n;r.warn?.(`Explicit config path not found: ${n}, trying fallbacks`)}let i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i),o=[c.join(a,Rr),c.join(a,z)];for(let e of o)if(s.existsSync(e))return e?.endsWith(z)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found configuration in legacy location '${e}'. Please migrate to .taskmaster/config.json. Run 'task-master migrate' to automatically migrate your project.`),e;if(!(Ni()||t?.storageType===`api`)){let e=`config_warning_${a}`;global._tmConfigWarningsThisRun||(global._tmConfigWarningsThisRun=new Set),global._tmConfigWarningsThisRun.has(e)||(global._tmConfigWarningsThisRun.add(e),r.warn?.(`No configuration file found in project: ${a}`))}return null}var J={anthropic:[{id:`claude-sonnet-4-20250514`,swe_score:.727,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:64e3,supported:!0},{id:`claude-opus-4-20250514`,swe_score:.725,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`],max_tokens:32e3,supported:!0},{id:`claude-3-7-sonnet-20250219`,swe_score:.623,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:12e4,supported:!0},{id:`claude-3-5-sonnet-20241022`,swe_score:.49,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:8192,supported:!0},{id:`claude-sonnet-4-5`,name:`Claude Sonnet 4.5`,swe_score:.772,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:64e3,supported:!0},{id:`claude-haiku-4-5`,name:`Claude Haiku 4.5`,swe_score:.733,cost_per_1m_tokens:{input:1,output:5},allowed_roles:[`main`,`fallback`],max_tokens:2e5,supported:!0},{id:`claude-opus-4-1`,name:`Claude Opus 4.1`,swe_score:.745,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`],max_tokens:32e3,supported:!0},{id:`claude-opus-4-5`,name:`Claude Opus 4.5`,swe_score:.809,cost_per_1m_tokens:{input:5,output:25},allowed_roles:[`main`,`fallback`],max_tokens:32e3,supported:!0}],"claude-code":[{id:`opus`,swe_score:.725,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32e3,supported:!0},{id:`sonnet`,swe_score:.727,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:64e3,supported:!0},{id:`haiku`,swe_score:.45,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:2e5,supported:!0}],"codex-cli":[{id:`gpt-5.3-codex`,name:`GPT-5.3 Codex`,swe_score:.84,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.2-codex`,name:`GPT-5.2 Codex`,swe_score:.82,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.1-codex-max`,name:`GPT-5.1 Codex Max`,swe_score:.78,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.1-codex-mini`,name:`GPT-5.1 Codex Mini`,swe_score:.72,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`],supported:!0},{id:`gpt-5.2`,name:`GPT-5.2`,swe_score:.8,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0}],mcp:[{id:`mcp-sampling`,swe_score:null,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:1e5,supported:!0}],"gemini-cli":[{id:`gemini-3-flash-preview`,name:`Gemini 3 Flash`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:1048576,supported:!0},{id:`gemini-3-pro-preview`,swe_score:.762,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0},{id:`gemini-2.5-pro`,swe_score:.72,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0},{id:`gemini-2.5-flash`,swe_score:.71,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0}],"grok-cli":[{id:`grok-4-latest`,name:`Grok 4 Latest`,swe_score:.7,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-latest`,name:`Grok 3 Latest`,swe_score:.65,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-fast`,name:`Grok 3 Fast`,swe_score:.6,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-mini-fast`,name:`Grok 3 Mini Fast`,swe_score:.55,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0}],openai:[{id:`gpt-4o`,swe_score:.332,cost_per_1m_tokens:{input:2.5,output:10},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`o1`,swe_score:.489,cost_per_1m_tokens:{input:15,output:60},allowed_roles:[`main`],supported:!0},{id:`o3`,swe_score:.5,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`o3-mini`,swe_score:.493,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`],max_tokens:1e5,supported:!0},{id:`o4-mini`,swe_score:.45,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],supported:!0},{id:`o1-mini`,swe_score:.4,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`],supported:!0},{id:`o1-pro`,swe_score:0,cost_per_1m_tokens:{input:150,output:600},allowed_roles:[`main`],supported:!0},{id:`gpt-4-5-preview`,swe_score:.38,cost_per_1m_tokens:{input:75,output:150},allowed_roles:[`main`],supported:!0},{id:`gpt-4-1-mini`,swe_score:0,cost_per_1m_tokens:{input:.4,output:1.6},allowed_roles:[`main`],supported:!0},{id:`gpt-4-1-nano`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.4},allowed_roles:[`main`],supported:!0},{id:`gpt-4o-mini`,swe_score:.3,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`],supported:!0},{id:`gpt-4o-search-preview`,swe_score:.33,cost_per_1m_tokens:{input:2.5,output:10},allowed_roles:[`research`],supported:!0},{id:`gpt-4o-mini-search-preview`,swe_score:.3,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`research`],supported:!0},{id:`gpt-5`,swe_score:.749,cost_per_1m_tokens:{input:5,output:20},allowed_roles:[`main`,`fallback`],max_tokens:1e5,temperature:1,supported:!0},{id:`gpt-5.1`,swe_score:.76,cost_per_1m_tokens:{input:1.25,output:10},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`],supported:!0},{id:`gpt-5.1-codex-max`,swe_score:.78,cost_per_1m_tokens:{input:1.25,output:10},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.2`,swe_score:.8,cost_per_1m_tokens:{input:1.75,output:14},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.2-pro`,swe_score:.82,cost_per_1m_tokens:{input:21,output:168},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`medium`,`high`,`xhigh`],supported:!0}],google:[{id:`gemini-3-flash-preview`,name:`Gemini 3 Flash`,swe_score:0,cost_per_1m_tokens:{input:.5,output:3},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`gemini-3-pro-preview`,swe_score:.762,cost_per_1m_tokens:{input:2,output:12},allowed_roles:[`main`,`fallback`,`research`],max_tokens:1e6,supported:!0},{id:`gemini-2.5-pro-preview-05-06`,swe_score:.638,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.5-pro-preview-03-25`,swe_score:.638,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.5-flash-preview-04-17`,swe_score:.604,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.0-flash`,swe_score:.518,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.0-flash-lite`,swe_score:0,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0}],xai:[{id:`grok-3`,name:`Grok 3`,swe_score:null,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-fast`,name:`Grok 3 Fast`,swe_score:0,cost_per_1m_tokens:{input:5,output:25},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-4`,name:`Grok 4`,swe_score:null,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0}],groq:[{id:`moonshotai/kimi-k2-instruct`,swe_score:.66,cost_per_1m_tokens:{input:1,output:3},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`llama-3.3-70b-versatile`,swe_score:.55,cost_per_1m_tokens:{input:.59,output:.79},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`llama-3.1-8b-instant`,swe_score:.32,cost_per_1m_tokens:{input:.05,output:.08},allowed_roles:[`main`,`fallback`],max_tokens:131072,supported:!0},{id:`llama-4-scout`,swe_score:.45,cost_per_1m_tokens:{input:.11,output:.34},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`llama-4-maverick`,swe_score:.52,cost_per_1m_tokens:{input:.5,output:.77},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`mixtral-8x7b-32768`,swe_score:.35,cost_per_1m_tokens:{input:.24,output:.24},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!0},{id:`qwen-qwq-32b-preview`,swe_score:.4,cost_per_1m_tokens:{input:.18,output:.18},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`deepseek-r1-distill-llama-70b`,swe_score:.52,cost_per_1m_tokens:{input:.75,output:.99},allowed_roles:[`main`,`research`],max_tokens:8192,supported:!0},{id:`gemma2-9b-it`,swe_score:.3,cost_per_1m_tokens:{input:.2,output:.2},allowed_roles:[`main`,`fallback`],max_tokens:8192,supported:!0},{id:`whisper-large-v3`,swe_score:0,cost_per_1m_tokens:{input:.11,output:0},allowed_roles:[`main`],max_tokens:0,supported:!0}],perplexity:[{id:`sonar-pro`,swe_score:0,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`research`],max_tokens:8700,supported:!0},{id:`sonar`,swe_score:0,cost_per_1m_tokens:{input:1,output:1},allowed_roles:[`research`],max_tokens:8700,supported:!0},{id:`sonar-deep-research`,swe_score:.211,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`research`],max_tokens:8700,supported:!0},{id:`sonar-reasoning-pro`,swe_score:.211,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`research`,`fallback`],max_tokens:8700,supported:!0},{id:`sonar-reasoning`,swe_score:.211,cost_per_1m_tokens:{input:1,output:5},allowed_roles:[`main`,`research`,`fallback`],max_tokens:8700,supported:!0}],openrouter:[{id:`google/gemini-2.5-flash-preview-05-20`,swe_score:0,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`google/gemini-2.5-flash-preview-05-20:thinking`,swe_score:0,cost_per_1m_tokens:{input:.15,output:3.5},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`google/gemini-2.5-pro-exp-03-25`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`deepseek/deepseek-chat-v3-0324:free`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:163840,supported:!1,reason:`Free OpenRouter models are not supported due to severe rate limits, lack of tool use support, and other reliability issues that make them impractical for production use.`},{id:`deepseek/deepseek-chat-v3-0324`,swe_score:0,cost_per_1m_tokens:{input:.27,output:1.1},allowed_roles:[`main`],max_tokens:64e3,supported:!0},{id:`openai/gpt-4.1`,swe_score:0,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`openai/gpt-4.1-mini`,swe_score:0,cost_per_1m_tokens:{input:.4,output:1.6},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`openai/gpt-4.1-nano`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.4},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`openai/o3`,swe_score:0,cost_per_1m_tokens:{input:10,output:40},allowed_roles:[`main`,`fallback`],max_tokens:2e5,supported:!0},{id:`openai/codex-mini`,swe_score:0,cost_per_1m_tokens:{input:1.5,output:6},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/gpt-4o-mini`,swe_score:0,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/o4-mini`,swe_score:.45,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/o4-mini-high`,swe_score:0,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/o1-pro`,swe_score:0,cost_per_1m_tokens:{input:150,output:600},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`meta-llama/llama-3.3-70b-instruct`,swe_score:0,cost_per_1m_tokens:{input:120,output:600},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`meta-llama/llama-4-maverick`,swe_score:0,cost_per_1m_tokens:{input:.18,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`meta-llama/llama-4-scout`,swe_score:0,cost_per_1m_tokens:{input:.08,output:.3},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`qwen/qwen-max`,swe_score:0,cost_per_1m_tokens:{input:1.6,output:6.4},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!0},{id:`qwen/qwen-turbo`,swe_score:0,cost_per_1m_tokens:{input:.05,output:.2},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!0},{id:`qwen/qwen3-235b-a22b`,swe_score:0,cost_per_1m_tokens:{input:.14,output:2},allowed_roles:[`main`,`fallback`],max_tokens:24e3,supported:!0},{id:`mistralai/mistral-small-3.1-24b-instruct:free`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:96e3,supported:!1,reason:`Free OpenRouter models are not supported due to severe rate limits, lack of tool use support, and other reliability issues that make them impractical for production use.`},{id:`mistralai/mistral-small-3.1-24b-instruct`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.3},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`mistralai/devstral-small`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.3},allowed_roles:[`main`],max_tokens:11e4,supported:!0},{id:`mistralai/mistral-nemo`,swe_score:0,cost_per_1m_tokens:{input:.03,output:.07},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`thudm/glm-4-32b:free`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!1,reason:`Free OpenRouter models are not supported due to severe rate limits, lack of tool use support, and other reliability issues that make them impractical for production use.`}],zai:[{id:`glm-4.6`,swe_score:.68,cost_per_1m_tokens:{input:.6,output:2.2},allowed_roles:[`main`,`fallback`,`research`],max_tokens:204800,supported:!0},{id:`glm-4.5`,swe_score:.65,cost_per_1m_tokens:{input:.6,output:2.2},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`glm-4.5-air`,swe_score:.62,cost_per_1m_tokens:{input:.2,output:1.1},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0}],"zai-coding":[{id:`glm-4.6`,swe_score:.68,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:204800,supported:!0},{id:`glm-4.5`,swe_score:.65,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`glm-4.5-air`,swe_score:.62,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0}],ollama:[{id:`gpt-oss:latest`,swe_score:.607,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`gpt-oss:20b`,swe_score:.607,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`gpt-oss:120b`,swe_score:.624,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`devstral:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`qwen3:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`qwen3:14b`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`qwen3:32b`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`mistral-small3.1:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`llama3.3:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`phi4:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0}],azure:[{id:`gpt-4o`,swe_score:.332,cost_per_1m_tokens:{input:2.5,output:10},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`gpt-4o-mini`,swe_score:.3,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`gpt-4-1`,swe_score:0,cost_per_1m_tokens:{input:2,output:10},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`gpt-5`,name:`GPT-5`,swe_score:.749,cost_per_1m_tokens:{input:5,output:20},allowed_roles:[`main`,`fallback`],max_tokens:1e5,temperature:1,supported:!0,api_type:`responses`},{id:`o1`,name:`o1`,swe_score:.489,cost_per_1m_tokens:{input:15,output:60},allowed_roles:[`main`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`o3`,name:`o3`,swe_score:.5,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`o3-mini`,name:`o3-mini`,swe_score:.493,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`o4-mini`,name:`o4-mini`,swe_score:.45,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`gpt-5.1`,name:`GPT-5.1`,swe_score:.76,cost_per_1m_tokens:{input:1.25,output:10},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`],supported:!0,api_type:`responses`},{id:`gpt-5.2`,name:`GPT-5.2`,swe_score:.8,cost_per_1m_tokens:{input:1.75,output:14},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0,api_type:`responses`}],bedrock:[{id:`us.anthropic.claude-3-haiku-20240307-v1:0`,swe_score:.4,cost_per_1m_tokens:{input:.25,output:1.25},allowed_roles:[`main`,`fallback`],supported:!0},{id:`us.anthropic.claude-3-opus-20240229-v1:0`,swe_score:.725,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-3-5-sonnet-20240620-v1:0`,swe_score:.49,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-3-5-sonnet-20241022-v2:0`,swe_score:.49,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-3-7-sonnet-20250219-v1:0`,swe_score:.623,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0},{id:`us.anthropic.claude-3-5-haiku-20241022-v1:0`,swe_score:.4,cost_per_1m_tokens:{input:.8,output:4},allowed_roles:[`main`,`fallback`],supported:!0},{id:`us.anthropic.claude-opus-4-20250514-v1:0`,swe_score:.725,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-sonnet-4-20250514-v1:0`,swe_score:.727,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.deepseek.r1-v1:0`,swe_score:0,cost_per_1m_tokens:{input:1.35,output:5.4},allowed_roles:[`research`],max_tokens:65536,supported:!0}]};const ki=ge(import.meta.url);c.dirname(ki);const Y={models:{main:{provider:`codex-cli`,modelId:`gpt-5.3-codex`,maxTokens:32e3,temperature:.2},research:{provider:`codex-cli`,modelId:`gpt-5.3-codex`,maxTokens:32e3,temperature:.1},fallback:{provider:`codex-cli`,modelId:`gpt-5.3-codex`,maxTokens:32e3,temperature:.2}},global:{logLevel:`info`,debug:!1,defaultNumTasks:10,defaultSubtasks:5,defaultPriority:`medium`,projectName:`Task Master`,ollamaBaseURL:`http://localhost:11434/api`,bedrockBaseURL:`https://bedrock.us-east-1.amazonaws.com`,responseLanguage:`Chinese`,enableCodebaseAnalysis:`auto`,enableProxy:!1,anonymousTelemetry:!0},claudeCode:{},codexCli:{approvalMode:`never`,sandboxMode:`danger-full-access`,fullAuto:!0,skipGitRepoCheck:!0,reasoningEffort:`xhigh`},grokCli:{timeout:12e4,workingDirectory:null,defaultModel:`grok-4-latest`}};let Ai=null,ji=null;function Mi(e){global._tmSuppressConfigWarnings=e}function Ni(){return global._tmSuppressConfigWarnings===!0}var Pi=class extends Error{constructor(e){super(e),this.name=`ConfigurationError`}};function Fi(e=null,t={}){let n=Y,r=e,{storageType:a}=t;e&&`${e}`,r||(r=V(),r||=process.cwd(),`${r}`);let o=null,l={...n};if((s.existsSync(c.join(r,Nr))||s.existsSync(c.join(r,z)))&&(o=Oi(null,{projectRoot:r,storageType:a})),o){let e=o.endsWith(z);try{let t=s.readFileSync(o,`utf-8`),r=JSON.parse(t);l={models:{main:{...n.models.main,...r?.models?.main},research:{...n.models.research,...r?.models?.research},fallback:r?.models?.fallback?.provider&&r?.models?.fallback?.modelId?{...n.models.fallback,...r.models.fallback}:{...n.models.fallback}},global:{...n.global,...r?.global},claudeCode:{...n.claudeCode,...r?.claudeCode},codexCli:{...n.codexCli,...r?.codexCli},grokCli:{...n.grokCli,...r?.grokCli}},`${o}`,e&&console.warn(i.yellow(`⚠️ DEPRECATION WARNING: Found configuration in legacy location '${o}'. Please migrate to .taskmaster/config.json. Run 'task-master migrate' to automatically migrate your project.`)),Ii(l.models.main.provider)||(console.warn(i.yellow(`Warning: Invalid main provider "${l.models.main.provider}" in ${o}. Falling back to default.`)),l.models.main={...n.models.main}),Ii(l.models.research.provider)||(console.warn(i.yellow(`Warning: Invalid research provider "${l.models.research.provider}" in ${o}. Falling back to default.`)),l.models.research={...n.models.research}),l.models.fallback?.provider&&!Ii(l.models.fallback.provider)&&(console.warn(i.yellow(`Warning: Invalid fallback provider "${l.models.fallback.provider}" in ${o}. Fallback model configuration will be ignored.`)),l.models.fallback.provider=void 0,l.models.fallback.modelId=void 0),l.claudeCode&&!mi(l.claudeCode)&&(l.claudeCode=Ri(l.claudeCode)),l.codexCli&&!mi(l.codexCli)&&(l.codexCli=zi(l.codexCli))}catch(e){console.error(i.red(`Error reading or parsing ${o}: ${e.message}. Using default configuration.`)),l={...n},`${o}`}}else{if(!Ni()&&a!==`api`)if(e)console.warn(i.yellow(`Warning: Configuration file not found at provided project root (${e}). Using default configuration. Run 'task-master models --setup' to configure.`));else{let e=s.existsSync(c.join(r,Nr)),t=s.existsSync(c.join(r,z));(e||t)&&console.warn(i.yellow(`Warning: Configuration file not found at derived root (${r}). Using defaults.`))}l={...n},`${r}`}return l}function X(e=null,t=!1,n={}){if(!Ai||t||e&&e!==ji){let r=Fi(e,n);return(t||e)&&(Ai=r,ji=e),r}return Ai}function Ii(e){return Re.includes(e)?!0:Le.includes(e)?!!(J&&J[e]):!1}function Li(e){return J[e]?J[e].filter(e=>e.supported!==!1).map(e=>e.id):[]}function Ri(e){let t=C.object({pathToClaudeCodeExecutable:C.string().optional(),maxTurns:C.number().int().positive().optional(),customSystemPrompt:C.string().optional(),appendSystemPrompt:C.string().optional(),permissionMode:C.enum([`default`,`acceptEdits`,`plan`,`bypassPermissions`]).optional(),allowedTools:C.array(C.string()).optional(),disallowedTools:C.array(C.string()).optional(),mcpServers:C.record(C.string(),C.object({type:C.enum([`stdio`,`sse`]).optional(),command:C.string(),args:C.array(C.string()).optional(),env:C.record(C.string(),C.string()).optional(),url:C.url().optional(),headers:C.record(C.string(),C.string()).optional()})).optional()}),n=C.record(C.string(),t).refine(e=>Object.keys(e||{}).every(e=>Mr.includes(e)),{message:`Invalid command name in commandSpecific`}),r=t.extend({commandSpecific:n.optional()}),a={};try{a=r.parse(e)}catch(e){console.warn(i.yellow(`Warning: Invalid Claude Code settings in config: ${e.message}. Falling back to default.`)),a={}}return a}function zi(e){let t=C.object({codexPath:C.string().optional(),cwd:C.string().optional(),approvalMode:C.enum([`untrusted`,`on-failure`,`on-request`,`never`]).optional(),sandboxMode:C.enum([`read-only`,`workspace-write`,`danger-full-access`]).optional(),fullAuto:C.boolean().optional(),dangerouslyBypassApprovalsAndSandbox:C.boolean().optional(),skipGitRepoCheck:C.boolean().optional(),color:C.enum([`always`,`never`,`auto`]).optional(),allowNpx:C.boolean().optional(),outputLastMessageFile:C.string().optional(),env:C.record(C.string(),C.string()).optional(),verbose:C.boolean().optional(),logger:C.union([C.object({}).passthrough(),C.literal(!1)]).optional(),reasoningEffort:C.enum([`none`,`minimal`,`low`,`medium`,`high`,`xhigh`]).optional()}),n=C.record(C.string(),t).refine(e=>Object.keys(e||{}).every(e=>Mr.includes(e)),{message:`Invalid command name in commandSpecific`}),r=t.extend({commandSpecific:n.optional()});try{return r.parse(e)}catch(e){return console.warn(i.yellow(`Warning: Invalid Codex CLI settings in config: ${e.message}. Falling back to default.`)),{}}}function Bi(e=null,t=!1){let n=X(e,t);return{...Y.claudeCode,...n?.claudeCode||{}}}function Vi(e=null,t=!1){let n=X(e,t);return{...Y.codexCli,...n?.codexCli||{}}}function Hi(e,t=null,n=!1){let r=Vi(t,n),i=r?.commandSpecific||{};return{...r,...i[e]}}function Ui(e,t=null,n=!1){let r=Bi(t,n),i=r?.commandSpecific||{};return{...r,...i[e]}}function Wi(e=null,t=!1){let n=X(e,t);return{...Y.grokCli,...n?.grokCli||{}}}function Gi(e,t=null,n=!1){let r=Wi(t,n),i=r?.commandSpecific||{};return{...r,...i[e]}}function Z(e,t=null){return X(t)?.models?.[e]||(U(`warn`,`No model configuration found for role: ${e}. Returning default.`),Y.models[e]||{})}function Ki(e=null){return Z(`main`,e).provider}function qi(e=null){return Z(`main`,e).modelId}function Ji(e=null){return Z(`research`,e).provider}function Yi(e){if(typeof e==`boolean`)return e?`always`:`never`;if(typeof e==`string`){let t=e.trim().toLowerCase();if(t===`true`||t===`1`||t===`always`||t===`on`||t===`enabled`)return`always`;if(t===`false`||t===`0`||t===`never`||t===`off`||t===`disabled`)return`never`;if(t===`auto`)return`auto`}return`auto`}function Xi(e=null,t=null){let n=B(`TASKMASTER_ENABLE_CODEBASE_ANALYSIS`,e,t);return n!=null&&n!==``?Yi(n):e?.env?.TASKMASTER_ENABLE_CODEBASE_ANALYSIS?Yi(e.env.TASKMASTER_ENABLE_CODEBASE_ANALYSIS):Yi(Q(t).enableCodebaseAnalysis)}function Zi(e=!1,t=null,n=null){if(Xi(n,t)===`never`)return!1;let r=e?Ji(t):Ki(t);return r===j.CLAUDE_CODE||r===j.GEMINI_CLI||r===j.GROK_CLI||r===j.CODEX_CLI}function Qi(e=null){return Z(`research`,e).modelId}function $i(e=null){return Z(`fallback`,e).provider}function ea(e=null){return Z(`fallback`,e).modelId}function Q(e=null){let t=X(e);return{...Y.global,...t?.global||{}}}function ta(e=null){return Q(e).logLevel.toLowerCase()}function $(e=null){return Q(e).debug===!0}function na(e=null){let t=Q(e).defaultSubtasks,n=parseInt(t,10);return Number.isNaN(n)?Y.global.defaultSubtasks:n}function ra(e=null){let t=Q(e).defaultNumTasks,n=parseInt(t,10);return Number.isNaN(n)?Y.global.defaultNumTasks:n}function ia(e=null){return Q(e).defaultPriority}function aa(e=null){return Q(e).projectName}function oa(e=null){return Q(e).ollamaBaseURL}function sa(e=null){return Q(e).azureBaseURL}function ca(e=null){return Q(e).bedrockBaseURL}function la(e=null){return Q(e).vertexProjectId}function ua(e=null){return Q(e).vertexLocation}function da(e=null){return Q(e).responseLanguage}function fa(e=null){return Q(e).enableProxy===!0}function pa(e=null){return Q(e).anonymousTelemetry!==!1}function ma(e=null,t=null){let n=B(`TASKMASTER_ENABLE_PROXY`,e,t);if(n!=null&&n!==``)return n.toLowerCase()===`true`||n===`1`;if(e?.env?.TASKMASTER_ENABLE_PROXY){let t=e.env.TASKMASTER_ENABLE_PROXY;return t.toLowerCase()===`true`||t===`1`}return fa(t)}function ha(e,t=null){let n=Z(e,t),r=n.maxTokens,i=n.temperature,a=n.modelId,o=n.provider,s=r,c=i;try{let e=J[o];if(e&&Array.isArray(e)){let t=e.find(e=>e.id===a);if(t&&typeof t.max_tokens==`number`&&t.max_tokens>0){let e=t.max_tokens;s=Math.min(r,e),U(`debug`,`Applying model-specific max_tokens (${e}) for ${a}. Effective limit: ${s}`)}else U(`debug`,`No valid model-specific max_tokens override found for ${a}. Using role default: ${r}`);t&&typeof t.temperature==`number`&&t.temperature>=0&&t.temperature<=1&&(c=t.temperature,U(`debug`,`Applying model-specific temperature (${t.temperature}) for ${a}`))}else o===j.OPENROUTER?(s=Math.min(r,32768),U(`debug`,`Custom OpenRouter model ${a} detected. Using conservative max_tokens: ${s}`)):U(`debug`,`No model definitions found for provider ${o} in MODEL_MAP. Using role default maxTokens: ${r}`)}catch(e){U(`warn`,`Error looking up model-specific parameters for ${a}: ${e.message}. Using role defaults.`),s=r,c=i}return{maxTokens:s,temperature:c}}function ga(e,t=null,n=null){if([j.OLLAMA,j.BEDROCK,j.GEMINI_CLI,j.GROK_CLI,j.MCP,j.CODEX_CLI].includes(e?.toLowerCase())||e?.toLowerCase()===`claude-code`||e?.toLowerCase()===`codex-cli`)return!0;let r={openai:`OPENAI_API_KEY`,anthropic:`ANTHROPIC_API_KEY`,google:`GOOGLE_API_KEY`,perplexity:`PERPLEXITY_API_KEY`,mistral:`MISTRAL_API_KEY`,azure:`AZURE_OPENAI_API_KEY`,openrouter:`OPENROUTER_API_KEY`,xai:`XAI_API_KEY`,zai:`ZAI_API_KEY`,"zai-coding":`ZAI_API_KEY`,groq:`GROQ_API_KEY`,vertex:`GOOGLE_API_KEY`,"claude-code":`CLAUDE_CODE_API_KEY`,bedrock:`AWS_ACCESS_KEY_ID`},i=e?.toLowerCase();if(!i||!r[i])return U(`warn`,`Unknown provider name: ${e} in isApiKeySet check.`),!1;let a=r[i],o=B(a,t,n);return o&&o.trim()!==``&&!/YOUR_.*_API_KEY_HERE/.test(o)&&!o.includes(`KEY_HERE`)}function _a(e,t=null){let n=t||V();if(!n)return console.warn(i.yellow(`Warning: Could not find project root to check mcp.json.`)),!1;let r=c.join(n,`.cursor`,`mcp.json`);if(!s.existsSync(r))return!1;try{let t=s.readFileSync(r,`utf-8`),n=JSON.parse(t),i=n?.mcpServers?.[`task-master-ai`]?.env||n?.mcpServers?.[`taskmaster-ai`]?.env;if(!i)return!1;let a=null;switch(e){case`anthropic`:a=i.ANTHROPIC_API_KEY;break;case`openai`:a=i.OPENAI_API_KEY;break;case`openrouter`:a=i.OPENROUTER_API_KEY;break;case`google`:a=i.GOOGLE_API_KEY;break;case`perplexity`:a=i.PERPLEXITY_API_KEY;break;case`xai`:a=i.XAI_API_KEY;break;case`zai`:case`zai-coding`:a=i.ZAI_API_KEY;break;case`groq`:a=i.GROQ_API_KEY;break;case`ollama`:return!0;case`claude-code`:return!0;case`codex-cli`:return!0;case`mistral`:a=i.MISTRAL_API_KEY;break;case`azure`:a=i.AZURE_OPENAI_API_KEY;break;case`vertex`:a=i.GOOGLE_API_KEY;break;case`bedrock`:a=i.AWS_ACCESS_KEY_ID;break;default:return!1}return!!a&&!/KEY_HERE$/.test(a)}catch(e){return console.error(i.red(`Error reading or parsing .cursor/mcp.json: ${e.message}`)),!1}}function va(){let e=[];for(let[t,n]of Object.entries(J))n.length>0?n.filter(e=>!!e.supported).forEach(n=>{let r=n.id,i=n.swe_score,a=n.cost_per_1m_tokens,o=n.allowed_roles||[`main`,`fallback`],s=n.name;s||(s=r.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `),r===`claude-3.5-sonnet-20240620`&&(s=`Claude 3.5 Sonnet`),r===`claude-3-7-sonnet-20250219`&&(s=`Claude 3.7 Sonnet`),r===`gpt-4o`&&(s=`GPT-4o`),r===`gpt-4-turbo`&&(s=`GPT-4 Turbo`),r===`sonar-pro`&&(s=`Perplexity Sonar Pro`),r===`sonar-mini`&&(s=`Perplexity Sonar Mini`)),e.push({id:r,name:s,provider:t,swe_score:i,cost_per_1m_tokens:a,allowed_roles:o,max_tokens:n.max_tokens})}):e.push({id:`[${t}-any]`,name:`Any (${t})`,provider:t});return e}function ya(e,t=null){let n=t;if(t==null){let e=V();if(!e)return console.error(i.red(`Error: Could not determine project root. Configuration not saved.`)),!1;n=e}let r=c.join(n,`.taskmaster`),a=c.join(r,`config.json`);try{return s.existsSync(r)||s.mkdirSync(r,{recursive:!0}),s.writeFileSync(a,JSON.stringify(e,null,2)),Ai=e,!0}catch(e){return console.error(i.red(`Error writing configuration to ${a}: ${e.message}`)),!1}}function ba(e=null){return Oi(null,{projectRoot:e})!==null}function xa(e=null){let t=X(e);return t.global||={},t.global.userId||(t.global.userId=`1234567890`,ya(t,e)||U(`warning`,`Failed to write updated configuration with new userId. Please let the developers know.`)),t.global.userId}function Sa(){return ze}function Ca(e,t=null){let n=Z(e,t);if(n&&typeof n.baseURL==`string`)return n.baseURL;let r=n?.provider;if(r)return B(`${r.toUpperCase()}_BASE_URL`,null,t)}async function wa(e){if(e===`solo`||e===`team`)return e;try{Mi(!0);let e=X(null,!1,{storageType:`api`});if(e?.storage?.operatingMode)return e.storage.operatingMode}catch{}finally{Mi(!1)}try{if(await M.getInstance().getAuthCredentials())return`team`}catch{}return`solo`}j.OLLAMA,j.BEDROCK,j.GEMINI_CLI,j.GROK_CLI,j.MCP,j.CODEX_CLI;export{wi as $,yr as $t,fa as A,pi as At,ba as B,Rr as Bt,qi as C,Le as Cn,ni as Ct,wa as D,ve as Dn,yi as Dt,oa as E,O as En,B as Et,xa as F,Hr as Ft,zi as G,Pr as Gt,ma as H,Fr as Ht,ua as I,Kr as It,J,jr as Jt,Ii as K,Ur as Kt,la as L,z as Lt,Ji as M,oi as Mt,da as N,Br as Nt,ha as O,be as On,ui as Ot,Li as P,Gr as Pt,q as Q,br as Qt,Zi as R,Wr as Rt,ta as S,Re as Sn,W as St,_a as T,k as Tn,ti as Tt,Mi as U,Ir as Ut,Ni as V,Nr as Vt,Ri as W,zr as Wt,Oi as X,Tr as Xt,Ei as Y,Cr as Yt,Ti as Z,wr as Zt,na as _,nt as _n,mi as _t,sa as a,rr as an,ii as at,Wi as b,ze as bn,ai as bt,Bi as c,er as cn,Si as ct,Vi as d,Mt as dn,fi as dt,mr as en,K as et,Hi as f,wt as fn,ci as ft,ia as g,tt as gn,bi as gt,ra as h,M as hn,vi as ht,va as i,ar as in,_i as it,Qi as j,Xr as jt,aa as k,ye as kn,gi as kt,Ui as l,Qn as ln,hi as lt,$ as m,N as mn,di as mt,Sa as n,pr as nn,H as nt,Ca as o,ir as on,Qr as ot,X as p,_t as pn,xi as pt,ya as q,Lr as qt,pa as r,hr as rn,li as rt,ca as s,nr as sn,Zr as st,Pi as t,gr as tn,Di as tt,Xi as u,It as un,V as ut,ea as v,Qe as vn,$r as vt,Ki as w,ke as wn,si as wt,Gi as x,j as xn,ri as xt,$i as y,et as yn,U as yt,ga as z,Vr as zt};
|
|
344
|
+
`,e.description&&(n+=`${e.description}\n`),e.details&&(n+=`\n**Details:**\n\n${e.details}\n`),n}formatDependenciesWithStatus(e,t){return e.map(e=>{let n=t.find(t=>String(t.id)===String(e));return n?`${e}${this.getStatusSymbol(n.status)}`:String(e)}).join(`, `)}getStatusSymbol(e){switch(e){case`done`:return` ✓`;case`in-progress`:return` ⧖`;case`blocked`:return` ⛔`;case`cancelled`:return` ✗`;case`deferred`:return` ⏸`;default:return``}}},Gn=class{taskService;executionService;loaderService;preflightChecker;briefsDomain;tagService;taskFileGenerator;projectRoot;configManager;constructor(e,t){this.projectRoot=e.getProjectRoot(),this.configManager=e,this.taskService=new An(e),this.executionService=new jn(this.taskService,this.projectRoot),this.loaderService=new Nn(this.taskService),this.preflightChecker=new Vn(this.projectRoot),this.briefsDomain=new vn}async initialize(){await this.taskService.initialize(),this.tagService=new Un(this.taskService.getStorage()),this.taskFileGenerator=new Wn(this.taskService.getStorage(),this.projectRoot,this.configManager)}async list(e){return this.taskService.getTaskList(e)}async get(e,t){let n=e.split(`.`),r=n[0],i=n[1],a=await this.taskService.getTask(r,t);if(!a)return{task:null,isSubtask:!1};if(i&&a.subtasks){let e=a.subtasks.find(e=>String(e.id)===i);return e?{task:e,isSubtask:!0}:{task:null,isSubtask:!0}}return{task:a,isSubtask:!1}}async getByStatus(e,t){return this.taskService.getTasksByStatus(e,t)}async getStats(e){return this.taskService.getTaskStats(e)}async getNext(e){return this.taskService.getNextTask(e)}async getCount(e,t){let n=await this.list({tag:t}),r=0;for(let t of n.tasks)if(t.status===e&&r++,t.subtasks&&t.subtasks.length>0)for(let n of t.subtasks)(n.status===e||e===`pending`&&!n.status)&&r++;return r}async update(e,t,n){return this.taskService.updateTask(e,t,n)}async updateWithPrompt(e,t,n,r){return this.taskService.updateTaskWithPrompt(e,t,n,r)}async expand(e,t,n){return this.taskService.expandTaskWithPrompt(e,t,n)}async updateStatus(e,t,n){return this.taskService.updateTaskStatus(e,t,n)}async setActiveTag(e){return this.taskService.setActiveTag(e)}async resolveBrief(e,t){return this.briefsDomain.resolveBrief(e,t)}async switchTag(e){this.taskService.getStorageType()===`file`?await this.setActiveTag(e):await this.briefsDomain.switchBrief(e)}async start(e,t){return this.executionService.startTask(e,t)}async checkInProgressConflicts(e){return this.executionService.checkInProgressConflicts(e)}async getNextAvailable(){return this.executionService.getNextAvailableTask()}async canStart(e,t){return this.executionService.canStartTask(e,t)}async loadAndValidate(e){return this.loaderService.loadAndValidateTask(e)}getExecutionOrder(e){return this.loaderService.getExecutionOrder(e)}async runPreflightChecks(){return this.preflightChecker.runAllChecks()}async detectTestCommand(){return this.preflightChecker.detectTestCommand()}async checkGitWorkingTree(){return this.preflightChecker.checkGitWorkingTree()}async validateRequiredTools(){return this.preflightChecker.validateRequiredTools()}async detectDefaultBranch(){return this.preflightChecker.detectDefaultBranch()}async createTag(e,t){return this.tagService.createTag(e,t)}async deleteTag(e,t){return this.tagService.deleteTag(e,t)}async renameTag(e,t){return this.tagService.renameTag(e,t)}async copyTag(e,t,n){return this.tagService.copyTag(e,t,n)}async getTagsWithStats(){return this.tagService.getTagsWithStats()}getStorageType(){return this.taskService.getStorageType()}async watch(e,t){return this.taskService.getStorage().watch(e,t)}async generateTaskFiles(e){return this.getStorageType()===`api`?{success:!1,count:0,directory:``,orphanedFilesRemoved:0,error:`Task file generation is only available for local file storage. API storage manages tasks in the cloud.`}:this.taskFileGenerator.generateTaskFiles(e)}async close(){await this.taskService.close()}},Kn=class{projectRoot;statePath;backupDir;sessionDir;maxBackups;logger=D(`WorkflowStateManager`);writer=null;writerInitPromise=null;constructor(e,n=5){this.projectRoot=t.resolve(e),this.maxBackups=n;let r=this.getProjectIdentifier(this.projectRoot),i=ue.homedir(),a=t.join(i,`.taskmaster`,r);this.sessionDir=t.join(a,`sessions`),this.statePath=t.join(this.sessionDir,`workflow-state.json`),this.backupDir=t.join(this.sessionDir,`backups`)}getProjectIdentifier(e){return`-`+t.resolve(e).replace(/^\//,``).replace(/[^a-zA-Z0-9]+/g,`-`).replace(/-+/g,`-`).replace(/-+$/,``)}async ensureWriter(){if(!this.writer){if(this.writerInitPromise){await this.writerInitPromise;return}this.writerInitPromise=(async()=>{await v.mkdir(this.sessionDir,{recursive:!0}),this.writer=new d(this.statePath)})(),await this.writerInitPromise,this.writerInitPromise=null}}async exists(){try{return await v.access(this.statePath),!0}catch{return!1}}async load(){try{let e=await v.readFile(this.statePath,`utf-8`);return JSON.parse(e)}catch(e){throw e.code===`ENOENT`?Error(`Workflow state file not found at ${this.statePath}`):Error(`Failed to load workflow state: ${e.message}`)}}async save(e){try{await this.ensureWriter();let t=JSON.stringify(e,null,2);try{JSON.parse(t)}catch{throw this.logger.error(`Generated invalid JSON:`,t),Error(`Failed to generate valid JSON from workflow state`)}await this.writer.write(t+`
|
|
345
|
+
`),this.logger.debug(`Saved workflow state (${t.length} bytes)`)}catch(e){throw Error(`Failed to save workflow state: ${e.message}`)}}async createBackup(){try{if(!await this.exists())return;let e=await this.load();await v.mkdir(this.backupDir,{recursive:!0});let n=new Date().toISOString().replace(/[:.]/g,`-`),r=t.join(this.backupDir,`workflow-state-${n}.json`),i={timestamp:new Date().toISOString(),state:e};await v.writeFile(r,JSON.stringify(i,null,2),`utf-8`),await this.pruneBackups()}catch(e){throw Error(`Failed to create backup: ${e.message}`)}}async delete(){try{await v.unlink(this.statePath)}catch(e){if(e.code!==`ENOENT`)throw Error(`Failed to delete workflow state: ${e.message}`)}}async listBackups(){try{return(await v.readdir(this.backupDir)).filter(e=>e.startsWith(`workflow-state-`)&&e.endsWith(`.json`)).sort().reverse()}catch(e){if(e.code===`ENOENT`)return[];throw Error(`Failed to list backups: ${e.message}`)}}async restoreBackup(e){try{let n=t.join(this.backupDir,e),r=await v.readFile(n,`utf-8`),i=JSON.parse(r);await this.save(i.state)}catch(e){throw Error(`Failed to restore backup: ${e.message}`)}}async pruneBackups(){try{let e=await this.listBackups();if(e.length>this.maxBackups){let n=e.slice(this.maxBackups);for(let e of n)await v.unlink(t.join(this.backupDir,e))}}catch(e){this.logger.warn(`Failed to prune backups: ${e.message}`)}}getStatePath(){return this.statePath}getBackupDir(){return this.backupDir}getSessionDir(){return this.sessionDir}getProjectRoot(){return this.projectRoot}getActivityLogPath(){return t.join(this.sessionDir,`activity.jsonl`)}},qn=class{currentPhase;context;transitions;eventListeners;persistCallback;autoPersistEnabled=!1;phaseGuards;aborted=!1;testResultValidator;gitOperationHook;executeHook;constructor(e){this.currentPhase=`PREFLIGHT`,this.context={...e},this.transitions=this.defineTransitions(),this.eventListeners=new Map,this.phaseGuards=new Map}defineTransitions(){return[{from:`PREFLIGHT`,to:`BRANCH_SETUP`,event:`PREFLIGHT_COMPLETE`},{from:`BRANCH_SETUP`,to:`SUBTASK_LOOP`,event:`BRANCH_CREATED`},{from:`SUBTASK_LOOP`,to:`FINALIZE`,event:`ALL_SUBTASKS_COMPLETE`},{from:`FINALIZE`,to:`COMPLETE`,event:`FINALIZE_COMPLETE`}]}getCurrentPhase(){return this.currentPhase}getCurrentTDDPhase(){if(this.currentPhase===`SUBTASK_LOOP`)return this.context.currentTDDPhase||`RED`}getContext(){return{...this.context}}async transition(e){if(this.aborted&&e.type!==`ABORT`)throw Error(`Workflow has been aborted`);if(e.type===`ERROR`){this.handleError(e.error),await this.triggerAutoPersist();return}if(e.type===`ABORT`){this.aborted=!0,await this.triggerAutoPersist();return}if(e.type===`RETRY`){this.handleRetry(),await this.triggerAutoPersist();return}if(this.currentPhase===`SUBTASK_LOOP`){await this.handleTDDPhaseTransition(e),await this.triggerAutoPersist();return}let t=this.transitions.find(t=>t.from===this.currentPhase&&t.event===e.type);if(!t)throw Error(`Invalid transition: ${e.type} from ${this.currentPhase}`);this.executeTransition(t,e),await this.triggerAutoPersist()}async handleTDDPhaseTransition(e){let t=this.context.currentTDDPhase||`RED`;switch(e.type){case`RED_PHASE_COMPLETE`:if(t!==`RED`)throw Error(`Invalid transition: RED_PHASE_COMPLETE from non-RED phase`);if(!e.testResults)throw Error(`Test results required for RED phase transition`);if(this.context.lastTestResults=e.testResults,e.testResults.failed===0){this.emit(`tdd:red:completed`),this.emit(`tdd:feature-already-implemented`,{subtaskId:this.getCurrentSubtaskId(),testResults:e.testResults});let t=this.context.subtasks[this.context.currentSubtaskIndex];t&&(t.status=`completed`),this.emit(`subtask:completed`),this.context.currentSubtaskIndex++;let n=this.getProgress();this.emit(`progress:updated`,{completed:n.completed,total:n.total,percentage:n.percentage}),this.context.currentSubtaskIndex<this.context.subtasks.length?(this.context.currentTDDPhase=`RED`,this.emit(`tdd:red:started`),this.emit(`subtask:started`)):await this.transition({type:`ALL_SUBTASKS_COMPLETE`});break}this.emit(`tdd:red:completed`),this.context.currentTDDPhase=`GREEN`,this.emit(`tdd:green:started`);break;case`GREEN_PHASE_COMPLETE`:if(t!==`GREEN`)throw Error(`Invalid transition: GREEN_PHASE_COMPLETE from non-GREEN phase`);if(!e.testResults)throw Error(`Test results required for GREEN phase transition`);if(e.testResults.failed!==0)throw Error(`GREEN phase must have zero failures`);this.context.lastTestResults=e.testResults,this.emit(`tdd:green:completed`),this.context.currentTDDPhase=`COMMIT`,this.emit(`tdd:commit:started`);break;case`COMMIT_COMPLETE`:if(t!==`COMMIT`)throw Error(`Invalid transition: COMMIT_COMPLETE from non-COMMIT phase`);this.emit(`tdd:commit:completed`);let n=this.context.subtasks[this.context.currentSubtaskIndex];n&&(n.status=`completed`);break;case`SUBTASK_COMPLETE`:this.emit(`subtask:completed`),this.context.currentSubtaskIndex++;let r=this.getProgress();this.emit(`progress:updated`,{completed:r.completed,total:r.total,percentage:r.percentage}),this.context.currentSubtaskIndex<this.context.subtasks.length?(this.context.currentTDDPhase=`RED`,this.emit(`tdd:red:started`),this.emit(`subtask:started`)):await this.transition({type:`ALL_SUBTASKS_COMPLETE`});break;case`ALL_SUBTASKS_COMPLETE`:this.emit(`phase:exited`),this.currentPhase=`FINALIZE`,this.context.currentTDDPhase=void 0,this.emit(`phase:entered`);break;default:throw Error(`Invalid transition: ${e.type} in SUBTASK_LOOP`)}}executeTransition(e,t){if(e.guard&&!e.guard(this.context))throw Error(`Guard condition failed for transition to ${e.to}`);let n=this.phaseGuards.get(e.to);if(n&&!n(this.context))throw Error(`Guard condition failed`);this.emit(`phase:exited`),this.updateContext(t),this.currentPhase=e.to,this.emit(`phase:entered`),this.currentPhase===`SUBTASK_LOOP`&&(this.context.currentTDDPhase=`RED`,this.emit(`tdd:red:started`),this.emit(`subtask:started`))}updateContext(e){switch(e.type){case`BRANCH_CREATED`:this.context.branchName=e.branchName,this.emit(`git:branch:created`,{branchName:e.branchName}),this.gitOperationHook&&this.gitOperationHook(`branch:created`,{branchName:e.branchName});break;case`ERROR`:this.context.errors.push(e.error),this.emit(`error:occurred`,{error:e.error});break}}getState(){return{phase:this.currentPhase,context:{...this.context}}}restoreState(e){this.currentPhase=e.phase,this.context={...e.context},this.emit(`workflow:resumed`,{phase:this.currentPhase,progress:this.getProgress()})}on(e,t){this.eventListeners.has(e)||this.eventListeners.set(e,new Set),this.eventListeners.get(e).add(t)}off(e,t){let n=this.eventListeners.get(e);n&&n.delete(t)}emit(e,t){let n={type:e,timestamp:new Date,phase:this.currentPhase,tddPhase:this.context.currentTDDPhase,subtaskId:this.getCurrentSubtaskId(),data:{...t,adapters:{testValidator:!!this.testResultValidator,gitHook:!!this.gitOperationHook,executeHook:!!this.executeHook}}},r=this.eventListeners.get(e);r&&r.forEach(e=>e(n))}getCurrentSubtaskId(){return this.context.subtasks[this.context.currentSubtaskIndex]?.id}onStatePersist(e){this.persistCallback=e}enableAutoPersist(e){this.persistCallback=e,this.autoPersistEnabled=!0}disableAutoPersist(){this.autoPersistEnabled=!1}async persistState(){this.persistCallback&&await this.persistCallback(this.getState()),this.emit(`state:persisted`)}async triggerAutoPersist(){this.autoPersistEnabled&&this.persistCallback&&await this.persistCallback(this.getState())}addGuard(e,t){this.phaseGuards.set(e,t)}removeGuard(e){this.phaseGuards.delete(e)}getCurrentSubtask(){return this.context.subtasks[this.context.currentSubtaskIndex]}getProgress(){let e=this.context.subtasks.filter(e=>e.status===`completed`).length,t=this.context.subtasks.length;return{completed:e,total:t,current:this.context.currentSubtaskIndex+1,percentage:t>0?Math.round(e/t*100):0}}canProceed(){return this.currentPhase===`SUBTASK_LOOP`?this.getCurrentSubtask()?.status===`completed`:!1}incrementAttempts(){let e=this.getCurrentSubtask();e&&e.attempts++}hasExceededMaxAttempts(){let e=this.getCurrentSubtask();return!e||!e.maxAttempts?!1:e.attempts>e.maxAttempts}handleError(e){this.context.errors.push(e),this.emit(`error:occurred`,{error:e})}handleRetry(){this.currentPhase===`SUBTASK_LOOP`&&(this.context.currentTDDPhase=`RED`,this.emit(`tdd:red:started`))}retryCurrentSubtask(){this.currentPhase===`SUBTASK_LOOP`&&(this.context.currentTDDPhase=`RED`,this.emit(`tdd:red:started`))}handleMaxAttemptsExceeded(){let e=this.getCurrentSubtask();e&&(e.status=`failed`,this.emit(`subtask:failed`,{subtaskId:e.id,attempts:e.attempts,maxAttempts:e.maxAttempts}))}isAborted(){return this.aborted}canResumeFromState(e){return!(![`PREFLIGHT`,`BRANCH_SETUP`,`SUBTASK_LOOP`,`FINALIZE`,`COMPLETE`].includes(e.phase)||!e.context||typeof e.context!=`object`||!e.context.taskId||!Array.isArray(e.context.subtasks)||typeof e.context.currentSubtaskIndex!=`number`||!Array.isArray(e.context.errors))}setTestResultValidator(e){this.testResultValidator=e,this.emit(`adapter:configured`,{adapterType:`test-validator`})}hasTestResultValidator(){return!!this.testResultValidator}removeTestResultValidator(){this.testResultValidator=void 0}onGitOperation(e){this.gitOperationHook=e}onExecute(e){this.executeHook=e}executeCommand(e){this.executeHook&&this.executeHook(e,this.context)}};async function Jn(e,t){let n={...t,timestamp:new Date().toISOString()};await ae.ensureDir(c.dirname(e));let r=JSON.stringify(n)+`
|
|
346
|
+
`;await ae.appendFile(e,r,`utf-8`)}const Yn=[`workflow:started`,`workflow:completed`,`workflow:error`,`workflow:resumed`,`phase:entered`,`phase:exited`,`tdd:feature-already-implemented`,`tdd:red:started`,`tdd:red:completed`,`tdd:green:started`,`tdd:green:completed`,`tdd:commit:started`,`tdd:commit:completed`,`subtask:started`,`subtask:completed`,`subtask:failed`,`test:run`,`test:passed`,`test:failed`,`git:branch:created`,`git:commit:created`,`error:occurred`,`state:persisted`,`progress:updated`,`adapter:configured`];var Xn=class{activityLogPath;orchestrator;logger=D(`WorkflowActivityLogger`);listenerMap=new Map;isActive=!1;constructor(e,t){this.orchestrator=e,this.activityLogPath=t}start(){if(this.isActive){this.logger.warn(`Activity logger is already active`);return}Yn.forEach(e=>{let t=e=>this.logEvent(e);this.listenerMap.set(e,t),this.orchestrator.on(e,t)}),this.isActive=!0,this.logger.debug(`Activity logger started, logging to: ${this.activityLogPath}`)}stop(){this.isActive&&(this.listenerMap.forEach((e,t)=>{this.orchestrator.off(t,e)}),this.listenerMap.clear(),this.isActive=!1,this.logger.debug(`Activity logger stopped and listeners removed`))}async logEvent(e){if(this.isActive)try{let t=e.timestamp instanceof Date?e.timestamp.toISOString():new Date(e.timestamp).toISOString(),n={type:e.type,phase:e.phase,tddPhase:e.tddPhase,subtaskId:e.subtaskId,eventTimestamp:t,...e.data||{}};await Jn(this.activityLogPath,n)}catch(t){this.logger.error(`Failed to log activity event ${e.type}: ${t.message}`)}}getActivityLogPath(){return this.activityLogPath}isLogging(){return this.isActive}},Zn=class{projectRoot;stateManager;taskStatusUpdater;tag;logger=D(`WorkflowService`);orchestrator;activityLogger;constructor(e){typeof e==`string`?this.projectRoot=e:(this.projectRoot=e.projectRoot,this.taskStatusUpdater=e.taskStatusUpdater,this.tag=e.tag),this.stateManager=new Kn(this.projectRoot)}async updateTaskStatus(e,t,n){if(this.taskStatusUpdater)try{await this.taskStatusUpdater.updateStatus(e,t,n??this.tag)}catch(t){let n=t instanceof Error?t.message:String(t);this.logger.warn(`Failed to update task ${e} status: ${n}`)}}async hasWorkflow(){return await this.stateManager.exists()}async startWorkflow(e){let{taskId:t,taskTitle:n,subtasks:r,maxAttempts:i=3,force:a,tag:o,orgSlug:s}=e;if(await this.hasWorkflow()&&!a)throw Error(`Workflow already exists. Use force=true to override or resume existing workflow.`);let c=new _t(this.projectRoot);await c.ensureGitRepository(),await c.ensureCleanWorkingTree();let l=r.map(e=>({id:e.id,title:e.title,status:e.status===`done`?`completed`:`pending`,attempts:0,maxAttempts:e.maxAttempts||i})),u=l.findIndex(e=>e.status!==`completed`);if(u===-1)throw Error(`All subtasks for task ${t} are already completed. Nothing to do.`);this.orchestrator=new qn({taskId:t,subtasks:l,currentSubtaskIndex:u,tag:o,errors:[],metadata:{startedAt:new Date().toISOString(),taskTitle:n,resumedFromSubtask:u>0?l[u].id:void 0}}),this.orchestrator.enableAutoPersist(async e=>{await this.stateManager.save(e)}),this.activityLogger=new Xn(this.orchestrator,this.stateManager.getActivityLogPath()),this.activityLogger.start(),await this.orchestrator.transition({type:`PREFLIGHT_COMPLETE`});let d=this.generateBranchName(t,n,o,s);return await c.getCurrentBranch()!==d&&await c.createAndCheckoutBranch(d),await this.orchestrator.transition({type:`BRANCH_CREATED`,branchName:d}),await this.updateTaskStatus(t,`in-progress`,o),this.getStatus()}async resumeWorkflow(){let e=await this.stateManager.load();if(this.orchestrator=new qn(e.context),!this.orchestrator.canResumeFromState(e))throw Error(`Invalid workflow state. State may be corrupted. Consider starting a new workflow.`);return this.orchestrator.restoreState(e),this.orchestrator.enableAutoPersist(async e=>{await this.stateManager.save(e)}),this.activityLogger=new Xn(this.orchestrator,this.stateManager.getActivityLogPath()),this.activityLogger.start(),this.getStatus()}getStatus(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getContext(),t=this.orchestrator.getProgress(),n=this.orchestrator.getCurrentSubtask();return{taskId:e.taskId,phase:this.orchestrator.getCurrentPhase(),tddPhase:this.orchestrator.getCurrentTDDPhase(),branchName:e.branchName,currentSubtask:n?{id:n.id,title:n.title,attempts:n.attempts,maxAttempts:n.maxAttempts||3}:void 0,progress:t}}getContext(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);return this.orchestrator.getContext()}getNextAction(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getCurrentPhase(),t=this.orchestrator.getCurrentTDDPhase(),n=this.orchestrator.getCurrentSubtask();if(e===`COMPLETE`)return{action:`workflow_complete`,description:`All subtasks completed`,nextSteps:`All subtasks completed! Review the entire implementation and merge your branch when ready.`,phase:e};if(e===`FINALIZE`)return{action:`finalize_workflow`,description:`Finalize and complete the workflow`,nextSteps:`All subtasks are complete! Use autopilot_finalize to verify no uncommitted changes remain and mark the workflow as complete.`,phase:e};if(e!==`SUBTASK_LOOP`||!t||!n)return{action:`unknown`,description:`Workflow is not in active state`,nextSteps:`Use autopilot_status to check workflow state.`,phase:e};let r={phase:e,tddPhase:t,subtask:{id:n.id,title:n.title}};switch(t){case`RED`:return{...r,action:`generate_test`,description:`Generate failing test for current subtask`,nextSteps:`Write failing tests for subtask ${n.id}: "${n.title}". Create test file(s) that validate the expected behavior. Run tests and use autopilot_complete_phase with results. Note: If all tests pass (0 failures), the feature is already implemented and the subtask will be auto-completed.`};case`GREEN`:return{...r,action:`implement_code`,description:`Implement feature to make tests pass`,nextSteps:`Implement code to make tests pass for subtask ${n.id}: "${n.title}". Write the minimal code needed to pass all tests (GREEN phase), then use autopilot_complete_phase with test results.`};case`COMMIT`:return{...r,action:`commit_changes`,description:`Commit RED-GREEN cycle changes`,nextSteps:`Review and commit your changes for subtask ${n.id}: "${n.title}". Use autopilot_commit to create the commit and advance to the next subtask.`};default:return{...r,action:`unknown`,description:`Unknown TDD phase`,nextSteps:`Use autopilot_status to check workflow state.`}}}async completePhase(e){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let t=this.orchestrator.getCurrentTDDPhase();if(!t)throw Error(`Not in active TDD phase`);switch(t){case`RED`:await this.orchestrator.transition({type:`RED_PHASE_COMPLETE`,testResults:e});break;case`GREEN`:await this.orchestrator.transition({type:`GREEN_PHASE_COMPLETE`,testResults:e});break;case`COMMIT`:throw Error(`Cannot complete COMMIT phase with test results. Use commit() instead.`);default:throw Error(`Unknown TDD phase: ${t}`)}return this.getStatus()}async commit(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getCurrentTDDPhase();if(e!==`COMMIT`)throw Error(`Cannot commit in ${e} phase. Complete RED and GREEN phases first.`);let t=this.orchestrator.getCurrentSubtask()?.id;await this.orchestrator.transition({type:`COMMIT_COMPLETE`});let n=this.orchestrator.getProgress();if(n.current<n.total?await this.orchestrator.transition({type:`SUBTASK_COMPLETE`}):await this.orchestrator.transition({type:`ALL_SUBTASKS_COMPLETE`}),t){let e=this.orchestrator.getContext();await this.updateTaskStatus(t,`done`,e.tag)}return this.getStatus()}async finalizeWorkflow(){if(!this.orchestrator)throw Error(`No active workflow. Start or resume a workflow first.`);let e=this.orchestrator.getCurrentPhase();if(e!==`FINALIZE`)throw Error(`Cannot finalize workflow in ${e} phase. Complete all subtasks first.`);let t=await new _t(this.projectRoot).getStatusSummary();if(!t.isClean)throw Error(`Cannot finalize workflow: working tree has uncommitted changes.\nStaged: ${t.staged}, Modified: ${t.modified}, Deleted: ${t.deleted}, Untracked: ${t.untracked}\nPlease commit all changes before finalizing the workflow.`);let n=this.orchestrator.getContext(),r=n.taskId;await this.orchestrator.transition({type:`FINALIZE_COMPLETE`});let i=this.getStatus();return await this.updateTaskStatus(r,`done`,n.tag),await this.stateManager.delete(),this.orchestrator=void 0,i}async abortWorkflow(){this.orchestrator&&await this.orchestrator.transition({type:`ABORT`}),await this.stateManager.delete(),this.orchestrator=void 0}generateBranchName(e,t,n,r){let i=t.toLowerCase().replace(/[^a-z0-9]+/g,`-`).replace(/^-+|-+$/g,``).substring(0,50),a=e.replace(/\./g,`-`),o=r||n;return`${o?`tm/${o}`:`tm`}/task-${a}-${i}`}},Qn=class{workflowService=null;projectRoot;configManager;tasksDomain=null;constructor(e){this.configManager=e,this.projectRoot=e.getProjectRoot()}setTasksDomain(e){this.tasksDomain=e}getWorkflowService(){if(!this.workflowService){let e=this.configManager.getActiveTag(),t=this.tasksDomain?{updateStatus:async(e,t,n)=>{await this.tasksDomain.updateStatus(e,t,n)}}:void 0;this.workflowService=new Zn({projectRoot:this.projectRoot,taskStatusUpdater:t,tag:e})}return this.workflowService}resetWorkflowService(){this.workflowService=null}async start(e){return this.resetWorkflowService(),this.getWorkflowService().startWorkflow(e)}async resume(){return this.resetWorkflowService(),this.getWorkflowService().resumeWorkflow()}getStatus(){return this.getWorkflowService().getStatus()}getContext(){return this.getWorkflowService().getContext()}getNextAction(){return this.getWorkflowService().getNextAction()}async completePhase(e){return this.getWorkflowService().completePhase(e)}async commit(){return this.getWorkflowService().commit()}async finalize(){let e=await this.getWorkflowService().finalizeWorkflow();return this.resetWorkflowService(),e}async abort(){await this.getWorkflowService().abortWorkflow(),this.resetWorkflowService()}async hasWorkflow(){return this.getWorkflowService().hasWorkflow()}},$n=class e{_projectPath;_configManager;_logger;_tasks;_auth;_workflow;_git;_config;_integration;_loop;_skillRun;get tasks(){return this._tasks}get auth(){return this._auth}get workflow(){return this._workflow}get git(){return this._git}get config(){return this._config}get integration(){return this._integration}get loop(){return this._loop}get skillRun(){return this._skillRun}get logger(){return this._logger}static async create(t){let n=new e(t);return await n.initialize(),n}_options;constructor(e){if(!e.projectPath)throw new T(`Project path is required`,w.MISSING_CONFIGURATION);if(!t.isAbsolute(e.projectPath))throw new T(`Project path must be an absolute path, received: "${e.projectPath}"`,w.INVALID_INPUT);this._projectPath=t.resolve(e.projectPath),this._options=e}async initialize(){try{this._logger=Ee(this._options.loggerConfig),this._configManager=await gt.create(this._projectPath),this._options.configuration&&await this._configManager.updateConfig(this._options.configuration),this._auth=new N,this._tasks=new Gn(this._configManager,this._auth),this._workflow=new Qn(this._configManager),this._git=new Tt(this._projectPath),this._config=new lt(this._configManager),this._integration=new Pt(this._configManager),this._loop=new $t(this._configManager),this._skillRun=new hn(this._configManager),await this._tasks.initialize(),this._workflow.setTasksDomain(this._tasks),this._skillRun.setTasksDomain(this._tasks),this._logger.info(`TmCore initialized successfully`)}catch(e){throw this._logger&&this._logger.error(`Failed to initialize TmCore:`,e),new T(`Failed to initialize TmCore`,w.INTERNAL_ERROR,{operation:`initialize`},e)}}get projectPath(){return this._projectPath}async close(){this._tasks&&await this._tasks.close()}};async function er(e){return $n.create(e)}function tr(e,n){try{return m.existsSync(t.join(e,n))}catch{return!1}}function R(e,t){return t.some(t=>tr(e,t))}function nr(e=process.cwd()){let n=t.resolve(e),r=t.parse(n).root,i=0,a=null;if(R(n,Ve)||R(n,He))return n;let o=t.dirname(n);for(i=1;i<50;){let e=R(o,Ve),n=R(o,He);if(e&&(n||i===1))return o;if(n&&!e){a=o;break}if(o===r)break;let s=t.dirname(o);if(s===o)break;o=s,i++}for(n=a||t.resolve(e),i=0;i<50;){if(R(n,Ue))return n;if(n===r)break;let e=t.dirname(n);if(e===n)break;n=e,i++}return t.resolve(e)}function rr(e){if(!e)return``;let n=String(e).split(t.sep),r=n.findIndex(e=>e===`.taskmaster`);return r===-1?String(e):n.slice(0,r).join(t.sep)||t.sep}function ir(e){let t=e?r(process.cwd(),e):nr();return{projectRoot:t,tasksPath:n(t,Be)}}function ar(e){return he(typeof e==`string`?new Date(e):e,{addSuffix:!0})}function or(e){return me(e,`hh:mm:ss a`)}function sr(e){if(!e)return e;let t=e.trim();if(/^\d+(\.\d+)?$/.test(t))return t;let n=t.match(/^([a-zA-Z]{3})-?(\d+)$/);return n?`${n[1].toUpperCase()}-${n[2]}`:t}const cr=/^\d+$/,lr=/^\d+\.\d+$/,ur=/^[a-zA-Z]{3}-?\d+$/;function dr(e){if(!e)return!1;let t=e.trim();return!!(cr.test(t)||lr.test(t)||ur.test(t))}function fr(e){if(!e)return!1;let t=e.trim();return!!(cr.test(t)||ur.test(t))}const pr=C.string().trim().refine(dr,{message:`Invalid task ID format. Expected: numeric ("1", "1.2") or prefixed with hyphen ("HAM-1")`}),mr=C.string().trim().refine(dr,{message:`Invalid task ID format. Expected: numeric ("1") or prefixed with hyphen ("HAM-1")`}).refine(fr,{message:`Subtask IDs are not allowed. Please provide a main task ID (e.g., "1", "HAM-1")`}),hr=pr.transform(sr),gr=mr.transform(sr),_r=pr,vr=mr,yr=/^(\d+(\.\d+)*|[A-Za-z]+-?\d+)$/;function br(e){return yr.test(e)}C.string().min(1,`Task ID cannot be empty`).refine(br,{message:`Invalid task ID format. Expected numeric (e.g., '15'), subtask (e.g., '15.2'), or display ID (e.g., 'HAM-123')`});const xr=C.string().min(1,`Task ID(s) cannot be empty`).refine(e=>{let t=e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0);return t.length>0&&t.every(br)},{message:`Invalid task ID format. Expected numeric (e.g., '15'), subtask (e.g., '15.2'), or display ID (e.g., 'HAM-123'). Multiple IDs should be comma-separated.`});function Sr(e){let t=e.split(`,`).map(e=>e.trim()).filter(e=>e.length>0);if(t.length===0)throw Error(`No valid task IDs provided`);let n=t.filter(e=>!br(e));if(n.length>0)throw Error(`Invalid task ID format: ${n.join(`, `)}. Expected numeric (e.g., '15'), subtask (e.g., '15.2'), or display ID (e.g., 'HAM-123')`);return t.map(sr)}const Cr=D(`TaskFilters`),wr=[`pending`,`in-progress`,`review`];function Tr(e){let t=new Map(e.map(e=>[String(e.id),[]])),n=[];for(let r of e)for(let e of r.dependencies??[]){let i=String(e),a=t.get(i);a?a.push(String(r.id)):n.push({taskId:String(r.id),depId:i})}return{blocksMap:t,invalidDependencies:n}}function Er(e){let t=new Set(e.filter(e=>et(e.status)).map(e=>String(e.id)));return e.filter(e=>(Qe.includes(e.status)||Cr.warn(`Task ${e.id} has unexpected status "${e.status}". Valid statuses are: ${Qe.join(`, `)}`),wr.includes(e.status)?(e.dependencies??[]).every(e=>t.has(String(e))):!1))}function Dr(e){return e.filter(e=>e.blocks.length>0)}const Or=[{type:`task_count`,threshold:10,message:`Your tasks are growing! Upgrade to Hamster Studio (Multiplayer) for coordinated team action, AI context sharing, and faster shipping.`,promptType:`upgrade_suggestion`,showOnce:!1,cooldownDays:7,priority:80},{type:`tags_used`,threshold:3,message:`Organize by tags? Hamster briefs let you group and collaborate on tagged tasks with your team.`,promptType:`educational_notice`,showOnce:!1,cooldownDays:14,priority:70},{type:`list_count`,threshold:5,message:`Managing multiple projects? Create Hamster briefs to organize work across your team.`,promptType:`educational_notice`,showOnce:!1,cooldownDays:14,priority:50},{type:`dependencies_complex`,threshold:5,message:`Your tasks have complex dependencies. Hamster visualizes these relationships and tracks blockers automatically.`,promptType:`educational_notice`,showOnce:!1,cooldownDays:14,priority:60},{type:`days_active`,threshold:7,message:`Ready to collaborate? Export your tasks to Hamster Studio and start shipping faster with your team.`,promptType:`upgrade_suggestion`,showOnce:!0,priority:90},{type:`export_attempt`,threshold:1,message:`Export to Hamster Studio to enable coordinated team action, AI context sharing, and alignment in hours.`,promptType:`critical_choice`,showOnce:!1,cooldownDays:1,priority:100},{type:`no_connection`,threshold:1,message:`Connect to Hamster Studio to sync your tasks across devices and collaborate with your team.`,promptType:`upgrade_suggestion`,showOnce:!1,cooldownDays:3,priority:75},{type:`parse_prd`,threshold:1,message:`Export your PRD to Hamster for dynamic task generation and team collaboration.`,promptType:`critical_choice`,showOnce:!1,cooldownDays:1,priority:95}],kr=`1.0.0`,Ar=`upgradePrompts`;var jr=class{logger=D(`PromptStateManager`);runtimeStateManager;cachedState=null;constructor(e){this.runtimeStateManager=new ht(e)}async getState(){return this.cachedState||=await this.loadState(),this.cachedState}async loadState(){try{await this.runtimeStateManager.loadState();let e=this.runtimeStateManager.getState().metadata?.[Ar];if(e&&typeof e==`object`)return this.validateAndMigrate(e)}catch(e){this.logger.warn(`Failed to load prompt state, using defaults:`,e)}return this.createDefaultState()}createDefaultState(){return{triggers:{},metrics:{totalTaskCount:0,tagCount:0,listCommandCount:0,tasksWithDependencies:0},lastUpdated:new Date().toISOString(),version:kr}}validateAndMigrate(e){return{triggers:e.triggers||{},metrics:{totalTaskCount:e.metrics?.totalTaskCount||0,tagCount:e.metrics?.tagCount||0,listCommandCount:e.metrics?.listCommandCount||0,tasksWithDependencies:e.metrics?.tasksWithDependencies||0,firstActivityAt:e.metrics?.firstActivityAt,lastActivityAt:e.metrics?.lastActivityAt},lastUpdated:e.lastUpdated||new Date().toISOString(),version:kr}}async saveState(){if(this.cachedState)try{this.cachedState.lastUpdated=new Date().toISOString(),await this.runtimeStateManager.updateMetadata({[Ar]:this.cachedState})}catch(e){throw this.logger.error(`Failed to save prompt state:`,e),e}}async getTriggerState(e){return(await this.getState()).triggers[e]||null}async recordPromptShown(e){let t=await this.getState(),n=new Date().toISOString(),r=t.triggers[e];t.triggers[e]={firstShownAt:r?.firstShownAt||n,lastShownAt:n,showCount:(r?.showCount||0)+1,dismissed:r?.dismissed||!1},await this.saveState()}async recordPromptAction(e,t){let n=await this.getState(),r=new Date().toISOString(),i=n.triggers[e]||{showCount:1,dismissed:!1};n.triggers[e]={...i,action:t,actionAt:r,dismissed:t===`dismissed`},await this.saveState()}async updateMetrics(e){let t=await this.getState(),n=new Date().toISOString();t.metrics.firstActivityAt||(t.metrics.firstActivityAt=n),t.metrics.lastActivityAt=n,Object.assign(t.metrics,e),await this.saveState()}async incrementMetric(e,t=1){let n=await this.getState();n.metrics[e]=(n.metrics[e]||0)+t,n.metrics.firstActivityAt||(n.metrics.firstActivityAt=new Date().toISOString()),n.metrics.lastActivityAt=new Date().toISOString(),await this.saveState()}async getMetrics(){return(await this.getState()).metrics}async isWithinCooldown(e,t){let n=await this.getTriggerState(e);if(!n?.lastShownAt)return!1;let r=new Date(n.lastShownAt),i=t*24*60*60*1e3;return Date.now()-r.getTime()<i}async isDismissed(e){return(await this.getTriggerState(e))?.dismissed||!1}async getDaysActive(){let e=await this.getState();if(!e.metrics.firstActivityAt)return 0;let t=new Date(e.metrics.firstActivityAt),n=Date.now();return Math.floor((n-t.getTime())/(1440*60*1e3))}async reset(){this.cachedState=this.createDefaultState(),await this.saveState()}async resetTrigger(e){let t=await this.getState();delete t.triggers[e],await this.saveState()}},Mr=class{stateManager;config;constructor(e,t){this.stateManager=e,this.config=t||{enabled:!0,triggers:Or,defaultCooldownDays:7,respectDismissed:!0}}async evaluate(e={}){if(!this.config.enabled)return{shouldShow:!1,reason:`Prompts are disabled`};let t=await this.stateManager.getMetrics(),n=await this.stateManager.getDaysActive(),r=[...this.config.triggers].sort((e,t)=>t.priority-e.priority);for(let i of r){let r=await this.evaluateTrigger(i,t,n,e);if(r.shouldShow)return r}return{shouldShow:!1,reason:`No trigger conditions met`}}async evaluateTriggerType(e,t={}){let n=this.config.triggers.find(t=>t.type===e);if(!n)return{shouldShow:!1,reason:`Unknown trigger type: ${e}`};let r=await this.stateManager.getMetrics(),i=await this.stateManager.getDaysActive();return this.evaluateTrigger(n,r,i,t)}async evaluateTrigger(e,t,n,r){if(this.config.respectDismissed&&await this.stateManager.isDismissed(e.type))return{shouldShow:!1,trigger:e,reason:`Prompt was dismissed by user`};let i=e.cooldownDays??this.config.defaultCooldownDays;if(await this.stateManager.isWithinCooldown(e.type,i))return{shouldShow:!1,trigger:e,reason:`Within cooldown period (${i} days)`};if(e.showOnce){let t=await this.stateManager.getTriggerState(e.type);if(t&&t.showCount>0)return{shouldShow:!1,trigger:e,reason:`Prompt already shown (showOnce=true)`}}let a=this.evaluateThreshold(e,t,n,r);return a.met?{shouldShow:!0,trigger:e,reason:a.reason}:{shouldShow:!1,trigger:e,reason:a.reason}}evaluateThreshold(e,t,n,r){switch(e.type){case`task_count`:let i=t.totalTaskCount>=e.threshold;return{met:i,reason:i?`Task count ${t.totalTaskCount} >= ${e.threshold}`:`Task count ${t.totalTaskCount} < ${e.threshold}`};case`tags_used`:let a=t.tagCount>=e.threshold;return{met:a,reason:a?`Tag count ${t.tagCount} >= ${e.threshold}`:`Tag count ${t.tagCount} < ${e.threshold}`};case`list_count`:let o=t.listCommandCount>=e.threshold;return{met:o,reason:o?`List count ${t.listCommandCount} >= ${e.threshold}`:`List count ${t.listCommandCount} < ${e.threshold}`};case`dependencies_complex`:let s=t.tasksWithDependencies>=e.threshold;return{met:s,reason:s?`Tasks with dependencies ${t.tasksWithDependencies} >= ${e.threshold}`:`Tasks with dependencies ${t.tasksWithDependencies} < ${e.threshold}`};case`days_active`:let c=n>=e.threshold;return{met:c,reason:c?`Days active ${n} >= ${e.threshold}`:`Days active ${n} < ${e.threshold}`};case`export_attempt`:let l=r.currentCommand===`export`;return{met:l,reason:l?`User is attempting export`:`Not an export command`};case`no_connection`:let u=!r.isAuthenticated||!r.hasBriefConnected;return{met:u,reason:u?`No Hamster connection detected`:`User is connected to Hamster`};case`parse_prd`:let d=r.currentCommand===`parse-prd`;return{met:d,reason:d?`User is parsing a PRD`:`Not a parse-prd command`};default:return{met:!1,reason:`Unknown trigger type: ${e.type}`}}}getTriggers(){return this.config.triggers}getTrigger(e){return this.config.triggers.find(t=>t.type===e)}isEnabled(){return this.config.enabled}},Nr=class{logger=D(`PromptService`);stateManager;evaluator;constructor(e,t){this.stateManager=new jr(e),this.evaluator=new Mr(this.stateManager,t)}async evaluatePrompts(e={}){try{return await this.evaluator.evaluate(e)}catch(e){return this.logger.error(`Error evaluating prompts:`,e),{shouldShow:!1,reason:`Evaluation error: ${e.message}`}}}async evaluateTrigger(e,t={}){try{return await this.evaluator.evaluateTriggerType(e,t)}catch(t){return this.logger.error(`Error evaluating trigger ${e}:`,t),{shouldShow:!1,reason:`Evaluation error: ${t.message}`}}}async recordPromptShown(e){try{await this.stateManager.recordPromptShown(e),this.logger.debug(`Recorded prompt shown: ${e}`)}catch(e){this.logger.error(`Error recording prompt shown:`,e)}}async recordAction(e,t){try{await this.stateManager.recordPromptAction(e,t),this.logger.debug(`Recorded prompt action: ${e} -> ${t}`)}catch(e){this.logger.error(`Error recording prompt action:`,e)}}async updateMetrics(e){try{await this.stateManager.updateMetrics(e)}catch(e){this.logger.error(`Error updating metrics:`,e)}}async incrementMetric(e,t=1){try{await this.stateManager.incrementMetric(e,t)}catch(t){this.logger.error(`Error incrementing metric ${e}:`,t)}}async getMetrics(){return this.stateManager.getMetrics()}async dismissPrompt(e){await this.recordAction(e,`dismissed`)}isEnabled(){return this.evaluator.isEnabled()}getPromptMessage(e){return this.evaluator.getTrigger(e)?.message||null}async reset(){await this.stateManager.reset()}async resetTrigger(e){await this.stateManager.resetTrigger(e)}async syncMetrics(e){let t={};e.taskCount!==void 0&&(t.totalTaskCount=e.taskCount),e.tagCount!==void 0&&(t.tagCount=e.tagCount),e.tasksWithDependencies!==void 0&&(t.tasksWithDependencies=e.tasksWithDependencies),Object.keys(t).length>0&&await this.updateMetrics(t)}static buildContext(e){return{currentCommand:e.command,isAuthenticated:e.isAuthenticated,hasBriefConnected:e.hasBriefConnected,custom:e.custom}}};const Pr=[`add-task`,`analyze-complexity`,`expand-task`,`parse-prd`,`research`,`research-save`,`update-subtask`,`update-task`,`update-tasks`],Fr=`.taskmaster`,Ir=`.taskmaster/tasks`,Lr=`.taskmaster/docs`,Rr=`.taskmaster/reports`,zr=`.taskmaster/templates`,Br=`.taskmaster/config.json`,Vr=`.taskmaster/state.json`,z=`.taskmasterconfig`,Hr=`.taskmaster/reports/task-complexity-report.json`,Ur=`.taskmaster/docs/prd.txt`,Wr=`.taskmaster/templates/example_prd.txt`,Gr=`.taskmaster/tasks/tasks.json`,Kr=`tasks/tasks.json`,qr=`.env.example`,Jr=`.gitignore`;let Yr=!1;const Xr={maxRetries:5,retryDelay:100,staleLockAge:1e4};function Zr(e){if(typeof SharedArrayBuffer<`u`&&typeof Atomics<`u`&&typeof Atomics.wait==`function`)try{let t=new SharedArrayBuffer(4),n=new Int32Array(t);Atomics.wait(n,0,0,e);return}catch{}let t=Date.now()+e;for(;Date.now()<t;);}function Qr(e,t,n={}){let{createIfMissing:r=!1}=n,i=c.dirname(e);if(s.existsSync(i)||s.mkdirSync(i,{recursive:!0}),r)try{s.writeFileSync(e,`{}`,{flag:`wx`})}catch(e){if(e.code!==`EEXIST`)throw e}let a=`${e}.lock`,{maxRetries:o,retryDelay:l,staleLockAge:u}=Xr,d=!1;for(let e=0;e<o;e++)try{let e=JSON.stringify({pid:process.pid,timestamp:Date.now()});s.writeFileSync(a,e,{flag:`wx`}),d=!0;break}catch(t){if(t.code===`EEXIST`){try{let e=s.statSync(a);if(Date.now()-e.mtimeMs>u){let e=`${a}.stale.${process.pid}.${Date.now()}`;try{s.renameSync(a,e);try{s.unlinkSync(e)}catch{}continue}catch{}}}catch(e){if(e.code===`ENOENT`)continue;throw e}e<o-1&&Zr(l*2**e)}else throw t}if(!d)throw Error(`Failed to acquire lock on ${e} after ${o} attempts`);try{return t()}finally{try{s.unlinkSync(a)}catch(t){U(`warn`,`Failed to release lock for ${e}: ${t.message}`)}}}function B(e,t=null,n=null){if(t?.env?.[e])return t.env[e];if(n){let t=c.join(n,`.env`);if(s.existsSync(t))try{let n=s.readFileSync(t,`utf-8`),r=_e.parse(n);if(r&&r[e])return r[e]}catch(e){U(`warn`,`Could not read or parse ${t}: ${e.message}`)}}if(process.env[e])return process.env[e]}function V(e=process.cwd(),t=[`package.json`,`pyproject.toml`,`.git`,z]){let n=c.resolve(e),r=c.parse(n).root;for(;n!==r;){if(t.some(e=>{let t=c.join(n,e);return s.existsSync(t)}))return n;n=c.dirname(n)}return t.some(e=>{let t=c.join(r,e);return s.existsSync(t)})?r:null}const H={debug:0,info:1,warn:2,error:3,success:1};function $r(){Yr=!0}function ei(){Yr=!1}function ti(){return Yr}function U(e,...t){if(ti())return;let n=`info`;try{n=ra()||`info`}catch{n=`info`}let r={debug:i.gray(`[DEBUG]`),info:i.blue(`[INFO]`),warn:i.yellow(`[WARN]`),error:i.red(`[ERROR]`),success:i.green(`[SUCCESS]`)},a=H.hasOwnProperty(e)?e:`info`;if(H[a]>=(H[n]??H.info)){let e=r[a]||``,n=t.map(e=>typeof e==`object`?JSON.stringify(e):e).join(` `);console.log(`${e} ${n}`)}}function ni(e){if(!e||typeof e!=`object`)return!1;for(let t in e)if(e.hasOwnProperty(t)&&typeof e[t]==`object`&&Array.isArray(e[t].tasks))return!0;return!1}function W(e){Array.isArray(e)&&e.forEach(e=>{if(e.id!==void 0){let t=parseInt(e.id,10);!isNaN(t)&&t>0&&(e.id=t)}Array.isArray(e.subtasks)&&e.subtasks.forEach(e=>{if(e.id!==void 0)if(typeof e.id==`string`&&e.id.includes(`.`)){let t=e.id.split(`.`);e.id=parseInt(t[t.length-1],10)}else{let t=parseInt(e.id,10);!isNaN(t)&&t>0&&(e.id=t)}})})}function ri(t,n=null,r=null){let i=!1;try{i=$()}catch{}if(i&&console.log(`readJSON called with: ${t}, projectRoot: ${n}, tag: ${r}`),!t)return null;let a;try{a=JSON.parse(s.readFileSync(t,`utf8`)),i&&console.log(`Successfully read JSON from ${t}`)}catch(e){return i&&console.log(`Failed to read JSON from ${t}: ${e.message}`),null}if(!t.includes(`tasks.json`)||!a)return i&&console.log(`File is not tasks.json or data is null, returning as-is`),a;if(Array.isArray(a.tasks)&&!a._rawTaggedData&&!ni(a)){i&&console.log(`File is in legacy format, performing migration...`),W(a.tasks);let r={master:{tasks:a.tasks,metadata:a.metadata||{created:new Date().toISOString(),updated:new Date().toISOString(),description:`Tasks for master context`}}};try{if(ci(t,r),i&&console.log(`Successfully migrated legacy format to tagged format`),ii(t),n)try{e(n,t)}catch{}si(t)}catch(e){i&&console.log(`Error writing migrated data: ${e.message}`)}a=r}if(typeof a==`object`&&!a.tasks){for(let e in i&&console.log(`File is in tagged format, resolving tag...`),a)if(a.hasOwnProperty(e)&&typeof a[e]==`object`&&a[e].tasks)try{wi(a[e],{description:`Tasks for ${e} context`,skipUpdate:!0})}catch(t){i&&console.log(`Failed to ensure metadata for tag ${e}: ${t.message}`)}let o=JSON.parse(JSON.stringify(a));for(let e in o)o[e]&&Array.isArray(o[e].tasks)&&W(o[e].tasks);if(n)try{e(n,t)}catch{}try{let e=`master`;try{if(r)e=r;else if(n)e=xi({projectRoot:n});else{let n=V(c.dirname(t));n&&(e=xi({projectRoot:n}))}}catch(e){i&&console.log(`Tag resolution failed, using master: ${e.message}`)}i&&console.log(`Resolved tag: ${e}`);let s=a[e];if(s&&s.tasks){W(s.tasks);let t={...s,tag:e,_rawTaggedData:o};return i&&console.log(`Returning data for tag '${e}' with ${s.tasks.length} tasks`),t}else{let t=a.master;return t&&t.tasks?(W(t.tasks),i&&console.log(`Tag '${e}' not found, falling back to master with ${t.tasks.length} tasks`),{...t,tag:`master`,_rawTaggedData:o}):(i&&console.log(`No valid tag data found, returning empty structure`),{tasks:[],tag:`master`,_rawTaggedData:o})}}catch(e){i&&console.log(`Error during tag resolution: ${e.message}`);let t=a.master;return t&&t.tasks?(W(t.tasks),{...t,_rawTaggedData:o}):{tasks:[],_rawTaggedData:o}}}return i&&console.log(`File format not recognized, returning as-is`),a}function ii(e){try{let t=V(c.dirname(e))||c.dirname(e),n=c.join(t,`.taskmaster`,`config.json`);s.existsSync(n)&&ai(n);let r=c.join(t,`.taskmaster`,`state.json`);s.existsSync(r)||oi(r),$()&&U(`debug`,`Complete tag migration performed for project: ${t}`)}catch(e){$()&&U(`warn`,`Error during complete tag migration: ${e.message}`)}}function ai(e){try{let t=s.readFileSync(e,`utf8`),n=JSON.parse(t);if(!n)return;let r=!1;n.global||={},n.global.defaultTag||(n.global.defaultTag=`master`,r=!0),r&&(s.writeFileSync(e,JSON.stringify(n,null,2),`utf8`),process.env.TASKMASTER_DEBUG===`true`&&console.log(`[DEBUG] Updated config.json with tagged task system settings`))}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error migrating config.json: ${e.message}`)}}function oi(e){try{let t={currentTag:`master`,lastSwitched:new Date().toISOString(),branchTagMapping:{},migrationNoticeShown:!1};s.writeFileSync(e,JSON.stringify(t,null,2),`utf8`),process.env.TASKMASTER_DEBUG===`true`&&console.log(`[DEBUG] Created initial state.json for tagged task system`)}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error creating state.json: ${e.message}`)}}function si(e){try{let t=c.dirname(c.dirname(e)),n=c.join(t,`.taskmaster`,`state.json`);s.existsSync(n)||oi(n);try{let e=s.readFileSync(n,`utf8`),t=JSON.parse(e)||{};t.migrationNoticeShown===void 0&&(t.migrationNoticeShown=!1,s.writeFileSync(n,JSON.stringify(t,null,2),`utf8`))}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error updating state for migration notice: ${e.message}`)}}catch(e){process.env.TASKMASTER_DEBUG===`true`&&console.warn(`[WARN] Error marking migration for notice: ${e.message}`)}}function ci(e,t,n=null,r=null){let i=process.env.TASKMASTER_DEBUG===`true`;try{Qr(e,()=>{let a=t;if(t&&!t._rawTaggedData&&n&&Array.isArray(t.tasks)&&!ni(t)){let o=r||bi(n);i&&console.log(`writeJSON: Detected resolved tag data missing _rawTaggedData. Re-reading raw data to prevent data loss for tag '${o}'.`);let c={};try{c=JSON.parse(s.readFileSync(e,`utf8`))}catch(e){i&&console.log(`writeJSON: Could not read existing file, starting fresh: ${e.message}`)}a={...c,[o]:{metadata:{...c[o]?.metadata||{},...t.metadata||{}},tasks:t.tasks}}}else if(t&&t._rawTaggedData&&n){let o=r||bi(n),c;try{c=JSON.parse(s.readFileSync(e,`utf8`))}catch(e){c=t._rawTaggedData,i&&console.log(`writeJSON: Using _rawTaggedData as fallback: ${e.message}`)}let{_rawTaggedData:l,tag:u,...d}=t;a={...c,[o]:d},i&&console.log(`writeJSON: Merging resolved data back into tag '${o}'`)}let o=a;if(o&&typeof o==`object`){let{_rawTaggedData:e,tag:t,...n}=o;if(o=n,typeof o==`object`&&!Array.isArray(o)){let e={};for(let[t,n]of Object.entries(o))if(n&&typeof n==`object`&&Array.isArray(n.tasks)){let{created:r,description:i,...a}=n;a.metadata||={},r&&!a.metadata.created&&(a.metadata.created=r),i&&!a.metadata.description&&(a.metadata.description=i),e[t]=a}else e[t]=n;o=e}}let c=`${e}.tmp.${process.pid}`;try{s.writeFileSync(c,JSON.stringify(o,null,2),`utf8`),s.renameSync(c,e)}catch(e){try{s.existsSync(c)&&s.unlinkSync(c)}catch{}throw e}i&&console.log(`writeJSON: Successfully wrote to ${e}`)},{createIfMissing:!0})}catch(t){throw U(`error`,`Error writing JSON file ${e}:`,t.message),i&&U(`error`,`Full error details:`,t),t}}function li(e=null){let t=!1;try{t=$()}catch{t=!1}try{let n;if(e)n=e;else{let e=c.join(process.cwd(),Hr),t=c.join(process.cwd(),`scripts/task-complexity-report.json`);n=s.existsSync(e)?e:t}if(!s.existsSync(n))return t&&U(`debug`,`Complexity report not found at ${n}`),null;let r=ri(n);return t&&U(`debug`,`Successfully read complexity report from ${n}`),r}catch(e){return t&&U(`error`,`Error reading complexity report: ${e.message}`),null}}function ui(e,t){return!e||!e.complexityAnalysis||!Array.isArray(e.complexityAnalysis)?null:e.complexityAnalysis.find(e=>e.taskId===t)}function di(e,t){let n;n=e.isSubtask?e.parentTask.id:e.parentId?e.parentId:e.id;let r=ui(t,n);r&&(e.complexityScore=r.complexityScore)}function fi(e,t){if(!t||!e||!Array.isArray(e))return!1;if(typeof t==`string`&&t.includes(`.`)){let[n,r]=t.split(`.`).map(e=>parseInt(e,10)),i=e.find(e=>e.id===n);return!i||!i.subtasks?!1:i.subtasks.some(e=>e.id===r)}let n=parseInt(t,10);return e.some(e=>e.id===n)}function pi(e){return typeof e==`string`&&e.includes(`.`)?e:typeof e==`number`?e.toString():e}function mi(e,t,n=null,r=null){if(!t||!e||!Array.isArray(e))return{task:null,originalSubtaskCount:null};if(typeof t==`string`&&t.includes(`.`)){let[r,i]=t.split(`.`).map(e=>parseInt(e,10)),a=e.find(e=>e.id===r);if(!a||!a.subtasks)return{task:null,originalSubtaskCount:null,originalSubtasks:null};let o=a.subtasks.find(e=>e.id===i);return o&&(o.parentTask={id:a.id,title:a.title,status:a.status},o.isSubtask=!0),o&&n&&di(o,n),{task:o||null,originalSubtaskCount:null,originalSubtasks:null}}let i=null,a=null,o=null,s=parseInt(t,10),c=e.find(e=>e.id===s)||null;if(!c)return{task:null,originalSubtaskCount:null,originalSubtasks:null};if(i=c,r&&c.subtasks&&Array.isArray(c.subtasks)){o=[...c.subtasks],a=c.subtasks.length;let e={...c};e.subtasks=c.subtasks.filter(e=>e.status&&e.status.toLowerCase()===r.toLowerCase()),i=e}return i&&n&&di(i,n),{task:i,originalSubtaskCount:a,originalSubtasks:o}}function hi(e,t){return!e||e.length<=t?e:`${e.slice(0,t-3)}...`}function gi(e){return Array.isArray(e)?e.length===0:typeof e==`object`&&e?Object.keys(e).length===0:!1}function _i(e,t,n=new Set,r=new Set,i=[]){n.add(e),r.add(e),i.push(e);let a=[],o=t.get(e)||[];for(let e of o)if(n.has(e)){if(r.has(e)){let t=i.indexOf(e);i.slice(t),a.push(e)}}else{let o=_i(e,t,n,r,[...i]);a.push(...o)}return r.delete(e),a}function vi(e,t,n={}){let{maxDepth:r=50,includeSelf:i=!1,direction:a=`forward`,logger:o=null}=n,s=new Set,c=new Set;function l(e){if(typeof e==`string`){if(e.includes(`.`))return e;let t=parseInt(e,10);return isNaN(t)?e:t}return e}function u(e,n=0){if(n>=r){let t=`Maximum recursion depth (${r}) reached for task ${e}`;o&&typeof o.warn==`function`?o.warn(t):U!==void 0&&U.warn?U.warn(t):console.warn(t);return}if(c.has(e))return;c.add(e);let a=t.find(t=>t.id===e);!a||!Array.isArray(a.dependencies)||a.dependencies.forEach(t=>{let r=l(t);r==null||!i&&r===e||(s.add(r),u(r,n+1))})}function d(e,n=0){if(n>=r){let t=`Maximum recursion depth (${r}) reached for task ${e}`;o&&typeof o.warn==`function`?o.warn(t):U!==void 0&&U.warn?U.warn(t):console.warn(t);return}c.has(e)||(c.add(e),t.forEach(t=>{if(t.dependencies&&Array.isArray(t.dependencies)&&t.dependencies.some(t=>l(t)===e)){if(t.id==null||!i&&t.id===e)return;s.add(t.id),d(t.id,n+1)}}))}let f=a===`reverse`?d:u;return e.forEach(e=>{e&&e.id&&f(e.id)}),Array.from(s)}function yi(e,t){if(!e||e.length===0)return null;let n={timestamp:new Date().toISOString(),userId:e[0].userId,commandName:t,modelUsed:`Multiple`,providerName:`Multiple`,inputTokens:0,outputTokens:0,totalTokens:0,totalCost:0,currency:e[0].currency||`USD`},r=new Set,i=new Set,a=new Set;return e.forEach(e=>{n.inputTokens+=e.inputTokens||0,n.outputTokens+=e.outputTokens||0,n.totalCost+=e.totalCost||0,r.add(e.modelUsed),i.add(e.providerName),a.add(e.currency||`USD`)}),n.totalTokens=n.inputTokens+n.outputTokens,n.totalCost=parseFloat(n.totalCost.toFixed(6)),r.size===1&&(n.modelUsed=[...r][0]),i.size===1&&(n.providerName=[...i][0]),a.size>1?n.currency=`Multiple`:a.size===1&&(n.currency=[...a][0]),n}function bi(e){if(!e)throw Error(`projectRoot is required for getCurrentTag`);try{let t=c.join(e,`.taskmaster`,`state.json`);if(s.existsSync(t)){let e=s.readFileSync(t,`utf8`),n=JSON.parse(e);if(n&&n.currentTag)return n.currentTag}}catch{}try{let t=c.join(e,`.taskmaster`,`config.json`);if(s.existsSync(t)){let e=s.readFileSync(t,`utf8`),n=JSON.parse(e);if(n&&n.global&&n.global.defaultTag)return n.global.defaultTag}}catch{}return`master`}function xi(e={}){let{projectRoot:t,tag:n}=e;if(!t)throw Error(`projectRoot is required for resolveTag`);return n||bi(t)}function Si(e,t){return!e||!t?[]:e[t]&&e[t].tasks&&Array.isArray(e[t].tasks)?e[t].tasks:[]}function Ci(e){let t=[];for(let n of e)if(t.push({...n,searchableId:n.id.toString(),isSubtask:!1}),n.subtasks&&n.subtasks.length>0)for(let e of n.subtasks)t.push({...e,searchableId:`${n.id}.${e.id}`,isSubtask:!0,parentId:n.id,parentTitle:n.title,title:`${e.title} (subtask of: ${n.title})`,description:`${e.description} [Parent: ${n.description}]`});return t}function wi(e,t={}){if(!e||typeof e!=`object`)throw Error(`tagObj must be a valid object`);let n=new Date().toISOString();return e.metadata?(e.metadata.created||(e.metadata.created=n),t.skipUpdate||(e.metadata.updated=n),t.description&&!e.metadata.description&&(e.metadata.description=t.description)):e.metadata={created:n,updated:n,...t.description?{description:t.description}:{}},e}function Ti(){return{info:(e,...t)=>U(`info`,e,...t),warn:(e,...t)=>U(`warn`,e,...t),error:(e,...t)=>U(`error`,e,...t),debug:(e,...t)=>U(`debug`,e,...t),success:(e,...t)=>U(`success`,e,...t)}}function G(e=null){return e||Ti()}function K(e){return rr(e)}function q(e=process.cwd()){return nr(e)}function Ei(e=null,t=null,n=null){let r=G(n),i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i);if(e){let t=c.isAbsolute(e)?e:c.resolve(a,e);if(s.existsSync(t))return r.info?.(`Using explicit tasks path: ${t}`),t;r.warn?.(`Explicit tasks path not found: ${t}, trying fallbacks`)}let o=[c.join(a,Gr),c.join(a,Kr)];for(let e of o)if(s.existsSync(e))return r.info?.(`Found tasks file at: ${e}`),e.includes(`tasks/tasks.json`)&&!e.includes(`.taskmaster`)?r.warn?.(`⚠️ DEPRECATION WARNING: Found tasks.json in legacy location '${e}'. Please migrate to the new .taskmaster directory structure. Run 'task-master migrate' to automatically migrate your project.`):e.endsWith(`tasks.json`)&&!e.includes(`.taskmaster`)&&!e.includes(`tasks/`)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found tasks.json in legacy root location '${e}'. Please migrate to the new .taskmaster directory structure. Run 'task-master migrate' to automatically migrate your project.`),e;return r.warn?.(`No tasks.json found in project: ${a}`),null}function Di(e=null,t=null,n=null){let r=G(n);if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);if(s.existsSync(n))return r.info?.(`Using explicit PRD path: ${n}`),n;r.warn?.(`Explicit PRD path not found: ${n}, trying fallbacks`)}let i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i),o=[Lr,`scripts/`,``],l=[`PRD.md`,`prd.md`,`PRD.txt`,`prd.txt`];for(let e of o)for(let t of l){let n=c.join(a,e,t);if(s.existsSync(n))return r.info?.(`Found PRD document at: ${n}`),(e===`scripts/`||e===``)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found PRD file in legacy location '${n}'. Please migrate to .taskmaster/docs/ directory. Run 'task-master migrate' to automatically migrate your project.`),n}return r.warn?.(`No PRD document found in project: ${a}`),null}function Oi(e=null,t=null,n=null){let r=G(n);if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);if(s.existsSync(n))return r.info?.(`Using explicit complexity report path: ${n}`),n;r.warn?.(`Explicit complexity report path not found: ${n}, trying fallbacks`)}let i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i),o=[Rr,`scripts/`,``],l=[`task-complexity-report`,`task-complexity`,`complexity-report`].map(e=>t?.tag&&t?.tag!==`master`?`${e}_${t.tag}.json`:`${e}.json`);for(let e of o)for(let t of l){let n=c.join(a,e,t);if(s.existsSync(n))return r.info?.(`Found complexity report at: ${n}`),(e===`scripts/`||e===``)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found complexity report in legacy location '${n}'. Please migrate to .taskmaster/reports/ directory. Run 'task-master migrate' to automatically migrate your project.`),n}return r.warn?.(`No complexity report found in project: ${a}`),null}function ki(e=null,t=null,n=null){let r=G(n),i=t?.tag;if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);return r.info?.(`Using explicit complexity report output path: ${n}`),n}let a=K(t?.projectRoot||q()||process.cwd()),o=`task-complexity-report.json`;i&&i!==`master`&&(o=`task-complexity-report_${i}.json`);let l=c.join(a,`.taskmaster/reports`,o);r.info?.(`Using tag-aware complexity report output path: ${l}`);let u=c.dirname(l);return s.existsSync(u)||(r.info?.(`Creating reports directory: ${u}`),s.mkdirSync(u,{recursive:!0})),l}function Ai(e=null,t=null,n=null){let r=G(n);if(e){let t=process.env.TASKMASTER_ORIGINAL_CWD||process.cwd(),n=c.isAbsolute(e)?e:c.resolve(t,e);if(s.existsSync(n))return r.info?.(`Using explicit config path: ${n}`),n;r.warn?.(`Explicit config path not found: ${n}, trying fallbacks`)}let i=t?.projectRoot||q();if(!i)return r.warn?.(`Could not determine project root directory`),null;let a=K(i),o=[c.join(a,Br),c.join(a,z)];for(let e of o)if(s.existsSync(e))return e?.endsWith(z)&&r.warn?.(`⚠️ DEPRECATION WARNING: Found configuration in legacy location '${e}'. Please migrate to .taskmaster/config.json. Run 'task-master migrate' to automatically migrate your project.`),e;if(!(Fi()||t?.storageType===`api`)){let e=`config_warning_${a}`;global._tmConfigWarningsThisRun||(global._tmConfigWarningsThisRun=new Set),global._tmConfigWarningsThisRun.has(e)||(global._tmConfigWarningsThisRun.add(e),r.warn?.(`No configuration file found in project: ${a}`))}return null}var J={anthropic:[{id:`claude-sonnet-4-20250514`,swe_score:.727,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:64e3,supported:!0},{id:`claude-opus-4-20250514`,swe_score:.725,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`],max_tokens:32e3,supported:!0},{id:`claude-3-7-sonnet-20250219`,swe_score:.623,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:12e4,supported:!0},{id:`claude-3-5-sonnet-20241022`,swe_score:.49,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:8192,supported:!0},{id:`claude-sonnet-4-5`,name:`Claude Sonnet 4.5`,swe_score:.772,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`],max_tokens:64e3,supported:!0},{id:`claude-haiku-4-5`,name:`Claude Haiku 4.5`,swe_score:.733,cost_per_1m_tokens:{input:1,output:5},allowed_roles:[`main`,`fallback`],max_tokens:2e5,supported:!0},{id:`claude-opus-4-1`,name:`Claude Opus 4.1`,swe_score:.745,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`],max_tokens:32e3,supported:!0},{id:`claude-opus-4-5`,name:`Claude Opus 4.5`,swe_score:.809,cost_per_1m_tokens:{input:5,output:25},allowed_roles:[`main`,`fallback`],max_tokens:32e3,supported:!0}],"claude-code":[{id:`opus`,swe_score:.725,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32e3,supported:!0},{id:`sonnet`,swe_score:.727,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:64e3,supported:!0},{id:`haiku`,swe_score:.45,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:2e5,supported:!0}],"codex-cli":[{id:`gpt-5.3-codex`,name:`GPT-5.3 Codex`,swe_score:.84,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.2-codex`,name:`GPT-5.2 Codex`,swe_score:.82,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.1-codex-max`,name:`GPT-5.1 Codex Max`,swe_score:.78,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.1-codex-mini`,name:`GPT-5.1 Codex Mini`,swe_score:.72,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`],supported:!0},{id:`gpt-5.2`,name:`GPT-5.2`,swe_score:.8,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0}],mcp:[{id:`mcp-sampling`,swe_score:null,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:1e5,supported:!0}],"gemini-cli":[{id:`gemini-3-flash-preview`,name:`Gemini 3 Flash`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:1048576,supported:!0},{id:`gemini-3-pro-preview`,swe_score:.762,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0},{id:`gemini-2.5-pro`,swe_score:.72,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0},{id:`gemini-2.5-flash`,swe_score:.71,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0}],"grok-cli":[{id:`grok-4-latest`,name:`Grok 4 Latest`,swe_score:.7,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-latest`,name:`Grok 3 Latest`,swe_score:.65,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-fast`,name:`Grok 3 Fast`,swe_score:.6,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-mini-fast`,name:`Grok 3 Mini Fast`,swe_score:.55,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0}],openai:[{id:`gpt-4o`,swe_score:.332,cost_per_1m_tokens:{input:2.5,output:10},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`o1`,swe_score:.489,cost_per_1m_tokens:{input:15,output:60},allowed_roles:[`main`],supported:!0},{id:`o3`,swe_score:.5,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`o3-mini`,swe_score:.493,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`],max_tokens:1e5,supported:!0},{id:`o4-mini`,swe_score:.45,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],supported:!0},{id:`o1-mini`,swe_score:.4,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`],supported:!0},{id:`o1-pro`,swe_score:0,cost_per_1m_tokens:{input:150,output:600},allowed_roles:[`main`],supported:!0},{id:`gpt-4-5-preview`,swe_score:.38,cost_per_1m_tokens:{input:75,output:150},allowed_roles:[`main`],supported:!0},{id:`gpt-4-1-mini`,swe_score:0,cost_per_1m_tokens:{input:.4,output:1.6},allowed_roles:[`main`],supported:!0},{id:`gpt-4-1-nano`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.4},allowed_roles:[`main`],supported:!0},{id:`gpt-4o-mini`,swe_score:.3,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`],supported:!0},{id:`gpt-4o-search-preview`,swe_score:.33,cost_per_1m_tokens:{input:2.5,output:10},allowed_roles:[`research`],supported:!0},{id:`gpt-4o-mini-search-preview`,swe_score:.3,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`research`],supported:!0},{id:`gpt-5`,swe_score:.749,cost_per_1m_tokens:{input:5,output:20},allowed_roles:[`main`,`fallback`],max_tokens:1e5,temperature:1,supported:!0},{id:`gpt-5.1`,swe_score:.76,cost_per_1m_tokens:{input:1.25,output:10},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`],supported:!0},{id:`gpt-5.1-codex-max`,swe_score:.78,cost_per_1m_tokens:{input:1.25,output:10},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.2`,swe_score:.8,cost_per_1m_tokens:{input:1.75,output:14},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0},{id:`gpt-5.2-pro`,swe_score:.82,cost_per_1m_tokens:{input:21,output:168},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`medium`,`high`,`xhigh`],supported:!0}],google:[{id:`gemini-3-flash-preview`,name:`Gemini 3 Flash`,swe_score:0,cost_per_1m_tokens:{input:.5,output:3},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`gemini-3-pro-preview`,swe_score:.762,cost_per_1m_tokens:{input:2,output:12},allowed_roles:[`main`,`fallback`,`research`],max_tokens:1e6,supported:!0},{id:`gemini-2.5-pro-preview-05-06`,swe_score:.638,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.5-pro-preview-03-25`,swe_score:.638,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.5-flash-preview-04-17`,swe_score:.604,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.0-flash`,swe_score:.518,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0},{id:`gemini-2.0-flash-lite`,swe_score:0,cost_per_1m_tokens:null,allowed_roles:[`main`,`fallback`],max_tokens:1048e3,supported:!0}],xai:[{id:`grok-3`,name:`Grok 3`,swe_score:null,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-3-fast`,name:`Grok 3 Fast`,swe_score:0,cost_per_1m_tokens:{input:5,output:25},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`grok-4`,name:`Grok 4`,swe_score:null,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0}],groq:[{id:`moonshotai/kimi-k2-instruct`,swe_score:.66,cost_per_1m_tokens:{input:1,output:3},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`llama-3.3-70b-versatile`,swe_score:.55,cost_per_1m_tokens:{input:.59,output:.79},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`llama-3.1-8b-instant`,swe_score:.32,cost_per_1m_tokens:{input:.05,output:.08},allowed_roles:[`main`,`fallback`],max_tokens:131072,supported:!0},{id:`llama-4-scout`,swe_score:.45,cost_per_1m_tokens:{input:.11,output:.34},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`llama-4-maverick`,swe_score:.52,cost_per_1m_tokens:{input:.5,output:.77},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`mixtral-8x7b-32768`,swe_score:.35,cost_per_1m_tokens:{input:.24,output:.24},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!0},{id:`qwen-qwq-32b-preview`,swe_score:.4,cost_per_1m_tokens:{input:.18,output:.18},allowed_roles:[`main`,`fallback`,`research`],max_tokens:32768,supported:!0},{id:`deepseek-r1-distill-llama-70b`,swe_score:.52,cost_per_1m_tokens:{input:.75,output:.99},allowed_roles:[`main`,`research`],max_tokens:8192,supported:!0},{id:`gemma2-9b-it`,swe_score:.3,cost_per_1m_tokens:{input:.2,output:.2},allowed_roles:[`main`,`fallback`],max_tokens:8192,supported:!0},{id:`whisper-large-v3`,swe_score:0,cost_per_1m_tokens:{input:.11,output:0},allowed_roles:[`main`],max_tokens:0,supported:!0}],perplexity:[{id:`sonar-pro`,swe_score:0,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`research`],max_tokens:8700,supported:!0},{id:`sonar`,swe_score:0,cost_per_1m_tokens:{input:1,output:1},allowed_roles:[`research`],max_tokens:8700,supported:!0},{id:`sonar-deep-research`,swe_score:.211,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`research`],max_tokens:8700,supported:!0},{id:`sonar-reasoning-pro`,swe_score:.211,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`research`,`fallback`],max_tokens:8700,supported:!0},{id:`sonar-reasoning`,swe_score:.211,cost_per_1m_tokens:{input:1,output:5},allowed_roles:[`main`,`research`,`fallback`],max_tokens:8700,supported:!0}],openrouter:[{id:`google/gemini-2.5-flash-preview-05-20`,swe_score:0,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`google/gemini-2.5-flash-preview-05-20:thinking`,swe_score:0,cost_per_1m_tokens:{input:.15,output:3.5},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`google/gemini-2.5-pro-exp-03-25`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`deepseek/deepseek-chat-v3-0324:free`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:163840,supported:!1,reason:`Free OpenRouter models are not supported due to severe rate limits, lack of tool use support, and other reliability issues that make them impractical for production use.`},{id:`deepseek/deepseek-chat-v3-0324`,swe_score:0,cost_per_1m_tokens:{input:.27,output:1.1},allowed_roles:[`main`],max_tokens:64e3,supported:!0},{id:`openai/gpt-4.1`,swe_score:0,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`openai/gpt-4.1-mini`,swe_score:0,cost_per_1m_tokens:{input:.4,output:1.6},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`openai/gpt-4.1-nano`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.4},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`openai/o3`,swe_score:0,cost_per_1m_tokens:{input:10,output:40},allowed_roles:[`main`,`fallback`],max_tokens:2e5,supported:!0},{id:`openai/codex-mini`,swe_score:0,cost_per_1m_tokens:{input:1.5,output:6},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/gpt-4o-mini`,swe_score:0,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/o4-mini`,swe_score:.45,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/o4-mini-high`,swe_score:0,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`openai/o1-pro`,swe_score:0,cost_per_1m_tokens:{input:150,output:600},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`meta-llama/llama-3.3-70b-instruct`,swe_score:0,cost_per_1m_tokens:{input:120,output:600},allowed_roles:[`main`,`fallback`],max_tokens:1048576,supported:!0},{id:`meta-llama/llama-4-maverick`,swe_score:0,cost_per_1m_tokens:{input:.18,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`meta-llama/llama-4-scout`,swe_score:0,cost_per_1m_tokens:{input:.08,output:.3},allowed_roles:[`main`,`fallback`],max_tokens:1e6,supported:!0},{id:`qwen/qwen-max`,swe_score:0,cost_per_1m_tokens:{input:1.6,output:6.4},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!0},{id:`qwen/qwen-turbo`,swe_score:0,cost_per_1m_tokens:{input:.05,output:.2},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!0},{id:`qwen/qwen3-235b-a22b`,swe_score:0,cost_per_1m_tokens:{input:.14,output:2},allowed_roles:[`main`,`fallback`],max_tokens:24e3,supported:!0},{id:`mistralai/mistral-small-3.1-24b-instruct:free`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:96e3,supported:!1,reason:`Free OpenRouter models are not supported due to severe rate limits, lack of tool use support, and other reliability issues that make them impractical for production use.`},{id:`mistralai/mistral-small-3.1-24b-instruct`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.3},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`mistralai/devstral-small`,swe_score:0,cost_per_1m_tokens:{input:.1,output:.3},allowed_roles:[`main`],max_tokens:11e4,supported:!0},{id:`mistralai/mistral-nemo`,swe_score:0,cost_per_1m_tokens:{input:.03,output:.07},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0},{id:`thudm/glm-4-32b:free`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:32768,supported:!1,reason:`Free OpenRouter models are not supported due to severe rate limits, lack of tool use support, and other reliability issues that make them impractical for production use.`}],zai:[{id:`glm-4.6`,swe_score:.68,cost_per_1m_tokens:{input:.6,output:2.2},allowed_roles:[`main`,`fallback`,`research`],max_tokens:204800,supported:!0},{id:`glm-4.5`,swe_score:.65,cost_per_1m_tokens:{input:.6,output:2.2},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`glm-4.5-air`,swe_score:.62,cost_per_1m_tokens:{input:.2,output:1.1},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0}],"zai-coding":[{id:`glm-4.6`,swe_score:.68,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:204800,supported:!0},{id:`glm-4.5`,swe_score:.65,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0},{id:`glm-4.5-air`,swe_score:.62,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`,`research`],max_tokens:131072,supported:!0}],ollama:[{id:`gpt-oss:latest`,swe_score:.607,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`gpt-oss:20b`,swe_score:.607,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`gpt-oss:120b`,swe_score:.624,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],max_tokens:128e3,supported:!0},{id:`devstral:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`qwen3:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`qwen3:14b`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`qwen3:32b`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`mistral-small3.1:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`llama3.3:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0},{id:`phi4:latest`,swe_score:0,cost_per_1m_tokens:{input:0,output:0},allowed_roles:[`main`,`fallback`],supported:!0}],azure:[{id:`gpt-4o`,swe_score:.332,cost_per_1m_tokens:{input:2.5,output:10},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`gpt-4o-mini`,swe_score:.3,cost_per_1m_tokens:{input:.15,output:.6},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`gpt-4-1`,swe_score:0,cost_per_1m_tokens:{input:2,output:10},allowed_roles:[`main`,`fallback`],max_tokens:16384,supported:!0},{id:`gpt-5`,name:`GPT-5`,swe_score:.749,cost_per_1m_tokens:{input:5,output:20},allowed_roles:[`main`,`fallback`],max_tokens:1e5,temperature:1,supported:!0,api_type:`responses`},{id:`o1`,name:`o1`,swe_score:.489,cost_per_1m_tokens:{input:15,output:60},allowed_roles:[`main`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`o3`,name:`o3`,swe_score:.5,cost_per_1m_tokens:{input:2,output:8},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`o3-mini`,name:`o3-mini`,swe_score:.493,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`o4-mini`,name:`o4-mini`,swe_score:.45,cost_per_1m_tokens:{input:1.1,output:4.4},allowed_roles:[`main`,`fallback`],max_tokens:1e5,supported:!0,api_type:`responses`},{id:`gpt-5.1`,name:`GPT-5.1`,swe_score:.76,cost_per_1m_tokens:{input:1.25,output:10},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`],supported:!0,api_type:`responses`},{id:`gpt-5.2`,name:`GPT-5.2`,swe_score:.8,cost_per_1m_tokens:{input:1.75,output:14},allowed_roles:[`main`,`fallback`],max_tokens:128e3,reasoning_efforts:[`none`,`low`,`medium`,`high`,`xhigh`],supported:!0,api_type:`responses`}],bedrock:[{id:`us.anthropic.claude-3-haiku-20240307-v1:0`,swe_score:.4,cost_per_1m_tokens:{input:.25,output:1.25},allowed_roles:[`main`,`fallback`],supported:!0},{id:`us.anthropic.claude-3-opus-20240229-v1:0`,swe_score:.725,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-3-5-sonnet-20240620-v1:0`,swe_score:.49,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-3-5-sonnet-20241022-v2:0`,swe_score:.49,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-3-7-sonnet-20250219-v1:0`,swe_score:.623,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],max_tokens:65536,supported:!0},{id:`us.anthropic.claude-3-5-haiku-20241022-v1:0`,swe_score:.4,cost_per_1m_tokens:{input:.8,output:4},allowed_roles:[`main`,`fallback`],supported:!0},{id:`us.anthropic.claude-opus-4-20250514-v1:0`,swe_score:.725,cost_per_1m_tokens:{input:15,output:75},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.anthropic.claude-sonnet-4-20250514-v1:0`,swe_score:.727,cost_per_1m_tokens:{input:3,output:15},allowed_roles:[`main`,`fallback`,`research`],supported:!0},{id:`us.deepseek.r1-v1:0`,swe_score:0,cost_per_1m_tokens:{input:1.35,output:5.4},allowed_roles:[`research`],max_tokens:65536,supported:!0}]};const ji=ge(import.meta.url);c.dirname(ji);const Y={models:{main:{provider:`codex-cli`,modelId:`gpt-5.3-codex`,maxTokens:32e3,temperature:.2},research:{provider:`codex-cli`,modelId:`gpt-5.3-codex`,maxTokens:32e3,temperature:.1},fallback:{provider:`codex-cli`,modelId:`gpt-5.3-codex`,maxTokens:32e3,temperature:.2}},global:{logLevel:`info`,debug:!1,defaultNumTasks:10,defaultSubtasks:5,defaultPriority:`medium`,projectName:`Task Master`,ollamaBaseURL:`http://localhost:11434/api`,bedrockBaseURL:`https://bedrock.us-east-1.amazonaws.com`,responseLanguage:`Chinese`,enableCodebaseAnalysis:`auto`,enableProxy:!1,anonymousTelemetry:!0},claudeCode:{},codexCli:{approvalMode:`never`,sandboxMode:`danger-full-access`,fullAuto:!0,skipGitRepoCheck:!0,reasoningEffort:`xhigh`},grokCli:{timeout:12e4,workingDirectory:null,defaultModel:`grok-4-latest`}};let Mi=null,Ni=null;function Pi(e){global._tmSuppressConfigWarnings=e}function Fi(){return global._tmSuppressConfigWarnings===!0}var Ii=class extends Error{constructor(e){super(e),this.name=`ConfigurationError`}};function Li(e=null,t={}){let n=Y,r=e,{storageType:a}=t;e&&`${e}`,r||(r=V(),r||=process.cwd(),`${r}`);let o=null,l={...n};if((s.existsSync(c.join(r,Fr))||s.existsSync(c.join(r,z)))&&(o=Ai(null,{projectRoot:r,storageType:a})),o){let e=o.endsWith(z);try{let t=s.readFileSync(o,`utf-8`),r=JSON.parse(t);l={models:{main:{...n.models.main,...r?.models?.main},research:{...n.models.research,...r?.models?.research},fallback:r?.models?.fallback?.provider&&r?.models?.fallback?.modelId?{...n.models.fallback,...r.models.fallback}:{...n.models.fallback}},global:{...n.global,...r?.global},claudeCode:{...n.claudeCode,...r?.claudeCode},codexCli:{...n.codexCli,...r?.codexCli},grokCli:{...n.grokCli,...r?.grokCli}},`${o}`,e&&console.warn(i.yellow(`⚠️ DEPRECATION WARNING: Found configuration in legacy location '${o}'. Please migrate to .taskmaster/config.json. Run 'task-master migrate' to automatically migrate your project.`)),Ri(l.models.main.provider)||(console.warn(i.yellow(`Warning: Invalid main provider "${l.models.main.provider}" in ${o}. Falling back to default.`)),l.models.main={...n.models.main}),Ri(l.models.research.provider)||(console.warn(i.yellow(`Warning: Invalid research provider "${l.models.research.provider}" in ${o}. Falling back to default.`)),l.models.research={...n.models.research}),l.models.fallback?.provider&&!Ri(l.models.fallback.provider)&&(console.warn(i.yellow(`Warning: Invalid fallback provider "${l.models.fallback.provider}" in ${o}. Fallback model configuration will be ignored.`)),l.models.fallback.provider=void 0,l.models.fallback.modelId=void 0),l.claudeCode&&!gi(l.claudeCode)&&(l.claudeCode=Bi(l.claudeCode)),l.codexCli&&!gi(l.codexCli)&&(l.codexCli=Vi(l.codexCli))}catch(e){console.error(i.red(`Error reading or parsing ${o}: ${e.message}. Using default configuration.`)),l={...n},`${o}`}}else{if(!Fi()&&a!==`api`)if(e)console.warn(i.yellow(`Warning: Configuration file not found at provided project root (${e}). Using default configuration. Run 'task-master models --setup' to configure.`));else{let e=s.existsSync(c.join(r,Fr)),t=s.existsSync(c.join(r,z));(e||t)&&console.warn(i.yellow(`Warning: Configuration file not found at derived root (${r}). Using defaults.`))}l={...n},`${r}`}return l}function X(e=null,t=!1,n={}){if(!Mi||t||e&&e!==Ni){let r=Li(e,n);return(t||e)&&(Mi=r,Ni=e),r}return Mi}function Ri(e){return Re.includes(e)?!0:Le.includes(e)?!!(J&&J[e]):!1}function zi(e){return J[e]?J[e].filter(e=>e.supported!==!1).map(e=>e.id):[]}function Bi(e){let t=C.object({pathToClaudeCodeExecutable:C.string().optional(),maxTurns:C.number().int().positive().optional(),customSystemPrompt:C.string().optional(),appendSystemPrompt:C.string().optional(),permissionMode:C.enum([`default`,`acceptEdits`,`plan`,`bypassPermissions`]).optional(),allowedTools:C.array(C.string()).optional(),disallowedTools:C.array(C.string()).optional(),mcpServers:C.record(C.string(),C.object({type:C.enum([`stdio`,`sse`]).optional(),command:C.string(),args:C.array(C.string()).optional(),env:C.record(C.string(),C.string()).optional(),url:C.url().optional(),headers:C.record(C.string(),C.string()).optional()})).optional()}),n=C.record(C.string(),t).refine(e=>Object.keys(e||{}).every(e=>Pr.includes(e)),{message:`Invalid command name in commandSpecific`}),r=t.extend({commandSpecific:n.optional()}),a={};try{a=r.parse(e)}catch(e){console.warn(i.yellow(`Warning: Invalid Claude Code settings in config: ${e.message}. Falling back to default.`)),a={}}return a}function Vi(e){let t=C.object({codexPath:C.string().optional(),cwd:C.string().optional(),approvalMode:C.enum([`untrusted`,`on-failure`,`on-request`,`never`]).optional(),sandboxMode:C.enum([`read-only`,`workspace-write`,`danger-full-access`]).optional(),fullAuto:C.boolean().optional(),dangerouslyBypassApprovalsAndSandbox:C.boolean().optional(),skipGitRepoCheck:C.boolean().optional(),color:C.enum([`always`,`never`,`auto`]).optional(),allowNpx:C.boolean().optional(),outputLastMessageFile:C.string().optional(),env:C.record(C.string(),C.string()).optional(),verbose:C.boolean().optional(),logger:C.union([C.object({}).passthrough(),C.literal(!1)]).optional(),reasoningEffort:C.enum([`none`,`minimal`,`low`,`medium`,`high`,`xhigh`]).optional()}),n=C.record(C.string(),t).refine(e=>Object.keys(e||{}).every(e=>Pr.includes(e)),{message:`Invalid command name in commandSpecific`}),r=t.extend({commandSpecific:n.optional()});try{return r.parse(e)}catch(e){return console.warn(i.yellow(`Warning: Invalid Codex CLI settings in config: ${e.message}. Falling back to default.`)),{}}}function Hi(e=null,t=!1){let n=X(e,t);return{...Y.claudeCode,...n?.claudeCode||{}}}function Ui(e=null,t=!1){let n=X(e,t);return{...Y.codexCli,...n?.codexCli||{}}}function Wi(e,t=null,n=!1){let r=Ui(t,n),i=r?.commandSpecific||{};return{...r,...i[e]}}function Gi(e,t=null,n=!1){let r=Hi(t,n),i=r?.commandSpecific||{};return{...r,...i[e]}}function Ki(e=null,t=!1){let n=X(e,t);return{...Y.grokCli,...n?.grokCli||{}}}function qi(e,t=null,n=!1){let r=Ki(t,n),i=r?.commandSpecific||{};return{...r,...i[e]}}function Z(e,t=null){return X(t)?.models?.[e]||(U(`warn`,`No model configuration found for role: ${e}. Returning default.`),Y.models[e]||{})}function Ji(e=null){return Z(`main`,e).provider}function Yi(e=null){return Z(`main`,e).modelId}function Xi(e=null){return Z(`research`,e).provider}function Zi(e){if(typeof e==`boolean`)return e?`always`:`never`;if(typeof e==`string`){let t=e.trim().toLowerCase();if(t===`true`||t===`1`||t===`always`||t===`on`||t===`enabled`)return`always`;if(t===`false`||t===`0`||t===`never`||t===`off`||t===`disabled`)return`never`;if(t===`auto`)return`auto`}return`auto`}function Qi(e=null,t=null){let n=B(`TASKMASTER_ENABLE_CODEBASE_ANALYSIS`,e,t);return n!=null&&n!==``?Zi(n):e?.env?.TASKMASTER_ENABLE_CODEBASE_ANALYSIS?Zi(e.env.TASKMASTER_ENABLE_CODEBASE_ANALYSIS):Zi(Q(t).enableCodebaseAnalysis)}function $i(e=!1,t=null,n=null){if(Qi(n,t)===`never`)return!1;let r=e?Xi(t):Ji(t);return r===j.CLAUDE_CODE||r===j.GEMINI_CLI||r===j.GROK_CLI||r===j.CODEX_CLI}function ea(e=null){return Z(`research`,e).modelId}function ta(e=null){return Z(`fallback`,e).provider}function na(e=null){return Z(`fallback`,e).modelId}function Q(e=null){let t=X(e);return{...Y.global,...t?.global||{}}}function ra(e=null){return Q(e).logLevel.toLowerCase()}function $(e=null){return Q(e).debug===!0}function ia(e=null){let t=Q(e).defaultSubtasks,n=parseInt(t,10);return Number.isNaN(n)?Y.global.defaultSubtasks:n}function aa(e=null){let t=Q(e).defaultNumTasks,n=parseInt(t,10);return Number.isNaN(n)?Y.global.defaultNumTasks:n}function oa(e=null){return Q(e).defaultPriority}function sa(e=null){return Q(e).projectName}function ca(e=null){return Q(e).ollamaBaseURL}function la(e=null){return Q(e).azureBaseURL}function ua(e=null){return Q(e).bedrockBaseURL}function da(e=null){return Q(e).vertexProjectId}function fa(e=null){return Q(e).vertexLocation}function pa(e=null){return Q(e).responseLanguage}function ma(e=null){return Q(e).enableProxy===!0}function ha(e=null){return Q(e).anonymousTelemetry!==!1}function ga(e=null,t=null){let n=B(`TASKMASTER_ENABLE_PROXY`,e,t);if(n!=null&&n!==``)return n.toLowerCase()===`true`||n===`1`;if(e?.env?.TASKMASTER_ENABLE_PROXY){let t=e.env.TASKMASTER_ENABLE_PROXY;return t.toLowerCase()===`true`||t===`1`}return ma(t)}function _a(e,t=null){let n=Z(e,t),r=n.maxTokens,i=n.temperature,a=n.modelId,o=n.provider,s=r,c=i;try{let e=J[o];if(e&&Array.isArray(e)){let t=e.find(e=>e.id===a);if(t&&typeof t.max_tokens==`number`&&t.max_tokens>0){let e=t.max_tokens;s=Math.min(r,e),U(`debug`,`Applying model-specific max_tokens (${e}) for ${a}. Effective limit: ${s}`)}else U(`debug`,`No valid model-specific max_tokens override found for ${a}. Using role default: ${r}`);t&&typeof t.temperature==`number`&&t.temperature>=0&&t.temperature<=1&&(c=t.temperature,U(`debug`,`Applying model-specific temperature (${t.temperature}) for ${a}`))}else o===j.OPENROUTER?(s=Math.min(r,32768),U(`debug`,`Custom OpenRouter model ${a} detected. Using conservative max_tokens: ${s}`)):U(`debug`,`No model definitions found for provider ${o} in MODEL_MAP. Using role default maxTokens: ${r}`)}catch(e){U(`warn`,`Error looking up model-specific parameters for ${a}: ${e.message}. Using role defaults.`),s=r,c=i}return{maxTokens:s,temperature:c}}function va(e,t=null,n=null){if([j.OLLAMA,j.BEDROCK,j.GEMINI_CLI,j.GROK_CLI,j.MCP,j.CODEX_CLI].includes(e?.toLowerCase())||e?.toLowerCase()===`claude-code`||e?.toLowerCase()===`codex-cli`)return!0;let r={openai:`OPENAI_API_KEY`,anthropic:`ANTHROPIC_API_KEY`,google:`GOOGLE_API_KEY`,perplexity:`PERPLEXITY_API_KEY`,mistral:`MISTRAL_API_KEY`,azure:`AZURE_OPENAI_API_KEY`,openrouter:`OPENROUTER_API_KEY`,xai:`XAI_API_KEY`,zai:`ZAI_API_KEY`,"zai-coding":`ZAI_API_KEY`,groq:`GROQ_API_KEY`,vertex:`GOOGLE_API_KEY`,"claude-code":`CLAUDE_CODE_API_KEY`,bedrock:`AWS_ACCESS_KEY_ID`},i=e?.toLowerCase();if(!i||!r[i])return U(`warn`,`Unknown provider name: ${e} in isApiKeySet check.`),!1;let a=r[i],o=B(a,t,n);return o&&o.trim()!==``&&!/YOUR_.*_API_KEY_HERE/.test(o)&&!o.includes(`KEY_HERE`)}function ya(e,t=null){let n=t||V();if(!n)return console.warn(i.yellow(`Warning: Could not find project root to check mcp.json.`)),!1;let r=c.join(n,`.cursor`,`mcp.json`);if(!s.existsSync(r))return!1;try{let t=s.readFileSync(r,`utf-8`),n=JSON.parse(t),i=n?.mcpServers?.[`task-master-ai`]?.env||n?.mcpServers?.[`taskmaster-ai`]?.env;if(!i)return!1;let a=null;switch(e){case`anthropic`:a=i.ANTHROPIC_API_KEY;break;case`openai`:a=i.OPENAI_API_KEY;break;case`openrouter`:a=i.OPENROUTER_API_KEY;break;case`google`:a=i.GOOGLE_API_KEY;break;case`perplexity`:a=i.PERPLEXITY_API_KEY;break;case`xai`:a=i.XAI_API_KEY;break;case`zai`:case`zai-coding`:a=i.ZAI_API_KEY;break;case`groq`:a=i.GROQ_API_KEY;break;case`ollama`:return!0;case`claude-code`:return!0;case`codex-cli`:return!0;case`mistral`:a=i.MISTRAL_API_KEY;break;case`azure`:a=i.AZURE_OPENAI_API_KEY;break;case`vertex`:a=i.GOOGLE_API_KEY;break;case`bedrock`:a=i.AWS_ACCESS_KEY_ID;break;default:return!1}return!!a&&!/KEY_HERE$/.test(a)}catch(e){return console.error(i.red(`Error reading or parsing .cursor/mcp.json: ${e.message}`)),!1}}function ba(){let e=[];for(let[t,n]of Object.entries(J))n.length>0?n.filter(e=>!!e.supported).forEach(n=>{let r=n.id,i=n.swe_score,a=n.cost_per_1m_tokens,o=n.allowed_roles||[`main`,`fallback`],s=n.name;s||(s=r.split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(` `),r===`claude-3.5-sonnet-20240620`&&(s=`Claude 3.5 Sonnet`),r===`claude-3-7-sonnet-20250219`&&(s=`Claude 3.7 Sonnet`),r===`gpt-4o`&&(s=`GPT-4o`),r===`gpt-4-turbo`&&(s=`GPT-4 Turbo`),r===`sonar-pro`&&(s=`Perplexity Sonar Pro`),r===`sonar-mini`&&(s=`Perplexity Sonar Mini`)),e.push({id:r,name:s,provider:t,swe_score:i,cost_per_1m_tokens:a,allowed_roles:o,max_tokens:n.max_tokens})}):e.push({id:`[${t}-any]`,name:`Any (${t})`,provider:t});return e}function xa(e,t=null){let n=t;if(t==null){let e=V();if(!e)return console.error(i.red(`Error: Could not determine project root. Configuration not saved.`)),!1;n=e}let r=c.join(n,`.taskmaster`),a=c.join(r,`config.json`);try{return s.existsSync(r)||s.mkdirSync(r,{recursive:!0}),s.writeFileSync(a,JSON.stringify(e,null,2)),Mi=e,!0}catch(e){return console.error(i.red(`Error writing configuration to ${a}: ${e.message}`)),!1}}function Sa(e=null){return Ai(null,{projectRoot:e})!==null}function Ca(e=null){let t=X(e);return t.global||={},t.global.userId||(t.global.userId=`1234567890`,xa(t,e)||U(`warning`,`Failed to write updated configuration with new userId. Please let the developers know.`)),t.global.userId}function wa(){return ze}function Ta(e,t=null){let n=Z(e,t);if(n&&typeof n.baseURL==`string`)return n.baseURL;let r=n?.provider;if(r)return B(`${r.toUpperCase()}_BASE_URL`,null,t)}async function Ea(e){if(e===`solo`||e===`team`)return e;try{Pi(!0);let e=X(null,!1,{storageType:`api`});if(e?.storage?.operatingMode)return e.storage.operatingMode}catch{}finally{Pi(!1)}try{if(await M.getInstance().getAuthCredentials())return`team`}catch{}return`solo`}j.OLLAMA,j.BEDROCK,j.GEMINI_CLI,j.GROK_CLI,j.MCP,j.CODEX_CLI;export{Ei as $,xr as $t,ma as A,hi as At,Sa as B,Br as Bt,Yi as C,Le as Cn,ii as Ct,Ea as D,ve as Dn,xi as Dt,ca as E,O as En,B as Et,Ca as F,Wr as Ft,Vi as G,Ir as Gt,ga as H,Lr as Ht,fa as I,Jr as It,J,Nr as Jt,Ri as K,Gr as Kt,da as L,z as Lt,Xi as M,ci as Mt,pa as N,Hr as Nt,_a as O,be as On,fi as Ot,zi as P,qr as Pt,q as Q,Sr as Qt,$i as R,Kr as Rt,ra as S,Re as Sn,W as St,ya as T,k as Tn,ri as Tt,Pi as U,Rr as Ut,Fi as V,Fr as Vt,Bi as W,Vr as Wt,Ai as X,Dr as Xt,Oi as Y,Tr as Yt,Di as Z,Er as Zt,ia as _,nt as _n,gi as _t,la as a,ar as an,oi as at,Ki as b,ze as bn,si as bt,Hi as c,nr as cn,wi as ct,Ui as d,Mt as dn,mi as dt,gr as en,K as et,Wi as f,wt as fn,ui as ft,oa as g,tt as gn,Si as gt,aa as h,M as hn,bi as ht,ba as i,sr as in,yi as it,ea as j,Qr as jt,sa as k,ye as kn,vi as kt,Gi as l,er as ln,_i as lt,$ as m,N as mn,pi as mt,wa as n,hr as nn,H as nt,Ta as o,or as on,ei as ot,X as p,_t as pn,Ci as pt,xa as q,zr as qt,ha as r,_r as rn,di as rt,ua as s,ir as sn,$r as st,Ii as t,vr as tn,ki as tt,Qi as u,It as un,V as ut,na as v,Qe as vn,ti as vt,Ji as w,ke as wn,li as wt,qi as x,j as xn,ai as xt,ta as y,et as yn,U as yt,va as z,Ur as zt};
|