Compare commits
10 Commits
fix/more.n
...
v0.20.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
458496e3b6 | ||
|
|
fb92693d81 | ||
|
|
f6ba4a36ee | ||
|
|
baf9bd545a | ||
|
|
fbea48d8ec | ||
|
|
d0fe7dc25a | ||
|
|
f380b8e86c | ||
|
|
bd89061a1d | ||
|
|
7d5ebf05e3 | ||
|
|
21392a1117 |
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Recover from `@anthropic-ai/claude-code` JSON truncation bug that caused Task Master to crash when handling large (>8 kB) structured responses. The CLI/SDK still truncates, but Task Master now detects the error, preserves buffered text, and returns a usable response instead of throwing.
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Updating dependency ai-sdk-provider-gemini-cli to 0.0.4 to address breaking change Google made to Gemini CLI and add better 'api-key' in addition to 'gemini-api-key' AI-SDK compatibility.
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add support for xAI Grok 4 model
|
||||
|
||||
- Add grok-4 model to xAI provider with $3/$15 per 1M token pricing
|
||||
- Enable main, fallback, and research roles for grok-4
|
||||
- Max tokens set to 131,072 (matching other xAI models)
|
||||
@@ -1,8 +0,0 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add stricter validation and clearer feedback for task priority when adding new tasks
|
||||
|
||||
- if a task priority is invalid, it will default to medium
|
||||
- made taks priority case-insensitive, essentially making HIGH and high the same value
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add support for MCP Sampling as AI provider, requires no API key, uses the client LLM provider
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Unify and streamline profile system architecture for improved maintainability
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Added Groq provider support
|
||||
@@ -1,21 +1,21 @@
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "groq",
|
||||
"modelId": "llama-3.1-8b-instant",
|
||||
"maxTokens": 131072,
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-7-sonnet-20250219",
|
||||
"maxTokens": 120000,
|
||||
"temperature": 0.2
|
||||
},
|
||||
"research": {
|
||||
"provider": "groq",
|
||||
"modelId": "llama-3.3-70b-versatile",
|
||||
"maxTokens": 32768,
|
||||
"provider": "perplexity",
|
||||
"modelId": "sonar",
|
||||
"maxTokens": 8700,
|
||||
"temperature": 0.1
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-7-sonnet-20250219",
|
||||
"maxTokens": 128000,
|
||||
"modelId": "claude-3-5-sonnet-20241022",
|
||||
"maxTokens": 8192,
|
||||
"temperature": 0.2
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
# Task ID: 1
|
||||
# Title: Implement TTS Flag for Taskmaster Commands
|
||||
# Status: pending
|
||||
# Dependencies: 16 (Not found)
|
||||
# Priority: medium
|
||||
# Description: Add text-to-speech functionality to taskmaster commands with configurable voice options and audio output settings.
|
||||
# Details:
|
||||
Implement TTS functionality including:
|
||||
- Add --tts flag to all relevant taskmaster commands (list, show, generate, etc.)
|
||||
- Integrate with system TTS engines (Windows SAPI, macOS say command, Linux espeak/festival)
|
||||
- Create TTS configuration options in the configuration management system
|
||||
- Add voice selection options (male/female, different languages if available)
|
||||
- Implement audio output settings (volume, speed, pitch)
|
||||
- Add TTS-specific error handling for cases where TTS is unavailable
|
||||
- Create fallback behavior when TTS fails (silent failure or text output)
|
||||
- Support for reading task titles, descriptions, and status updates aloud
|
||||
- Add option to read entire task lists or individual task details
|
||||
- Implement TTS for command confirmations and error messages
|
||||
- Create TTS output formatting to make spoken text more natural (removing markdown, formatting numbers/dates appropriately)
|
||||
- Add configuration option to enable/disable TTS globally
|
||||
|
||||
# Test Strategy:
|
||||
Test TTS functionality across different operating systems (Windows, macOS, Linux). Verify that the --tts flag works with all major commands. Test voice configuration options and ensure audio output settings are properly applied. Test error handling when TTS services are unavailable. Verify that text formatting for speech is natural and understandable. Test with various task content types including special characters, code snippets, and long descriptions. Ensure TTS can be disabled and enabled through configuration.
|
||||
5648
.taskmaster/tasks/tasks.json
Normal file
5648
.taskmaster/tasks/tasks.json
Normal file
File diff suppressed because one or more lines are too long
50
CHANGELOG.md
50
CHANGELOG.md
@@ -1,5 +1,55 @@
|
||||
# task-master-ai
|
||||
|
||||
## 0.20.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#950](https://github.com/eyaltoledano/claude-task-master/pull/950) [`699e9ee`](https://github.com/eyaltoledano/claude-task-master/commit/699e9eefb5d687b256e9402d686bdd5e3a358b4a) Thanks [@ben-vargas](https://github.com/ben-vargas)! - Add support for xAI Grok 4 model
|
||||
- Add grok-4 model to xAI provider with $3/$15 per 1M token pricing
|
||||
- Enable main, fallback, and research roles for grok-4
|
||||
- Max tokens set to 131,072 (matching other xAI models)
|
||||
|
||||
- [#946](https://github.com/eyaltoledano/claude-task-master/pull/946) [`5f009a5`](https://github.com/eyaltoledano/claude-task-master/commit/5f009a5e1fc10e37be26f5135df4b7f44a9c5320) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add stricter validation and clearer feedback for task priority when adding new tasks
|
||||
- if a task priority is invalid, it will default to medium
|
||||
- made taks priority case-insensitive, essentially making HIGH and high the same value
|
||||
|
||||
- [#863](https://github.com/eyaltoledano/claude-task-master/pull/863) [`b530657`](https://github.com/eyaltoledano/claude-task-master/commit/b53065713c8da0ae6f18eb2655397aa975004923) Thanks [@OrenMe](https://github.com/OrenMe)! - Add support for MCP Sampling as AI provider, requires no API key, uses the client LLM provider
|
||||
|
||||
- [#930](https://github.com/eyaltoledano/claude-task-master/pull/930) [`98d1c97`](https://github.com/eyaltoledano/claude-task-master/commit/98d1c974361a56ddbeb772b1272986b9d3913459) Thanks [@OmarElKadri](https://github.com/OmarElKadri)! - Added Groq provider support
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#958](https://github.com/eyaltoledano/claude-task-master/pull/958) [`6c88a4a`](https://github.com/eyaltoledano/claude-task-master/commit/6c88a4a749083e3bd2d073a9240799771774495a) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Recover from `@anthropic-ai/claude-code` JSON truncation bug that caused Task Master to crash when handling large (>8 kB) structured responses. The CLI/SDK still truncates, but Task Master now detects the error, preserves buffered text, and returns a usable response instead of throwing.
|
||||
|
||||
- [#958](https://github.com/eyaltoledano/claude-task-master/pull/958) [`3334e40`](https://github.com/eyaltoledano/claude-task-master/commit/3334e409ae659d5223bb136ae23fd22c5e219073) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Updating dependency ai-sdk-provider-gemini-cli to 0.0.4 to address breaking change Google made to Gemini CLI and add better 'api-key' in addition to 'gemini-api-key' AI-SDK compatibility.
|
||||
|
||||
- [#853](https://github.com/eyaltoledano/claude-task-master/pull/853) [`95c299d`](https://github.com/eyaltoledano/claude-task-master/commit/95c299df642bd8e6d75f8fa5110ac705bcc72edf) Thanks [@joedanz](https://github.com/joedanz)! - Unify and streamline profile system architecture for improved maintainability
|
||||
|
||||
## 0.20.0-rc.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
- [#950](https://github.com/eyaltoledano/claude-task-master/pull/950) [`699e9ee`](https://github.com/eyaltoledano/claude-task-master/commit/699e9eefb5d687b256e9402d686bdd5e3a358b4a) Thanks [@ben-vargas](https://github.com/ben-vargas)! - Add support for xAI Grok 4 model
|
||||
- Add grok-4 model to xAI provider with $3/$15 per 1M token pricing
|
||||
- Enable main, fallback, and research roles for grok-4
|
||||
- Max tokens set to 131,072 (matching other xAI models)
|
||||
|
||||
- [#946](https://github.com/eyaltoledano/claude-task-master/pull/946) [`5f009a5`](https://github.com/eyaltoledano/claude-task-master/commit/5f009a5e1fc10e37be26f5135df4b7f44a9c5320) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Add stricter validation and clearer feedback for task priority when adding new tasks
|
||||
- if a task priority is invalid, it will default to medium
|
||||
- made taks priority case-insensitive, essentially making HIGH and high the same value
|
||||
|
||||
- [#863](https://github.com/eyaltoledano/claude-task-master/pull/863) [`b530657`](https://github.com/eyaltoledano/claude-task-master/commit/b53065713c8da0ae6f18eb2655397aa975004923) Thanks [@OrenMe](https://github.com/OrenMe)! - Add support for MCP Sampling as AI provider, requires no API key, uses the client LLM provider
|
||||
|
||||
- [#930](https://github.com/eyaltoledano/claude-task-master/pull/930) [`98d1c97`](https://github.com/eyaltoledano/claude-task-master/commit/98d1c974361a56ddbeb772b1272986b9d3913459) Thanks [@OmarElKadri](https://github.com/OmarElKadri)! - Added Groq provider support
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- [#916](https://github.com/eyaltoledano/claude-task-master/pull/916) [`6c88a4a`](https://github.com/eyaltoledano/claude-task-master/commit/6c88a4a749083e3bd2d073a9240799771774495a) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Recover from `@anthropic-ai/claude-code` JSON truncation bug that caused Task Master to crash when handling large (>8 kB) structured responses. The CLI/SDK still truncates, but Task Master now detects the error, preserves buffered text, and returns a usable response instead of throwing.
|
||||
|
||||
- [#916](https://github.com/eyaltoledano/claude-task-master/pull/916) [`3334e40`](https://github.com/eyaltoledano/claude-task-master/commit/3334e409ae659d5223bb136ae23fd22c5e219073) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Updating dependency ai-sdk-provider-gemini-cli to 0.0.4 to address breaking change Google made to Gemini CLI and add better 'api-key' in addition to 'gemini-api-key' AI-SDK compatibility.
|
||||
|
||||
- [#853](https://github.com/eyaltoledano/claude-task-master/pull/853) [`95c299d`](https://github.com/eyaltoledano/claude-task-master/commit/95c299df642bd8e6d75f8fa5110ac705bcc72edf) Thanks [@joedanz](https://github.com/joedanz)! - Unify and streamline profile system architecture for improved maintainability
|
||||
|
||||
## 0.19.0
|
||||
|
||||
### Minor Changes
|
||||
|
||||
@@ -4,30 +4,7 @@ Taskmaster uses two primary methods for configuration:
|
||||
|
||||
1. **`.taskmaster/config.json` File (Recommended - New Structure)**
|
||||
|
||||
- This JSON file stores most configuration settings, including A5. **Usage Requirements**:
|
||||
8. **Troubleshooting**:
|
||||
- "MCP provider requires session context" → Ensure running in MCP environment
|
||||
- See the [MCP Provider Guide](./mcp-provider-guide.md) for detailed troubleshootingust be running in an MCP context (session must be available)
|
||||
- Session must provide `clientCapabilities.sampling` capability
|
||||
|
||||
6. **Best Practices**:
|
||||
- Always configure a non-MCP fallback provider
|
||||
- Use `mcp` for main/research roles when in MCP environments
|
||||
- Test sampling capability before production use
|
||||
|
||||
7. **Setup Commands**:
|
||||
```bash
|
||||
# Set MCP provider for main role
|
||||
task-master models set-main --provider mcp --model claude-3-5-sonnet-20241022
|
||||
|
||||
# Set MCP provider for research role
|
||||
task-master models set-research --provider mcp --model claude-3-opus-20240229
|
||||
|
||||
# Verify configuration
|
||||
task-master models list
|
||||
```
|
||||
|
||||
8. **Troubleshooting**:lections, parameters, logging levels, and project defaults.
|
||||
- This JSON file stores most configuration settings, including AI model selections, parameters, logging levels, and project defaults.
|
||||
- **Location:** This file is created in the `.taskmaster/` directory when you run the `task-master models --setup` interactive setup or initialize a new project with `task-master init`.
|
||||
- **Migration:** Existing projects with `.taskmasterconfig` in the root will continue to work, but should be migrated to the new structure using `task-master migrate`.
|
||||
- **Management:** Use the `task-master models --setup` command (or `models` MCP tool) to interactively create and manage this file. You can also set specific models directly using `task-master models --set-<role>=<model_id>`, adding `--ollama` or `--openrouter` flags for custom models. Manual editing is possible but not recommended unless you understand the structure.
|
||||
@@ -68,11 +45,12 @@ Taskmaster uses two primary methods for configuration:
|
||||
"azureBaseURL": "https://your-endpoint.azure.com/openai/deployments",
|
||||
"vertexProjectId": "your-gcp-project-id",
|
||||
"vertexLocation": "us-central1",
|
||||
"responseLanguage": "English"
|
||||
"responseLanguage": "English"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> For MCP-specific setup and troubleshooting, see [Provider-Specific Configuration](#provider-specific-configuration).
|
||||
|
||||
2. **Legacy `.taskmasterconfig` File (Backward Compatibility)**
|
||||
|
||||
@@ -198,8 +176,6 @@ node scripts/init.js
|
||||
|
||||
### MCP (Model Context Protocol) Provider
|
||||
|
||||
The MCP provider enables Task Master to use MCP servers as AI providers. This is particularly useful when running Task Master within MCP-compatible development environments like Claude Desktop or Cursor.
|
||||
|
||||
1. **Prerequisites**:
|
||||
- An active MCP session with sampling capability
|
||||
- MCP client with sampling support (e.g. VS Code)
|
||||
@@ -238,12 +214,24 @@ The MCP provider enables Task Master to use MCP servers as AI providers. This is
|
||||
- Must be running in an MCP context (session must be available)
|
||||
- Session must provide `clientCapabilities.sampling` capability
|
||||
|
||||
5. **Best Practices**:
|
||||
6. **Best Practices**:
|
||||
- Always configure a non-MCP fallback provider
|
||||
- Use `mcp` for main/research roles when in MCP environments
|
||||
- Test sampling capability before production use
|
||||
|
||||
6. **Troubleshooting**:
|
||||
7. **Setup Commands**:
|
||||
```bash
|
||||
# Set MCP provider for main role
|
||||
task-master models set-main --provider mcp --model claude-3-5-sonnet-20241022
|
||||
|
||||
# Set MCP provider for research role
|
||||
task-master models set-research --provider mcp --model claude-3-opus-20240229
|
||||
|
||||
# Verify configuration
|
||||
task-master models list
|
||||
```
|
||||
|
||||
8. **Troubleshooting**:
|
||||
- "MCP provider requires session context" → Ensure running in MCP environment
|
||||
- See the [MCP Provider Guide](./mcp-provider-guide.md) for detailed troubleshooting
|
||||
|
||||
|
||||
@@ -125,8 +125,7 @@ export async function addTaskDirect(args, log, context = {}) {
|
||||
},
|
||||
'json', // outputFormat
|
||||
manualTaskData, // Pass the manual task data
|
||||
false, // research flag is false for manual creation
|
||||
projectRoot // Pass projectRoot
|
||||
false // research flag is false for manual creation
|
||||
);
|
||||
newTaskId = result.newTaskId;
|
||||
telemetryData = result.telemetryData;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "task-master-ai",
|
||||
"version": "0.19.0",
|
||||
"version": "0.20.0",
|
||||
"description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
|
||||
@@ -1500,10 +1500,16 @@ function registerCommands(programInstance) {
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true,
|
||||
complexityReportPath: options.report || false
|
||||
});
|
||||
const initOptions = {
|
||||
tasksPath: options.file || true
|
||||
};
|
||||
|
||||
// Only pass complexityReportPath if user provided a custom path
|
||||
if (options.report && options.report !== COMPLEXITY_REPORT_FILE) {
|
||||
initOptions.complexityReportPath = options.report;
|
||||
}
|
||||
|
||||
const taskMaster = initTaskMaster(initOptions);
|
||||
|
||||
const statusFilter = options.status;
|
||||
const withSubtasks = options.withSubtasks || false;
|
||||
@@ -1690,7 +1696,7 @@ function registerCommands(programInstance) {
|
||||
const outputPath =
|
||||
options.output === COMPLEXITY_REPORT_FILE && targetTag !== 'master'
|
||||
? baseOutputPath.replace('.json', `_${targetTag}.json`)
|
||||
: baseOutputPath;
|
||||
: options.output || baseOutputPath;
|
||||
|
||||
console.log(
|
||||
chalk.blue(
|
||||
@@ -1770,6 +1776,11 @@ function registerCommands(programInstance) {
|
||||
)
|
||||
.option('--tag <tag>', 'Specify tag context for task operations')
|
||||
.action(async (prompt, options) => {
|
||||
// Initialize TaskMaster
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
|
||||
// Parameter validation
|
||||
if (!prompt || typeof prompt !== 'string' || prompt.trim().length === 0) {
|
||||
console.error(
|
||||
@@ -2211,6 +2222,8 @@ ${result.result}
|
||||
tasksPath: options.file || true
|
||||
});
|
||||
|
||||
const projectRoot = taskMaster.getProjectRoot();
|
||||
|
||||
// Show current tag context
|
||||
displayCurrentTagIndicator(
|
||||
options.tag || getCurrentTag(taskMaster.getProjectRoot()) || 'master'
|
||||
@@ -3462,6 +3475,9 @@ Examples:
|
||||
const taskMaster = initTaskMaster({
|
||||
tasksPath: options.file || false
|
||||
});
|
||||
|
||||
const projectRoot = taskMaster.getProjectRoot();
|
||||
|
||||
// Validate flags: cannot use multiple provider flags simultaneously
|
||||
const providerFlags = [
|
||||
options.openrouter,
|
||||
|
||||
@@ -4,7 +4,10 @@ import chalk from 'chalk';
|
||||
import { z } from 'zod';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { log, findProjectRoot, resolveEnvVariable, isEmpty } from './utils.js';
|
||||
import { LEGACY_CONFIG_FILE } from '../../src/constants/paths.js';
|
||||
import {
|
||||
LEGACY_CONFIG_FILE,
|
||||
TASKMASTER_DIR
|
||||
} from '../../src/constants/paths.js';
|
||||
import { findConfigPath } from '../../src/utils/path-utils.js';
|
||||
import {
|
||||
VALIDATED_PROVIDERS,
|
||||
@@ -99,17 +102,30 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
||||
if (rootToUse) {
|
||||
configSource = `found root (${rootToUse})`;
|
||||
} else {
|
||||
// No root found, return defaults immediately
|
||||
return defaults;
|
||||
// No root found, use current working directory as fallback
|
||||
// This prevents infinite loops during initialization
|
||||
rootToUse = process.cwd();
|
||||
configSource = `current directory (${rootToUse}) - no project markers found`;
|
||||
}
|
||||
}
|
||||
// ---> End find project root logic <---
|
||||
|
||||
// --- Find configuration file using centralized path utility ---
|
||||
const configPath = findConfigPath(null, { projectRoot: rootToUse });
|
||||
// --- Find configuration file ---
|
||||
let configPath = null;
|
||||
let config = { ...defaults }; // Start with a deep copy of defaults
|
||||
let configExists = false;
|
||||
|
||||
// During initialization (no project markers), skip config file search entirely
|
||||
const hasProjectMarkers =
|
||||
fs.existsSync(path.join(rootToUse, TASKMASTER_DIR)) ||
|
||||
fs.existsSync(path.join(rootToUse, LEGACY_CONFIG_FILE));
|
||||
|
||||
if (hasProjectMarkers) {
|
||||
// Only try to find config if we have project markers
|
||||
// This prevents the repeated warnings during init
|
||||
configPath = findConfigPath(null, { projectRoot: rootToUse });
|
||||
}
|
||||
|
||||
if (configPath) {
|
||||
configExists = true;
|
||||
const isLegacy = configPath.endsWith(LEGACY_CONFIG_FILE);
|
||||
@@ -199,11 +215,22 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`Warning: Configuration file not found at derived root (${rootToUse}). Using defaults.`
|
||||
)
|
||||
// Don't warn about missing config during initialization
|
||||
// Only warn if this looks like an existing project (has .taskmaster dir or legacy config marker)
|
||||
const hasTaskmasterDir = fs.existsSync(
|
||||
path.join(rootToUse, TASKMASTER_DIR)
|
||||
);
|
||||
const hasLegacyMarker = fs.existsSync(
|
||||
path.join(rootToUse, LEGACY_CONFIG_FILE)
|
||||
);
|
||||
|
||||
if (hasTaskmasterDir || hasLegacyMarker) {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`Warning: Configuration file not found at derived root (${rootToUse}). Using defaults.`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
// Keep config as defaults
|
||||
config = { ...defaults };
|
||||
|
||||
@@ -561,16 +561,6 @@ async function addTask(
|
||||
writeJSON(tasksPath, rawData, projectRoot, targetTag);
|
||||
report('DEBUG: tasks.json written.', 'debug');
|
||||
|
||||
// Generate markdown task files
|
||||
report('Generating task files...', 'info');
|
||||
report('DEBUG: Calling generateTaskFiles...', 'debug');
|
||||
// Pass mcpLog if available to generateTaskFiles
|
||||
await generateTaskFiles(tasksPath, path.dirname(tasksPath), {
|
||||
projectRoot,
|
||||
tag: targetTag
|
||||
});
|
||||
report('DEBUG: generateTaskFiles finished.', 'debug');
|
||||
|
||||
// Show success message - only for text output (CLI)
|
||||
if (outputFormat === 'text') {
|
||||
const table = new Table({
|
||||
|
||||
@@ -461,19 +461,44 @@ async function expandTask(
|
||||
`${combinedAdditionalContext}\n\n# Project Context\n\n${gatheredContext}`.trim();
|
||||
}
|
||||
|
||||
// Ensure expansionPrompt is a string (handle both string and object formats)
|
||||
let expansionPromptText = undefined;
|
||||
if (taskAnalysis?.expansionPrompt) {
|
||||
if (typeof taskAnalysis.expansionPrompt === 'string') {
|
||||
expansionPromptText = taskAnalysis.expansionPrompt;
|
||||
} else if (
|
||||
typeof taskAnalysis.expansionPrompt === 'object' &&
|
||||
taskAnalysis.expansionPrompt.text
|
||||
) {
|
||||
expansionPromptText = taskAnalysis.expansionPrompt.text;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure gatheredContext is a string (handle both string and object formats)
|
||||
let gatheredContextText = gatheredContext;
|
||||
if (typeof gatheredContext === 'object' && gatheredContext !== null) {
|
||||
if (gatheredContext.data) {
|
||||
gatheredContextText = gatheredContext.data;
|
||||
} else if (gatheredContext.text) {
|
||||
gatheredContextText = gatheredContext.text;
|
||||
} else {
|
||||
gatheredContextText = JSON.stringify(gatheredContext);
|
||||
}
|
||||
}
|
||||
|
||||
const promptParams = {
|
||||
task: task,
|
||||
subtaskCount: finalSubtaskCount,
|
||||
nextSubtaskId: nextSubtaskId,
|
||||
additionalContext: additionalContext,
|
||||
complexityReasoningContext: complexityReasoningContext,
|
||||
gatheredContext: gatheredContext,
|
||||
gatheredContext: gatheredContextText || '',
|
||||
useResearch: useResearch,
|
||||
expansionPrompt: taskAnalysis?.expansionPrompt || null
|
||||
expansionPrompt: expansionPromptText || undefined
|
||||
};
|
||||
|
||||
let variantKey = 'default';
|
||||
if (taskAnalysis?.expansionPrompt) {
|
||||
if (expansionPromptText) {
|
||||
variantKey = 'complexity-report';
|
||||
logger.info(
|
||||
`Using expansion prompt from complexity report for task ${task.id}.`
|
||||
|
||||
@@ -205,12 +205,10 @@ async function performResearch(
|
||||
}
|
||||
};
|
||||
|
||||
// Select variant based on detail level
|
||||
const variantKey = detailLevel; // 'low', 'medium', or 'high'
|
||||
// Load prompts - the research template handles detail level internally
|
||||
const { systemPrompt, userPrompt } = await promptManager.loadPrompt(
|
||||
'research',
|
||||
promptParams,
|
||||
variantKey
|
||||
promptParams
|
||||
);
|
||||
|
||||
// Count tokens for system and user prompts
|
||||
|
||||
@@ -214,7 +214,7 @@ async function updateSubtaskById(
|
||||
title: parentTask.subtasks[subtaskIndex - 1].title,
|
||||
status: parentTask.subtasks[subtaskIndex - 1].status
|
||||
}
|
||||
: null;
|
||||
: undefined;
|
||||
const nextSubtask =
|
||||
subtaskIndex < parentTask.subtasks.length - 1
|
||||
? {
|
||||
@@ -222,7 +222,7 @@ async function updateSubtaskById(
|
||||
title: parentTask.subtasks[subtaskIndex + 1].title,
|
||||
status: parentTask.subtasks[subtaskIndex + 1].status
|
||||
}
|
||||
: null;
|
||||
: undefined;
|
||||
|
||||
// Build prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
|
||||
@@ -218,7 +218,16 @@ export function initTaskMaster(overrides = {}) {
|
||||
);
|
||||
}
|
||||
|
||||
// Remaining paths - only resolve if key exists in overrides
|
||||
// Always set default paths first
|
||||
// These can be overridden below if needed
|
||||
paths.configPath = path.join(paths.projectRoot, TASKMASTER_CONFIG_FILE);
|
||||
paths.statePath = path.join(
|
||||
paths.taskMasterDir || path.join(paths.projectRoot, TASKMASTER_DIR),
|
||||
'state.json'
|
||||
);
|
||||
paths.tasksPath = path.join(paths.projectRoot, TASKMASTER_TASKS_FILE);
|
||||
|
||||
// Handle overrides - only validate/resolve if explicitly provided
|
||||
if ('configPath' in overrides) {
|
||||
paths.configPath = resolvePath(
|
||||
'config file',
|
||||
|
||||
@@ -557,7 +557,10 @@ describe('getConfig Tests', () => {
|
||||
// Assert
|
||||
expect(config).toEqual(DEFAULT_CONFIG);
|
||||
expect(mockFindProjectRoot).not.toHaveBeenCalled(); // Explicit root provided
|
||||
expect(fsExistsSyncSpy).toHaveBeenCalledWith(MOCK_CONFIG_PATH);
|
||||
// The implementation checks for .taskmaster directory first
|
||||
expect(fsExistsSyncSpy).toHaveBeenCalledWith(
|
||||
path.join(MOCK_PROJECT_ROOT, '.taskmaster')
|
||||
);
|
||||
expect(fsReadFileSyncSpy).not.toHaveBeenCalled(); // No read if file doesn't exist
|
||||
expect(consoleWarnSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining('not found at provided project root')
|
||||
|
||||
@@ -184,7 +184,7 @@ jest.unstable_mockModule(
|
||||
);
|
||||
|
||||
// Import the mocked modules
|
||||
const { readJSON, writeJSON, log, CONFIG } = await import(
|
||||
const { readJSON, writeJSON, log, CONFIG, findTaskById } = await import(
|
||||
'../../../../../scripts/modules/utils.js'
|
||||
);
|
||||
|
||||
@@ -265,6 +265,13 @@ describe('analyzeTaskComplexity', () => {
|
||||
_rawTaggedData: sampleTasks
|
||||
};
|
||||
});
|
||||
|
||||
// Mock findTaskById to return the expected structure
|
||||
findTaskById.mockImplementation((tasks, taskId) => {
|
||||
const task = tasks?.find((t) => t.id === parseInt(taskId));
|
||||
return { task: task || null, originalSubtaskCount: null };
|
||||
});
|
||||
|
||||
generateTextService.mockResolvedValue(sampleApiResponse);
|
||||
});
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ describe('initTaskMaster', () => {
|
||||
expect(taskMaster.getTasksPath()).toBeNull();
|
||||
});
|
||||
|
||||
test('should return null when optional files not specified in overrides', () => {
|
||||
test('should return default paths when optional files not specified in overrides', () => {
|
||||
// Arrange - Remove all optional files
|
||||
fs.unlinkSync(tasksPath);
|
||||
fs.unlinkSync(configPath);
|
||||
@@ -257,10 +257,16 @@ describe('initTaskMaster', () => {
|
||||
// Act - Don't specify any optional paths
|
||||
const taskMaster = initTaskMaster({});
|
||||
|
||||
// Assert
|
||||
expect(taskMaster.getTasksPath()).toBeUndefined();
|
||||
expect(taskMaster.getConfigPath()).toBeUndefined();
|
||||
expect(taskMaster.getStatePath()).toBeUndefined();
|
||||
// Assert - Should return absolute paths with default locations
|
||||
expect(taskMaster.getTasksPath()).toBe(
|
||||
path.join(tempDir, TASKMASTER_TASKS_FILE)
|
||||
);
|
||||
expect(taskMaster.getConfigPath()).toBe(
|
||||
path.join(tempDir, TASKMASTER_CONFIG_FILE)
|
||||
);
|
||||
expect(taskMaster.getStatePath()).toBe(
|
||||
path.join(tempDir, TASKMASTER_DIR, 'state.json')
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -415,11 +421,19 @@ describe('initTaskMaster', () => {
|
||||
// Assert
|
||||
expect(taskMaster.getProjectRoot()).toBe(tempDir);
|
||||
expect(taskMaster.getTaskMasterDir()).toBe(taskMasterDir);
|
||||
expect(taskMaster.getTasksPath()).toBeUndefined();
|
||||
// Default paths are always set for tasks, config, and state
|
||||
expect(taskMaster.getTasksPath()).toBe(
|
||||
path.join(tempDir, TASKMASTER_TASKS_FILE)
|
||||
);
|
||||
expect(taskMaster.getConfigPath()).toBe(
|
||||
path.join(tempDir, TASKMASTER_CONFIG_FILE)
|
||||
);
|
||||
expect(taskMaster.getStatePath()).toBe(
|
||||
path.join(taskMasterDir, 'state.json')
|
||||
);
|
||||
// PRD and complexity report paths are undefined when not provided
|
||||
expect(taskMaster.getPrdPath()).toBeUndefined();
|
||||
expect(taskMaster.getComplexityReportPath()).toBeUndefined();
|
||||
expect(taskMaster.getConfigPath()).toBeUndefined();
|
||||
expect(taskMaster.getStatePath()).toBeUndefined();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user