feat(telemetry): Implement AI usage telemetry pattern and apply to add-task
This commit introduces a standardized pattern for capturing and propagating AI usage telemetry (cost, tokens, model used) across the Task Master stack and applies it to the 'add-task' functionality. Key changes include: - **Telemetry Pattern Definition:** - Added defining the integration pattern for core logic, direct functions, MCP tools, and CLI commands. - Updated related rules (, , Usage: mcp [OPTIONS] COMMAND [ARGS]... MCP development tools ╭─ Options ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ --help Show this message and exit. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Commands ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ version Show the MCP version. │ │ dev Run a MCP server with the MCP Inspector. │ │ run Run a MCP server. │ │ install Install a MCP server in the Claude desktop app. │ ╰────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯, , ) to reference the new telemetry rule. - **Core Telemetry Implementation ():** - Refactored the unified AI service to generate and return a object alongside the main AI result. - Fixed an MCP server startup crash by removing redundant local loading of and instead using the imported from for cost calculations. - Added to the object. - ** Integration:** - Modified (core) to receive from the AI service, return it, and call the new UI display function for CLI output. - Updated to receive from the core function and include it in the payload of its response. - Ensured (MCP tool) correctly passes the through via . - Updated to correctly pass context (, ) to the core function and rely on it for CLI telemetry display. - **UI Enhancement:** - Added function to to show telemetry details in the CLI. - **Project Management:** - Added subtasks 77.6 through 77.12 to track the rollout of this telemetry pattern to other AI-powered commands (, , , , , , ). This establishes the foundation for tracking AI usage across the application.
This commit is contained in:
@@ -62,7 +62,8 @@ import {
|
||||
stopLoadingIndicator,
|
||||
displayModelConfiguration,
|
||||
displayAvailableModels,
|
||||
displayApiKeyStatus
|
||||
displayApiKeyStatus,
|
||||
displayAiUsageSummary
|
||||
} from './ui.js';
|
||||
|
||||
import { initializeProject } from '../init.js';
|
||||
@@ -1263,7 +1264,7 @@ function registerCommands(programInstance) {
|
||||
// add-task command
|
||||
programInstance
|
||||
.command('add-task')
|
||||
.description('Add a new task using AI or manual input')
|
||||
.description('Add a new task using AI, optionally providing manual details')
|
||||
.option('-f, --file <file>', 'Path to the tasks file', 'tasks/tasks.json')
|
||||
.option(
|
||||
'-p, --prompt <prompt>',
|
||||
@@ -1308,74 +1309,70 @@ function registerCommands(programInstance) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const tasksPath =
|
||||
options.file ||
|
||||
path.join(findProjectRoot() || '.', 'tasks', 'tasks.json') || // Ensure tasksPath is also relative to a found root or current dir
|
||||
'tasks/tasks.json';
|
||||
|
||||
// Correctly determine projectRoot
|
||||
const projectRoot = findProjectRoot();
|
||||
|
||||
let manualTaskData = null;
|
||||
if (isManualCreation) {
|
||||
manualTaskData = {
|
||||
title: options.title,
|
||||
description: options.description,
|
||||
details: options.details || '',
|
||||
testStrategy: options.testStrategy || ''
|
||||
};
|
||||
// Restore specific logging for manual creation
|
||||
console.log(
|
||||
chalk.blue(`Creating task manually with title: "${options.title}"`)
|
||||
);
|
||||
} else {
|
||||
// Restore specific logging for AI creation
|
||||
console.log(
|
||||
chalk.blue(`Creating task with AI using prompt: "${options.prompt}"`)
|
||||
);
|
||||
}
|
||||
|
||||
// Log dependencies and priority if provided (restored)
|
||||
const dependenciesArray = options.dependencies
|
||||
? options.dependencies.split(',').map((id) => id.trim())
|
||||
: [];
|
||||
if (dependenciesArray.length > 0) {
|
||||
console.log(
|
||||
chalk.blue(`Dependencies: [${dependenciesArray.join(', ')}]`)
|
||||
);
|
||||
}
|
||||
if (options.priority) {
|
||||
console.log(chalk.blue(`Priority: ${options.priority}`));
|
||||
}
|
||||
|
||||
const context = {
|
||||
projectRoot,
|
||||
commandName: 'add-task',
|
||||
outputType: 'cli'
|
||||
};
|
||||
|
||||
try {
|
||||
// Prepare dependencies if provided
|
||||
let dependencies = [];
|
||||
if (options.dependencies) {
|
||||
dependencies = options.dependencies
|
||||
.split(',')
|
||||
.map((id) => parseInt(id.trim(), 10));
|
||||
}
|
||||
|
||||
// Create manual task data if title and description are provided
|
||||
let manualTaskData = null;
|
||||
if (isManualCreation) {
|
||||
manualTaskData = {
|
||||
title: options.title,
|
||||
description: options.description,
|
||||
details: options.details || '',
|
||||
testStrategy: options.testStrategy || ''
|
||||
};
|
||||
|
||||
console.log(
|
||||
chalk.blue(`Creating task manually with title: "${options.title}"`)
|
||||
);
|
||||
if (dependencies.length > 0) {
|
||||
console.log(
|
||||
chalk.blue(`Dependencies: [${dependencies.join(', ')}]`)
|
||||
);
|
||||
}
|
||||
if (options.priority) {
|
||||
console.log(chalk.blue(`Priority: ${options.priority}`));
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
chalk.blue(
|
||||
`Creating task with AI using prompt: "${options.prompt}"`
|
||||
)
|
||||
);
|
||||
if (dependencies.length > 0) {
|
||||
console.log(
|
||||
chalk.blue(`Dependencies: [${dependencies.join(', ')}]`)
|
||||
);
|
||||
}
|
||||
if (options.priority) {
|
||||
console.log(chalk.blue(`Priority: ${options.priority}`));
|
||||
}
|
||||
}
|
||||
|
||||
// Pass mcpLog and session for MCP mode
|
||||
const newTaskId = await addTask(
|
||||
options.file,
|
||||
options.prompt, // Pass prompt (will be null/undefined if not provided)
|
||||
dependencies,
|
||||
const { newTaskId, telemetryData } = await addTask(
|
||||
tasksPath,
|
||||
options.prompt,
|
||||
dependenciesArray,
|
||||
options.priority,
|
||||
{
|
||||
// For CLI, session context isn't directly available like MCP
|
||||
// We don't need to pass session here for CLI API key resolution
|
||||
// as dotenv loads .env, and utils.resolveEnvVariable checks process.env
|
||||
},
|
||||
'text', // outputFormat
|
||||
manualTaskData, // Pass the potentially created manualTaskData object
|
||||
options.research || false // Pass the research flag value
|
||||
context,
|
||||
'text',
|
||||
manualTaskData,
|
||||
options.research
|
||||
);
|
||||
|
||||
console.log(chalk.green(`✓ Added new task #${newTaskId}`));
|
||||
console.log(chalk.gray('Next: Complete this task or add more tasks'));
|
||||
// addTask handles detailed CLI success logging AND telemetry display when outputFormat is 'text'
|
||||
// No need to call displayAiUsageSummary here anymore.
|
||||
} catch (error) {
|
||||
console.error(chalk.red(`Error adding task: ${error.message}`));
|
||||
if (error.stack && getDebugFlag()) {
|
||||
console.error(error.stack);
|
||||
if (error.details) {
|
||||
console.error(chalk.red(error.details));
|
||||
}
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user