refactor(config): Standardize env var access and config getters
This commit focuses on standardizing configuration and API key access patterns across key modules as part of subtask 61.34. Key changes include: - Refactored `ai-services.js` to remove global AI clients and use `resolveEnvVariable` for API key checks. Client instantiation now relies on `getAnthropicClient`/`getPerplexityClient` accepting a session object. - Refactored `task-manager.js` (`analyzeTaskComplexity` function) to use the unified `generateTextService` from `ai-services-unified.js`, removing direct AI client calls. - Replaced direct `process.env` access for model parameters and other configurations (`PERPLEXITY_MODEL`, `CONFIG.*`) in `task-manager.js` with calls to the appropriate getters from `config-manager.js` (e.g., `getResearchModelId(session)`, `getMainMaxTokens(session)`). - Ensured `utils.js` (`resolveEnvVariable`) correctly handles potentially undefined session objects. - Updated function signatures where necessary to propagate the `session` object for correct context-aware configuration/key retrieval. This moves towards the goal of using `ai-client-factory.js` and `ai-services-unified.js` as the standard pattern for AI interactions and centralizing configuration management through `config-manager.js`.
This commit is contained in:
140
scripts/modules/task-manager/parse-prd.js
Normal file
140
scripts/modules/task-manager/parse-prd.js
Normal file
@@ -0,0 +1,140 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import chalk from 'chalk';
|
||||
import boxen from 'boxen';
|
||||
|
||||
import {
|
||||
log,
|
||||
writeJSON,
|
||||
enableSilentMode,
|
||||
disableSilentMode,
|
||||
isSilentMode
|
||||
} from '../utils.js';
|
||||
|
||||
import { callClaude } from '../ai-services.js';
|
||||
import { getDebugFlag } from '../config-manager.js';
|
||||
import generateTaskFiles from './generate-task-files.js';
|
||||
|
||||
/**
|
||||
* Parse a PRD file and generate tasks
|
||||
* @param {string} prdPath - Path to the PRD file
|
||||
* @param {string} tasksPath - Path to the tasks.json file
|
||||
* @param {number} numTasks - Number of tasks to generate
|
||||
* @param {Object} options - Additional options
|
||||
* @param {Object} options.reportProgress - Function to report progress to MCP server (optional)
|
||||
* @param {Object} options.mcpLog - MCP logger object (optional)
|
||||
* @param {Object} options.session - Session object from MCP server (optional)
|
||||
* @param {Object} aiClient - AI client to use (optional)
|
||||
* @param {Object} modelConfig - Model configuration (optional)
|
||||
*/
|
||||
async function parsePRD(
|
||||
prdPath,
|
||||
tasksPath,
|
||||
numTasks,
|
||||
options = {},
|
||||
aiClient = null,
|
||||
modelConfig = null
|
||||
) {
|
||||
const { reportProgress, mcpLog, session } = options;
|
||||
|
||||
// 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);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
report(`Parsing PRD file: ${prdPath}`, 'info');
|
||||
|
||||
// Read the PRD content
|
||||
const prdContent = fs.readFileSync(prdPath, 'utf8');
|
||||
|
||||
// Call Claude to generate tasks, passing the provided AI client if available
|
||||
const tasksData = await callClaude(
|
||||
prdContent,
|
||||
prdPath,
|
||||
numTasks,
|
||||
0,
|
||||
{ reportProgress, mcpLog, session },
|
||||
aiClient,
|
||||
modelConfig
|
||||
);
|
||||
|
||||
// Create the directory if it doesn't exist
|
||||
const tasksDir = path.dirname(tasksPath);
|
||||
if (!fs.existsSync(tasksDir)) {
|
||||
fs.mkdirSync(tasksDir, { recursive: true });
|
||||
}
|
||||
// Write the tasks to the file
|
||||
writeJSON(tasksPath, tasksData);
|
||||
report(
|
||||
`Successfully generated ${tasksData.tasks.length} tasks from PRD`,
|
||||
'success'
|
||||
);
|
||||
report(`Tasks saved to: ${tasksPath}`, 'info');
|
||||
|
||||
// Generate individual task files
|
||||
if (reportProgress && mcpLog) {
|
||||
// Enable silent mode when being called from MCP server
|
||||
enableSilentMode();
|
||||
await generateTaskFiles(tasksPath, tasksDir);
|
||||
disableSilentMode();
|
||||
} else {
|
||||
await generateTaskFiles(tasksPath, tasksDir);
|
||||
}
|
||||
|
||||
// Only show success boxes for text output (CLI)
|
||||
if (outputFormat === 'text') {
|
||||
console.log(
|
||||
boxen(
|
||||
chalk.green(
|
||||
`Successfully generated ${tasksData.tasks.length} tasks from PRD`
|
||||
),
|
||||
{ padding: 1, borderColor: 'green', borderStyle: 'round' }
|
||||
)
|
||||
);
|
||||
|
||||
console.log(
|
||||
boxen(
|
||||
chalk.white.bold('Next Steps:') +
|
||||
'\n\n' +
|
||||
`${chalk.cyan('1.')} Run ${chalk.yellow('task-master list')} to view all tasks\n` +
|
||||
`${chalk.cyan('2.')} Run ${chalk.yellow('task-master expand --id=<id>')} to break down a task into subtasks`,
|
||||
{
|
||||
padding: 1,
|
||||
borderColor: 'cyan',
|
||||
borderStyle: 'round',
|
||||
margin: { top: 1 }
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return tasksData;
|
||||
} catch (error) {
|
||||
report(`Error parsing PRD: ${error.message}`, 'error');
|
||||
|
||||
// Only show error UI for text output (CLI)
|
||||
if (outputFormat === 'text') {
|
||||
console.error(chalk.red(`Error: ${error.message}`));
|
||||
|
||||
if (getDebugFlag()) {
|
||||
// Use getter
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
} else {
|
||||
throw error; // Re-throw for JSON output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default parsePRD;
|
||||
Reference in New Issue
Block a user