feat(config): Implement TASK_MASTER_PROJECT_ROOT support for project root resolution (#604)

* feat(config): Implement TASK_MASTER_PROJECT_ROOT support for project root resolution

- Added support for the TASK_MASTER_PROJECT_ROOT environment variable in MCP configuration, establishing a clear precedence order for project root resolution.
- Updated utility functions to prioritize the environment variable, followed by args.projectRoot and session-based resolution.
- Enhanced error handling and logging for project root determination.
- Introduced new tasks for comprehensive testing and documentation updates related to the new configuration options.

* chore: fix CI issues
This commit is contained in:
Ralph Khreish
2025-05-28 00:32:34 +02:00
committed by GitHub
parent 48732d5423
commit 80735f9e60
8 changed files with 239 additions and 43 deletions

View File

@@ -21,7 +21,7 @@ import {
getBaseUrlForRole,
isApiKeySet
} from './config-manager.js';
import { log, resolveEnvVariable, findProjectRoot } from './utils.js';
import { log, findProjectRoot, resolveEnvVariable } from './utils.js';
import * as anthropic from '../../src/ai-providers/anthropic.js';
import * as perplexity from '../../src/ai-providers/perplexity.js';

View File

@@ -13,7 +13,7 @@ import http from 'http';
import inquirer from 'inquirer';
import ora from 'ora'; // Import ora
import { log, readJSON } from './utils.js';
import { log, readJSON, findProjectRoot } from './utils.js';
import {
parsePRD,
updateTasks,
@@ -76,7 +76,6 @@ import {
setModel,
getApiKeyStatusReport
} from './task-manager/models.js';
import { findProjectRoot } from './utils.js';
import {
isValidTaskStatus,
TASK_STATUS_OPTIONS
@@ -2307,8 +2306,11 @@ Examples:
$ task-master models --setup # Run interactive setup`
)
.action(async (options) => {
const projectRoot = findProjectRoot(); // Find project root for context
const projectRoot = findProjectRoot();
if (!projectRoot) {
console.error(chalk.red('Error: Could not find project root.'));
process.exit(1);
}
// Validate flags: cannot use both --openrouter and --ollama simultaneously
if (options.openrouter && options.ollama) {
console.error(

View File

@@ -2,7 +2,7 @@ import fs from 'fs';
import path from 'path';
import chalk from 'chalk';
import { fileURLToPath } from 'url';
import { log, resolveEnvVariable, findProjectRoot } from './utils.js';
import { log, findProjectRoot, resolveEnvVariable } from './utils.js';
// Calculate __dirname in ESM
const __filename = fileURLToPath(import.meta.url);

View File

@@ -60,8 +60,7 @@ function resolveEnvVariable(key, session = null, projectRoot = null) {
// --- Project Root Finding Utility ---
/**
* Finds the project root directory by searching upwards from a given starting point
* for a marker file or directory (e.g., 'package.json', '.git').
* Finds the project root directory by searching for marker files/directories.
* @param {string} [startPath=process.cwd()] - The directory to start searching from.
* @param {string[]} [markers=['package.json', '.git', '.taskmasterconfig']] - Marker files/dirs to look for.
* @returns {string|null} The path to the project root directory, or null if not found.
@@ -71,27 +70,35 @@ function findProjectRoot(
markers = ['package.json', '.git', '.taskmasterconfig']
) {
let currentPath = path.resolve(startPath);
while (true) {
for (const marker of markers) {
if (fs.existsSync(path.join(currentPath, marker))) {
return currentPath;
}
const rootPath = path.parse(currentPath).root;
while (currentPath !== rootPath) {
// Check if any marker exists in the current directory
const hasMarker = markers.some((marker) => {
const markerPath = path.join(currentPath, marker);
return fs.existsSync(markerPath);
});
if (hasMarker) {
return currentPath;
}
const parentPath = path.dirname(currentPath);
if (parentPath === currentPath) {
// Reached the filesystem root
return null;
}
currentPath = parentPath;
// Move up one directory
currentPath = path.dirname(currentPath);
}
// Check the root directory as well
const hasMarkerInRoot = markers.some((marker) => {
const markerPath = path.join(rootPath, marker);
return fs.existsSync(markerPath);
});
return hasMarkerInRoot ? rootPath : null;
}
// --- Dynamic Configuration Function --- (REMOVED)
/*
function getConfig(session = null) {
// ... implementation removed ...
}
*/
// --- Logging and Utility Functions ---
// Set up logging based on log level
const LOG_LEVELS = {