feat: Modernize package with ES modules and improve error handling

- Update to ES modules syntax throughout the codebase
- Add fileURLToPath and dirname imports to handle __dirname in ES modules
- Upgrade Anthropic SDK from 0.10.0 to 0.39.0
- Fix JSON parsing to handle responses wrapped in Markdown code blocks
- Improve documentation with clearer installation instructions
- Add important notes about ES modules and SDK requirements
- Update environment examples with API key format and model recommendations
- Include index.js in package files list
- Bump version to 1.0.2
This commit is contained in:
Eyal Toledano
2025-03-04 14:11:57 -05:00
parent 07648a1417
commit c72373d761
10 changed files with 100 additions and 51 deletions

View File

@@ -1,8 +1,8 @@
# API Keys (Required) # API Keys (Required)
ANTHROPIC_API_KEY=your_anthropic_api_key_here ANTHROPIC_API_KEY=your_anthropic_api_key_here # Format: sk-ant-api03-...
# Model Configuration # Model Configuration
MODEL=claude-3-7-sonnet-20250219 # Specify which Claude model to use MODEL=claude-3-7-sonnet-20250219 # Recommended models: claude-3-7-sonnet-20250219, claude-3-opus-20240229
MAX_TOKENS=4000 # Maximum tokens for model responses MAX_TOKENS=4000 # Maximum tokens for model responses
TEMPERATURE=0.7 # Temperature for model responses (0.0-1.0) TEMPERATURE=0.7 # Temperature for model responses (0.0-1.0)

View File

@@ -2,10 +2,16 @@
A task management system for AI-driven development with Claude, designed to work seamlessly with Cursor AI. A task management system for AI-driven development with Claude, designed to work seamlessly with Cursor AI.
## Requirements
- Node.js 14.0.0 or higher
- Anthropic API key (Claude API)
- Anthropic SDK version 0.39.0 or higher
## Installation ## Installation
```bash ```bash
npm install -g claude-task-master npm install claude-task-master
``` ```
## Usage ## Usage
@@ -13,25 +19,15 @@ npm install -g claude-task-master
### Initialize a new project ### Initialize a new project
```bash ```bash
# Navigate to your project directory npx claude-task-init
mkdir my-new-project
cd my-new-project
# Initialize the project
claude-task-init
``` ```
This will create the necessary file structure for your project, including: This will prompt you for project details and set up a new project with the necessary files and structure.
- `.cursor/rules/dev_workflow.mdc` - Cursor rules for AI-driven development ### Important Notes
- `scripts/dev.js` - Task management script
- `scripts/README.md` - Documentation for the script 1. This package uses ES modules. Your package.json should include `"type": "module"`.
- `scripts/example_prd.txt` - Example PRD template 2. The Anthropic SDK version should be 0.39.0 or higher.
- `.env.example` - Example environment variables
- `.gitignore` - Git ignore file
- `package.json` - Project configuration
- `tasks.json` - Empty tasks file
- `tasks/` - Directory for task files
## Integrating with Cursor AI ## Integrating with Cursor AI

View File

@@ -6,14 +6,22 @@
// This file serves as the main entry point for the package // This file serves as the main entry point for the package
// The primary functionality is provided through the CLI commands // The primary functionality is provided through the CLI commands
import { fileURLToPath } from 'url';
import { dirname, resolve } from 'path';
import { createRequire } from 'module';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const require = createRequire(import.meta.url);
// Export the path to the dev.js script for programmatic usage // Export the path to the dev.js script for programmatic usage
exports.devScriptPath = require.resolve('./scripts/dev.js'); export const devScriptPath = resolve(__dirname, './scripts/dev.js');
// Export a function to initialize a new project programmatically // Export a function to initialize a new project programmatically
exports.initProject = async (options = {}) => { export const initProject = async (options = {}) => {
const init = require('./scripts/init'); const init = await import('./scripts/init.js');
return init.initializeProject(options); return init.initializeProject(options);
}; };
// Export version information // Export version information
exports.version = require('./package.json').version; export const version = require('./package.json').version;

View File

@@ -1,10 +1,11 @@
{ {
"name": "claude-task-master", "name": "claude-task-master",
"version": "1.0.1", "version": "1.0.2",
"description": "A task management system for AI-driven development with Claude", "description": "A task management system for AI-driven development with Claude",
"main": "index.js", "main": "index.js",
"type": "module",
"bin": { "bin": {
"claude-task-init": "./scripts/init.js" "claude-task-init": "scripts/init.js"
}, },
"scripts": { "scripts": {
"test": "echo \"Error: no test specified\" && exit 1", "test": "echo \"Error: no test specified\" && exit 1",
@@ -23,7 +24,7 @@
"author": "Eyal Toledano", "author": "Eyal Toledano",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@anthropic-ai/sdk": "^0.10.0", "@anthropic-ai/sdk": "^0.39.0",
"chalk": "^4.1.2", "chalk": "^4.1.2",
"commander": "^11.1.0", "commander": "^11.1.0",
"dotenv": "^16.3.1" "dotenv": "^16.3.1"
@@ -43,6 +44,7 @@
"scripts/init.js", "scripts/init.js",
"scripts/dev.js", "scripts/dev.js",
"templates/**", "templates/**",
"README.md" "README.md",
"index.js"
] ]
} }

View File

@@ -42,6 +42,11 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Load environment variables from .env file // Load environment variables from .env file
dotenv.config(); dotenv.config();
@@ -169,9 +174,17 @@ async function callClaude(prdContent, prdPath, numTasks) {
log('debug', `Response length: ${textContent.length} characters`); log('debug', `Response length: ${textContent.length} characters`);
try { try {
// Try to parse the response as JSON // Check if the response is wrapped in a Markdown code block and extract the JSON
log('info', "Parsing response as JSON..."); log('info', "Parsing response as JSON...");
const parsedJson = JSON.parse(textContent); let jsonText = textContent;
const codeBlockMatch = textContent.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
if (codeBlockMatch) {
log('debug', "Detected JSON wrapped in Markdown code block, extracting...");
jsonText = codeBlockMatch[1];
}
// Try to parse the response as JSON
const parsedJson = JSON.parse(jsonText);
log('info', `Successfully parsed JSON with ${parsedJson.tasks?.length || 0} tasks`); log('info', `Successfully parsed JSON with ${parsedJson.tasks?.length || 0} tasks`);
return parsedJson; return parsedJson;
} catch (error) { } catch (error) {

View File

@@ -1,9 +1,14 @@
#!/usr/bin/env node #!/usr/bin/env node
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
const { execSync } = require('child_process'); import { execSync } from 'child_process';
const readline = require('readline'); import readline from 'readline';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Create readline interface for user input // Create readline interface for user input
const rl = readline.createInterface({ const rl = readline.createInterface({
@@ -143,6 +148,7 @@ function createProjectStructure(projectName, projectDescription, projectVersion,
version: projectVersion, version: projectVersion,
description: projectDescription, description: projectDescription,
author: authorName, author: authorName,
type: "module",
scripts: { scripts: {
"dev": "node scripts/dev.js", "dev": "node scripts/dev.js",
"list": "node scripts/dev.js list", "list": "node scripts/dev.js list",
@@ -150,7 +156,7 @@ function createProjectStructure(projectName, projectDescription, projectVersion,
"parse-prd": "node scripts/dev.js parse-prd" "parse-prd": "node scripts/dev.js parse-prd"
}, },
dependencies: { dependencies: {
"@anthropic-ai/sdk": "^0.10.0", "@anthropic-ai/sdk": "^0.39.0",
"chalk": "^4.1.2", "chalk": "^4.1.2",
"commander": "^11.1.0", "commander": "^11.1.0",
"dotenv": "^16.3.1" "dotenv": "^16.3.1"
@@ -230,7 +236,7 @@ function createProjectStructure(projectName, projectDescription, projectVersion,
} }
// Run the initialization if this script is executed directly // Run the initialization if this script is executed directly
if (require.main === module) { if (process.argv[1] === fileURLToPath(import.meta.url)) {
(async function main() { (async function main() {
try { try {
await initializeProject(); await initializeProject();
@@ -242,7 +248,7 @@ if (require.main === module) {
} }
// Export functions for programmatic use // Export functions for programmatic use
module.exports = { export {
initializeProject, initializeProject,
createProjectStructure, createProjectStructure,
log log

View File

@@ -5,9 +5,14 @@
* It ensures all necessary files are included and properly configured. * It ensures all necessary files are included and properly configured.
*/ */
const fs = require('fs'); import fs from 'fs';
const path = require('path'); import path from 'path';
const { execSync } = require('child_process'); import { execSync } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Define colors for console output // Define colors for console output
const COLORS = { const COLORS = {

View File

@@ -34,6 +34,12 @@ This project uses the Claude Task Master system to manage development tasks in a
npm run generate npm run generate
``` ```
### Important Notes
1. This project uses ES modules. The package.json includes `"type": "module"`.
2. The Anthropic SDK version should be 0.39.0 or higher.
3. If you encounter JSON parsing errors, make sure your Anthropic API key is valid and your environment is set up correctly.
## Integrating with Cursor AI ## Integrating with Cursor AI
This project includes Cursor AI integration through the `.cursor/rules/dev_workflow.mdc` file, which provides the AI with knowledge about the task management system. This project includes Cursor AI integration through the `.cursor/rules/dev_workflow.mdc` file, which provides the AI with knowledge about the task management system.

View File

@@ -42,6 +42,11 @@
import fs from 'fs'; import fs from 'fs';
import path from 'path'; import path from 'path';
import dotenv from 'dotenv'; import dotenv from 'dotenv';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// Load environment variables from .env file // Load environment variables from .env file
dotenv.config(); dotenv.config();
@@ -169,9 +174,17 @@ async function callClaude(prdContent, prdPath, numTasks) {
log('debug', `Response length: ${textContent.length} characters`); log('debug', `Response length: ${textContent.length} characters`);
try { try {
// Try to parse the response as JSON // Check if the response is wrapped in a Markdown code block and extract the JSON
log('info', "Parsing response as JSON..."); log('info', "Parsing response as JSON...");
const parsedJson = JSON.parse(textContent); let jsonText = textContent;
const codeBlockMatch = textContent.match(/```(?:json)?\s*([\s\S]*?)\s*```/);
if (codeBlockMatch) {
log('debug', "Detected JSON wrapped in Markdown code block, extracting...");
jsonText = codeBlockMatch[1];
}
// Try to parse the response as JSON
const parsedJson = JSON.parse(jsonText);
log('info', `Successfully parsed JSON with ${parsedJson.tasks?.length || 0} tasks`); log('info', `Successfully parsed JSON with ${parsedJson.tasks?.length || 0} tasks`);
return parsedJson; return parsedJson;
} catch (error) { } catch (error) {

View File

@@ -1,13 +1,13 @@
# Required # Required
ANTHROPIC_API_KEY=your-api-key-here ANTHROPIC_API_KEY=your-api-key-here # Format: sk-ant-api03-...
# Optional - defaults shown # Optional - defaults shown
MODEL=claude-3-7-sonnet-20250219 MODEL=claude-3-7-sonnet-20250219 # Recommended models: claude-3-7-sonnet-20250219, claude-3-opus-20240229
MAX_TOKENS=4000 MAX_TOKENS=4000 # Maximum tokens for model responses
TEMPERATURE=0.7 TEMPERATURE=0.7 # Temperature for model responses (0.0-1.0)
DEBUG=false DEBUG=false # Enable debug logging (true/false)
LOG_LEVEL=info LOG_LEVEL=info # Log level (debug, info, warn, error)
DEFAULT_SUBTASKS=3 DEFAULT_SUBTASKS=3 # Default number of subtasks when expanding
DEFAULT_PRIORITY=medium DEFAULT_PRIORITY=medium # Default priority for generated tasks (high, medium, low)
PROJECT_NAME={{projectName}} PROJECT_NAME={{projectName}} # Project name for tasks.json metadata
PROJECT_VERSION={{projectVersion}} PROJECT_VERSION={{projectVersion}} # Project version for tasks.json metadata