Fixes streamingInterval issue. Updates system prompt for tasks json.
This commit is contained in:
@@ -172,7 +172,7 @@ async function callClaude(prdContent, prdPath, numTasks, retryCount = 0) {
|
||||
]
|
||||
}`
|
||||
|
||||
let systemPrompt = "You are a helpful assistant that generates tasks from a PRD using the following template: " + TASKS_JSON_TEMPLATE + "ONLY RETURN THE JSON, NOTHING ELSE.";
|
||||
let systemPrompt = "You are a helpful assistant that generates tasks from a PRD using the below json template. You don't worry much about non-task related content, nor do you worry about tasks that don't particularly add value to an mvp. Things like implementing security enhancements, documentation, expansive testing etc are nice to have. The most important is to turn the PRD into a task list that fully materializes the product enough so it can go to market. The JSON template goes as follows -- make sure to only return the json, nothing else: " + TASKS_JSON_TEMPLATE + "ONLY RETURN THE JSON, NOTHING ELSE.";
|
||||
|
||||
// Add instruction about the number of tasks if specified
|
||||
if (numTasks) {
|
||||
@@ -275,25 +275,21 @@ async function handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens,
|
||||
let fullResponse = '';
|
||||
let streamComplete = false;
|
||||
let streamError = null;
|
||||
|
||||
let streamingInterval = null; // Initialize streamingInterval here
|
||||
|
||||
try {
|
||||
const stream = await anthropic.messages.create({
|
||||
max_tokens: maxTokens,
|
||||
model: CONFIG.model,
|
||||
temperature: CONFIG.temperature,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: prdContent
|
||||
}
|
||||
],
|
||||
messages: [{ role: "user", content: prdContent }],
|
||||
system: systemPrompt,
|
||||
stream: true
|
||||
});
|
||||
|
||||
// Update loading indicator to show streaming progress
|
||||
let dotCount = 0;
|
||||
const streamingInterval = setInterval(() => {
|
||||
streamingInterval = setInterval(() => {
|
||||
readline.cursorTo(process.stdout, 0);
|
||||
process.stdout.write(`Receiving streaming response from Claude${'.'.repeat(dotCount)}`);
|
||||
dotCount = (dotCount + 1) % 4;
|
||||
@@ -316,7 +312,7 @@ async function handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens,
|
||||
|
||||
return processClaudeResponse(fullResponse, numTasks, 0, prdContent, prdPath);
|
||||
} catch (error) {
|
||||
clearInterval(streamingInterval);
|
||||
if (streamingInterval) clearInterval(streamingInterval); // Safely clear interval
|
||||
stopLoadingIndicator(loadingIndicator);
|
||||
log('error', "Error during streaming response:", error);
|
||||
throw error;
|
||||
|
||||
@@ -1,101 +1,202 @@
|
||||
# {{projectName}}
|
||||
|
||||
{{projectDescription}}
|
||||
# Claude Task Master
|
||||
|
||||
A task management system for AI-driven development with Claude, designed to work seamlessly with Cursor AI.
|
||||
|
||||
## Overview
|
||||
## Requirements
|
||||
|
||||
This project uses the Claude Task Master system to manage development tasks in an AI-driven workflow. The system revolves around a `tasks.json` file, which holds an up-to-date list of development tasks.
|
||||
- Node.js 14.0.0 or higher
|
||||
- Anthropic API key (Claude API)
|
||||
- Anthropic SDK version 0.39.0 or higher
|
||||
|
||||
## Getting Started
|
||||
## Installation
|
||||
|
||||
1. Install dependencies:
|
||||
```bash
|
||||
npm install
|
||||
```
|
||||
```bash
|
||||
npm install claude-task-master
|
||||
```
|
||||
|
||||
2. Set up your environment:
|
||||
- Copy `.env.example` to `.env`
|
||||
- Add your Anthropic API key to the `.env` file
|
||||
## Usage
|
||||
|
||||
3. Parse your PRD to generate tasks:
|
||||
```bash
|
||||
npm run parse-prd -- --input=your-prd-file.txt
|
||||
```
|
||||
### Initialize a new project
|
||||
|
||||
4. View current tasks:
|
||||
```bash
|
||||
npm run list
|
||||
```
|
||||
```bash
|
||||
npx claude-task-init
|
||||
```
|
||||
|
||||
5. Generate task files:
|
||||
```bash
|
||||
npm run generate
|
||||
```
|
||||
This will prompt you for project details and set up a new project with the necessary files and structure.
|
||||
|
||||
### Important Notes
|
||||
|
||||
1. This project uses ES modules. The package.json includes `"type": "module"`.
|
||||
1. This package uses ES modules. Your package.json should include `"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.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### If `npx claude-task-init` doesn't respond:
|
||||
|
||||
Try running it with Node directly:
|
||||
|
||||
```bash
|
||||
node node_modules/claude-task-master/scripts/init.js
|
||||
```
|
||||
|
||||
Or clone the repository and run:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/eyaltoledano/claude-task-master.git
|
||||
cd claude-task-master
|
||||
node scripts/init.js
|
||||
```
|
||||
|
||||
## 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.
|
||||
Claude Task Master is designed to work seamlessly with [Cursor AI](https://www.cursor.so/), providing a structured workflow for AI-driven development.
|
||||
|
||||
### Using Cursor Agent Mode
|
||||
### Setup with Cursor
|
||||
|
||||
1. Open this project in Cursor
|
||||
2. Open Cursor's AI chat and switch to Agent mode
|
||||
3. The agent will automatically understand the task management workflow
|
||||
1. After initializing your project, open it in Cursor
|
||||
2. The `.cursor/rules/dev_workflow.mdc` file is automatically loaded by Cursor, providing the AI with knowledge about the task management system
|
||||
3. Place your PRD document in the `scripts/` directory (e.g., `scripts/prd.txt`)
|
||||
4. Open Cursor's AI chat and switch to Agent mode
|
||||
|
||||
### Working with the Agent
|
||||
### Initial Task Generation
|
||||
|
||||
You can ask the Cursor agent to:
|
||||
In Cursor's AI chat, instruct the agent to generate tasks from your PRD:
|
||||
|
||||
- **Generate tasks**: "Please parse my PRD at scripts/prd.txt and generate tasks"
|
||||
- **List tasks**: "What tasks are available to work on next?"
|
||||
- **Implement tasks**: "Let's implement task 3. What does it involve?"
|
||||
- **Update task status**: "Task 3 is now complete. Please update its status"
|
||||
- **Handle changes**: "We're now using Express instead of Fastify. Update future tasks"
|
||||
- **Break down tasks**: "Task 5 seems complex. Can you break it down into subtasks?"
|
||||
```
|
||||
Please use the dev.js script to parse my PRD and generate tasks. The PRD is located at scripts/prd.txt.
|
||||
```
|
||||
|
||||
The agent will execute the appropriate commands and guide you through the development process.
|
||||
The agent will execute:
|
||||
```bash
|
||||
node scripts/dev.js parse-prd --input=scripts/prd.txt
|
||||
```
|
||||
|
||||
## Development Workflow
|
||||
This will:
|
||||
- Parse your PRD document
|
||||
- Generate a structured `tasks.json` file with tasks, dependencies, priorities, and test strategies
|
||||
- The agent will understand this process due to the Cursor rules
|
||||
|
||||
The development workflow follows these steps:
|
||||
### Generate Individual Task Files
|
||||
|
||||
1. **Initial Setup**: If starting a new project with a PRD document, run `npm run parse-prd -- --input=<prd-file.txt>` to generate the initial tasks.json file.
|
||||
Next, ask the agent to generate individual task files:
|
||||
|
||||
2. **Task Discovery**: When a coding session begins, run `npm run list` to see the current tasks, their status, and IDs.
|
||||
```
|
||||
Please generate individual task files from tasks.json
|
||||
```
|
||||
|
||||
3. **Task Selection**: Select the next pending task based on these criteria:
|
||||
- Dependencies: Only select tasks whose dependencies are marked as 'done'
|
||||
- Priority: Choose higher priority tasks first ('high' > 'medium' > 'low')
|
||||
- ID order: When priorities are equal, select the task with the lowest ID
|
||||
The agent will execute:
|
||||
```bash
|
||||
node scripts/dev.js generate
|
||||
```
|
||||
|
||||
4. **Task Clarification**: If a task description is unclear or lacks detail:
|
||||
- Check if a corresponding task file exists in the tasks/ directory
|
||||
- If more information is needed, ask for clarification
|
||||
- If architectural changes have occurred, run `npm run dev -- update --from=<id> --prompt="<new architectural context>"` to update the task and all subsequent tasks
|
||||
This creates individual task files in the `tasks/` directory (e.g., `task_001.txt`, `task_002.txt`), making it easier to reference specific tasks.
|
||||
|
||||
5. **Task Breakdown**: For complex tasks that need to be broken down into smaller steps:
|
||||
- Use `npm run dev -- expand --id=<id> --subtasks=<number>` to generate detailed subtasks
|
||||
- Optionally provide additional context with `--prompt="<context>"` to guide subtask generation
|
||||
## AI-Driven Development Workflow
|
||||
|
||||
6. **Task Implementation**: Implement the code necessary for the chosen task.
|
||||
The Cursor agent is pre-configured (via the rules file) to follow this workflow:
|
||||
|
||||
7. **Task Verification**: Before marking a task as done, verify it according to the task's specified 'testStrategy'.
|
||||
### 1. Task Discovery and Selection
|
||||
|
||||
8. **Task Completion**: When a task is completed and verified, run `npm run dev -- set-status --id=<id> --status=done` to mark it as done.
|
||||
Ask the agent to list available tasks:
|
||||
|
||||
9. **Implementation Drift Handling**: If during implementation, you discover that the approach differs significantly from what was planned, call `npm run dev -- update --from=<futureTaskId> --prompt="Detailed explanation of changes..."` to rewrite subsequent tasks.
|
||||
```
|
||||
What tasks are available to work on next?
|
||||
```
|
||||
|
||||
10. **Task File Generation**: After any updates to tasks.json, run `npm run generate` to regenerate the individual task files.
|
||||
The agent will:
|
||||
- Run `node scripts/dev.js list` to see all tasks
|
||||
- Analyze dependencies to determine which tasks are ready to be worked on
|
||||
- Prioritize tasks based on priority level and ID order
|
||||
- Suggest the next task(s) to implement
|
||||
|
||||
## Command Reference
|
||||
### 2. Task Implementation
|
||||
|
||||
When implementing a task, the agent will:
|
||||
- Reference the task's details section for implementation specifics
|
||||
- Consider dependencies on previous tasks
|
||||
- Follow the project's coding standards
|
||||
- Create appropriate tests based on the task's testStrategy
|
||||
|
||||
You can ask:
|
||||
```
|
||||
Let's implement task 3. What does it involve?
|
||||
```
|
||||
|
||||
### 3. Task Verification
|
||||
|
||||
Before marking a task as complete, verify it according to:
|
||||
- The task's specified testStrategy
|
||||
- Any automated tests in the codebase
|
||||
- Manual verification if required
|
||||
|
||||
### 4. Task Completion
|
||||
|
||||
When a task is completed, tell the agent:
|
||||
|
||||
```
|
||||
Task 3 is now complete. Please update its status.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
```bash
|
||||
node scripts/dev.js set-status --id=3 --status=done
|
||||
```
|
||||
|
||||
### 5. Handling Implementation Drift
|
||||
|
||||
If during implementation, you discover that:
|
||||
- The current approach differs significantly from what was planned
|
||||
- Future tasks need to be modified due to current implementation choices
|
||||
- New dependencies or requirements have emerged
|
||||
|
||||
Tell the agent:
|
||||
```
|
||||
We've changed our approach. We're now using Express instead of Fastify. Please update all future tasks to reflect this change.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
```bash
|
||||
node scripts/dev.js update --from=4 --prompt="Now we are using Express instead of Fastify."
|
||||
```
|
||||
|
||||
This will rewrite or re-scope subsequent tasks in tasks.json while preserving completed work.
|
||||
|
||||
### 6. Breaking Down Complex Tasks
|
||||
|
||||
For complex tasks that need more granularity:
|
||||
|
||||
```
|
||||
Task 5 seems complex. Can you break it down into subtasks?
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
```bash
|
||||
node scripts/dev.js expand --id=5 --subtasks=3
|
||||
```
|
||||
|
||||
You can provide additional context:
|
||||
```
|
||||
Please break down task 5 with a focus on security considerations.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
```bash
|
||||
node scripts/dev.js expand --id=5 --prompt="Focus on security aspects"
|
||||
```
|
||||
|
||||
You can also expand all pending tasks:
|
||||
```
|
||||
Please break down all pending tasks into subtasks.
|
||||
```
|
||||
|
||||
The agent will execute:
|
||||
```bash
|
||||
node scripts/dev.js expand --all
|
||||
```
|
||||
|
||||
## Manual Command Reference
|
||||
|
||||
While the Cursor agent will handle most commands for you, you can also run them manually:
|
||||
|
||||
### Parse PRD
|
||||
```bash
|
||||
@@ -161,28 +262,39 @@ Tasks in tasks.json have the following structure:
|
||||
|
||||
7. **Communicate context to the agent**: When asking the Cursor agent to help with a task, provide context about what you're trying to achieve.
|
||||
|
||||
## Configuration
|
||||
## Example Cursor AI Interactions
|
||||
|
||||
The system can be configured through environment variables in a `.env` file:
|
||||
### Starting a new project
|
||||
```
|
||||
I've just initialized a new project with Claude Task Master. I have a PRD at scripts/prd.txt.
|
||||
Can you help me parse it and set up the initial tasks?
|
||||
```
|
||||
|
||||
### Required Configuration
|
||||
- `ANTHROPIC_API_KEY`: Your Anthropic API key for Claude
|
||||
### Working on tasks
|
||||
```
|
||||
What's the next task I should work on? Please consider dependencies and priorities.
|
||||
```
|
||||
|
||||
### Optional Configuration
|
||||
- `MODEL`: Specify which Claude model to use (default: "claude-3-7-sonnet-20250219")
|
||||
- `MAX_TOKENS`: Maximum tokens for model responses (default: 4000)
|
||||
- `TEMPERATURE`: Temperature for model responses (default: 0.7)
|
||||
- `DEBUG`: Enable debug logging (default: false)
|
||||
- `LOG_LEVEL`: Log level - debug, info, warn, error (default: info)
|
||||
- `DEFAULT_SUBTASKS`: Default number of subtasks when expanding (default: 3)
|
||||
- `DEFAULT_PRIORITY`: Default priority for generated tasks (default: medium)
|
||||
- `PROJECT_NAME`: Override default project name in tasks.json
|
||||
- `PROJECT_VERSION`: Override default version in tasks.json
|
||||
### Implementing a specific task
|
||||
```
|
||||
I'd like to implement task 4. Can you help me understand what needs to be done and how to approach it?
|
||||
```
|
||||
|
||||
## Additional Documentation
|
||||
### Handling changes
|
||||
```
|
||||
We've decided to use MongoDB instead of PostgreSQL. Can you update all future tasks to reflect this change?
|
||||
```
|
||||
|
||||
For more detailed documentation on the scripts, see the [scripts/README.md](scripts/README.md) file.
|
||||
### Completing work
|
||||
```
|
||||
I've finished implementing the authentication system described in task 2. All tests are passing.
|
||||
Please mark it as complete and tell me what I should work on next.
|
||||
```
|
||||
|
||||
## Documentation
|
||||
|
||||
For more detailed documentation on the scripts, see the [scripts/README.md](scripts/README.md) file in your initialized project.
|
||||
|
||||
## License
|
||||
|
||||
Copyright (c) {{year}} {{authorName}}
|
||||
MIT
|
||||
79
templates/dev.js
Normal file → Executable file
79
templates/dev.js
Normal file → Executable file
@@ -45,6 +45,7 @@ import path from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname } from 'path';
|
||||
import readline from 'readline';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
@@ -98,6 +99,16 @@ const anthropic = new Anthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY,
|
||||
});
|
||||
|
||||
function readJSON(filepath) {
|
||||
if (!fs.existsSync(filepath)) return null;
|
||||
const content = fs.readFileSync(filepath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
function writeJSON(filepath, data) {
|
||||
fs.writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
// Add a simple loading indicator function
|
||||
function startLoadingIndicator(message) {
|
||||
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
||||
@@ -118,16 +129,6 @@ function stopLoadingIndicator(interval) {
|
||||
readline.clearLine(process.stdout, 0);
|
||||
}
|
||||
|
||||
function readJSON(filepath) {
|
||||
if (!fs.existsSync(filepath)) return null;
|
||||
const content = fs.readFileSync(filepath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
function writeJSON(filepath, data) {
|
||||
fs.writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
async function callClaude(prdContent, prdPath, numTasks, retryCount = 0) {
|
||||
const MAX_RETRIES = 3;
|
||||
const INITIAL_BACKOFF_MS = 1000;
|
||||
@@ -197,62 +198,14 @@ async function callClaude(prdContent, prdPath, numTasks, retryCount = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if we should use streaming based on PRD size
|
||||
// For PRDs larger than 20,000 characters (roughly 5,000 tokens), use streaming
|
||||
const useStreaming = prdContent.length > 20000;
|
||||
// Always use streaming to avoid "Streaming is strongly recommended" error
|
||||
log('info', `Using streaming API for PRD processing...`);
|
||||
return await handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens, systemPrompt, loadingIndicator);
|
||||
|
||||
if (useStreaming) {
|
||||
log('info', `Large PRD detected (${prdContent.length} characters). Using streaming API...`);
|
||||
return await handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens, systemPrompt, loadingIndicator);
|
||||
} else {
|
||||
log('info', "Sending request to Claude API...");
|
||||
|
||||
const response = await anthropic.messages.create({
|
||||
max_tokens: maxTokens,
|
||||
model: CONFIG.model,
|
||||
temperature: CONFIG.temperature,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: prdContent
|
||||
}
|
||||
],
|
||||
system: systemPrompt
|
||||
});
|
||||
|
||||
// Stop loading indicator
|
||||
stopLoadingIndicator(loadingIndicator);
|
||||
log('info', "Received response from Claude API!");
|
||||
|
||||
// Extract the text content from the response
|
||||
const textContent = response.content[0].text;
|
||||
return processClaudeResponse(textContent, numTasks, retryCount, prdContent, prdPath);
|
||||
}
|
||||
} catch (error) {
|
||||
// Stop loading indicator
|
||||
stopLoadingIndicator(loadingIndicator);
|
||||
|
||||
// Check if this is the streaming recommendation error
|
||||
if (error.message && error.message.includes("Streaming is strongly recommended")) {
|
||||
log('info', "Claude recommends streaming for this large PRD. Switching to streaming mode...");
|
||||
try {
|
||||
// Calculate appropriate max tokens based on PRD size
|
||||
let maxTokens = CONFIG.maxTokens;
|
||||
const estimatedPrdTokens = Math.ceil(prdContent.length / 4);
|
||||
const suggestedMaxTokens = Math.min(32000, estimatedPrdTokens * 2);
|
||||
if (suggestedMaxTokens > maxTokens) {
|
||||
maxTokens = suggestedMaxTokens;
|
||||
}
|
||||
|
||||
// Restart the loading indicator
|
||||
const newLoadingIndicator = startLoadingIndicator(loadingMessage);
|
||||
return await handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens, systemPrompt, newLoadingIndicator);
|
||||
} catch (streamingError) {
|
||||
log('error', "Error with streaming API call:", streamingError);
|
||||
throw streamingError;
|
||||
}
|
||||
}
|
||||
|
||||
log('error', "Error calling Claude API:", error);
|
||||
|
||||
// Implement exponential backoff for retries
|
||||
@@ -465,7 +418,7 @@ async function parsePRD(prdPath, tasksPath, numTasks) {
|
||||
writeJSON(tasksPath, data);
|
||||
log('info', `Parsed PRD from '${prdPath}' -> wrote ${tasks.length} tasks to '${tasksPath}'.`);
|
||||
} catch (error) {
|
||||
log('error', `Failed to generate tasks from PRD: ${error.message}`);
|
||||
log('error', "Failed to generate tasks:", error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -499,7 +452,7 @@ function generateTaskFiles(tasksPath, outputDir) {
|
||||
log('info', `Reading tasks from ${tasksPath}...`);
|
||||
const data = readJSON(tasksPath);
|
||||
if (!data || !data.tasks) {
|
||||
log('error', "No valid tasks to generate. Please run parse-prd first.");
|
||||
log('error', "No valid tasks to generate files for.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user