2025-04-21 17:48:30 -04:00
import fs from 'fs' ;
import path from 'path' ;
import chalk from 'chalk' ;
import boxen from 'boxen' ;
import Table from 'cli-table3' ;
import {
getStatusWithColor ,
startLoadingIndicator ,
stopLoadingIndicator
} from '../ui.js' ;
import { log , readJSON , writeJSON , truncate , isSilentMode } from '../utils.js' ;
import { getAvailableAIModel } from '../ai-services.js' ;
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
import {
getDebugFlag ,
getMainModelId ,
getMainMaxTokens ,
getMainTemperature ,
getResearchModelId ,
getResearchMaxTokens ,
getResearchTemperature
} from '../config-manager.js' ;
2025-04-21 17:48:30 -04:00
import generateTaskFiles from './generate-task-files.js' ;
/ * *
* Update a subtask by appending additional information to its description and details
* @ param { string } tasksPath - Path to the tasks . json file
* @ param { string } subtaskId - ID of the subtask to update in format "parentId.subtaskId"
* @ param { string } prompt - Prompt for generating additional information
* @ param { boolean } useResearch - Whether to use Perplexity AI for research - backed updates
* @ param { function } reportProgress - Function to report progress to MCP server ( optional )
* @ param { Object } mcpLog - MCP logger object ( optional )
* @ param { Object } session - Session object from MCP server ( optional )
* @ returns { Object | null } - The updated subtask or null if update failed
* /
async function updateSubtaskById (
tasksPath ,
subtaskId ,
prompt ,
useResearch = false ,
{ reportProgress , mcpLog , session } = { }
) {
// Determine output format based on mcpLog presence (simplification)
const outputFormat = mcpLog ? 'json' : 'text' ;
// Create custom reporter that checks for MCP log and silent mode
const report = ( message , level = 'info' ) => {
if ( mcpLog ) {
mcpLog [ level ] ( message ) ;
} else if ( ! isSilentMode ( ) && outputFormat === 'text' ) {
// Only log to console if not in silent mode and outputFormat is 'text'
log ( level , message ) ;
}
} ;
let loadingIndicator = null ;
try {
report ( ` Updating subtask ${ subtaskId } with prompt: " ${ prompt } " ` , 'info' ) ;
// Validate subtask ID format
if (
! subtaskId ||
typeof subtaskId !== 'string' ||
! subtaskId . includes ( '.' )
) {
throw new Error (
` Invalid subtask ID format: ${ subtaskId } . Subtask ID must be in format "parentId.subtaskId" `
) ;
}
// Validate prompt
if ( ! prompt || typeof prompt !== 'string' || prompt . trim ( ) === '' ) {
throw new Error (
'Prompt cannot be empty. Please provide context for the subtask update.'
) ;
}
// Prepare for fallback handling
let claudeOverloaded = false ;
// Validate tasks file exists
if ( ! fs . existsSync ( tasksPath ) ) {
throw new Error ( ` Tasks file not found at path: ${ tasksPath } ` ) ;
}
// Read the tasks file
const data = readJSON ( tasksPath ) ;
if ( ! data || ! data . tasks ) {
throw new Error (
` No valid tasks found in ${ tasksPath } . The file may be corrupted or have an invalid format. `
) ;
}
// Parse parent and subtask IDs
const [ parentIdStr , subtaskIdStr ] = subtaskId . split ( '.' ) ;
const parentId = parseInt ( parentIdStr , 10 ) ;
const subtaskIdNum = parseInt ( subtaskIdStr , 10 ) ;
if (
isNaN ( parentId ) ||
parentId <= 0 ||
isNaN ( subtaskIdNum ) ||
subtaskIdNum <= 0
) {
throw new Error (
` Invalid subtask ID format: ${ subtaskId } . Both parent ID and subtask ID must be positive integers. `
) ;
}
// Find the parent task
const parentTask = data . tasks . find ( ( task ) => task . id === parentId ) ;
if ( ! parentTask ) {
throw new Error (
` Parent task with ID ${ parentId } not found. Please verify the task ID and try again. `
) ;
}
// Find the subtask
if ( ! parentTask . subtasks || ! Array . isArray ( parentTask . subtasks ) ) {
throw new Error ( ` Parent task ${ parentId } has no subtasks. ` ) ;
}
const subtask = parentTask . subtasks . find ( ( st ) => st . id === subtaskIdNum ) ;
if ( ! subtask ) {
throw new Error (
` Subtask with ID ${ subtaskId } not found. Please verify the subtask ID and try again. `
) ;
}
// Check if subtask is already completed
if ( subtask . status === 'done' || subtask . status === 'completed' ) {
report (
` Subtask ${ subtaskId } is already marked as done and cannot be updated ` ,
'warn'
) ;
// Only show UI elements for text output (CLI)
if ( outputFormat === 'text' ) {
console . log (
boxen (
chalk . yellow (
` Subtask ${ subtaskId } is already marked as ${ subtask . status } and cannot be updated. `
) +
'\n\n' +
chalk . white (
'Completed subtasks are locked to maintain consistency. To modify a completed subtask, you must first:'
) +
'\n' +
chalk . white (
'1. Change its status to "pending" or "in-progress"'
) +
'\n' +
chalk . white ( '2. Then run the update-subtask command' ) ,
{ padding : 1 , borderColor : 'yellow' , borderStyle : 'round' }
)
) ;
}
return null ;
}
// Only show UI elements for text output (CLI)
if ( outputFormat === 'text' ) {
// Show the subtask that will be updated
const table = new Table ( {
head : [
chalk . cyan . bold ( 'ID' ) ,
chalk . cyan . bold ( 'Title' ) ,
chalk . cyan . bold ( 'Status' )
] ,
colWidths : [ 10 , 55 , 10 ]
} ) ;
table . push ( [
subtaskId ,
truncate ( subtask . title , 52 ) ,
getStatusWithColor ( subtask . status )
] ) ;
console . log (
boxen ( chalk . white . bold ( ` Updating Subtask # ${ subtaskId } ` ) , {
padding : 1 ,
borderColor : 'blue' ,
borderStyle : 'round' ,
margin : { top : 1 , bottom : 0 }
} )
) ;
console . log ( table . toString ( ) ) ;
// Start the loading indicator - only for text output
loadingIndicator = startLoadingIndicator (
'Generating additional information with AI...'
) ;
}
// Create the system prompt (as before)
const systemPrompt = ` You are an AI assistant helping to update software development subtasks with additional information.
Given a subtask , you will provide additional details , implementation notes , or technical insights based on user request .
Focus only on adding content that enhances the subtask - don ' t repeat existing information .
Be technical , specific , and implementation - focused rather than general .
Provide concrete examples , code snippets , or implementation details when relevant . ` ;
// Replace the old research/Claude code with the new model selection approach
let additionalInformation = '' ;
let modelAttempts = 0 ;
const maxModelAttempts = 2 ; // Try up to 2 models before giving up
while ( modelAttempts < maxModelAttempts && ! additionalInformation ) {
modelAttempts ++ ; // Increment attempt counter at the start
const isLastAttempt = modelAttempts >= maxModelAttempts ;
let modelType = null ; // Declare modelType outside the try block
try {
// Get the best available model based on our current state
const result = getAvailableAIModel ( {
claudeOverloaded ,
requiresResearch : useResearch
} ) ;
m odelType = result . type ;
const client = result . client ;
report (
` Attempt ${ modelAttempts } / ${ maxModelAttempts } : Generating subtask info using ${ modelType } ` ,
'info'
) ;
// Update loading indicator text - only for text output
if ( outputFormat === 'text' ) {
if ( loadingIndicator ) {
stopLoadingIndicator ( loadingIndicator ) ; // Stop previous indicator
}
loadingIndicator = startLoadingIndicator (
` Attempt ${ modelAttempts } : Using ${ modelType . toUpperCase ( ) } ... `
) ;
}
const subtaskData = JSON . stringify ( subtask , null , 2 ) ;
const userMessageContent = ` Here is the subtask to enhance: \n ${ subtaskData } \n \n Please provide additional information addressing this request: \n ${ prompt } \n \n Return ONLY the new information to add - do not repeat existing content. ` ;
if ( modelType === 'perplexity' ) {
// Construct Perplexity payload
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
const perplexityModel = getResearchModelId ( session ) ;
2025-04-21 17:48:30 -04:00
const response = await client . chat . completions . create ( {
model : perplexityModel ,
messages : [
{ role : 'system' , content : systemPrompt } ,
{ role : 'user' , content : userMessageContent }
] ,
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
temperature : getResearchTemperature ( session ) ,
max _tokens : getResearchMaxTokens ( session )
2025-04-21 17:48:30 -04:00
} ) ;
additionalInformation = response . choices [ 0 ] . message . content . trim ( ) ;
} else {
// Claude
let responseText = '' ;
let streamingInterval = null ;
try {
// Only update streaming indicator for text output
if ( outputFormat === 'text' ) {
let dotCount = 0 ;
const readline = await import ( 'readline' ) ;
streamingInterval = setInterval ( ( ) => {
readline . cursorTo ( process . stdout , 0 ) ;
process . stdout . write (
` Receiving streaming response from Claude ${ '.' . repeat ( dotCount ) } `
) ;
dotCount = ( dotCount + 1 ) % 4 ;
} , 500 ) ;
}
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
// Construct Claude payload using config getters
2025-04-21 17:48:30 -04:00
const stream = await client . messages . create ( {
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
model : getMainModelId ( session ) ,
max _tokens : getMainMaxTokens ( session ) ,
temperature : getMainTemperature ( session ) ,
2025-04-21 17:48:30 -04:00
system : systemPrompt ,
messages : [ { role : 'user' , content : userMessageContent } ] ,
stream : true
} ) ;
for await ( const chunk of stream ) {
if ( chunk . type === 'content_block_delta' && chunk . delta . text ) {
responseText += chunk . delta . text ;
}
if ( reportProgress ) {
await reportProgress ( {
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
progress :
( responseText . length / getMainMaxTokens ( session ) ) * 100
2025-04-21 17:48:30 -04:00
} ) ;
}
if ( mcpLog ) {
mcpLog . info (
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
` Progress: ${ ( responseText . length / getMainMaxTokens ( session ) ) * 100 } % `
2025-04-21 17:48:30 -04:00
) ;
}
}
} finally {
if ( streamingInterval ) clearInterval ( streamingInterval ) ;
// Clear the loading dots line - only for text output
if ( outputFormat === 'text' ) {
const readline = await import ( 'readline' ) ;
readline . cursorTo ( process . stdout , 0 ) ;
process . stdout . clearLine ( 0 ) ;
}
}
report (
` Completed streaming response from Claude API! (Attempt ${ modelAttempts } ) ` ,
'info'
) ;
additionalInformation = responseText . trim ( ) ;
}
// Success - break the loop
if ( additionalInformation ) {
report (
` Successfully generated information using ${ modelType } on attempt ${ modelAttempts } . ` ,
'info'
) ;
break ;
} else {
// Handle case where AI gave empty response without erroring
report (
` AI ( ${ modelType } ) returned empty response on attempt ${ modelAttempts } . ` ,
'warn'
) ;
if ( isLastAttempt ) {
throw new Error (
'AI returned empty response after maximum attempts.'
) ;
}
// Allow loop to continue to try another model/attempt if possible
}
} catch ( modelError ) {
const failedModel =
modelType || modelError . modelType || 'unknown model' ;
report (
` Attempt ${ modelAttempts } failed using ${ failedModel } : ${ modelError . message } ` ,
'warn'
) ;
// --- More robust overload check ---
let isOverload = false ;
// Check 1: SDK specific property (common pattern)
if ( modelError . type === 'overloaded_error' ) {
isOverload = true ;
}
// Check 2: Check nested error property (as originally intended)
else if ( modelError . error ? . type === 'overloaded_error' ) {
isOverload = true ;
}
// Check 3: Check status code if available (e.g., 429 Too Many Requests or 529 Overloaded)
else if ( modelError . status === 429 || modelError . status === 529 ) {
isOverload = true ;
}
// Check 4: Check the message string itself (less reliable)
else if ( modelError . message ? . toLowerCase ( ) . includes ( 'overloaded' ) ) {
isOverload = true ;
}
// --- End robust check ---
if ( isOverload ) {
// Use the result of the check
claudeOverloaded = true ; // Mark Claude as overloaded for the *next* potential attempt
if ( ! isLastAttempt ) {
report (
'Claude overloaded. Will attempt fallback model if available.' ,
'info'
) ;
// Stop the current indicator before continuing - only for text output
if ( outputFormat === 'text' && loadingIndicator ) {
stopLoadingIndicator ( loadingIndicator ) ;
loadingIndicator = null ; // Reset indicator
}
continue ; // Go to next iteration of the while loop to try fallback
} else {
// It was the last attempt, and it failed due to overload
report (
` Overload error on final attempt ( ${ modelAttempts } / ${ maxModelAttempts } ). No fallback possible. ` ,
'error'
) ;
// Let the error be thrown after the loop finishes, as additionalInformation will be empty.
// We don't throw immediately here, let the loop exit and the check after the loop handle it.
}
} else {
// Error was NOT an overload
// If it's not an overload, throw it immediately to be caught by the outer catch.
report (
` Non-overload error on attempt ${ modelAttempts } : ${ modelError . message } ` ,
'error'
) ;
throw modelError ; // Re-throw non-overload errors immediately.
}
} // End inner catch
} // End while loop
// If loop finished without getting information
if ( ! additionalInformation ) {
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log (
'>>> DEBUG: additionalInformation is falsy! Value:' ,
additionalInformation
) ;
}
throw new Error (
'Failed to generate additional information after all attempts.'
) ;
}
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log (
'>>> DEBUG: Got additionalInformation:' ,
additionalInformation . substring ( 0 , 50 ) + '...'
) ;
}
// Create timestamp
const currentDate = new Date ( ) ;
const timestamp = currentDate . toISOString ( ) ;
// Format the additional information with timestamp
const formattedInformation = ` \n \n <info added on ${ timestamp } > \n ${ additionalInformation } \n </info added on ${ timestamp } > ` ;
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log (
'>>> DEBUG: formattedInformation:' ,
formattedInformation . substring ( 0 , 70 ) + '...'
) ;
}
// Append to subtask details and description
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log ( '>>> DEBUG: Subtask details BEFORE append:' , subtask . details ) ;
}
if ( subtask . details ) {
subtask . details += formattedInformation ;
} else {
subtask . details = ` ${ formattedInformation } ` ;
}
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log ( '>>> DEBUG: Subtask details AFTER append:' , subtask . details ) ;
}
if ( subtask . description ) {
// Only append to description if it makes sense (for shorter updates)
if ( additionalInformation . length < 200 ) {
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log (
'>>> DEBUG: Subtask description BEFORE append:' ,
subtask . description
) ;
}
subtask . description += ` [Updated: ${ currentDate . toLocaleDateString ( ) } ] ` ;
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log (
'>>> DEBUG: Subtask description AFTER append:' ,
subtask . description
) ;
}
}
}
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log ( '>>> DEBUG: About to call writeJSON with updated data...' ) ;
}
// Write the updated tasks to the file
writeJSON ( tasksPath , data ) ;
// Only show debug info for text output (CLI)
if ( outputFormat === 'text' ) {
console . log ( '>>> DEBUG: writeJSON call completed.' ) ;
}
report ( ` Successfully updated subtask ${ subtaskId } ` , 'success' ) ;
// Generate individual task files
await generateTaskFiles ( tasksPath , path . dirname ( tasksPath ) ) ;
// Stop indicator before final console output - only for text output (CLI)
if ( outputFormat === 'text' ) {
if ( loadingIndicator ) {
stopLoadingIndicator ( loadingIndicator ) ;
loadingIndicator = null ;
}
console . log (
boxen (
chalk . green ( ` Successfully updated subtask # ${ subtaskId } ` ) +
'\n\n' +
chalk . white . bold ( 'Title:' ) +
' ' +
subtask . title +
'\n\n' +
chalk . white . bold ( 'Information Added:' ) +
'\n' +
chalk . white ( truncate ( additionalInformation , 300 , true ) ) ,
{ padding : 1 , borderColor : 'green' , borderStyle : 'round' }
)
) ;
}
return subtask ;
} catch ( error ) {
// Outer catch block handles final errors after loop/attempts
// Stop indicator on error - only for text output (CLI)
if ( outputFormat === 'text' && loadingIndicator ) {
stopLoadingIndicator ( loadingIndicator ) ;
loadingIndicator = null ;
}
report ( ` Error updating subtask: ${ error . message } ` , 'error' ) ;
// Only show error UI for text output (CLI)
if ( outputFormat === 'text' ) {
console . error ( chalk . red ( ` Error: ${ error . message } ` ) ) ;
// Provide helpful error messages based on error type
if ( error . message ? . includes ( 'ANTHROPIC_API_KEY' ) ) {
console . log (
chalk . yellow ( '\nTo fix this issue, set your Anthropic API key:' )
) ;
console . log ( ' export ANTHROPIC_API_KEY=your_api_key_here' ) ;
} else if ( error . message ? . includes ( 'PERPLEXITY_API_KEY' ) ) {
console . log ( chalk . yellow ( '\nTo fix this issue:' ) ) ;
console . log (
' 1. Set your Perplexity API key: export PERPLEXITY_API_KEY=your_api_key_here'
) ;
console . log (
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
' 2. Or run without the research flag: task-master update-subtask --id=<id> --prompt="..."'
2025-04-21 17:48:30 -04:00
) ;
} else if ( error . message ? . includes ( 'overloaded' ) ) {
// Catch final overload error
console . log (
chalk . yellow (
'\nAI model overloaded, and fallback failed or was unavailable:'
)
) ;
console . log ( ' 1. Try again in a few minutes.' ) ;
console . log ( ' 2. Ensure PERPLEXITY_API_KEY is set for fallback.' ) ;
console . log ( ' 3. Consider breaking your prompt into smaller updates.' ) ;
} else if ( error . message ? . includes ( 'not found' ) ) {
console . log ( chalk . yellow ( '\nTo fix this issue:' ) ) ;
console . log (
' 1. Run task-master list --with-subtasks to see all available subtask IDs'
) ;
console . log (
' 2. Use a valid subtask ID with the --id parameter in format \"parentId.subtaskId\"'
) ;
} else if ( error . message ? . includes ( 'empty response from AI' ) ) {
console . log (
chalk . yellow (
'\nThe AI model returned an empty response. This might be due to the prompt or API issues. Try rephrasing or trying again later.'
)
) ;
}
refactor: Standardize configuration and environment variable access
This commit centralizes configuration and environment variable access across various modules by consistently utilizing getters from scripts/modules/config-manager.js. This replaces direct access to process.env and the global CONFIG object, leading to improved consistency, maintainability, testability, and better handling of session-specific configurations within the MCP context.
Key changes include:
- Centralized Getters: Replaced numerous instances of process.env.* and CONFIG.* with corresponding getter functions (e.g., getLogLevel, getMainModelId, getResearchMaxTokens, getMainTemperature, isApiKeySet, getDebugFlag, getDefaultSubtasks).
- Session Awareness: Ensured that the session object is passed to config getters where necessary, particularly within AI service calls (ai-services.js, add-task.js) and error handling (ai-services.js), allowing for session-specific environment overrides.
- API Key Checks: Standardized API key availability checks using isApiKeySet() instead of directly checking process.env.* (e.g., for Perplexity in commands.js and ai-services.js).
- Client Instantiation Cleanup: Removed now-redundant/obsolete local client instantiation functions (getAnthropicClient, getPerplexityClient) from ai-services.js and the global Anthropic client initialization from dependency-manager.js. Client creation should now rely on the config manager and factory patterns.
- Consistent Debug Flag Usage: Standardized calls to getDebugFlag() in commands.js, removing potentially unnecessary null arguments.
- Accurate Progress Calculation: Updated AI stream progress reporting (ai-services.js, add-task.js) to use getMainMaxTokens(session) for more accurate calculations.
- Minor Cleanup: Removed unused import from scripts/modules/commands.js.
Specific module updates:
- :
- Uses getLogLevel() instead of process.env.LOG_LEVEL.
- :
- Replaced direct env/config access for model IDs, tokens, temperature, API keys, and default subtasks with appropriate getters.
- Passed session to handleClaudeError.
- Removed local getPerplexityClient and getAnthropicClient functions.
- Updated progress calculations to use getMainMaxTokens(session).
- :
- Uses isApiKeySet('perplexity') for API key checks.
- Uses getDebugFlag() consistently for debug checks.
- Removed unused import.
- :
- Removed global Anthropic client initialization.
- :
- Uses config getters (getResearch..., getMain...) for Perplexity and Claude API call parameters, preserving customEnv override logic.
This refactoring also resolves a potential SyntaxError: Identifier 'getPerplexityClient' has already been declared by removing the duplicated/obsolete function definition previously present in ai-services.js.
2025-04-21 21:30:12 -04:00
if ( getDebugFlag ( session ) ) {
2025-04-21 17:48:30 -04:00
// Use getter
console . error ( error ) ;
}
} else {
throw error ; // Re-throw for JSON output
}
return null ;
} finally {
// Final cleanup check for the indicator, although it should be stopped by now
if ( outputFormat === 'text' && loadingIndicator ) {
stopLoadingIndicator ( loadingIndicator ) ;
}
}
}
export default updateSubtaskById ;