diff --git a/.cursor/rules/architecture.mdc b/.cursor/rules/architecture.mdc index 13b6e935..26d9efad 100644 --- a/.cursor/rules/architecture.mdc +++ b/.cursor/rules/architecture.mdc @@ -84,24 +84,24 @@ alwaysApply: false - `expandTaskWithAI(taskDescription, numSubtasks, researchContext)`: Generates subtasks using AI. - `parsePRDWithAI(prdContent)`: Extracts tasks from PRD content using AI. - - **[`utils.js`](mdc:scripts/modules/utils.js): Utility Functions and Configuration** - - **Purpose**: Provides reusable utility functions and global configuration settings used across the **CLI application**. + - **[`utils.js`](mdc:scripts/modules/utils.js): Core Utility Functions** + - **Purpose**: Provides low-level, reusable utility functions used across the **CLI application**. **Note:** Configuration management is now handled by [`config-manager.js`](mdc:scripts/modules/config-manager.js). - **Responsibilities** (See also: [`utilities.mdc`](mdc:.cursor/rules/utilities.mdc)): - - Manages global configuration settings loaded from environment variables and defaults. - Implements logging utility with different log levels and output formatting. - Provides file system operation utilities (read/write JSON files). - Includes string manipulation utilities (e.g., `truncate`, `sanitizePrompt`). - Offers task-specific utility functions (e.g., `formatTaskId`, `findTaskById`, `taskExists`). - Implements graph algorithms like cycle detection for dependency management. + - Provides API Key resolution logic (`resolveEnvVariable`) used by `config-manager.js`. - **Silent Mode Control**: Provides `enableSilentMode` and `disableSilentMode` functions to control log output. - **Key Components**: - - `CONFIG`: Global configuration object. - `log(level, ...args)`: Logging function. - `readJSON(filepath)` / `writeJSON(filepath, data)`: File I/O utilities for JSON files. - `truncate(text, maxLength)`: String truncation utility. - `formatTaskId(id)` / `findTaskById(tasks, taskId)`: Task ID and search utilities. - `findCycles(subtaskId, dependencyMap)`: Cycle detection algorithm. - `enableSilentMode()` / `disableSilentMode()`: Control console logging output. + - `resolveEnvVariable(key, session)`: Resolves environment variables (primarily API keys) from `process.env` and `session.env`. - **[`mcp-server/`](mdc:mcp-server/): MCP Server Integration** - **Purpose**: Provides an MCP (Model Context Protocol) interface for Task Master, allowing integration with external tools like Cursor. Uses FastMCP framework. @@ -113,7 +113,6 @@ alwaysApply: false - **Direct function wrappers (`*Direct` functions in `mcp-server/src/core/direct-functions/*.js`) contain the main logic for handling MCP requests**, including path resolution, argument validation, caching, and calling core Task Master functions. - Direct functions use `findTasksJsonPath` (from [`core/utils/path-utils.js`](mdc:mcp-server/src/core/utils/path-utils.js)) to locate `tasks.json` based on the provided `projectRoot`. - **Silent Mode Implementation**: Direct functions use `enableSilentMode` and `disableSilentMode` to prevent logs from interfering with JSON responses. - - **Async Operations**: Uses `AsyncOperationManager` to handle long-running operations in the background. - **Project Initialization**: Provides `initialize_project` command for setting up new projects from within integrated clients. - Tool `execute` methods use `handleApiResult` from [`tools/utils.js`](mdc:mcp-server/src/tools/utils.js) to process the result from the direct function and format the final MCP response. - Uses CLI execution via `executeTaskMasterCommand` as a fallback only when necessary. @@ -126,7 +125,7 @@ alwaysApply: false - `mcp-server/src/server.js`: Main server setup and initialization. - `mcp-server/src/tools/`: Directory containing individual tool definitions. Each tool's `execute` method orchestrates the call to core logic and handles the response. - `mcp-server/src/tools/utils.js`: Provides MCP-specific utilities like `handleApiResult`, `processMCPResponseData`, `getCachedOrExecute`, and **`getProjectRootFromSession`**. - - `mcp-server/src/core/utils/`: Directory containing utility functions specific to the MCP server, like **`path-utils.js` for resolving `tasks.json` within a given root** and **`async-manager.js` for handling background operations**. + - `mcp-server/src/core/utils/`: Directory containing utility functions specific to the MCP server, like **`path-utils.js` for resolving `tasks.json` within a given root**. - `mcp-server/src/core/direct-functions/`: Directory containing individual files for each **direct function wrapper (`*Direct`)**. These files contain the primary logic for MCP tool execution. - `mcp-server/src/core/resources/`: Directory containing resource handlers for task templates, workflow definitions, and other static/dynamic data exposed to LLM clients. - [`task-master-core.js`](mdc:mcp-server/src/core/task-master-core.js): Acts as an import/export hub, collecting and exporting direct functions from the `direct-functions` directory and MCP utility functions. @@ -136,17 +135,6 @@ alwaysApply: false - **Tool Registration Functions** use **camelCase** with `Tool` suffix: `registerListTasksTool`, `registerSetTaskStatusTool` - **MCP Tool Names** use **snake_case**: `list_tasks`, `set_task_status`, `parse_prd_document` - **Resource Handlers** use **camelCase** with pattern URI: `@mcp.resource("tasks://templates/{template_id}")` - - **AsyncOperationManager**: - - **Purpose**: Manages background execution of long-running operations. - - **Location**: `mcp-server/src/core/utils/async-manager.js` - - **Key Features**: - - Operation tracking with unique IDs using UUID - - Status management (pending, running, completed, failed) - - Progress reporting forwarded from background tasks - - Operation history with automatic cleanup of completed operations - - Context preservation (log, session, reportProgress) - - Robust error handling for background tasks - - **Usage**: Used for CPU-intensive operations like task expansion and PRD parsing - **[`init.js`](mdc:scripts/init.js): Project Initialization Logic** - **Purpose**: Contains the core logic for setting up a new Task Master project structure. @@ -365,20 +353,4 @@ The `initialize_project` command provides a way to set up a new Task Master proj - Sets up `tasks.json` and initial task files - Configures project metadata (name, description, version) - Handles shell alias creation if requested - - Works in both interactive and non-interactive modes - -## Async Operation Management - -The AsyncOperationManager provides background task execution capabilities: - -- **Location**: `mcp-server/src/core/utils/async-manager.js` -- **Key Components**: - - `asyncOperationManager` singleton instance - - `addOperation(operationFn, args, context)` method - - `getStatus(operationId)` method -- **Usage Flow**: - 1. Client calls an MCP tool that may take time to complete - 2. Tool uses AsyncOperationManager to run the operation in background - 3. Tool returns immediate response with operation ID - 4. Client polls `get_operation_status` tool with the ID - 5. Once completed, client can access operation results \ No newline at end of file + - Works in both interactive and non-interactive modes \ No newline at end of file diff --git a/.cursor/rules/dev_workflow.mdc b/.cursor/rules/dev_workflow.mdc index 42ea0eb1..8a330ea0 100644 --- a/.cursor/rules/dev_workflow.mdc +++ b/.cursor/rules/dev_workflow.mdc @@ -99,22 +99,26 @@ Task Master offers two primary ways to interact: - **subtasks**: List of smaller, more specific tasks (Example: `[{"id": 1, "title": "Configure OAuth", ...}]`) - Refer to [`tasks.mdc`](mdc:.cursor/rules/tasks.mdc) for more details on the task data structure. -## Environment Variables Configuration +## Configuration Management -- Task Master behavior is configured via environment variables: - - **ANTHROPIC_API_KEY** (Required): Your Anthropic API key for Claude. - - **MODEL**: Claude model to use (e.g., `claude-3-opus-20240229`). - - **MAX_TOKENS**: Maximum tokens for AI responses. - - **TEMPERATURE**: Temperature for AI model responses. - - **DEBUG**: Enable debug logging (`true`/`false`). - - **LOG_LEVEL**: Console output level (`debug`, `info`, `warn`, `error`). - - **DEFAULT_SUBTASKS**: Default number of subtasks for `expand`. - - **DEFAULT_PRIORITY**: Default priority for new tasks. - - **PROJECT_NAME**: Project name used in metadata. - - **PROJECT_VERSION**: Project version used in metadata. - - **PERPLEXITY_API_KEY**: API key for Perplexity AI (for `--research` flags). - - **PERPLEXITY_MODEL**: Perplexity model to use (e.g., `sonar-medium-online`). -- See [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc) for default values and examples. +Taskmaster configuration is managed through two main mechanisms: + +1. **`.taskmasterconfig` File (Primary):** + * Located in the project root directory. + * Stores most configuration settings: AI model selections (main, research, fallback), parameters (max tokens, temperature), logging level, default subtasks/priority, project name, etc. + * **Managed via `task-master models --setup` command.** Do not edit manually unless you know what you are doing. + * Created automatically when you run `task-master models --setup` for the first time. + * View the current configuration using `task-master models`. + +2. **Environment Variables (`.env` / `mcp.json`):** + * Used **only** for sensitive API keys and specific endpoint URLs. + * Place API keys (one per provider) in a `.env` file in the project root for CLI usage. + * For MCP/Cursor integration, configure these keys in the `env` section of `.cursor/mcp.json`. + * Available keys/variables: See `assets/env.example` or the `Configuration` section in [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc). + +**Important:** Non-API key settings (like `MODEL`, `MAX_TOKENS`, `LOG_LEVEL`) are **no longer configured via environment variables**. Use `task-master models --setup` instead. +**If AI commands FAIL in MCP** verify that the API key for the selected provider is present in the mcp.json +**If AI commands FAIL in CLI** verify that the API key for the selected provider is present in the .env in the root of the project. ## Determining the Next Task diff --git a/.cursor/rules/new_features.mdc b/.cursor/rules/new_features.mdc index a900c70d..7fb5ecf2 100644 --- a/.cursor/rules/new_features.mdc +++ b/.cursor/rules/new_features.mdc @@ -28,7 +28,7 @@ The standard pattern for adding a feature follows this workflow: 2. **UI Components**: Add any display functions to [`ui.js`](mdc:scripts/modules/ui.js) following [`ui.mdc`](mdc:.cursor/rules/ui.mdc). 3. **Command Integration**: Add the CLI command to [`commands.js`](mdc:scripts/modules/commands.js) following [`commands.mdc`](mdc:.cursor/rules/commands.mdc). 4. **Testing**: Write tests for all components of the feature (following [`tests.mdc`](mdc:.cursor/rules/tests.mdc)) -5. **Configuration**: Update any configuration in [`utils.js`](mdc:scripts/modules/utils.js) if needed, following [`utilities.mdc`](mdc:.cursor/rules/utilities.mdc). +5. **Configuration**: Update configuration settings or add new ones in [`config-manager.js`](mdc:scripts/modules/config-manager.js) and ensure getters/setters are appropriate. Update documentation in [`utilities.mdc`](mdc:.cursor/rules/utilities.mdc) and [`taskmaster.mdc`](mdc:.cursor/rules/taskmaster.mdc). Update the `.taskmasterconfig` structure if needed. 6. **Documentation**: Update help text and documentation in [dev_workflow.mdc](mdc:scripts/modules/dev_workflow.mdc) ## Critical Checklist for New Features @@ -590,3 +590,8 @@ When implementing project initialization commands: }); } ``` + + } + }); + } + ``` diff --git a/.cursor/rules/taskmaster.mdc b/.cursor/rules/taskmaster.mdc index fb40828c..262a44ea 100644 --- a/.cursor/rules/taskmaster.mdc +++ b/.cursor/rules/taskmaster.mdc @@ -327,22 +327,23 @@ This document provides a detailed reference for interacting with Taskmaster, cov ## Environment Variables Configuration -Taskmaster's behavior can be customized via environment variables. These affect both CLI and MCP server operation: +Taskmaster primarily uses the `.taskmasterconfig` file for configuration (models, parameters, logging level, etc.), managed via the `task-master models --setup` command. API keys are stored in either the .env file (for CLI usage) or the mcp.json (for MCP usage) -* **ANTHROPIC_API_KEY** (Required): Your Anthropic API key for Claude. -* **MODEL**: Claude model to use (default: `claude-3-opus-20240229`). -* **MAX_TOKENS**: Maximum tokens for AI responses (default: 8192). -* **TEMPERATURE**: Temperature for AI model responses (default: 0.7). -* **DEBUG**: Enable debug logging (`true`/`false`, default: `false`). -* **LOG_LEVEL**: Console output level (`debug`, `info`, `warn`, `error`, default: `info`). -* **DEFAULT_SUBTASKS**: Default number of subtasks for `expand` (default: 5). -* **DEFAULT_PRIORITY**: Default priority for new tasks (default: `medium`). -* **PROJECT_NAME**: Project name used in metadata. -* **PROJECT_VERSION**: Project version used in metadata. -* **PERPLEXITY_API_KEY**: API key for Perplexity AI (for `--research` flags). -* **PERPLEXITY_MODEL**: Perplexity model to use (default: `sonar-medium-online`). +Environment variables are used **only** for sensitive API keys related to AI providers and specific overrides like the Ollama base URL: -Set these in your `.env` file in the project root or in your environment before running Taskmaster. +* **API Keys (Required for corresponding provider):** + * `ANTHROPIC_API_KEY` + * `PERPLEXITY_API_KEY` + * `OPENAI_API_KEY` + * `GOOGLE_API_KEY` + * `GROK_API_KEY` + * `MISTRAL_API_KEY` + * `AZURE_OPENAI_API_KEY` (Requires `AZURE_OPENAI_ENDPOINT` too) +* **Endpoints (Optional/Provider Specific):** + * `AZURE_OPENAI_ENDPOINT` + * `OLLAMA_BASE_URL` (Default: `http://localhost:11434/api`) + +Set these in your `.env` file in the project root (for CLI use) or within the `env` section of your `.cursor/mcp.json` file (for MCP/Cursor integration). All other settings like model choice, max tokens, temperature, logging level, etc., are now managed in `.taskmasterconfig` via `task-master models --setup`. --- @@ -351,3 +352,8 @@ For implementation details: * MCP server: See [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) * Task structure: See [`tasks.mdc`](mdc:.cursor/rules/tasks.mdc) * Workflow: See [`dev_workflow.mdc`](mdc:.cursor/rules/dev_workflow.mdc) + +* CLI commands: See [`commands.mdc`](mdc:.cursor/rules/commands.mdc) +* MCP server: See [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) +* Task structure: See [`tasks.mdc`](mdc:.cursor/rules/tasks.mdc) +* Workflow: See [`dev_workflow.mdc`](mdc:.cursor/rules/dev_workflow.mdc) diff --git a/.cursor/rules/utilities.mdc b/.cursor/rules/utilities.mdc index 429601f5..80aa2ed7 100644 --- a/.cursor/rules/utilities.mdc +++ b/.cursor/rules/utilities.mdc @@ -79,28 +79,30 @@ alwaysApply: false } ``` -## Configuration Management (in `scripts/modules/utils.js`) +## Configuration Management (via `config-manager.js`) -- **Environment Variables**: - - ✅ DO: Provide default values for all configuration - - ✅ DO: Use environment variables for customization - - ✅ DO: Document available configuration options - - ❌ DON'T: Hardcode values that should be configurable +Taskmaster configuration (excluding API keys) is primarily managed through the `.taskmasterconfig` file located in the project root and accessed via getters in [`scripts/modules/config-manager.js`](mdc:scripts/modules/config-manager.js). - ```javascript - // ✅ DO: Set up configuration with defaults and environment overrides - const CONFIG = { - model: process.env.MODEL || 'claude-3-opus-20240229', // Updated default model - maxTokens: parseInt(process.env.MAX_TOKENS || '4000'), - temperature: parseFloat(process.env.TEMPERATURE || '0.7'), - debug: process.env.DEBUG === "true", - logLevel: process.env.LOG_LEVEL || "info", - defaultSubtasks: parseInt(process.env.DEFAULT_SUBTASKS || "3"), - defaultPriority: process.env.DEFAULT_PRIORITY || "medium", - projectName: process.env.PROJECT_NAME || "Task Master Project", // Generic project name - projectVersion: "1.5.0" // Version should be updated via release process - }; - ``` +- **`.taskmasterconfig` File**: + - ✅ DO: Use this JSON file to store settings like AI model selections (main, research, fallback), parameters (temperature, maxTokens), logging level, default priority/subtasks, etc. + - ✅ DO: Manage this file using the `task-master models --setup` command. + - ✅ DO: Rely on [`config-manager.js`](mdc:scripts/modules/config-manager.js) to load this file, merge with defaults, and provide validated settings. + - ❌ DON'T: Store API keys in this file. + - ❌ DON'T: Rely on the old `CONFIG` object previously defined in `utils.js`. + +- **Configuration Getters (`config-manager.js`)**: + - ✅ DO: Import and use specific getters from `config-manager.js` (e.g., `getMainProvider()`, `getLogLevel()`, `getMainMaxTokens()`) to access configuration values. + - ✅ DO: Pass the optional `explicitRoot` parameter to getters if you need to load config from a specific project path (mainly relevant for MCP direct functions). + - ❌ DON'T: Access configuration values directly from environment variables (except API keys). + - ❌ DON'T: Use the now-removed `CONFIG` object from `utils.js`. + +- **API Key Handling (`utils.js` & `config-manager.js`)**: + - ✅ DO: Store API keys **only** in `.env` (for CLI) or `.cursor/mcp.json` (for MCP). + - ✅ DO: Use `isApiKeySet(providerName, session)` from `config-manager.js` to check if a provider's key is available. + - ✅ DO: Internally, API keys are resolved using `resolveEnvVariable(key, session)` (from `utils.js`), which checks `process.env` and `session.env`. + +- **Error Handling**: + - ✅ DO: Be prepared to handle `ConfigurationError` if the `.taskmasterconfig` file is missing (see `runCLI` in [`commands.js`](mdc:scripts/modules/commands.js) for example). ## Logging Utilities (in `scripts/modules/utils.js`) @@ -514,4 +516,9 @@ export { }; ``` +Refer to [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) and [`architecture.mdc`](mdc:.cursor/rules/architecture.mdc) for more context on MCP server architecture and integration. + getCachedOrExecute +}; +``` + Refer to [`mcp.mdc`](mdc:.cursor/rules/mcp.mdc) and [`architecture.mdc`](mdc:.cursor/rules/architecture.mdc) for more context on MCP server architecture and integration. \ No newline at end of file diff --git a/tasks/task_061.txt b/tasks/task_061.txt index 9ca807bc..e2a3e099 100644 --- a/tasks/task_061.txt +++ b/tasks/task_061.txt @@ -1222,7 +1222,7 @@ function checkProviderCapability(provider, capability) { ### Details: -## 30. Update Configuration Management for AI Providers [pending] +## 30. Update Configuration Management for AI Providers [done] ### Dependencies: None ### Description: Update `config-manager.js` and related configuration logic/documentation to support the new provider/model selection mechanism for `ai-services-unified.js` (e.g., using `AI_PROVIDER`, `AI_MODEL` env vars from `process.env` or `session.env`), ensuring compatibility with existing role-based selection if needed. ### Details: @@ -1375,6 +1375,24 @@ Implementation notes: + +**Implementation Update (Deviation from Original Plan):** + +- The configuration management system has been refactored to **eliminate environment variable overrides** (such as `AI_PROVIDER`, `AI_MODEL`, `MAX_TOKENS`, etc.) for all settings except API keys and select endpoints. All configuration values for providers, models, parameters, and logging are now sourced *exclusively* from the loaded `.taskmasterconfig` file (merged with defaults), ensuring a single source of truth. + +- The `resolveConfig` and `resolveAIConfig` helpers, which previously checked `process.env` and `session.env`, have been **removed**. All configuration getters now directly access the loaded configuration object. + +- A new `MissingConfigError` is thrown if the `.taskmasterconfig` file is not found at startup. This error is caught in the application entrypoint (`ai-services-unified.js`), which then instructs the user to initialize the configuration file before proceeding. + +- API key and endpoint resolution remains an exception: environment variable overrides are still supported for secrets like `OPENAI_API_KEY` or provider-specific endpoints, maintaining security best practices. + +- Documentation (`README.md`, inline JSDoc, and `.taskmasterconfig` schema) has been updated to clarify that **environment variables are no longer used for general configuration** (other than secrets), and that all settings must be defined in `.taskmasterconfig`. + +- All application components have been updated to use the new configuration getters, and any direct access to `CONFIG`, `process.env`, or the previous helpers has been removed. + +- This stricter approach enforces configuration-as-code principles, ensures reproducibility, and prevents configuration drift, aligning with modern best practices for immutable infrastructure and automated configuration management[2][4]. + + ## 31. Implement Integration Tests for Unified AI Service [pending] ### Dependencies: 61.18 ### Description: Implement integration tests for `ai-services-unified.js`. These tests should verify the correct routing to different provider modules based on configuration and ensure the unified service functions (`generateTextService`, `generateObjectService`, etc.) work correctly when called from modules like `task-manager.js`. diff --git a/tasks/tasks.json b/tasks/tasks.json index 3b16419e..e9fb9e31 100644 --- a/tasks/tasks.json +++ b/tasks/tasks.json @@ -3064,8 +3064,8 @@ "id": 30, "title": "Update Configuration Management for AI Providers", "description": "Update `config-manager.js` and related configuration logic/documentation to support the new provider/model selection mechanism for `ai-services-unified.js` (e.g., using `AI_PROVIDER`, `AI_MODEL` env vars from `process.env` or `session.env`), ensuring compatibility with existing role-based selection if needed.", - "details": "\n\n\n```javascript\n// Implementation details for config-manager.js updates\n\n/**\n * Unified configuration resolution function that checks multiple sources in priority order:\n * 1. process.env\n * 2. session.env (if available)\n * 3. Default values from .taskmasterconfig\n * \n * @param {string} key - Configuration key to resolve\n * @param {object} session - Optional session object that may contain env values\n * @param {*} defaultValue - Default value if not found in any source\n * @returns {*} Resolved configuration value\n */\nfunction resolveConfig(key, session = null, defaultValue = null) {\n return process.env[key] ?? session?.env?.[key] ?? defaultValue;\n}\n\n// AI provider/model resolution with fallback to role-based selection\nfunction resolveAIConfig(session = null, role = 'default') {\n const provider = resolveConfig('AI_PROVIDER', session);\n const model = resolveConfig('AI_MODEL', session);\n \n // If explicit provider/model specified, use those\n if (provider && model) {\n return { provider, model };\n }\n \n // Otherwise fall back to role-based configuration\n const roleConfig = getRoleBasedAIConfig(role);\n return {\n provider: provider || roleConfig.provider,\n model: model || roleConfig.model\n };\n}\n\n// Example usage in ai-services-unified.js:\n// const { provider, model } = resolveAIConfig(session, role);\n// const client = getProviderClient(provider, resolveConfig(`${provider.toUpperCase()}_API_KEY`, session));\n\n/**\n * Configuration Resolution Documentation:\n * \n * 1. Environment Variables:\n * - AI_PROVIDER: Explicitly sets the AI provider (e.g., 'openai', 'anthropic')\n * - AI_MODEL: Explicitly sets the model to use (e.g., 'gpt-4', 'claude-2')\n * - OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.: Provider-specific API keys\n * \n * 2. Resolution Strategy:\n * - Values are first checked in process.env\n * - If not found, session.env is checked (when available)\n * - If still not found, defaults from .taskmasterconfig are used\n * - For AI provider/model, explicit settings override role-based configuration\n * \n * 3. Backward Compatibility:\n * - Role-based selection continues to work when AI_PROVIDER/AI_MODEL are not set\n * - Existing code using getRoleBasedAIConfig() will continue to function\n */\n```\n\n\n\n\n```javascript\n/**\n * Refactored configuration management implementation\n */\n\n// Core configuration getters - replace direct CONFIG access\nconst getMainProvider = () => resolveConfig('AI_PROVIDER', null, CONFIG.ai?.mainProvider || 'openai');\nconst getMainModel = () => resolveConfig('AI_MODEL', null, CONFIG.ai?.mainModel || 'gpt-4');\nconst getLogLevel = () => resolveConfig('LOG_LEVEL', null, CONFIG.logging?.level || 'info');\nconst getMaxTokens = (role = 'default') => {\n const explicitMaxTokens = parseInt(resolveConfig('MAX_TOKENS', null, 0), 10);\n if (explicitMaxTokens > 0) return explicitMaxTokens;\n \n // Fall back to role-based configuration\n return CONFIG.ai?.roles?.[role]?.maxTokens || CONFIG.ai?.defaultMaxTokens || 4096;\n};\n\n// API key resolution - separate from general configuration\nfunction resolveEnvVariable(key, session = null) {\n return process.env[key] ?? session?.env?.[key] ?? null;\n}\n\nfunction isApiKeySet(provider, session = null) {\n const keyName = `${provider.toUpperCase()}_API_KEY`;\n return Boolean(resolveEnvVariable(keyName, session));\n}\n\n/**\n * Migration guide for application components:\n * \n * 1. Replace direct CONFIG access:\n * - Before: `const provider = CONFIG.ai.mainProvider;`\n * - After: `const provider = getMainProvider();`\n * \n * 2. Replace direct process.env access for API keys:\n * - Before: `const apiKey = process.env.OPENAI_API_KEY;`\n * - After: `const apiKey = resolveEnvVariable('OPENAI_API_KEY', session);`\n * \n * 3. Check API key availability:\n * - Before: `if (process.env.OPENAI_API_KEY) {...}`\n * - After: `if (isApiKeySet('openai', session)) {...}`\n * \n * 4. Update provider/model selection in ai-services:\n * - Before: \n * ```\n * const provider = role ? CONFIG.ai.roles[role]?.provider : CONFIG.ai.mainProvider;\n * const model = role ? CONFIG.ai.roles[role]?.model : CONFIG.ai.mainModel;\n * ```\n * - After:\n * ```\n * const { provider, model } = resolveAIConfig(session, role);\n * ```\n */\n\n// Update .taskmasterconfig schema documentation\nconst configSchema = {\n \"ai\": {\n \"mainProvider\": \"Default AI provider (overridden by AI_PROVIDER env var)\",\n \"mainModel\": \"Default AI model (overridden by AI_MODEL env var)\",\n \"defaultMaxTokens\": \"Default max tokens (overridden by MAX_TOKENS env var)\",\n \"roles\": {\n \"role_name\": {\n \"provider\": \"Provider for this role (fallback if AI_PROVIDER not set)\",\n \"model\": \"Model for this role (fallback if AI_MODEL not set)\",\n \"maxTokens\": \"Max tokens for this role (fallback if MAX_TOKENS not set)\"\n }\n }\n },\n \"logging\": {\n \"level\": \"Logging level (overridden by LOG_LEVEL env var)\"\n }\n};\n```\n\nImplementation notes:\n1. All configuration getters should provide environment variable override capability first, then fall back to .taskmasterconfig values\n2. API key resolution should be kept separate from general configuration to maintain security boundaries\n3. Update all application components to use these new getters rather than accessing CONFIG or process.env directly\n4. Document the priority order (env vars > session.env > .taskmasterconfig) in JSDoc comments\n5. Ensure backward compatibility by maintaining support for role-based configuration when explicit env vars aren't set\n\n", - "status": "pending", + "details": "\n\n\n```javascript\n// Implementation details for config-manager.js updates\n\n/**\n * Unified configuration resolution function that checks multiple sources in priority order:\n * 1. process.env\n * 2. session.env (if available)\n * 3. Default values from .taskmasterconfig\n * \n * @param {string} key - Configuration key to resolve\n * @param {object} session - Optional session object that may contain env values\n * @param {*} defaultValue - Default value if not found in any source\n * @returns {*} Resolved configuration value\n */\nfunction resolveConfig(key, session = null, defaultValue = null) {\n return process.env[key] ?? session?.env?.[key] ?? defaultValue;\n}\n\n// AI provider/model resolution with fallback to role-based selection\nfunction resolveAIConfig(session = null, role = 'default') {\n const provider = resolveConfig('AI_PROVIDER', session);\n const model = resolveConfig('AI_MODEL', session);\n \n // If explicit provider/model specified, use those\n if (provider && model) {\n return { provider, model };\n }\n \n // Otherwise fall back to role-based configuration\n const roleConfig = getRoleBasedAIConfig(role);\n return {\n provider: provider || roleConfig.provider,\n model: model || roleConfig.model\n };\n}\n\n// Example usage in ai-services-unified.js:\n// const { provider, model } = resolveAIConfig(session, role);\n// const client = getProviderClient(provider, resolveConfig(`${provider.toUpperCase()}_API_KEY`, session));\n\n/**\n * Configuration Resolution Documentation:\n * \n * 1. Environment Variables:\n * - AI_PROVIDER: Explicitly sets the AI provider (e.g., 'openai', 'anthropic')\n * - AI_MODEL: Explicitly sets the model to use (e.g., 'gpt-4', 'claude-2')\n * - OPENAI_API_KEY, ANTHROPIC_API_KEY, etc.: Provider-specific API keys\n * \n * 2. Resolution Strategy:\n * - Values are first checked in process.env\n * - If not found, session.env is checked (when available)\n * - If still not found, defaults from .taskmasterconfig are used\n * - For AI provider/model, explicit settings override role-based configuration\n * \n * 3. Backward Compatibility:\n * - Role-based selection continues to work when AI_PROVIDER/AI_MODEL are not set\n * - Existing code using getRoleBasedAIConfig() will continue to function\n */\n```\n\n\n\n\n```javascript\n/**\n * Refactored configuration management implementation\n */\n\n// Core configuration getters - replace direct CONFIG access\nconst getMainProvider = () => resolveConfig('AI_PROVIDER', null, CONFIG.ai?.mainProvider || 'openai');\nconst getMainModel = () => resolveConfig('AI_MODEL', null, CONFIG.ai?.mainModel || 'gpt-4');\nconst getLogLevel = () => resolveConfig('LOG_LEVEL', null, CONFIG.logging?.level || 'info');\nconst getMaxTokens = (role = 'default') => {\n const explicitMaxTokens = parseInt(resolveConfig('MAX_TOKENS', null, 0), 10);\n if (explicitMaxTokens > 0) return explicitMaxTokens;\n \n // Fall back to role-based configuration\n return CONFIG.ai?.roles?.[role]?.maxTokens || CONFIG.ai?.defaultMaxTokens || 4096;\n};\n\n// API key resolution - separate from general configuration\nfunction resolveEnvVariable(key, session = null) {\n return process.env[key] ?? session?.env?.[key] ?? null;\n}\n\nfunction isApiKeySet(provider, session = null) {\n const keyName = `${provider.toUpperCase()}_API_KEY`;\n return Boolean(resolveEnvVariable(keyName, session));\n}\n\n/**\n * Migration guide for application components:\n * \n * 1. Replace direct CONFIG access:\n * - Before: `const provider = CONFIG.ai.mainProvider;`\n * - After: `const provider = getMainProvider();`\n * \n * 2. Replace direct process.env access for API keys:\n * - Before: `const apiKey = process.env.OPENAI_API_KEY;`\n * - After: `const apiKey = resolveEnvVariable('OPENAI_API_KEY', session);`\n * \n * 3. Check API key availability:\n * - Before: `if (process.env.OPENAI_API_KEY) {...}`\n * - After: `if (isApiKeySet('openai', session)) {...}`\n * \n * 4. Update provider/model selection in ai-services:\n * - Before: \n * ```\n * const provider = role ? CONFIG.ai.roles[role]?.provider : CONFIG.ai.mainProvider;\n * const model = role ? CONFIG.ai.roles[role]?.model : CONFIG.ai.mainModel;\n * ```\n * - After:\n * ```\n * const { provider, model } = resolveAIConfig(session, role);\n * ```\n */\n\n// Update .taskmasterconfig schema documentation\nconst configSchema = {\n \"ai\": {\n \"mainProvider\": \"Default AI provider (overridden by AI_PROVIDER env var)\",\n \"mainModel\": \"Default AI model (overridden by AI_MODEL env var)\",\n \"defaultMaxTokens\": \"Default max tokens (overridden by MAX_TOKENS env var)\",\n \"roles\": {\n \"role_name\": {\n \"provider\": \"Provider for this role (fallback if AI_PROVIDER not set)\",\n \"model\": \"Model for this role (fallback if AI_MODEL not set)\",\n \"maxTokens\": \"Max tokens for this role (fallback if MAX_TOKENS not set)\"\n }\n }\n },\n \"logging\": {\n \"level\": \"Logging level (overridden by LOG_LEVEL env var)\"\n }\n};\n```\n\nImplementation notes:\n1. All configuration getters should provide environment variable override capability first, then fall back to .taskmasterconfig values\n2. API key resolution should be kept separate from general configuration to maintain security boundaries\n3. Update all application components to use these new getters rather than accessing CONFIG or process.env directly\n4. Document the priority order (env vars > session.env > .taskmasterconfig) in JSDoc comments\n5. Ensure backward compatibility by maintaining support for role-based configuration when explicit env vars aren't set\n\n\n\n\n**Implementation Update (Deviation from Original Plan):**\n\n- The configuration management system has been refactored to **eliminate environment variable overrides** (such as `AI_PROVIDER`, `AI_MODEL`, `MAX_TOKENS`, etc.) for all settings except API keys and select endpoints. All configuration values for providers, models, parameters, and logging are now sourced *exclusively* from the loaded `.taskmasterconfig` file (merged with defaults), ensuring a single source of truth.\n\n- The `resolveConfig` and `resolveAIConfig` helpers, which previously checked `process.env` and `session.env`, have been **removed**. All configuration getters now directly access the loaded configuration object.\n\n- A new `MissingConfigError` is thrown if the `.taskmasterconfig` file is not found at startup. This error is caught in the application entrypoint (`ai-services-unified.js`), which then instructs the user to initialize the configuration file before proceeding.\n\n- API key and endpoint resolution remains an exception: environment variable overrides are still supported for secrets like `OPENAI_API_KEY` or provider-specific endpoints, maintaining security best practices.\n\n- Documentation (`README.md`, inline JSDoc, and `.taskmasterconfig` schema) has been updated to clarify that **environment variables are no longer used for general configuration** (other than secrets), and that all settings must be defined in `.taskmasterconfig`.\n\n- All application components have been updated to use the new configuration getters, and any direct access to `CONFIG`, `process.env`, or the previous helpers has been removed.\n\n- This stricter approach enforces configuration-as-code principles, ensures reproducibility, and prevents configuration drift, aligning with modern best practices for immutable infrastructure and automated configuration management[2][4].\n", + "status": "done", "dependencies": [], "parentTaskId": 61 },