Skip to content

Commit 916e8d6

Browse files
committed
feat: align with latest task-master-ai features
- Add Tags & Workstreams menu (list, add, use, rename, copy, remove) - Add Research menu with optional context and file-tree support - Add cross-tag task move (--from-tag, --to-tag, --with-dependencies, --ignore-dependencies) - Add show multiple tasks via comma-separated IDs - Add 'rules add' support in init menu - Add Groq provider models (llama-3.3-70b, llama-3.1-8b, deepseek-r1-distill-llama-70b) - Add Claude Code no-key models (claude-code/sonnet, claude-code/opus) - Extend T_Provider type to include 'groq' - Update .env.example: add GROQ_API_KEY, TASK_MASTER_TOOLS comment, fix typos - Update NOTE_MODELS to mention Groq and Claude Code
1 parent fc20f8d commit 916e8d6

8 files changed

Lines changed: 648 additions & 12 deletions

File tree

.env.example

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ ANTHROPIC_API_KEY="your_anthropic_api_key_here" # Required: Format: sk-ant
33
PERPLEXITY_API_KEY="your_perplexity_api_key_here" # Optional: Format: pplx-...
44
OPENAI_API_KEY="your_openai_api_key_here" # Optional, for OpenAI/OpenRouter models. Format: sk-proj-...
55
GOOGLE_API_KEY="your_google_api_key_here" # Optional, for Google Gemini models.
6-
GEMINI_API_KEY="your_gemini_api_key_here"
76
MISTRAL_API_KEY="your_mistral_key_here" # Optional, for Mistral AI models.
8-
XAI_API_KEY="YOUR_XAI_KEY_HERE" # Optional, for xAI AI models.
7+
GROQ_API_KEY="your_groq_api_key_here" # Optional, for Groq models. Format: gsk_...
8+
XAI_API_KEY="your_xai_key_here" # Optional, for xAI AI models.
99
AZURE_OPENAI_API_KEY="your_azure_key_here" # Optional, for Azure OpenAI models (requires endpoint in .taskmaster/config.json).
1010
OLLAMA_API_KEY="your_ollama_api_key_here" # Optional: For remote Ollama servers that require authentication.
1111
GITHUB_API_KEY="your_github_api_key_here" # Optional: For GitHub import/export features. Format: ghp_... or github_pat_...
12-
OPENROUTER_API_KEY="your_openrouter_api_key_here" # Optional: For OpenRouter models. Format: sk-proj-...
12+
OPENROUTER_API_KEY="your_openrouter_api_key_here" # Optional: For OpenRouter models. Format: sk-or-...
13+
14+
# MCP Tool Loading (optional - controls which tools are loaded by the MCP server)
15+
# Options: "all" (default, 36 tools), "standard" (15 tools), "core" (7 tools), or comma-separated list
16+
# TASK_MASTER_TOOLS="standard"

src/@types/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export const VALID_PROVIDERS = [
66
"bedrock",
77
"azure",
88
"vertex",
9+
"groq",
910
] as const;
1011

1112
export type T_Provider = (typeof VALID_PROVIDERS)[number];

src/constants/index.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,18 +63,47 @@ const MODELS_COMPATIBILITY = {
6363
low: "🟣",
6464
};
6565
export const AI_MODELS: I_AIModel[] = [
66+
// --- No API key required ---
6667
{
67-
name: `${MODELS_COMPATIBILITY.high} Gemini 2.5 Flash (free) ${chalk.gray("(google > free | 1M context)")}`,
68+
name: `${MODELS_COMPATIBILITY.high} Claude Code / Sonnet ${chalk.gray("(claude-code > no API key | requires Claude Code CLI)")}`,
69+
value: "claude-code/sonnet",
70+
provider: null,
71+
},
72+
{
73+
name: `${MODELS_COMPATIBILITY.high} Claude Code / Opus ${chalk.gray("(claude-code > no API key | requires Claude Code CLI)")}`,
74+
value: "claude-code/opus",
75+
provider: null,
76+
},
77+
// --- Google ---
78+
{
79+
name: `${MODELS_COMPATIBILITY.high} Gemini 2.5 Flash (free) ${chalk.gray("(google > free | 1M context)")}`,
6880
value: "gemini-2.5-flash",
6981
provider: null,
7082
},
7183
{
72-
name: `${MODELS_COMPATIBILITY.high} Gemini 2.5 Pro (free) ${chalk.gray("(google > free | 1M context)")}`,
84+
name: `${MODELS_COMPATIBILITY.high} Gemini 2.5 Pro (free) ${chalk.gray("(google > free | 1M context)")}`,
7385
value: "gemini-2.5-pro",
7486
provider: null,
7587
},
88+
// --- Groq ---
89+
{
90+
name: `${MODELS_COMPATIBILITY.high} Llama 3.3 70B (Groq) ${chalk.gray("(groq > $0.05/M input | $0.10/M output | 128k context)")}`,
91+
value: "llama-3.3-70b-versatile",
92+
provider: "groq",
93+
},
94+
{
95+
name: `${MODELS_COMPATIBILITY.high} Llama 3.1 8B (Groq) ${chalk.gray("(groq > free tier | 128k context)")}`,
96+
value: "llama-3.1-8b-instant",
97+
provider: "groq",
98+
},
99+
{
100+
name: `${MODELS_COMPATIBILITY.medium} DeepSeek R1 Distill Llama 70B (Groq) ${chalk.gray("(groq > $0.07/M input | $0.17/M output | 128k context)")}`,
101+
value: "deepseek-r1-distill-llama-70b",
102+
provider: "groq",
103+
},
104+
// --- OpenRouter ---
76105
{
77-
name: `${MODELS_COMPATIBILITY.medium} Qwen 3 Coder ${chalk.gray("(openrouter > $0.20/M input | $0.80/M output | 262k context)")}`,
106+
name: `${MODELS_COMPATIBILITY.medium} Qwen 3 Coder ${chalk.gray("(openrouter > $0.20/M input | $0.80/M output | 262k context)")}`,
78107
value: "qwen/qwen3-coder",
79108
provider: "openrouter",
80109
},
@@ -99,7 +128,7 @@ export const AI_MODELS: I_AIModel[] = [
99128
provider: "openrouter",
100129
},
101130
{
102-
name: `${MODELS_COMPATIBILITY.low} DeepSeek Chat V3‑0324 (free) ${chalk.gray("(openrouter > fre | 163k context)")}`,
131+
name: `${MODELS_COMPATIBILITY.low} DeepSeek Chat V3‑0324 (free) ${chalk.gray("(openrouter > free | 163k context)")}`,
103132
value: "deepseek/deepseek-chat-v3-0324:free",
104133
provider: "openrouter",
105134
},
@@ -179,7 +208,7 @@ export const SUBTASK_TO_TASK_RULES = [
179208
];
180209

181210
// notes
182-
export const NOTE_MODELS = `Note: Model compatibility levels are indicated by: ${MODELS_COMPATIBILITY.high} high (most reliable), ${MODELS_COMPATIBILITY.medium} medium, ${MODELS_COMPATIBILITY.low} low. Higher compatibility means more reliable TMAI operations with fewer errors. While all models can perform tasks, those with higher compatibility are recommended for critical operations. Additional models — including popular paid options with competitive pricing — are available, mostly via OpenRouter.`;
211+
export const NOTE_MODELS = `Note: Model compatibility levels are indicated by: ${MODELS_COMPATIBILITY.high} high (most reliable), ${MODELS_COMPATIBILITY.medium} medium, ${MODELS_COMPATIBILITY.low} low. Higher compatibility means more reliable TMAI operations with fewer errors. Claude Code models (claude-code/sonnet, claude-code/opus) require no API key but need the Claude Code CLI installed. Groq models offer fast inference. Additional models are available via OpenRouter.`;
183212
export const NOTE_LANGS =
184213
"Note: Make sure the LLM used by TMAI supports the language you choose!";
185214

src/core/TaskMaster.ts

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,21 @@ export class TaskMaster {
10271027
);
10281028
}
10291029

1030+
// TODO: done
1031+
/**
1032+
* @description Shows details of multiple tasks by comma-separated IDs
1033+
* @param ids Comma-separated task IDs (e.g. "1,3,5" or "1,2.1,4")
1034+
*/
1035+
public async showMultipleAsync(ids: string): Promise<void> {
1036+
await this._executeCommandAsync(
1037+
`Fetching details for tasks ${chalk.bold(ids)}...`,
1038+
"Task details retrieved successfully!",
1039+
"Failed to retrieve task details",
1040+
this._mainCommand,
1041+
["show", ids],
1042+
);
1043+
}
1044+
10301045
// TODO: done
10311046
/**
10321047
* @description Shows the next available task to work on
@@ -1864,4 +1879,201 @@ export class TaskMaster {
18641879
}, oraOptions);
18651880
}
18661881
}
1882+
1883+
// ==============================================
1884+
// Research Methods
1885+
// ==============================================
1886+
1887+
/**
1888+
* @description Performs an AI-powered research query with optional project context
1889+
* @param prompt Research query
1890+
* @param context Optional additional context string
1891+
* @param useTree Include project file tree as context
1892+
*/
1893+
public async researchAsync(
1894+
prompt: string,
1895+
context: string,
1896+
useTree: boolean,
1897+
): Promise<void> {
1898+
const args = ["research", prompt];
1899+
if (context) args.push(`-c=${context}`);
1900+
if (useTree) args.push("--tree");
1901+
1902+
await this._executeCommandAsync(
1903+
`Researching: "${chalk.bold(prompt)}"...`,
1904+
"Research completed successfully!",
1905+
"Research query failed",
1906+
this._mainCommand,
1907+
args,
1908+
);
1909+
}
1910+
1911+
// ==============================================
1912+
// Move Methods (cross-tag)
1913+
// ==============================================
1914+
1915+
/**
1916+
* @description Moves task(s) from one tag to another
1917+
* @param fromIds Comma-separated task IDs to move
1918+
* @param fromTag Source tag
1919+
* @param toTag Destination tag
1920+
* @param withDependencies Also move dependencies
1921+
* @param ignoreDependencies Skip dependency checks
1922+
*/
1923+
public async moveTaskAsync(
1924+
fromIds: string,
1925+
fromTag: string,
1926+
toTag: string,
1927+
withDependencies: boolean,
1928+
ignoreDependencies: boolean,
1929+
): Promise<void> {
1930+
const args = [
1931+
"move",
1932+
`--from=${fromIds}`,
1933+
`--from-tag=${fromTag}`,
1934+
`--to-tag=${toTag}`,
1935+
];
1936+
if (withDependencies) args.push("--with-dependencies");
1937+
if (ignoreDependencies) args.push("--ignore-dependencies");
1938+
1939+
await this._executeCommandAsync(
1940+
`Moving task(s) ${chalk.bold(fromIds)} from ${chalk.bold(fromTag)} to ${chalk.bold(toTag)}...`,
1941+
"Task(s) moved successfully!",
1942+
"Failed to move task(s)",
1943+
this._mainCommand,
1944+
args,
1945+
);
1946+
}
1947+
1948+
// ==============================================
1949+
// Tags Methods
1950+
// ==============================================
1951+
1952+
/**
1953+
* @description Lists all available tags
1954+
*/
1955+
public async tagsListAsync(): Promise<void> {
1956+
await this._executeCommandAsync(
1957+
"Listing all tags...",
1958+
"Tags listed successfully!",
1959+
"Failed to list tags",
1960+
this._mainCommand,
1961+
["tags", "list"],
1962+
);
1963+
}
1964+
1965+
/**
1966+
* @description Creates a new tag
1967+
* @param name Tag name
1968+
* @param description Optional tag description
1969+
*/
1970+
public async tagsAddAsync(name: string, description: string): Promise<void> {
1971+
const args = ["tags", "add", name];
1972+
if (description) args.push("--description", description);
1973+
1974+
await this._executeCommandAsync(
1975+
`Creating tag ${chalk.bold(name)}...`,
1976+
`Tag "${name}" created successfully!`,
1977+
`Failed to create tag "${name}"`,
1978+
this._mainCommand,
1979+
args,
1980+
);
1981+
}
1982+
1983+
/**
1984+
* @description Switches to a different tag context
1985+
* @param name Tag name to switch to
1986+
*/
1987+
public async tagsUseAsync(name: string): Promise<void> {
1988+
await this._executeCommandAsync(
1989+
`Switching to tag ${chalk.bold(name)}...`,
1990+
`Switched to tag "${name}" successfully!`,
1991+
`Failed to switch to tag "${name}"`,
1992+
this._mainCommand,
1993+
["tags", "use", name],
1994+
);
1995+
}
1996+
1997+
/**
1998+
* @description Renames an existing tag
1999+
* @param oldName Current tag name
2000+
* @param newName New tag name
2001+
*/
2002+
public async tagsRenameAsync(oldName: string, newName: string): Promise<void> {
2003+
await this._executeCommandAsync(
2004+
`Renaming tag ${chalk.bold(oldName)} to ${chalk.bold(newName)}...`,
2005+
`Tag renamed successfully!`,
2006+
`Failed to rename tag "${oldName}"`,
2007+
this._mainCommand,
2008+
["tags", "rename", oldName, newName],
2009+
);
2010+
}
2011+
2012+
/**
2013+
* @description Copies a tag with all its tasks
2014+
* @param source Source tag name
2015+
* @param target Target tag name
2016+
* @param description Optional description for the new tag
2017+
*/
2018+
public async tagsCopyAsync(
2019+
source: string,
2020+
target: string,
2021+
description: string,
2022+
): Promise<void> {
2023+
const args = ["tags", "copy", source, target];
2024+
if (description) args.push("--description", description);
2025+
2026+
await this._executeCommandAsync(
2027+
`Copying tag ${chalk.bold(source)} to ${chalk.bold(target)}...`,
2028+
`Tag copied successfully!`,
2029+
`Failed to copy tag "${source}"`,
2030+
this._mainCommand,
2031+
args,
2032+
);
2033+
}
2034+
2035+
/**
2036+
* @description Removes an existing tag and all its tasks
2037+
* @param name Tag name to remove
2038+
*/
2039+
public async tagsRemoveAsync(name: string): Promise<void> {
2040+
const { confirm } = await inquirer.prompt({
2041+
type: "confirm",
2042+
name: "confirm",
2043+
message: chalk.red(
2044+
`Are you sure you want to delete tag "${name}" and ALL its tasks?`,
2045+
),
2046+
default: false,
2047+
});
2048+
2049+
if (confirm) {
2050+
await this._executeCommandAsync(
2051+
`Removing tag ${chalk.bold(name)}...`,
2052+
`Tag "${name}" removed successfully!`,
2053+
`Failed to remove tag "${name}"`,
2054+
this._mainCommand,
2055+
["tags", "remove", name, "-y"],
2056+
);
2057+
} else {
2058+
console.log(chalk.yellow("Tag removal cancelled."));
2059+
}
2060+
}
2061+
2062+
// ==============================================
2063+
// Rules Methods
2064+
// ==============================================
2065+
2066+
/**
2067+
* @description Adds editor rules after initialization
2068+
* @param rules Comma-separated list of rules (e.g. "cursor,windsurf,vscode")
2069+
*/
2070+
public async rulesAddAsync(rules: string): Promise<void> {
2071+
await this._executeCommandAsync(
2072+
`Adding rules: ${chalk.bold(rules)}...`,
2073+
"Rules added successfully!",
2074+
"Failed to add rules",
2075+
this._mainCommand,
2076+
["rules", "add", rules],
2077+
);
2078+
}
18672079
}

0 commit comments

Comments
 (0)