Compare commits
21 Commits
v0.19.0
...
fix/expand
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e42e4d778c | ||
|
|
b8649b2f8d | ||
|
|
21392a1117 | ||
|
|
3e61d26235 | ||
|
|
dc5de53dcd | ||
|
|
4312d3bd67 | ||
|
|
0253f3ed87 | ||
|
|
a65ad0a47c | ||
|
|
4bc8029080 | ||
|
|
31d395322f | ||
|
|
699e9eefb5 | ||
|
|
95c299df64 | ||
|
|
5f009a5e1f | ||
|
|
38e6f3798e | ||
|
|
b53065713c | ||
|
|
de28026b32 | ||
|
|
f62eaad709 | ||
|
|
98d1c97436 | ||
|
|
3334e409ae | ||
|
|
5b9416f673 | ||
|
|
6c88a4a749 |
5
.changeset/claude-code-json-truncation.md
Normal file
5
.changeset/claude-code-json-truncation.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Recover from `@anthropic-ai/claude-code` JSON truncation bug that caused Task Master to crash when handling large (>8 kB) structured responses. The CLI/SDK still truncates, but Task Master now detects the error, preserves buffered text, and returns a usable response instead of throwing.
|
||||
5
.changeset/cuddly-baboons-invent.md
Normal file
5
.changeset/cuddly-baboons-invent.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Updating dependency ai-sdk-provider-gemini-cli to 0.0.4 to address breaking change Google made to Gemini CLI and add better 'api-key' in addition to 'gemini-api-key' AI-SDK compatibility.
|
||||
9
.changeset/grok-4-support.md
Normal file
9
.changeset/grok-4-support.md
Normal file
@@ -0,0 +1,9 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add support for xAI Grok 4 model
|
||||
|
||||
- Add grok-4 model to xAI provider with $3/$15 per 1M token pricing
|
||||
- Enable main, fallback, and research roles for grok-4
|
||||
- Max tokens set to 131,072 (matching other xAI models)
|
||||
8
.changeset/quick-laws-cover.md
Normal file
8
.changeset/quick-laws-cover.md
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add stricter validation and clearer feedback for task priority when adding new tasks
|
||||
|
||||
- if a task priority is invalid, it will default to medium
|
||||
- made taks priority case-insensitive, essentially making HIGH and high the same value
|
||||
5
.changeset/some-lies-grin.md
Normal file
5
.changeset/some-lies-grin.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Add support for MCP Sampling as AI provider, requires no API key, uses the client LLM provider
|
||||
5
.changeset/spicy-badgers-fail.md
Normal file
5
.changeset/spicy-badgers-fail.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": patch
|
||||
---
|
||||
|
||||
Unify and streamline profile system architecture for improved maintainability
|
||||
5
.changeset/tender-ads-joke.md
Normal file
5
.changeset/tender-ads-joke.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"task-master-ai": minor
|
||||
---
|
||||
|
||||
Added Groq provider support
|
||||
@@ -8,6 +8,7 @@
|
||||
"PERPLEXITY_API_KEY": "PERPLEXITY_API_KEY_HERE",
|
||||
"OPENAI_API_KEY": "OPENAI_API_KEY_HERE",
|
||||
"GOOGLE_API_KEY": "GOOGLE_API_KEY_HERE",
|
||||
"GROQ_API_KEY": "GROQ_API_KEY_HERE",
|
||||
"XAI_API_KEY": "XAI_API_KEY_HERE",
|
||||
"OPENROUTER_API_KEY": "OPENROUTER_API_KEY_HERE",
|
||||
"MISTRAL_API_KEY": "MISTRAL_API_KEY_HERE",
|
||||
|
||||
@@ -4,6 +4,7 @@ PERPLEXITY_API_KEY=YOUR_PERPLEXITY_KEY_HERE
|
||||
OPENAI_API_KEY=YOUR_OPENAI_KEY_HERE
|
||||
GOOGLE_API_KEY=YOUR_GOOGLE_KEY_HERE
|
||||
MISTRAL_API_KEY=YOUR_MISTRAL_KEY_HERE
|
||||
GROQ_API_KEY=YOUR_GROQ_KEY_HERE
|
||||
OPENROUTER_API_KEY=YOUR_OPENROUTER_KEY_HERE
|
||||
XAI_API_KEY=YOUR_XAI_KEY_HERE
|
||||
AZURE_OPENAI_API_KEY=YOUR_AZURE_KEY_HERE
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "vertex",
|
||||
"modelId": "gemini-1.5-pro-002",
|
||||
"maxTokens": 50000,
|
||||
"provider": "groq",
|
||||
"modelId": "llama-3.1-8b-instant",
|
||||
"maxTokens": 131072,
|
||||
"temperature": 0.2
|
||||
},
|
||||
"research": {
|
||||
"provider": "perplexity",
|
||||
"modelId": "sonar",
|
||||
"maxTokens": 8700,
|
||||
"provider": "groq",
|
||||
"modelId": "llama-3.3-70b-versatile",
|
||||
"maxTokens": 32768,
|
||||
"temperature": 0.1
|
||||
},
|
||||
"fallback": {
|
||||
@@ -22,15 +22,16 @@
|
||||
"global": {
|
||||
"logLevel": "info",
|
||||
"debug": false,
|
||||
"defaultNumTasks": 10,
|
||||
"defaultSubtasks": 5,
|
||||
"defaultPriority": "medium",
|
||||
"projectName": "Taskmaster",
|
||||
"ollamaBaseURL": "http://localhost:11434/api",
|
||||
"bedrockBaseURL": "https://bedrock.us-east-1.amazonaws.com",
|
||||
"responseLanguage": "English",
|
||||
"userId": "1234567890",
|
||||
"azureBaseURL": "https://your-endpoint.azure.com/",
|
||||
"defaultTag": "master",
|
||||
"responseLanguage": "English"
|
||||
"defaultTag": "master"
|
||||
},
|
||||
"claudeCode": {}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
14
.vscode/settings.json
vendored
Normal file
14
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"json.schemas": [
|
||||
{
|
||||
"fileMatch": ["src/prompts/*.json"],
|
||||
"url": "./src/prompts/schemas/prompt-template.schema.json"
|
||||
}
|
||||
],
|
||||
"files.associations": {
|
||||
"src/prompts/*.json": "json"
|
||||
},
|
||||
|
||||
"json.format.enable": true,
|
||||
"json.validate.enable": true
|
||||
}
|
||||
147
assets/claude/TM_COMMANDS_GUIDE.md
Normal file
147
assets/claude/TM_COMMANDS_GUIDE.md
Normal file
@@ -0,0 +1,147 @@
|
||||
# Task Master Commands for Claude Code
|
||||
|
||||
Complete guide to using Task Master through Claude Code's slash commands.
|
||||
|
||||
## Overview
|
||||
|
||||
All Task Master functionality is available through the `/project:tm/` namespace with natural language support and intelligent features.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Install Task Master
|
||||
/project:tm/setup/quick-install
|
||||
|
||||
# Initialize project
|
||||
/project:tm/init/quick
|
||||
|
||||
# Parse requirements
|
||||
/project:tm/parse-prd requirements.md
|
||||
|
||||
# Start working
|
||||
/project:tm/next
|
||||
```
|
||||
|
||||
## Command Structure
|
||||
|
||||
Commands are organized hierarchically to match Task Master's CLI:
|
||||
- Main commands at `/project:tm/[command]`
|
||||
- Subcommands for specific operations `/project:tm/[command]/[subcommand]`
|
||||
- Natural language arguments accepted throughout
|
||||
|
||||
## Complete Command Reference
|
||||
|
||||
### Setup & Configuration
|
||||
- `/project:tm/setup/install` - Full installation guide
|
||||
- `/project:tm/setup/quick-install` - One-line install
|
||||
- `/project:tm/init` - Initialize project
|
||||
- `/project:tm/init/quick` - Quick init with -y
|
||||
- `/project:tm/models` - View AI config
|
||||
- `/project:tm/models/setup` - Configure AI
|
||||
|
||||
### Task Generation
|
||||
- `/project:tm/parse-prd` - Generate from PRD
|
||||
- `/project:tm/parse-prd/with-research` - Enhanced parsing
|
||||
- `/project:tm/generate` - Create task files
|
||||
|
||||
### Task Management
|
||||
- `/project:tm/list` - List with natural language filters
|
||||
- `/project:tm/list/with-subtasks` - Hierarchical view
|
||||
- `/project:tm/list/by-status <status>` - Filter by status
|
||||
- `/project:tm/show <id>` - Task details
|
||||
- `/project:tm/add-task` - Create task
|
||||
- `/project:tm/update` - Update tasks
|
||||
- `/project:tm/remove-task` - Delete task
|
||||
|
||||
### Status Management
|
||||
- `/project:tm/set-status/to-pending <id>`
|
||||
- `/project:tm/set-status/to-in-progress <id>`
|
||||
- `/project:tm/set-status/to-done <id>`
|
||||
- `/project:tm/set-status/to-review <id>`
|
||||
- `/project:tm/set-status/to-deferred <id>`
|
||||
- `/project:tm/set-status/to-cancelled <id>`
|
||||
|
||||
### Task Analysis
|
||||
- `/project:tm/analyze-complexity` - AI analysis
|
||||
- `/project:tm/complexity-report` - View report
|
||||
- `/project:tm/expand <id>` - Break down task
|
||||
- `/project:tm/expand/all` - Expand all complex
|
||||
|
||||
### Dependencies
|
||||
- `/project:tm/add-dependency` - Add dependency
|
||||
- `/project:tm/remove-dependency` - Remove dependency
|
||||
- `/project:tm/validate-dependencies` - Check issues
|
||||
- `/project:tm/fix-dependencies` - Auto-fix
|
||||
|
||||
### Workflows
|
||||
- `/project:tm/workflows/smart-flow` - Adaptive workflows
|
||||
- `/project:tm/workflows/pipeline` - Chain commands
|
||||
- `/project:tm/workflows/auto-implement` - AI implementation
|
||||
|
||||
### Utilities
|
||||
- `/project:tm/status` - Project dashboard
|
||||
- `/project:tm/next` - Next task recommendation
|
||||
- `/project:tm/utils/analyze` - Project analysis
|
||||
- `/project:tm/learn` - Interactive help
|
||||
|
||||
## Key Features
|
||||
|
||||
### Natural Language Support
|
||||
All commands understand natural language:
|
||||
```
|
||||
/project:tm/list pending high priority
|
||||
/project:tm/update mark 23 as done
|
||||
/project:tm/add-task implement OAuth login
|
||||
```
|
||||
|
||||
### Smart Context
|
||||
Commands analyze project state and provide intelligent suggestions based on:
|
||||
- Current task status
|
||||
- Dependencies
|
||||
- Team patterns
|
||||
- Project phase
|
||||
|
||||
### Visual Enhancements
|
||||
- Progress bars and indicators
|
||||
- Status badges
|
||||
- Organized displays
|
||||
- Clear hierarchies
|
||||
|
||||
## Common Workflows
|
||||
|
||||
### Daily Development
|
||||
```
|
||||
/project:tm/workflows/smart-flow morning
|
||||
/project:tm/next
|
||||
/project:tm/set-status/to-in-progress <id>
|
||||
/project:tm/set-status/to-done <id>
|
||||
```
|
||||
|
||||
### Task Breakdown
|
||||
```
|
||||
/project:tm/show <id>
|
||||
/project:tm/expand <id>
|
||||
/project:tm/list/with-subtasks
|
||||
```
|
||||
|
||||
### Sprint Planning
|
||||
```
|
||||
/project:tm/analyze-complexity
|
||||
/project:tm/workflows/pipeline init → expand/all → status
|
||||
```
|
||||
|
||||
## Migration from Old Commands
|
||||
|
||||
| Old | New |
|
||||
|-----|-----|
|
||||
| `/project:task-master:list` | `/project:tm/list` |
|
||||
| `/project:task-master:complete` | `/project:tm/set-status/to-done` |
|
||||
| `/project:workflows:auto-implement` | `/project:tm/workflows/auto-implement` |
|
||||
|
||||
## Tips
|
||||
|
||||
1. Use `/project:tm/` + Tab for command discovery
|
||||
2. Natural language is supported everywhere
|
||||
3. Commands provide smart defaults
|
||||
4. Chain commands for automation
|
||||
5. Check `/project:tm/learn` for interactive help
|
||||
55
assets/claude/commands/tm/add-dependency/add-dependency.md
Normal file
55
assets/claude/commands/tm/add-dependency/add-dependency.md
Normal file
@@ -0,0 +1,55 @@
|
||||
Add a dependency between tasks.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the task IDs to establish dependency relationship.
|
||||
|
||||
## Adding Dependencies
|
||||
|
||||
Creates a dependency where one task must be completed before another can start.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Parse natural language or IDs:
|
||||
- "make 5 depend on 3" → task 5 depends on task 3
|
||||
- "5 needs 3" → task 5 depends on task 3
|
||||
- "5 3" → task 5 depends on task 3
|
||||
- "5 after 3" → task 5 depends on task 3
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master add-dependency --id=<task-id> --depends-on=<dependency-id>
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Before adding:
|
||||
1. **Verify both tasks exist**
|
||||
2. **Check for circular dependencies**
|
||||
3. **Ensure dependency makes logical sense**
|
||||
4. **Warn if creating complex chains**
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Detect if dependency already exists
|
||||
- Suggest related dependencies
|
||||
- Show impact on task flow
|
||||
- Update task priorities if needed
|
||||
|
||||
## Post-Addition
|
||||
|
||||
After adding dependency:
|
||||
1. Show updated dependency graph
|
||||
2. Identify any newly blocked tasks
|
||||
3. Suggest task order changes
|
||||
4. Update project timeline
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/add-dependency 5 needs 3
|
||||
→ Task #5 now depends on Task #3
|
||||
→ Task #5 is now blocked until #3 completes
|
||||
→ Suggested: Also consider if #5 needs #4
|
||||
```
|
||||
76
assets/claude/commands/tm/add-subtask/add-subtask.md
Normal file
76
assets/claude/commands/tm/add-subtask/add-subtask.md
Normal file
@@ -0,0 +1,76 @@
|
||||
Add a subtask to a parent task.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse arguments to create a new subtask or convert existing task.
|
||||
|
||||
## Adding Subtasks
|
||||
|
||||
Creates subtasks to break down complex parent tasks into manageable pieces.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Flexible natural language:
|
||||
- "add subtask to 5: implement login form"
|
||||
- "break down 5 with: setup, implement, test"
|
||||
- "subtask for 5: handle edge cases"
|
||||
- "5: validate user input" → adds subtask to task 5
|
||||
|
||||
## Execution Modes
|
||||
|
||||
### 1. Create New Subtask
|
||||
```bash
|
||||
task-master add-subtask --parent=<id> --title="<title>" --description="<desc>"
|
||||
```
|
||||
|
||||
### 2. Convert Existing Task
|
||||
```bash
|
||||
task-master add-subtask --parent=<id> --task-id=<existing-id>
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Automatic Subtask Generation**
|
||||
- If title contains "and" or commas, create multiple
|
||||
- Suggest common subtask patterns
|
||||
- Inherit parent's context
|
||||
|
||||
2. **Intelligent Defaults**
|
||||
- Priority based on parent
|
||||
- Appropriate time estimates
|
||||
- Logical dependencies between subtasks
|
||||
|
||||
3. **Validation**
|
||||
- Check parent task complexity
|
||||
- Warn if too many subtasks
|
||||
- Ensure subtask makes sense
|
||||
|
||||
## Creation Process
|
||||
|
||||
1. Parse parent task context
|
||||
2. Generate subtask with ID like "5.1"
|
||||
3. Set appropriate defaults
|
||||
4. Link to parent task
|
||||
5. Update parent's time estimate
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/add-subtask to 5: implement user authentication
|
||||
→ Created subtask #5.1: "implement user authentication"
|
||||
→ Parent task #5 now has 1 subtask
|
||||
→ Suggested next subtasks: tests, documentation
|
||||
|
||||
/project:tm/add-subtask 5: setup, implement, test
|
||||
→ Created 3 subtasks:
|
||||
#5.1: setup
|
||||
#5.2: implement
|
||||
#5.3: test
|
||||
```
|
||||
|
||||
## Post-Creation
|
||||
|
||||
- Show updated task hierarchy
|
||||
- Suggest logical next subtasks
|
||||
- Update complexity estimates
|
||||
- Recommend subtask order
|
||||
@@ -0,0 +1,71 @@
|
||||
Convert an existing task into a subtask.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse parent ID and task ID to convert.
|
||||
|
||||
## Task Conversion
|
||||
|
||||
Converts an existing standalone task into a subtask of another task.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "move task 8 under 5"
|
||||
- "make 8 a subtask of 5"
|
||||
- "nest 8 in 5"
|
||||
- "5 8" → make task 8 a subtask of task 5
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master add-subtask --parent=<parent-id> --task-id=<task-to-convert>
|
||||
```
|
||||
|
||||
## Pre-Conversion Checks
|
||||
|
||||
1. **Validation**
|
||||
- Both tasks exist and are valid
|
||||
- No circular parent relationships
|
||||
- Task isn't already a subtask
|
||||
- Logical hierarchy makes sense
|
||||
|
||||
2. **Impact Analysis**
|
||||
- Dependencies that will be affected
|
||||
- Tasks that depend on converting task
|
||||
- Priority alignment needed
|
||||
- Status compatibility
|
||||
|
||||
## Conversion Process
|
||||
|
||||
1. Change task ID from "8" to "5.1" (next available)
|
||||
2. Update all dependency references
|
||||
3. Inherit parent's context where appropriate
|
||||
4. Adjust priorities if needed
|
||||
5. Update time estimates
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Preserve task history
|
||||
- Maintain dependencies
|
||||
- Update all references
|
||||
- Create conversion log
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
/project:tm/add-subtask/from-task 5 8
|
||||
→ Converting: Task #8 becomes subtask #5.1
|
||||
→ Updated: 3 dependency references
|
||||
→ Parent task #5 now has 1 subtask
|
||||
→ Note: Subtask inherits parent's priority
|
||||
|
||||
Before: #8 "Implement validation" (standalone)
|
||||
After: #5.1 "Implement validation" (subtask of #5)
|
||||
```
|
||||
|
||||
## Post-Conversion
|
||||
|
||||
- Show new task hierarchy
|
||||
- List updated dependencies
|
||||
- Verify project integrity
|
||||
- Suggest related conversions
|
||||
78
assets/claude/commands/tm/add-task/add-task.md
Normal file
78
assets/claude/commands/tm/add-task/add-task.md
Normal file
@@ -0,0 +1,78 @@
|
||||
Add new tasks with intelligent parsing and context awareness.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Smart Task Addition
|
||||
|
||||
Parse natural language to create well-structured tasks.
|
||||
|
||||
### 1. **Input Understanding**
|
||||
|
||||
I'll intelligently parse your request:
|
||||
- Natural language → Structured task
|
||||
- Detect priority from keywords (urgent, ASAP, important)
|
||||
- Infer dependencies from context
|
||||
- Suggest complexity based on description
|
||||
- Determine task type (feature, bug, refactor, test, docs)
|
||||
|
||||
### 2. **Smart Parsing Examples**
|
||||
|
||||
**"Add urgent task to fix login bug"**
|
||||
→ Title: Fix login bug
|
||||
→ Priority: high
|
||||
→ Type: bug
|
||||
→ Suggested complexity: medium
|
||||
|
||||
**"Create task for API documentation after task 23 is done"**
|
||||
→ Title: API documentation
|
||||
→ Dependencies: [23]
|
||||
→ Type: documentation
|
||||
→ Priority: medium
|
||||
|
||||
**"Need to refactor auth module - depends on 12 and 15, high complexity"**
|
||||
→ Title: Refactor auth module
|
||||
→ Dependencies: [12, 15]
|
||||
→ Complexity: high
|
||||
→ Type: refactor
|
||||
|
||||
### 3. **Context Enhancement**
|
||||
|
||||
Based on current project state:
|
||||
- Suggest related existing tasks
|
||||
- Warn about potential conflicts
|
||||
- Recommend dependencies
|
||||
- Propose subtasks if complex
|
||||
|
||||
### 4. **Interactive Refinement**
|
||||
|
||||
```yaml
|
||||
Task Preview:
|
||||
─────────────
|
||||
Title: [Extracted title]
|
||||
Priority: [Inferred priority]
|
||||
Dependencies: [Detected dependencies]
|
||||
Complexity: [Estimated complexity]
|
||||
|
||||
Suggestions:
|
||||
- Similar task #34 exists, consider as dependency?
|
||||
- This seems complex, break into subtasks?
|
||||
- Tasks #45-47 work on same module
|
||||
```
|
||||
|
||||
### 5. **Validation & Creation**
|
||||
|
||||
Before creating:
|
||||
- Validate dependencies exist
|
||||
- Check for duplicates
|
||||
- Ensure logical ordering
|
||||
- Verify task completeness
|
||||
|
||||
### 6. **Smart Defaults**
|
||||
|
||||
Intelligent defaults based on:
|
||||
- Task type patterns
|
||||
- Team conventions
|
||||
- Historical data
|
||||
- Current sprint/phase
|
||||
|
||||
Result: High-quality tasks from minimal input.
|
||||
@@ -0,0 +1,121 @@
|
||||
Analyze task complexity and generate expansion recommendations.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Perform deep analysis of task complexity across the project.
|
||||
|
||||
## Complexity Analysis
|
||||
|
||||
Uses AI to analyze tasks and recommend which ones need breakdown.
|
||||
|
||||
## Execution Options
|
||||
|
||||
```bash
|
||||
task-master analyze-complexity [--research] [--threshold=5]
|
||||
```
|
||||
|
||||
## Analysis Parameters
|
||||
|
||||
- `--research` → Use research AI for deeper analysis
|
||||
- `--threshold=5` → Only flag tasks above complexity 5
|
||||
- Default: Analyze all pending tasks
|
||||
|
||||
## Analysis Process
|
||||
|
||||
### 1. **Task Evaluation**
|
||||
For each task, AI evaluates:
|
||||
- Technical complexity
|
||||
- Time requirements
|
||||
- Dependency complexity
|
||||
- Risk factors
|
||||
- Knowledge requirements
|
||||
|
||||
### 2. **Complexity Scoring**
|
||||
Assigns score 1-10 based on:
|
||||
- Implementation difficulty
|
||||
- Integration challenges
|
||||
- Testing requirements
|
||||
- Unknown factors
|
||||
- Technical debt risk
|
||||
|
||||
### 3. **Recommendations**
|
||||
For complex tasks:
|
||||
- Suggest expansion approach
|
||||
- Recommend subtask breakdown
|
||||
- Identify risk areas
|
||||
- Propose mitigation strategies
|
||||
|
||||
## Smart Analysis Features
|
||||
|
||||
1. **Pattern Recognition**
|
||||
- Similar task comparisons
|
||||
- Historical complexity accuracy
|
||||
- Team velocity consideration
|
||||
- Technology stack factors
|
||||
|
||||
2. **Contextual Factors**
|
||||
- Team expertise
|
||||
- Available resources
|
||||
- Timeline constraints
|
||||
- Business criticality
|
||||
|
||||
3. **Risk Assessment**
|
||||
- Technical risks
|
||||
- Timeline risks
|
||||
- Dependency risks
|
||||
- Knowledge gaps
|
||||
|
||||
## Output Format
|
||||
|
||||
```
|
||||
Task Complexity Analysis Report
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
High Complexity Tasks (>7):
|
||||
📍 #5 "Implement real-time sync" - Score: 9/10
|
||||
Factors: WebSocket complexity, state management, conflict resolution
|
||||
Recommendation: Expand into 5-7 subtasks
|
||||
Risks: Performance, data consistency
|
||||
|
||||
📍 #12 "Migrate database schema" - Score: 8/10
|
||||
Factors: Data migration, zero downtime, rollback strategy
|
||||
Recommendation: Expand into 4-5 subtasks
|
||||
Risks: Data loss, downtime
|
||||
|
||||
Medium Complexity Tasks (5-7):
|
||||
📍 #23 "Add export functionality" - Score: 6/10
|
||||
Consider expansion if timeline tight
|
||||
|
||||
Low Complexity Tasks (<5):
|
||||
✅ 15 tasks - No expansion needed
|
||||
|
||||
Summary:
|
||||
- Expand immediately: 2 tasks
|
||||
- Consider expanding: 5 tasks
|
||||
- Keep as-is: 15 tasks
|
||||
```
|
||||
|
||||
## Actionable Output
|
||||
|
||||
For each high-complexity task:
|
||||
1. Complexity score with reasoning
|
||||
2. Specific expansion suggestions
|
||||
3. Risk mitigation approaches
|
||||
4. Recommended subtask structure
|
||||
|
||||
## Integration
|
||||
|
||||
Results are:
|
||||
- Saved to `.taskmaster/reports/complexity-analysis.md`
|
||||
- Used by expand command
|
||||
- Inform sprint planning
|
||||
- Guide resource allocation
|
||||
|
||||
## Next Steps
|
||||
|
||||
After analysis:
|
||||
```
|
||||
/project:tm/expand 5 # Expand specific task
|
||||
/project:tm/expand/all # Expand all recommended
|
||||
/project:tm/complexity-report # View detailed report
|
||||
```
|
||||
@@ -0,0 +1,93 @@
|
||||
Clear all subtasks from all tasks globally.
|
||||
|
||||
## Global Subtask Clearing
|
||||
|
||||
Remove all subtasks across the entire project. Use with extreme caution.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master clear-subtasks --all
|
||||
```
|
||||
|
||||
## Pre-Clear Analysis
|
||||
|
||||
1. **Project-Wide Summary**
|
||||
```
|
||||
Global Subtask Summary
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
Total parent tasks: 12
|
||||
Total subtasks: 47
|
||||
- Completed: 15
|
||||
- In-progress: 8
|
||||
- Pending: 24
|
||||
|
||||
Work at risk: ~120 hours
|
||||
```
|
||||
|
||||
2. **Critical Warnings**
|
||||
- In-progress subtasks that will lose work
|
||||
- Completed subtasks with valuable history
|
||||
- Complex dependency chains
|
||||
- Integration test results
|
||||
|
||||
## Double Confirmation
|
||||
|
||||
```
|
||||
⚠️ DESTRUCTIVE OPERATION WARNING ⚠️
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
This will remove ALL 47 subtasks from your project
|
||||
Including 8 in-progress and 15 completed subtasks
|
||||
|
||||
This action CANNOT be undone
|
||||
|
||||
Type 'CLEAR ALL SUBTASKS' to confirm:
|
||||
```
|
||||
|
||||
## Smart Safeguards
|
||||
|
||||
- Require explicit confirmation phrase
|
||||
- Create automatic backup
|
||||
- Log all removed data
|
||||
- Option to export first
|
||||
|
||||
## Use Cases
|
||||
|
||||
Valid reasons for global clear:
|
||||
- Project restructuring
|
||||
- Major pivot in approach
|
||||
- Starting fresh breakdown
|
||||
- Switching to different task organization
|
||||
|
||||
## Process
|
||||
|
||||
1. Full project analysis
|
||||
2. Create backup file
|
||||
3. Show detailed impact
|
||||
4. Require confirmation
|
||||
5. Execute removal
|
||||
6. Generate summary report
|
||||
|
||||
## Alternative Suggestions
|
||||
|
||||
Before clearing all:
|
||||
- Export subtasks to file
|
||||
- Clear only pending subtasks
|
||||
- Clear by task category
|
||||
- Archive instead of delete
|
||||
|
||||
## Post-Clear Report
|
||||
|
||||
```
|
||||
Global Subtask Clear Complete
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Removed: 47 subtasks from 12 tasks
|
||||
Backup saved: .taskmaster/backup/subtasks-20240115.json
|
||||
Parent tasks updated: 12
|
||||
Time estimates adjusted: Yes
|
||||
|
||||
Next steps:
|
||||
- Review updated task list
|
||||
- Re-expand complex tasks as needed
|
||||
- Check project timeline
|
||||
```
|
||||
86
assets/claude/commands/tm/clear-subtasks/clear-subtasks.md
Normal file
86
assets/claude/commands/tm/clear-subtasks/clear-subtasks.md
Normal file
@@ -0,0 +1,86 @@
|
||||
Clear all subtasks from a specific task.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
Remove all subtasks from a parent task at once.
|
||||
|
||||
## Clearing Subtasks
|
||||
|
||||
Bulk removal of all subtasks from a parent task.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master clear-subtasks --id=<task-id>
|
||||
```
|
||||
|
||||
## Pre-Clear Analysis
|
||||
|
||||
1. **Subtask Summary**
|
||||
- Number of subtasks
|
||||
- Completion status of each
|
||||
- Work already done
|
||||
- Dependencies affected
|
||||
|
||||
2. **Impact Assessment**
|
||||
- Data that will be lost
|
||||
- Dependencies to be removed
|
||||
- Effect on project timeline
|
||||
- Parent task implications
|
||||
|
||||
## Confirmation Required
|
||||
|
||||
```
|
||||
Clear Subtasks Confirmation
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Parent Task: #5 "Implement user authentication"
|
||||
Subtasks to remove: 4
|
||||
- #5.1 "Setup auth framework" (done)
|
||||
- #5.2 "Create login form" (in-progress)
|
||||
- #5.3 "Add validation" (pending)
|
||||
- #5.4 "Write tests" (pending)
|
||||
|
||||
⚠️ This will permanently delete all subtask data
|
||||
Continue? (y/n)
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Option to convert to standalone tasks
|
||||
- Backup task data before clearing
|
||||
- Preserve completed work history
|
||||
- Update parent task appropriately
|
||||
|
||||
## Process
|
||||
|
||||
1. List all subtasks for confirmation
|
||||
2. Check for in-progress work
|
||||
3. Remove all subtasks
|
||||
4. Update parent task
|
||||
5. Clean up dependencies
|
||||
|
||||
## Alternative Options
|
||||
|
||||
Suggest alternatives:
|
||||
- Convert important subtasks to tasks
|
||||
- Keep completed subtasks
|
||||
- Archive instead of delete
|
||||
- Export subtask data first
|
||||
|
||||
## Post-Clear
|
||||
|
||||
- Show updated parent task
|
||||
- Recalculate time estimates
|
||||
- Update task complexity
|
||||
- Suggest next steps
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
/project:tm/clear-subtasks 5
|
||||
→ Found 4 subtasks to remove
|
||||
→ Warning: Subtask #5.2 is in-progress
|
||||
→ Cleared all subtasks from task #5
|
||||
→ Updated parent task estimates
|
||||
→ Suggestion: Consider re-expanding with better breakdown
|
||||
```
|
||||
117
assets/claude/commands/tm/complexity-report/complexity-report.md
Normal file
117
assets/claude/commands/tm/complexity-report/complexity-report.md
Normal file
@@ -0,0 +1,117 @@
|
||||
Display the task complexity analysis report.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
View the detailed complexity analysis generated by analyze-complexity command.
|
||||
|
||||
## Viewing Complexity Report
|
||||
|
||||
Shows comprehensive task complexity analysis with actionable insights.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master complexity-report [--file=<path>]
|
||||
```
|
||||
|
||||
## Report Location
|
||||
|
||||
Default: `.taskmaster/reports/complexity-analysis.md`
|
||||
Custom: Specify with --file parameter
|
||||
|
||||
## Report Contents
|
||||
|
||||
### 1. **Executive Summary**
|
||||
```
|
||||
Complexity Analysis Summary
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Analysis Date: 2024-01-15
|
||||
Tasks Analyzed: 32
|
||||
High Complexity: 5 (16%)
|
||||
Medium Complexity: 12 (37%)
|
||||
Low Complexity: 15 (47%)
|
||||
|
||||
Critical Findings:
|
||||
- 5 tasks need immediate expansion
|
||||
- 3 tasks have high technical risk
|
||||
- 2 tasks block critical path
|
||||
```
|
||||
|
||||
### 2. **Detailed Task Analysis**
|
||||
For each complex task:
|
||||
- Complexity score breakdown
|
||||
- Contributing factors
|
||||
- Specific risks identified
|
||||
- Expansion recommendations
|
||||
- Similar completed tasks
|
||||
|
||||
### 3. **Risk Matrix**
|
||||
Visual representation:
|
||||
```
|
||||
Risk vs Complexity Matrix
|
||||
━━━━━━━━━━━━━━━━━━━━━━━
|
||||
High Risk | #5(9) #12(8) | #23(6)
|
||||
Med Risk | #34(7) | #45(5) #67(5)
|
||||
Low Risk | #78(8) | [15 tasks]
|
||||
| High Complex | Med Complex
|
||||
```
|
||||
|
||||
### 4. **Recommendations**
|
||||
|
||||
**Immediate Actions:**
|
||||
1. Expand task #5 - Critical path + high complexity
|
||||
2. Expand task #12 - High risk + dependencies
|
||||
3. Review task #34 - Consider splitting
|
||||
|
||||
**Sprint Planning:**
|
||||
- Don't schedule multiple high-complexity tasks together
|
||||
- Ensure expertise available for complex tasks
|
||||
- Build in buffer time for unknowns
|
||||
|
||||
## Interactive Features
|
||||
|
||||
When viewing report:
|
||||
1. **Quick Actions**
|
||||
- Press 'e' to expand a task
|
||||
- Press 'd' for task details
|
||||
- Press 'r' to refresh analysis
|
||||
|
||||
2. **Filtering**
|
||||
- View by complexity level
|
||||
- Filter by risk factors
|
||||
- Show only actionable items
|
||||
|
||||
3. **Export Options**
|
||||
- Markdown format
|
||||
- CSV for spreadsheets
|
||||
- JSON for tools
|
||||
|
||||
## Report Intelligence
|
||||
|
||||
- Compares with historical data
|
||||
- Shows complexity trends
|
||||
- Identifies patterns
|
||||
- Suggests process improvements
|
||||
|
||||
## Integration
|
||||
|
||||
Use report for:
|
||||
- Sprint planning sessions
|
||||
- Resource allocation
|
||||
- Risk assessment
|
||||
- Team discussions
|
||||
- Client updates
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
/project:tm/complexity-report
|
||||
→ Opens latest analysis
|
||||
|
||||
/project:tm/complexity-report --file=archived/2024-01-01.md
|
||||
→ View historical analysis
|
||||
|
||||
After viewing:
|
||||
/project:tm/expand 5
|
||||
→ Expand high-complexity task
|
||||
```
|
||||
51
assets/claude/commands/tm/expand/expand-all-tasks.md
Normal file
51
assets/claude/commands/tm/expand/expand-all-tasks.md
Normal file
@@ -0,0 +1,51 @@
|
||||
Expand all pending tasks that need subtasks.
|
||||
|
||||
## Bulk Task Expansion
|
||||
|
||||
Intelligently expands all tasks that would benefit from breakdown.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master expand --all
|
||||
```
|
||||
|
||||
## Smart Selection
|
||||
|
||||
Only expands tasks that:
|
||||
- Are marked as pending
|
||||
- Have high complexity (>5)
|
||||
- Lack existing subtasks
|
||||
- Would benefit from breakdown
|
||||
|
||||
## Expansion Process
|
||||
|
||||
1. **Analysis Phase**
|
||||
- Identify expansion candidates
|
||||
- Group related tasks
|
||||
- Plan expansion strategy
|
||||
|
||||
2. **Batch Processing**
|
||||
- Expand tasks in logical order
|
||||
- Maintain consistency
|
||||
- Preserve relationships
|
||||
- Optimize for parallelism
|
||||
|
||||
3. **Quality Control**
|
||||
- Ensure subtask quality
|
||||
- Avoid over-decomposition
|
||||
- Maintain task coherence
|
||||
- Update dependencies
|
||||
|
||||
## Options
|
||||
|
||||
- Add `force` to expand all regardless of complexity
|
||||
- Add `research` for enhanced AI analysis
|
||||
|
||||
## Results
|
||||
|
||||
After bulk expansion:
|
||||
- Summary of tasks expanded
|
||||
- New subtask count
|
||||
- Updated complexity metrics
|
||||
- Suggested task order
|
||||
49
assets/claude/commands/tm/expand/expand-task.md
Normal file
49
assets/claude/commands/tm/expand/expand-task.md
Normal file
@@ -0,0 +1,49 @@
|
||||
Break down a complex task into subtasks.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Intelligent Task Expansion
|
||||
|
||||
Analyzes a task and creates detailed subtasks for better manageability.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master expand --id=$ARGUMENTS
|
||||
```
|
||||
|
||||
## Expansion Process
|
||||
|
||||
1. **Task Analysis**
|
||||
- Review task complexity
|
||||
- Identify components
|
||||
- Detect technical challenges
|
||||
- Estimate time requirements
|
||||
|
||||
2. **Subtask Generation**
|
||||
- Create 3-7 subtasks typically
|
||||
- Each subtask 1-4 hours
|
||||
- Logical implementation order
|
||||
- Clear acceptance criteria
|
||||
|
||||
3. **Smart Breakdown**
|
||||
- Setup/configuration tasks
|
||||
- Core implementation
|
||||
- Testing components
|
||||
- Integration steps
|
||||
- Documentation updates
|
||||
|
||||
## Enhanced Features
|
||||
|
||||
Based on task type:
|
||||
- **Feature**: Setup → Implement → Test → Integrate
|
||||
- **Bug Fix**: Reproduce → Diagnose → Fix → Verify
|
||||
- **Refactor**: Analyze → Plan → Refactor → Validate
|
||||
|
||||
## Post-Expansion
|
||||
|
||||
After expansion:
|
||||
1. Show subtask hierarchy
|
||||
2. Update time estimates
|
||||
3. Suggest implementation order
|
||||
4. Highlight critical path
|
||||
@@ -0,0 +1,81 @@
|
||||
Automatically fix dependency issues found during validation.
|
||||
|
||||
## Automatic Dependency Repair
|
||||
|
||||
Intelligently fixes common dependency problems while preserving project logic.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master fix-dependencies
|
||||
```
|
||||
|
||||
## What Gets Fixed
|
||||
|
||||
### 1. **Auto-Fixable Issues**
|
||||
- Remove references to deleted tasks
|
||||
- Break simple circular dependencies
|
||||
- Remove self-dependencies
|
||||
- Clean up duplicate dependencies
|
||||
|
||||
### 2. **Smart Resolutions**
|
||||
- Reorder dependencies to maintain logic
|
||||
- Suggest task merging for over-dependent tasks
|
||||
- Flatten unnecessary dependency chains
|
||||
- Remove redundant transitive dependencies
|
||||
|
||||
### 3. **Manual Review Required**
|
||||
- Complex circular dependencies
|
||||
- Critical path modifications
|
||||
- Business logic dependencies
|
||||
- High-impact changes
|
||||
|
||||
## Fix Process
|
||||
|
||||
1. **Analysis Phase**
|
||||
- Run validation check
|
||||
- Categorize issues by type
|
||||
- Determine fix strategy
|
||||
|
||||
2. **Execution Phase**
|
||||
- Apply automatic fixes
|
||||
- Log all changes made
|
||||
- Preserve task relationships
|
||||
|
||||
3. **Verification Phase**
|
||||
- Re-validate after fixes
|
||||
- Show before/after comparison
|
||||
- Highlight manual fixes needed
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Preserves intended task flow
|
||||
- Minimal disruption approach
|
||||
- Creates fix history/log
|
||||
- Suggests manual interventions
|
||||
|
||||
## Output Example
|
||||
|
||||
```
|
||||
Dependency Auto-Fix Report
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Fixed Automatically:
|
||||
✅ Removed 2 references to deleted tasks
|
||||
✅ Resolved 1 self-dependency
|
||||
✅ Cleaned 3 redundant dependencies
|
||||
|
||||
Manual Review Needed:
|
||||
⚠️ Complex circular dependency: #12 → #15 → #18 → #12
|
||||
Suggestion: Make #15 not depend on #12
|
||||
⚠️ Task #45 has 8 dependencies
|
||||
Suggestion: Break into subtasks
|
||||
|
||||
Run '/project:tm/validate-dependencies' to verify fixes
|
||||
```
|
||||
|
||||
## Safety
|
||||
|
||||
- Preview mode available
|
||||
- Rollback capability
|
||||
- Change logging
|
||||
- No data loss
|
||||
121
assets/claude/commands/tm/generate/generate-tasks.md
Normal file
121
assets/claude/commands/tm/generate/generate-tasks.md
Normal file
@@ -0,0 +1,121 @@
|
||||
Generate individual task files from tasks.json.
|
||||
|
||||
## Task File Generation
|
||||
|
||||
Creates separate markdown files for each task, perfect for AI agents or documentation.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master generate
|
||||
```
|
||||
|
||||
## What It Creates
|
||||
|
||||
For each task, generates a file like `task_001.txt`:
|
||||
|
||||
```
|
||||
Task ID: 1
|
||||
Title: Implement user authentication
|
||||
Status: pending
|
||||
Priority: high
|
||||
Dependencies: []
|
||||
Created: 2024-01-15
|
||||
Complexity: 7
|
||||
|
||||
## Description
|
||||
Create a secure user authentication system with login, logout, and session management.
|
||||
|
||||
## Details
|
||||
- Use JWT tokens for session management
|
||||
- Implement secure password hashing
|
||||
- Add remember me functionality
|
||||
- Include password reset flow
|
||||
|
||||
## Test Strategy
|
||||
- Unit tests for auth functions
|
||||
- Integration tests for login flow
|
||||
- Security testing for vulnerabilities
|
||||
- Performance tests for concurrent logins
|
||||
|
||||
## Subtasks
|
||||
1.1 Setup authentication framework (pending)
|
||||
1.2 Create login endpoints (pending)
|
||||
1.3 Implement session management (pending)
|
||||
1.4 Add password reset (pending)
|
||||
```
|
||||
|
||||
## File Organization
|
||||
|
||||
Creates structure:
|
||||
```
|
||||
.taskmaster/
|
||||
└── tasks/
|
||||
├── task_001.txt
|
||||
├── task_002.txt
|
||||
├── task_003.txt
|
||||
└── ...
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Consistent Formatting**
|
||||
- Standardized structure
|
||||
- Clear sections
|
||||
- AI-readable format
|
||||
- Markdown compatible
|
||||
|
||||
2. **Contextual Information**
|
||||
- Full task details
|
||||
- Related task references
|
||||
- Progress indicators
|
||||
- Implementation notes
|
||||
|
||||
3. **Incremental Updates**
|
||||
- Only regenerate changed tasks
|
||||
- Preserve custom additions
|
||||
- Track generation timestamp
|
||||
- Version control friendly
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **AI Context**: Provide task context to AI assistants
|
||||
- **Documentation**: Standalone task documentation
|
||||
- **Archival**: Task history preservation
|
||||
- **Sharing**: Send specific tasks to team members
|
||||
- **Review**: Easier task review process
|
||||
|
||||
## Generation Options
|
||||
|
||||
Based on arguments:
|
||||
- Filter by status
|
||||
- Include/exclude completed
|
||||
- Custom templates
|
||||
- Different formats
|
||||
|
||||
## Post-Generation
|
||||
|
||||
```
|
||||
Task File Generation Complete
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Generated: 45 task files
|
||||
Location: .taskmaster/tasks/
|
||||
Total size: 156 KB
|
||||
|
||||
New files: 5
|
||||
Updated files: 12
|
||||
Unchanged: 28
|
||||
|
||||
Ready for:
|
||||
- AI agent consumption
|
||||
- Version control
|
||||
- Team distribution
|
||||
```
|
||||
|
||||
## Integration Benefits
|
||||
|
||||
- Git-trackable task history
|
||||
- Easy task sharing
|
||||
- AI tool compatibility
|
||||
- Offline task access
|
||||
- Backup redundancy
|
||||
81
assets/claude/commands/tm/help.md
Normal file
81
assets/claude/commands/tm/help.md
Normal file
@@ -0,0 +1,81 @@
|
||||
Show help for Task Master commands.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Display help for Task Master commands. If arguments provided, show specific command help.
|
||||
|
||||
## Task Master Command Help
|
||||
|
||||
### Quick Navigation
|
||||
|
||||
Type `/project:tm/` and use tab completion to explore all commands.
|
||||
|
||||
### Command Categories
|
||||
|
||||
#### 🚀 Setup & Installation
|
||||
- `/project:tm/setup/install` - Comprehensive installation guide
|
||||
- `/project:tm/setup/quick-install` - One-line global install
|
||||
|
||||
#### 📋 Project Setup
|
||||
- `/project:tm/init` - Initialize new project
|
||||
- `/project:tm/init/quick` - Quick setup with auto-confirm
|
||||
- `/project:tm/models` - View AI configuration
|
||||
- `/project:tm/models/setup` - Configure AI providers
|
||||
|
||||
#### 🎯 Task Generation
|
||||
- `/project:tm/parse-prd` - Generate tasks from PRD
|
||||
- `/project:tm/parse-prd/with-research` - Enhanced parsing
|
||||
- `/project:tm/generate` - Create task files
|
||||
|
||||
#### 📝 Task Management
|
||||
- `/project:tm/list` - List tasks (natural language filters)
|
||||
- `/project:tm/show <id>` - Display task details
|
||||
- `/project:tm/add-task` - Create new task
|
||||
- `/project:tm/update` - Update tasks naturally
|
||||
- `/project:tm/next` - Get next task recommendation
|
||||
|
||||
#### 🔄 Status Management
|
||||
- `/project:tm/set-status/to-pending <id>`
|
||||
- `/project:tm/set-status/to-in-progress <id>`
|
||||
- `/project:tm/set-status/to-done <id>`
|
||||
- `/project:tm/set-status/to-review <id>`
|
||||
- `/project:tm/set-status/to-deferred <id>`
|
||||
- `/project:tm/set-status/to-cancelled <id>`
|
||||
|
||||
#### 🔍 Analysis & Breakdown
|
||||
- `/project:tm/analyze-complexity` - Analyze task complexity
|
||||
- `/project:tm/expand <id>` - Break down complex task
|
||||
- `/project:tm/expand/all` - Expand all eligible tasks
|
||||
|
||||
#### 🔗 Dependencies
|
||||
- `/project:tm/add-dependency` - Add task dependency
|
||||
- `/project:tm/remove-dependency` - Remove dependency
|
||||
- `/project:tm/validate-dependencies` - Check for issues
|
||||
|
||||
#### 🤖 Workflows
|
||||
- `/project:tm/workflows/smart-flow` - Intelligent workflows
|
||||
- `/project:tm/workflows/pipeline` - Command chaining
|
||||
- `/project:tm/workflows/auto-implement` - Auto-implementation
|
||||
|
||||
#### 📊 Utilities
|
||||
- `/project:tm/utils/analyze` - Project analysis
|
||||
- `/project:tm/status` - Project dashboard
|
||||
- `/project:tm/learn` - Interactive learning
|
||||
|
||||
### Natural Language Examples
|
||||
|
||||
```
|
||||
/project:tm/list pending high priority
|
||||
/project:tm/update mark all API tasks as done
|
||||
/project:tm/add-task create login system with OAuth
|
||||
/project:tm/show current
|
||||
```
|
||||
|
||||
### Getting Started
|
||||
|
||||
1. Install: `/project:tm/setup/quick-install`
|
||||
2. Initialize: `/project:tm/init/quick`
|
||||
3. Learn: `/project:tm/learn start`
|
||||
4. Work: `/project:tm/workflows/smart-flow`
|
||||
|
||||
For detailed command info: `/project:tm/help <command-name>`
|
||||
46
assets/claude/commands/tm/init/init-project-quick.md
Normal file
46
assets/claude/commands/tm/init/init-project-quick.md
Normal file
@@ -0,0 +1,46 @@
|
||||
Quick initialization with auto-confirmation.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Initialize a Task Master project without prompts, accepting all defaults.
|
||||
|
||||
## Quick Setup
|
||||
|
||||
```bash
|
||||
task-master init -y
|
||||
```
|
||||
|
||||
## What It Does
|
||||
|
||||
1. Creates `.taskmaster/` directory structure
|
||||
2. Initializes empty `tasks.json`
|
||||
3. Sets up default configuration
|
||||
4. Uses directory name as project name
|
||||
5. Skips all confirmation prompts
|
||||
|
||||
## Smart Defaults
|
||||
|
||||
- Project name: Current directory name
|
||||
- Description: "Task Master Project"
|
||||
- Model config: Existing environment vars
|
||||
- Task structure: Standard format
|
||||
|
||||
## Next Steps
|
||||
|
||||
After quick init:
|
||||
1. Configure AI models if needed:
|
||||
```
|
||||
/project:tm/models/setup
|
||||
```
|
||||
|
||||
2. Parse PRD if available:
|
||||
```
|
||||
/project:tm/parse-prd <file>
|
||||
```
|
||||
|
||||
3. Or create first task:
|
||||
```
|
||||
/project:tm/add-task create initial setup
|
||||
```
|
||||
|
||||
Perfect for rapid project setup!
|
||||
50
assets/claude/commands/tm/init/init-project.md
Normal file
50
assets/claude/commands/tm/init/init-project.md
Normal file
@@ -0,0 +1,50 @@
|
||||
Initialize a new Task Master project.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse arguments to determine initialization preferences.
|
||||
|
||||
## Initialization Process
|
||||
|
||||
1. **Parse Arguments**
|
||||
- PRD file path (if provided)
|
||||
- Project name
|
||||
- Auto-confirm flag (-y)
|
||||
|
||||
2. **Project Setup**
|
||||
```bash
|
||||
task-master init
|
||||
```
|
||||
|
||||
3. **Smart Initialization**
|
||||
- Detect existing project files
|
||||
- Suggest project name from directory
|
||||
- Check for git repository
|
||||
- Verify AI provider configuration
|
||||
|
||||
## Configuration Options
|
||||
|
||||
Based on arguments:
|
||||
- `quick` / `-y` → Skip confirmations
|
||||
- `<file.md>` → Use as PRD after init
|
||||
- `--name=<name>` → Set project name
|
||||
- `--description=<desc>` → Set description
|
||||
|
||||
## Post-Initialization
|
||||
|
||||
After successful init:
|
||||
1. Show project structure created
|
||||
2. Verify AI models configured
|
||||
3. Suggest next steps:
|
||||
- Parse PRD if available
|
||||
- Configure AI providers
|
||||
- Set up git hooks
|
||||
- Create first tasks
|
||||
|
||||
## Integration
|
||||
|
||||
If PRD file provided:
|
||||
```
|
||||
/project:tm/init my-prd.md
|
||||
→ Automatically runs parse-prd after init
|
||||
```
|
||||
103
assets/claude/commands/tm/learn.md
Normal file
103
assets/claude/commands/tm/learn.md
Normal file
@@ -0,0 +1,103 @@
|
||||
Learn about Task Master capabilities through interactive exploration.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Interactive Task Master Learning
|
||||
|
||||
Based on your input, I'll help you discover capabilities:
|
||||
|
||||
### 1. **What are you trying to do?**
|
||||
|
||||
If $ARGUMENTS contains:
|
||||
- "start" / "begin" → Show project initialization workflows
|
||||
- "manage" / "organize" → Show task management commands
|
||||
- "automate" / "auto" → Show automation workflows
|
||||
- "analyze" / "report" → Show analysis tools
|
||||
- "fix" / "problem" → Show troubleshooting commands
|
||||
- "fast" / "quick" → Show efficiency shortcuts
|
||||
|
||||
### 2. **Intelligent Suggestions**
|
||||
|
||||
Based on your project state:
|
||||
|
||||
**No tasks yet?**
|
||||
```
|
||||
You'll want to start with:
|
||||
1. /project:task-master:init <prd-file>
|
||||
→ Creates tasks from requirements
|
||||
|
||||
2. /project:task-master:parse-prd <file>
|
||||
→ Alternative task generation
|
||||
|
||||
Try: /project:task-master:init demo-prd.md
|
||||
```
|
||||
|
||||
**Have tasks?**
|
||||
Let me analyze what you might need...
|
||||
- Many pending tasks? → Learn sprint planning
|
||||
- Complex tasks? → Learn task expansion
|
||||
- Daily work? → Learn workflow automation
|
||||
|
||||
### 3. **Command Discovery**
|
||||
|
||||
**By Category:**
|
||||
- 📋 Task Management: list, show, add, update, complete
|
||||
- 🔄 Workflows: auto-implement, sprint-plan, daily-standup
|
||||
- 🛠️ Utilities: check-health, complexity-report, sync-memory
|
||||
- 🔍 Analysis: validate-deps, show dependencies
|
||||
|
||||
**By Scenario:**
|
||||
- "I want to see what to work on" → `/project:task-master:next`
|
||||
- "I need to break this down" → `/project:task-master:expand <id>`
|
||||
- "Show me everything" → `/project:task-master:status`
|
||||
- "Just do it for me" → `/project:workflows:auto-implement`
|
||||
|
||||
### 4. **Power User Patterns**
|
||||
|
||||
**Command Chaining:**
|
||||
```
|
||||
/project:task-master:next
|
||||
/project:task-master:start <id>
|
||||
/project:workflows:auto-implement
|
||||
```
|
||||
|
||||
**Smart Filters:**
|
||||
```
|
||||
/project:task-master:list pending high
|
||||
/project:task-master:list blocked
|
||||
/project:task-master:list 1-5 tree
|
||||
```
|
||||
|
||||
**Automation:**
|
||||
```
|
||||
/project:workflows:pipeline init → expand-all → sprint-plan
|
||||
```
|
||||
|
||||
### 5. **Learning Path**
|
||||
|
||||
Based on your experience level:
|
||||
|
||||
**Beginner Path:**
|
||||
1. init → Create project
|
||||
2. status → Understand state
|
||||
3. next → Find work
|
||||
4. complete → Finish task
|
||||
|
||||
**Intermediate Path:**
|
||||
1. expand → Break down complex tasks
|
||||
2. sprint-plan → Organize work
|
||||
3. complexity-report → Understand difficulty
|
||||
4. validate-deps → Ensure consistency
|
||||
|
||||
**Advanced Path:**
|
||||
1. pipeline → Chain operations
|
||||
2. smart-flow → Context-aware automation
|
||||
3. Custom commands → Extend the system
|
||||
|
||||
### 6. **Try This Now**
|
||||
|
||||
Based on what you asked about, try:
|
||||
[Specific command suggestion based on $ARGUMENTS]
|
||||
|
||||
Want to learn more about a specific command?
|
||||
Type: /project:help <command-name>
|
||||
39
assets/claude/commands/tm/list/list-tasks-by-status.md
Normal file
39
assets/claude/commands/tm/list/list-tasks-by-status.md
Normal file
@@ -0,0 +1,39 @@
|
||||
List tasks filtered by a specific status.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the status from arguments and list only tasks matching that status.
|
||||
|
||||
## Status Options
|
||||
- `pending` - Not yet started
|
||||
- `in-progress` - Currently being worked on
|
||||
- `done` - Completed
|
||||
- `review` - Awaiting review
|
||||
- `deferred` - Postponed
|
||||
- `cancelled` - Cancelled
|
||||
|
||||
## Execution
|
||||
|
||||
Based on $ARGUMENTS, run:
|
||||
```bash
|
||||
task-master list --status=$ARGUMENTS
|
||||
```
|
||||
|
||||
## Enhanced Display
|
||||
|
||||
For the filtered results:
|
||||
- Group by priority within the status
|
||||
- Show time in current status
|
||||
- Highlight tasks approaching deadlines
|
||||
- Display blockers and dependencies
|
||||
- Suggest next actions for each status group
|
||||
|
||||
## Intelligent Insights
|
||||
|
||||
Based on the status filter:
|
||||
- **Pending**: Show recommended start order
|
||||
- **In-Progress**: Display idle time warnings
|
||||
- **Done**: Show newly unblocked tasks
|
||||
- **Review**: Indicate review duration
|
||||
- **Deferred**: Show reactivation criteria
|
||||
- **Cancelled**: Display impact analysis
|
||||
29
assets/claude/commands/tm/list/list-tasks-with-subtasks.md
Normal file
29
assets/claude/commands/tm/list/list-tasks-with-subtasks.md
Normal file
@@ -0,0 +1,29 @@
|
||||
List all tasks including their subtasks in a hierarchical view.
|
||||
|
||||
This command shows all tasks with their nested subtasks, providing a complete project overview.
|
||||
|
||||
## Execution
|
||||
|
||||
Run the Task Master list command with subtasks flag:
|
||||
```bash
|
||||
task-master list --with-subtasks
|
||||
```
|
||||
|
||||
## Enhanced Display
|
||||
|
||||
I'll organize the output to show:
|
||||
- Parent tasks with clear indicators
|
||||
- Nested subtasks with proper indentation
|
||||
- Status badges for quick scanning
|
||||
- Dependencies and blockers highlighted
|
||||
- Progress indicators for tasks with subtasks
|
||||
|
||||
## Smart Filtering
|
||||
|
||||
Based on the task hierarchy:
|
||||
- Show completion percentage for parent tasks
|
||||
- Highlight blocked subtask chains
|
||||
- Group by functional areas
|
||||
- Indicate critical path items
|
||||
|
||||
This gives you a complete tree view of your project structure.
|
||||
43
assets/claude/commands/tm/list/list-tasks.md
Normal file
43
assets/claude/commands/tm/list/list-tasks.md
Normal file
@@ -0,0 +1,43 @@
|
||||
List tasks with intelligent argument parsing.
|
||||
|
||||
Parse arguments to determine filters and display options:
|
||||
- Status: pending, in-progress, done, review, deferred, cancelled
|
||||
- Priority: high, medium, low (or priority:high)
|
||||
- Special: subtasks, tree, dependencies, blocked
|
||||
- IDs: Direct numbers (e.g., "1,3,5" or "1-5")
|
||||
- Complex: "pending high" = pending AND high priority
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Let me parse your request intelligently:
|
||||
|
||||
1. **Detect Filter Intent**
|
||||
- If arguments contain status keywords → filter by status
|
||||
- If arguments contain priority → filter by priority
|
||||
- If arguments contain "subtasks" → include subtasks
|
||||
- If arguments contain "tree" → hierarchical view
|
||||
- If arguments contain numbers → show specific tasks
|
||||
- If arguments contain "blocked" → show blocked tasks only
|
||||
|
||||
2. **Smart Combinations**
|
||||
Examples of what I understand:
|
||||
- "pending high" → pending tasks with high priority
|
||||
- "done today" → tasks completed today
|
||||
- "blocked" → tasks with unmet dependencies
|
||||
- "1-5" → tasks 1 through 5
|
||||
- "subtasks tree" → hierarchical view with subtasks
|
||||
|
||||
3. **Execute Appropriate Query**
|
||||
Based on parsed intent, run the most specific task-master command
|
||||
|
||||
4. **Enhanced Display**
|
||||
- Group by relevant criteria
|
||||
- Show most important information first
|
||||
- Use visual indicators for quick scanning
|
||||
- Include relevant metrics
|
||||
|
||||
5. **Intelligent Suggestions**
|
||||
Based on what you're viewing, suggest next actions:
|
||||
- Many pending? → Suggest priority order
|
||||
- Many blocked? → Show dependency resolution
|
||||
- Looking at specific tasks? → Show related tasks
|
||||
51
assets/claude/commands/tm/models/setup-models.md
Normal file
51
assets/claude/commands/tm/models/setup-models.md
Normal file
@@ -0,0 +1,51 @@
|
||||
Run interactive setup to configure AI models.
|
||||
|
||||
## Interactive Model Configuration
|
||||
|
||||
Guides you through setting up AI providers for Task Master.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master models --setup
|
||||
```
|
||||
|
||||
## Setup Process
|
||||
|
||||
1. **Environment Check**
|
||||
- Detect existing API keys
|
||||
- Show current configuration
|
||||
- Identify missing providers
|
||||
|
||||
2. **Provider Selection**
|
||||
- Choose main provider (required)
|
||||
- Select research provider (recommended)
|
||||
- Configure fallback (optional)
|
||||
|
||||
3. **API Key Configuration**
|
||||
- Prompt for missing keys
|
||||
- Validate key format
|
||||
- Test connectivity
|
||||
- Save configuration
|
||||
|
||||
## Smart Recommendations
|
||||
|
||||
Based on your needs:
|
||||
- **For best results**: Claude + Perplexity
|
||||
- **Budget conscious**: GPT-3.5 + Perplexity
|
||||
- **Maximum capability**: GPT-4 + Perplexity + Claude fallback
|
||||
|
||||
## Configuration Storage
|
||||
|
||||
Keys can be stored in:
|
||||
1. Environment variables (recommended)
|
||||
2. `.env` file in project
|
||||
3. Global `.taskmaster/config`
|
||||
|
||||
## Post-Setup
|
||||
|
||||
After configuration:
|
||||
- Test each provider
|
||||
- Show usage examples
|
||||
- Suggest next steps
|
||||
- Verify parse-prd works
|
||||
51
assets/claude/commands/tm/models/view-models.md
Normal file
51
assets/claude/commands/tm/models/view-models.md
Normal file
@@ -0,0 +1,51 @@
|
||||
View current AI model configuration.
|
||||
|
||||
## Model Configuration Display
|
||||
|
||||
Shows the currently configured AI providers and models for Task Master.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master models
|
||||
```
|
||||
|
||||
## Information Displayed
|
||||
|
||||
1. **Main Provider**
|
||||
- Model ID and name
|
||||
- API key status (configured/missing)
|
||||
- Usage: Primary task generation
|
||||
|
||||
2. **Research Provider**
|
||||
- Model ID and name
|
||||
- API key status
|
||||
- Usage: Enhanced research mode
|
||||
|
||||
3. **Fallback Provider**
|
||||
- Model ID and name
|
||||
- API key status
|
||||
- Usage: Backup when main fails
|
||||
|
||||
## Visual Status
|
||||
|
||||
```
|
||||
Task Master AI Model Configuration
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Main: ✅ claude-3-5-sonnet (configured)
|
||||
Research: ✅ perplexity-sonar (configured)
|
||||
Fallback: ⚠️ Not configured (optional)
|
||||
|
||||
Available Models:
|
||||
- claude-3-5-sonnet
|
||||
- gpt-4-turbo
|
||||
- gpt-3.5-turbo
|
||||
- perplexity-sonar
|
||||
```
|
||||
|
||||
## Next Actions
|
||||
|
||||
Based on configuration:
|
||||
- If missing API keys → Suggest setup
|
||||
- If no research model → Explain benefits
|
||||
- If all configured → Show usage tips
|
||||
66
assets/claude/commands/tm/next/next-task.md
Normal file
66
assets/claude/commands/tm/next/next-task.md
Normal file
@@ -0,0 +1,66 @@
|
||||
Intelligently determine and prepare the next action based on comprehensive context.
|
||||
|
||||
This enhanced version of 'next' considers:
|
||||
- Current task states
|
||||
- Recent activity
|
||||
- Time constraints
|
||||
- Dependencies
|
||||
- Your working patterns
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Next Action
|
||||
|
||||
### 1. **Context Gathering**
|
||||
Let me analyze the current situation:
|
||||
- Active tasks (in-progress)
|
||||
- Recently completed tasks
|
||||
- Blocked tasks
|
||||
- Time since last activity
|
||||
- Arguments provided: $ARGUMENTS
|
||||
|
||||
### 2. **Smart Decision Tree**
|
||||
|
||||
**If you have an in-progress task:**
|
||||
- Has it been idle > 2 hours? → Suggest resuming or switching
|
||||
- Near completion? → Show remaining steps
|
||||
- Blocked? → Find alternative task
|
||||
|
||||
**If no in-progress tasks:**
|
||||
- Unblocked high-priority tasks? → Start highest
|
||||
- Complex tasks need breakdown? → Suggest expansion
|
||||
- All tasks blocked? → Show dependency resolution
|
||||
|
||||
**Special arguments handling:**
|
||||
- "quick" → Find task < 2 hours
|
||||
- "easy" → Find low complexity task
|
||||
- "important" → Find high priority regardless of complexity
|
||||
- "continue" → Resume last worked task
|
||||
|
||||
### 3. **Preparation Workflow**
|
||||
|
||||
Based on selected task:
|
||||
1. Show full context and history
|
||||
2. Set up development environment
|
||||
3. Run relevant tests
|
||||
4. Open related files
|
||||
5. Show similar completed tasks
|
||||
6. Estimate completion time
|
||||
|
||||
### 4. **Alternative Suggestions**
|
||||
|
||||
Always provide options:
|
||||
- Primary recommendation
|
||||
- Quick alternative (< 1 hour)
|
||||
- Strategic option (unblocks most tasks)
|
||||
- Learning option (new technology/skill)
|
||||
|
||||
### 5. **Workflow Integration**
|
||||
|
||||
Seamlessly connect to:
|
||||
- `/project:task-master:start [selected]`
|
||||
- `/project:workflows:auto-implement`
|
||||
- `/project:task-master:expand` (if complex)
|
||||
- `/project:utils:complexity-report` (if unsure)
|
||||
|
||||
The goal: Zero friction from decision to implementation.
|
||||
@@ -0,0 +1,48 @@
|
||||
Parse PRD with enhanced research mode for better task generation.
|
||||
|
||||
Arguments: $ARGUMENTS (PRD file path)
|
||||
|
||||
## Research-Enhanced Parsing
|
||||
|
||||
Uses the research AI provider (typically Perplexity) for more comprehensive task generation with current best practices.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master parse-prd --input=$ARGUMENTS --research
|
||||
```
|
||||
|
||||
## Research Benefits
|
||||
|
||||
1. **Current Best Practices**
|
||||
- Latest framework patterns
|
||||
- Security considerations
|
||||
- Performance optimizations
|
||||
- Accessibility requirements
|
||||
|
||||
2. **Technical Deep Dive**
|
||||
- Implementation approaches
|
||||
- Library recommendations
|
||||
- Architecture patterns
|
||||
- Testing strategies
|
||||
|
||||
3. **Comprehensive Coverage**
|
||||
- Edge cases consideration
|
||||
- Error handling tasks
|
||||
- Monitoring setup
|
||||
- Deployment tasks
|
||||
|
||||
## Enhanced Output
|
||||
|
||||
Research mode typically:
|
||||
- Generates more detailed tasks
|
||||
- Includes industry standards
|
||||
- Adds compliance considerations
|
||||
- Suggests modern tooling
|
||||
|
||||
## When to Use
|
||||
|
||||
- New technology domains
|
||||
- Complex requirements
|
||||
- Regulatory compliance needed
|
||||
- Best practices crucial
|
||||
49
assets/claude/commands/tm/parse-prd/parse-prd.md
Normal file
49
assets/claude/commands/tm/parse-prd/parse-prd.md
Normal file
@@ -0,0 +1,49 @@
|
||||
Parse a PRD document to generate tasks.
|
||||
|
||||
Arguments: $ARGUMENTS (PRD file path)
|
||||
|
||||
## Intelligent PRD Parsing
|
||||
|
||||
Analyzes your requirements document and generates a complete task breakdown.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master parse-prd --input=$ARGUMENTS
|
||||
```
|
||||
|
||||
## Parsing Process
|
||||
|
||||
1. **Document Analysis**
|
||||
- Extract key requirements
|
||||
- Identify technical components
|
||||
- Detect dependencies
|
||||
- Estimate complexity
|
||||
|
||||
2. **Task Generation**
|
||||
- Create 10-15 tasks by default
|
||||
- Include implementation tasks
|
||||
- Add testing tasks
|
||||
- Include documentation tasks
|
||||
- Set logical dependencies
|
||||
|
||||
3. **Smart Enhancements**
|
||||
- Group related functionality
|
||||
- Set appropriate priorities
|
||||
- Add acceptance criteria
|
||||
- Include test strategies
|
||||
|
||||
## Options
|
||||
|
||||
Parse arguments for modifiers:
|
||||
- Number after filename → `--num-tasks`
|
||||
- `research` → Use research mode
|
||||
- `comprehensive` → Generate more tasks
|
||||
|
||||
## Post-Generation
|
||||
|
||||
After parsing:
|
||||
1. Display task summary
|
||||
2. Show dependency graph
|
||||
3. Suggest task expansion for complex items
|
||||
4. Recommend sprint planning
|
||||
@@ -0,0 +1,62 @@
|
||||
Remove a dependency between tasks.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse the task IDs to remove dependency relationship.
|
||||
|
||||
## Removing Dependencies
|
||||
|
||||
Removes a dependency relationship, potentially unblocking tasks.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Parse natural language or IDs:
|
||||
- "remove dependency between 5 and 3"
|
||||
- "5 no longer needs 3"
|
||||
- "unblock 5 from 3"
|
||||
- "5 3" → remove dependency of 5 on 3
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master remove-dependency --id=<task-id> --depends-on=<dependency-id>
|
||||
```
|
||||
|
||||
## Pre-Removal Checks
|
||||
|
||||
1. **Verify dependency exists**
|
||||
2. **Check impact on task flow**
|
||||
3. **Warn if it breaks logical sequence**
|
||||
4. **Show what will be unblocked**
|
||||
|
||||
## Smart Analysis
|
||||
|
||||
Before removing:
|
||||
- Show why dependency might have existed
|
||||
- Check if removal makes tasks executable
|
||||
- Verify no critical path disruption
|
||||
- Suggest alternative dependencies
|
||||
|
||||
## Post-Removal
|
||||
|
||||
After removing:
|
||||
1. Show updated task status
|
||||
2. List newly unblocked tasks
|
||||
3. Update project timeline
|
||||
4. Suggest next actions
|
||||
|
||||
## Safety Features
|
||||
|
||||
- Confirm if removing critical dependency
|
||||
- Show tasks that become immediately actionable
|
||||
- Warn about potential issues
|
||||
- Keep removal history
|
||||
|
||||
## Example
|
||||
|
||||
```
|
||||
/project:tm/remove-dependency 5 from 3
|
||||
→ Removed: Task #5 no longer depends on #3
|
||||
→ Task #5 is now UNBLOCKED and ready to start
|
||||
→ Warning: Consider if #5 still needs #2 completed first
|
||||
```
|
||||
84
assets/claude/commands/tm/remove-subtask/remove-subtask.md
Normal file
84
assets/claude/commands/tm/remove-subtask/remove-subtask.md
Normal file
@@ -0,0 +1,84 @@
|
||||
Remove a subtask from its parent task.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse subtask ID to remove, with option to convert to standalone task.
|
||||
|
||||
## Removing Subtasks
|
||||
|
||||
Remove a subtask and optionally convert it back to a standalone task.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "remove subtask 5.1"
|
||||
- "delete 5.1"
|
||||
- "convert 5.1 to task" → remove and convert
|
||||
- "5.1 standalone" → convert to standalone
|
||||
|
||||
## Execution Options
|
||||
|
||||
### 1. Delete Subtask
|
||||
```bash
|
||||
task-master remove-subtask --id=<parentId.subtaskId>
|
||||
```
|
||||
|
||||
### 2. Convert to Standalone
|
||||
```bash
|
||||
task-master remove-subtask --id=<parentId.subtaskId> --convert
|
||||
```
|
||||
|
||||
## Pre-Removal Checks
|
||||
|
||||
1. **Validate Subtask**
|
||||
- Verify subtask exists
|
||||
- Check completion status
|
||||
- Review dependencies
|
||||
|
||||
2. **Impact Analysis**
|
||||
- Other subtasks that depend on it
|
||||
- Parent task implications
|
||||
- Data that will be lost
|
||||
|
||||
## Removal Process
|
||||
|
||||
### For Deletion:
|
||||
1. Confirm if subtask has work done
|
||||
2. Update parent task estimates
|
||||
3. Remove subtask and its data
|
||||
4. Clean up dependencies
|
||||
|
||||
### For Conversion:
|
||||
1. Assign new standalone task ID
|
||||
2. Preserve all task data
|
||||
3. Update dependency references
|
||||
4. Maintain task history
|
||||
|
||||
## Smart Features
|
||||
|
||||
- Warn if subtask is in-progress
|
||||
- Show impact on parent task
|
||||
- Preserve important data
|
||||
- Update related estimates
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/remove-subtask 5.1
|
||||
→ Warning: Subtask #5.1 is in-progress
|
||||
→ This will delete all subtask data
|
||||
→ Parent task #5 will be updated
|
||||
Confirm deletion? (y/n)
|
||||
|
||||
/project:tm/remove-subtask 5.1 convert
|
||||
→ Converting subtask #5.1 to standalone task #89
|
||||
→ Preserved: All task data and history
|
||||
→ Updated: 2 dependency references
|
||||
→ New task #89 is now independent
|
||||
```
|
||||
|
||||
## Post-Removal
|
||||
|
||||
- Update parent task status
|
||||
- Recalculate estimates
|
||||
- Show updated hierarchy
|
||||
- Suggest next actions
|
||||
107
assets/claude/commands/tm/remove-task/remove-task.md
Normal file
107
assets/claude/commands/tm/remove-task/remove-task.md
Normal file
@@ -0,0 +1,107 @@
|
||||
Remove a task permanently from the project.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
Delete a task and handle all its relationships properly.
|
||||
|
||||
## Task Removal
|
||||
|
||||
Permanently removes a task while maintaining project integrity.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "remove task 5"
|
||||
- "delete 5"
|
||||
- "5" → remove task 5
|
||||
- Can include "-y" for auto-confirm
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master remove-task --id=<id> [-y]
|
||||
```
|
||||
|
||||
## Pre-Removal Analysis
|
||||
|
||||
1. **Task Details**
|
||||
- Current status
|
||||
- Work completed
|
||||
- Time invested
|
||||
- Associated data
|
||||
|
||||
2. **Relationship Check**
|
||||
- Tasks that depend on this
|
||||
- Dependencies this task has
|
||||
- Subtasks that will be removed
|
||||
- Blocking implications
|
||||
|
||||
3. **Impact Assessment**
|
||||
```
|
||||
Task Removal Impact
|
||||
━━━━━━━━━━━━━━━━━━
|
||||
Task: #5 "Implement authentication" (in-progress)
|
||||
Status: 60% complete (~8 hours work)
|
||||
|
||||
Will affect:
|
||||
- 3 tasks depend on this (will be blocked)
|
||||
- Has 4 subtasks (will be deleted)
|
||||
- Part of critical path
|
||||
|
||||
⚠️ This action cannot be undone
|
||||
```
|
||||
|
||||
## Smart Warnings
|
||||
|
||||
- Warn if task is in-progress
|
||||
- Show dependent tasks that will be blocked
|
||||
- Highlight if part of critical path
|
||||
- Note any completed work being lost
|
||||
|
||||
## Removal Process
|
||||
|
||||
1. Show comprehensive impact
|
||||
2. Require confirmation (unless -y)
|
||||
3. Update dependent task references
|
||||
4. Remove task and subtasks
|
||||
5. Clean up orphaned dependencies
|
||||
6. Log removal with timestamp
|
||||
|
||||
## Alternative Actions
|
||||
|
||||
Suggest before deletion:
|
||||
- Mark as cancelled instead
|
||||
- Convert to documentation
|
||||
- Archive task data
|
||||
- Transfer work to another task
|
||||
|
||||
## Post-Removal
|
||||
|
||||
- List affected tasks
|
||||
- Show broken dependencies
|
||||
- Update project statistics
|
||||
- Suggest dependency fixes
|
||||
- Recalculate timeline
|
||||
|
||||
## Example Flows
|
||||
|
||||
```
|
||||
/project:tm/remove-task 5
|
||||
→ Task #5 is in-progress with 8 hours logged
|
||||
→ 3 other tasks depend on this
|
||||
→ Suggestion: Mark as cancelled instead?
|
||||
Remove anyway? (y/n)
|
||||
|
||||
/project:tm/remove-task 5 -y
|
||||
→ Removed: Task #5 and 4 subtasks
|
||||
→ Updated: 3 task dependencies
|
||||
→ Warning: Tasks #7, #8, #9 now have missing dependency
|
||||
→ Run /project:tm/fix-dependencies to resolve
|
||||
```
|
||||
|
||||
## Safety Features
|
||||
|
||||
- Confirmation required
|
||||
- Impact preview
|
||||
- Removal logging
|
||||
- Suggest alternatives
|
||||
- No cascade delete of dependents
|
||||
55
assets/claude/commands/tm/set-status/to-cancelled.md
Normal file
55
assets/claude/commands/tm/set-status/to-cancelled.md
Normal file
@@ -0,0 +1,55 @@
|
||||
Cancel a task permanently.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Cancelling a Task
|
||||
|
||||
This status indicates a task is no longer needed and won't be completed.
|
||||
|
||||
## Valid Reasons for Cancellation
|
||||
|
||||
- Requirements changed
|
||||
- Feature deprecated
|
||||
- Duplicate of another task
|
||||
- Strategic pivot
|
||||
- Technical approach invalidated
|
||||
|
||||
## Pre-Cancellation Checks
|
||||
|
||||
1. Confirm no critical dependencies
|
||||
2. Check for partial implementation
|
||||
3. Verify cancellation rationale
|
||||
4. Document lessons learned
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=cancelled
|
||||
```
|
||||
|
||||
## Cancellation Impact
|
||||
|
||||
When cancelling:
|
||||
1. **Dependency Updates**
|
||||
- Notify dependent tasks
|
||||
- Update project scope
|
||||
- Recalculate timelines
|
||||
|
||||
2. **Clean-up Actions**
|
||||
- Remove related branches
|
||||
- Archive any work done
|
||||
- Update documentation
|
||||
- Close related issues
|
||||
|
||||
3. **Learning Capture**
|
||||
- Document why cancelled
|
||||
- Note what was learned
|
||||
- Update estimation models
|
||||
- Prevent future duplicates
|
||||
|
||||
## Historical Preservation
|
||||
|
||||
- Keep for reference
|
||||
- Tag with cancellation reason
|
||||
- Link to replacement if any
|
||||
- Maintain audit trail
|
||||
47
assets/claude/commands/tm/set-status/to-deferred.md
Normal file
47
assets/claude/commands/tm/set-status/to-deferred.md
Normal file
@@ -0,0 +1,47 @@
|
||||
Defer a task for later consideration.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Deferring a Task
|
||||
|
||||
This status indicates a task is valid but not currently actionable or prioritized.
|
||||
|
||||
## Valid Reasons for Deferral
|
||||
|
||||
- Waiting for external dependencies
|
||||
- Reprioritized for future sprint
|
||||
- Blocked by technical limitations
|
||||
- Resource constraints
|
||||
- Strategic timing considerations
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=deferred
|
||||
```
|
||||
|
||||
## Deferral Management
|
||||
|
||||
When deferring:
|
||||
1. **Document Reason**
|
||||
- Capture why it's being deferred
|
||||
- Set reactivation criteria
|
||||
- Note any partial work completed
|
||||
|
||||
2. **Impact Analysis**
|
||||
- Check dependent tasks
|
||||
- Update project timeline
|
||||
- Notify affected stakeholders
|
||||
|
||||
3. **Future Planning**
|
||||
- Set review reminders
|
||||
- Tag for specific milestone
|
||||
- Preserve context for reactivation
|
||||
- Link to blocking issues
|
||||
|
||||
## Smart Tracking
|
||||
|
||||
- Monitor deferral duration
|
||||
- Alert when criteria met
|
||||
- Prevent scope creep
|
||||
- Regular review cycles
|
||||
44
assets/claude/commands/tm/set-status/to-done.md
Normal file
44
assets/claude/commands/tm/set-status/to-done.md
Normal file
@@ -0,0 +1,44 @@
|
||||
Mark a task as completed.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Completing a Task
|
||||
|
||||
This command validates task completion and updates project state intelligently.
|
||||
|
||||
## Pre-Completion Checks
|
||||
|
||||
1. Verify test strategy was followed
|
||||
2. Check if all subtasks are complete
|
||||
3. Validate acceptance criteria met
|
||||
4. Ensure code is committed
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=done
|
||||
```
|
||||
|
||||
## Post-Completion Actions
|
||||
|
||||
1. **Update Dependencies**
|
||||
- Identify newly unblocked tasks
|
||||
- Update sprint progress
|
||||
- Recalculate project timeline
|
||||
|
||||
2. **Documentation**
|
||||
- Generate completion summary
|
||||
- Update CLAUDE.md with learnings
|
||||
- Log implementation approach
|
||||
|
||||
3. **Next Steps**
|
||||
- Show newly available tasks
|
||||
- Suggest logical next task
|
||||
- Update velocity metrics
|
||||
|
||||
## Celebration & Learning
|
||||
|
||||
- Show impact of completion
|
||||
- Display unblocked work
|
||||
- Recognize achievement
|
||||
- Capture lessons learned
|
||||
36
assets/claude/commands/tm/set-status/to-in-progress.md
Normal file
36
assets/claude/commands/tm/set-status/to-in-progress.md
Normal file
@@ -0,0 +1,36 @@
|
||||
Start working on a task by setting its status to in-progress.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Starting Work on Task
|
||||
|
||||
This command does more than just change status - it prepares your environment for productive work.
|
||||
|
||||
## Pre-Start Checks
|
||||
|
||||
1. Verify dependencies are met
|
||||
2. Check if another task is already in-progress
|
||||
3. Ensure task details are complete
|
||||
4. Validate test strategy exists
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=in-progress
|
||||
```
|
||||
|
||||
## Environment Setup
|
||||
|
||||
After setting to in-progress:
|
||||
1. Create/checkout appropriate git branch
|
||||
2. Open relevant documentation
|
||||
3. Set up test watchers if applicable
|
||||
4. Display task details and acceptance criteria
|
||||
5. Show similar completed tasks for reference
|
||||
|
||||
## Smart Suggestions
|
||||
|
||||
- Estimated completion time based on complexity
|
||||
- Related files from similar tasks
|
||||
- Potential blockers to watch for
|
||||
- Recommended first steps
|
||||
32
assets/claude/commands/tm/set-status/to-pending.md
Normal file
32
assets/claude/commands/tm/set-status/to-pending.md
Normal file
@@ -0,0 +1,32 @@
|
||||
Set a task's status to pending.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Setting Task to Pending
|
||||
|
||||
This moves a task back to the pending state, useful for:
|
||||
- Resetting erroneously started tasks
|
||||
- Deferring work that was prematurely begun
|
||||
- Reorganizing sprint priorities
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=pending
|
||||
```
|
||||
|
||||
## Validation
|
||||
|
||||
Before setting to pending:
|
||||
- Warn if task is currently in-progress
|
||||
- Check if this will block other tasks
|
||||
- Suggest documenting why it's being reset
|
||||
- Preserve any work already done
|
||||
|
||||
## Smart Actions
|
||||
|
||||
After setting to pending:
|
||||
- Update sprint planning if needed
|
||||
- Notify about freed resources
|
||||
- Suggest priority reassessment
|
||||
- Log the status change with context
|
||||
40
assets/claude/commands/tm/set-status/to-review.md
Normal file
40
assets/claude/commands/tm/set-status/to-review.md
Normal file
@@ -0,0 +1,40 @@
|
||||
Set a task's status to review.
|
||||
|
||||
Arguments: $ARGUMENTS (task ID)
|
||||
|
||||
## Marking Task for Review
|
||||
|
||||
This status indicates work is complete but needs verification before final approval.
|
||||
|
||||
## When to Use Review Status
|
||||
|
||||
- Code complete but needs peer review
|
||||
- Implementation done but needs testing
|
||||
- Documentation written but needs proofreading
|
||||
- Design complete but needs stakeholder approval
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master set-status --id=$ARGUMENTS --status=review
|
||||
```
|
||||
|
||||
## Review Preparation
|
||||
|
||||
When setting to review:
|
||||
1. **Generate Review Checklist**
|
||||
- Link to PR/MR if applicable
|
||||
- Highlight key changes
|
||||
- Note areas needing attention
|
||||
- Include test results
|
||||
|
||||
2. **Documentation**
|
||||
- Update task with review notes
|
||||
- Link relevant artifacts
|
||||
- Specify reviewers if known
|
||||
|
||||
3. **Smart Actions**
|
||||
- Create review reminders
|
||||
- Track review duration
|
||||
- Suggest reviewers based on expertise
|
||||
- Prepare rollback plan if needed
|
||||
117
assets/claude/commands/tm/setup/install-taskmaster.md
Normal file
117
assets/claude/commands/tm/setup/install-taskmaster.md
Normal file
@@ -0,0 +1,117 @@
|
||||
Check if Task Master is installed and install it if needed.
|
||||
|
||||
This command helps you get Task Master set up globally on your system.
|
||||
|
||||
## Detection and Installation Process
|
||||
|
||||
1. **Check Current Installation**
|
||||
```bash
|
||||
# Check if task-master command exists
|
||||
which task-master || echo "Task Master not found"
|
||||
|
||||
# Check npm global packages
|
||||
npm list -g task-master-ai
|
||||
```
|
||||
|
||||
2. **System Requirements Check**
|
||||
```bash
|
||||
# Verify Node.js is installed
|
||||
node --version
|
||||
|
||||
# Verify npm is installed
|
||||
npm --version
|
||||
|
||||
# Check Node version (need 16+)
|
||||
```
|
||||
|
||||
3. **Install Task Master Globally**
|
||||
If not installed, run:
|
||||
```bash
|
||||
npm install -g task-master-ai
|
||||
```
|
||||
|
||||
4. **Verify Installation**
|
||||
```bash
|
||||
# Check version
|
||||
task-master --version
|
||||
|
||||
# Verify command is available
|
||||
which task-master
|
||||
```
|
||||
|
||||
5. **Initial Setup**
|
||||
```bash
|
||||
# Initialize in current directory
|
||||
task-master init
|
||||
```
|
||||
|
||||
6. **Configure AI Provider**
|
||||
Ensure you have at least one AI provider API key set:
|
||||
```bash
|
||||
# Check current configuration
|
||||
task-master models --status
|
||||
|
||||
# If no API keys found, guide setup
|
||||
echo "You'll need at least one API key:"
|
||||
echo "- ANTHROPIC_API_KEY for Claude"
|
||||
echo "- OPENAI_API_KEY for GPT models"
|
||||
echo "- PERPLEXITY_API_KEY for research"
|
||||
echo ""
|
||||
echo "Set them in your shell profile or .env file"
|
||||
```
|
||||
|
||||
7. **Quick Test**
|
||||
```bash
|
||||
# Create a test PRD
|
||||
echo "Build a simple hello world API" > test-prd.txt
|
||||
|
||||
# Try parsing it
|
||||
task-master parse-prd test-prd.txt -n 3
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If installation fails:
|
||||
|
||||
**Permission Errors:**
|
||||
```bash
|
||||
# Try with sudo (macOS/Linux)
|
||||
sudo npm install -g task-master-ai
|
||||
|
||||
# Or fix npm permissions
|
||||
npm config set prefix ~/.npm-global
|
||||
export PATH=~/.npm-global/bin:$PATH
|
||||
```
|
||||
|
||||
**Network Issues:**
|
||||
```bash
|
||||
# Use different registry
|
||||
npm install -g task-master-ai --registry https://registry.npmjs.org/
|
||||
```
|
||||
|
||||
**Node Version Issues:**
|
||||
```bash
|
||||
# Install Node 18+ via nvm
|
||||
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||
nvm install 18
|
||||
nvm use 18
|
||||
```
|
||||
|
||||
## Success Confirmation
|
||||
|
||||
Once installed, you should see:
|
||||
```
|
||||
✅ Task Master v0.16.2 (or higher) installed
|
||||
✅ Command 'task-master' available globally
|
||||
✅ AI provider configured
|
||||
✅ Ready to use slash commands!
|
||||
|
||||
Try: /project:task-master:init your-prd.md
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
After installation:
|
||||
1. Run `/project:utils:check-health` to verify setup
|
||||
2. Configure AI providers with `/project:task-master:models`
|
||||
3. Start using Task Master commands!
|
||||
22
assets/claude/commands/tm/setup/quick-install-taskmaster.md
Normal file
22
assets/claude/commands/tm/setup/quick-install-taskmaster.md
Normal file
@@ -0,0 +1,22 @@
|
||||
Quick install Task Master globally if not already installed.
|
||||
|
||||
Execute this streamlined installation:
|
||||
|
||||
```bash
|
||||
# Check and install in one command
|
||||
task-master --version 2>/dev/null || npm install -g task-master-ai
|
||||
|
||||
# Verify installation
|
||||
task-master --version
|
||||
|
||||
# Quick setup check
|
||||
task-master models --status || echo "Note: You'll need to set up an AI provider API key"
|
||||
```
|
||||
|
||||
If you see "command not found" after installation, you may need to:
|
||||
1. Restart your terminal
|
||||
2. Or add npm global bin to PATH: `export PATH=$(npm bin -g):$PATH`
|
||||
|
||||
Once installed, you can use all the Task Master commands!
|
||||
|
||||
Quick test: Run `/project:help` to see all available commands.
|
||||
82
assets/claude/commands/tm/show/show-task.md
Normal file
82
assets/claude/commands/tm/show/show-task.md
Normal file
@@ -0,0 +1,82 @@
|
||||
Show detailed task information with rich context and insights.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Enhanced Task Display
|
||||
|
||||
Parse arguments to determine what to show and how.
|
||||
|
||||
### 1. **Smart Task Selection**
|
||||
|
||||
Based on $ARGUMENTS:
|
||||
- Number → Show specific task with full context
|
||||
- "current" → Show active in-progress task(s)
|
||||
- "next" → Show recommended next task
|
||||
- "blocked" → Show all blocked tasks with reasons
|
||||
- "critical" → Show critical path tasks
|
||||
- Multiple IDs → Comparative view
|
||||
|
||||
### 2. **Contextual Information**
|
||||
|
||||
For each task, intelligently include:
|
||||
|
||||
**Core Details**
|
||||
- Full task information (id, title, description, details)
|
||||
- Current status with history
|
||||
- Test strategy and acceptance criteria
|
||||
- Priority and complexity analysis
|
||||
|
||||
**Relationships**
|
||||
- Dependencies (what it needs)
|
||||
- Dependents (what needs it)
|
||||
- Parent/subtask hierarchy
|
||||
- Related tasks (similar work)
|
||||
|
||||
**Time Intelligence**
|
||||
- Created/updated timestamps
|
||||
- Time in current status
|
||||
- Estimated vs actual time
|
||||
- Historical completion patterns
|
||||
|
||||
### 3. **Visual Enhancements**
|
||||
|
||||
```
|
||||
📋 Task #45: Implement User Authentication
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
Status: 🟡 in-progress (2 hours)
|
||||
Priority: 🔴 High | Complexity: 73/100
|
||||
|
||||
Dependencies: ✅ #41, ✅ #42, ⏳ #43 (blocked)
|
||||
Blocks: #46, #47, #52
|
||||
|
||||
Progress: ████████░░ 80% complete
|
||||
|
||||
Recent Activity:
|
||||
- 2h ago: Status changed to in-progress
|
||||
- 4h ago: Dependency #42 completed
|
||||
- Yesterday: Task expanded with 3 subtasks
|
||||
```
|
||||
|
||||
### 4. **Intelligent Insights**
|
||||
|
||||
Based on task analysis:
|
||||
- **Risk Assessment**: Complexity vs time remaining
|
||||
- **Bottleneck Analysis**: Is this blocking critical work?
|
||||
- **Recommendation**: Suggested approach or concerns
|
||||
- **Similar Tasks**: How others completed similar work
|
||||
|
||||
### 5. **Action Suggestions**
|
||||
|
||||
Context-aware next steps:
|
||||
- If blocked → Show how to unblock
|
||||
- If complex → Suggest expansion
|
||||
- If in-progress → Show completion checklist
|
||||
- If done → Show dependent tasks ready to start
|
||||
|
||||
### 6. **Multi-Task View**
|
||||
|
||||
When showing multiple tasks:
|
||||
- Common dependencies
|
||||
- Optimal completion order
|
||||
- Parallel work opportunities
|
||||
- Combined complexity analysis
|
||||
64
assets/claude/commands/tm/status/project-status.md
Normal file
64
assets/claude/commands/tm/status/project-status.md
Normal file
@@ -0,0 +1,64 @@
|
||||
Enhanced status command with comprehensive project insights.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Status Overview
|
||||
|
||||
### 1. **Executive Summary**
|
||||
Quick dashboard view:
|
||||
- 🏃 Active work (in-progress tasks)
|
||||
- 📊 Progress metrics (% complete, velocity)
|
||||
- 🚧 Blockers and risks
|
||||
- ⏱️ Time analysis (estimated vs actual)
|
||||
- 🎯 Sprint/milestone progress
|
||||
|
||||
### 2. **Contextual Analysis**
|
||||
|
||||
Based on $ARGUMENTS, focus on:
|
||||
- "sprint" → Current sprint progress and burndown
|
||||
- "blocked" → Dependency chains and resolution paths
|
||||
- "team" → Task distribution and workload
|
||||
- "timeline" → Schedule adherence and projections
|
||||
- "risk" → High complexity or overdue items
|
||||
|
||||
### 3. **Smart Insights**
|
||||
|
||||
**Workflow Health:**
|
||||
- Idle tasks (in-progress > 24h without updates)
|
||||
- Bottlenecks (multiple tasks waiting on same dependency)
|
||||
- Quick wins (low complexity, high impact)
|
||||
|
||||
**Predictive Analytics:**
|
||||
- Completion projections based on velocity
|
||||
- Risk of missing deadlines
|
||||
- Recommended task order for optimal flow
|
||||
|
||||
### 4. **Visual Intelligence**
|
||||
|
||||
Dynamic visualization based on data:
|
||||
```
|
||||
Sprint Progress: ████████░░ 80% (16/20 tasks)
|
||||
Velocity Trend: ↗️ +15% this week
|
||||
Blocked Tasks: 🔴 3 critical path items
|
||||
|
||||
Priority Distribution:
|
||||
High: ████████ 8 tasks (2 blocked)
|
||||
Medium: ████░░░░ 4 tasks
|
||||
Low: ██░░░░░░ 2 tasks
|
||||
```
|
||||
|
||||
### 5. **Actionable Recommendations**
|
||||
|
||||
Based on analysis:
|
||||
1. **Immediate actions** (unblock critical path)
|
||||
2. **Today's focus** (optimal task sequence)
|
||||
3. **Process improvements** (recurring patterns)
|
||||
4. **Resource needs** (skills, time, dependencies)
|
||||
|
||||
### 6. **Historical Context**
|
||||
|
||||
Compare to previous periods:
|
||||
- Velocity changes
|
||||
- Pattern recognition
|
||||
- Improvement areas
|
||||
- Success patterns to repeat
|
||||
117
assets/claude/commands/tm/sync-readme/sync-readme.md
Normal file
117
assets/claude/commands/tm/sync-readme/sync-readme.md
Normal file
@@ -0,0 +1,117 @@
|
||||
Export tasks to README.md with professional formatting.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Generate a well-formatted README with current task information.
|
||||
|
||||
## README Synchronization
|
||||
|
||||
Creates or updates README.md with beautifully formatted task information.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Optional filters:
|
||||
- "pending" → Only pending tasks
|
||||
- "with-subtasks" → Include subtask details
|
||||
- "by-priority" → Group by priority
|
||||
- "sprint" → Current sprint only
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master sync-readme [--with-subtasks] [--status=<status>]
|
||||
```
|
||||
|
||||
## README Generation
|
||||
|
||||
### 1. **Project Header**
|
||||
```markdown
|
||||
# Project Name
|
||||
|
||||
## 📋 Task Progress
|
||||
|
||||
Last Updated: 2024-01-15 10:30 AM
|
||||
|
||||
### Summary
|
||||
- Total Tasks: 45
|
||||
- Completed: 15 (33%)
|
||||
- In Progress: 5 (11%)
|
||||
- Pending: 25 (56%)
|
||||
```
|
||||
|
||||
### 2. **Task Sections**
|
||||
Organized by status or priority:
|
||||
- Progress indicators
|
||||
- Task descriptions
|
||||
- Dependencies noted
|
||||
- Time estimates
|
||||
|
||||
### 3. **Visual Elements**
|
||||
- Progress bars
|
||||
- Status badges
|
||||
- Priority indicators
|
||||
- Completion checkmarks
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Intelligent Grouping**
|
||||
- By feature area
|
||||
- By sprint/milestone
|
||||
- By assigned developer
|
||||
- By priority
|
||||
|
||||
2. **Progress Tracking**
|
||||
- Overall completion
|
||||
- Sprint velocity
|
||||
- Burndown indication
|
||||
- Time tracking
|
||||
|
||||
3. **Formatting Options**
|
||||
- GitHub-flavored markdown
|
||||
- Task checkboxes
|
||||
- Collapsible sections
|
||||
- Table format available
|
||||
|
||||
## Example Output
|
||||
|
||||
```markdown
|
||||
## 🚀 Current Sprint
|
||||
|
||||
### In Progress
|
||||
- [ ] 🔄 #5 **Implement user authentication** (60% complete)
|
||||
- Dependencies: API design (#3 ✅)
|
||||
- Subtasks: 4 (2 completed)
|
||||
- Est: 8h / Spent: 5h
|
||||
|
||||
### Pending (High Priority)
|
||||
- [ ] ⚡ #8 **Create dashboard UI**
|
||||
- Blocked by: #5
|
||||
- Complexity: High
|
||||
- Est: 12h
|
||||
```
|
||||
|
||||
## Customization
|
||||
|
||||
Based on arguments:
|
||||
- Include/exclude sections
|
||||
- Detail level control
|
||||
- Custom grouping
|
||||
- Filter by criteria
|
||||
|
||||
## Post-Sync
|
||||
|
||||
After generation:
|
||||
1. Show diff preview
|
||||
2. Backup existing README
|
||||
3. Write new content
|
||||
4. Commit reminder
|
||||
5. Update timestamp
|
||||
|
||||
## Integration
|
||||
|
||||
Works well with:
|
||||
- Git workflows
|
||||
- CI/CD pipelines
|
||||
- Project documentation
|
||||
- Team updates
|
||||
- Client reports
|
||||
146
assets/claude/commands/tm/tm-main.md
Normal file
146
assets/claude/commands/tm/tm-main.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Task Master Command Reference
|
||||
|
||||
Comprehensive command structure for Task Master integration with Claude Code.
|
||||
|
||||
## Command Organization
|
||||
|
||||
Commands are organized hierarchically to match Task Master's CLI structure while providing enhanced Claude Code integration.
|
||||
|
||||
## Project Setup & Configuration
|
||||
|
||||
### `/project:tm/init`
|
||||
- `init-project` - Initialize new project (handles PRD files intelligently)
|
||||
- `init-project-quick` - Quick setup with auto-confirmation (-y flag)
|
||||
|
||||
### `/project:tm/models`
|
||||
- `view-models` - View current AI model configuration
|
||||
- `setup-models` - Interactive model configuration
|
||||
- `set-main` - Set primary generation model
|
||||
- `set-research` - Set research model
|
||||
- `set-fallback` - Set fallback model
|
||||
|
||||
## Task Generation
|
||||
|
||||
### `/project:tm/parse-prd`
|
||||
- `parse-prd` - Generate tasks from PRD document
|
||||
- `parse-prd-with-research` - Enhanced parsing with research mode
|
||||
|
||||
### `/project:tm/generate`
|
||||
- `generate-tasks` - Create individual task files from tasks.json
|
||||
|
||||
## Task Management
|
||||
|
||||
### `/project:tm/list`
|
||||
- `list-tasks` - Smart listing with natural language filters
|
||||
- `list-tasks-with-subtasks` - Include subtasks in hierarchical view
|
||||
- `list-tasks-by-status` - Filter by specific status
|
||||
|
||||
### `/project:tm/set-status`
|
||||
- `to-pending` - Reset task to pending
|
||||
- `to-in-progress` - Start working on task
|
||||
- `to-done` - Mark task complete
|
||||
- `to-review` - Submit for review
|
||||
- `to-deferred` - Defer task
|
||||
- `to-cancelled` - Cancel task
|
||||
|
||||
### `/project:tm/sync-readme`
|
||||
- `sync-readme` - Export tasks to README.md with formatting
|
||||
|
||||
### `/project:tm/update`
|
||||
- `update-task` - Update tasks with natural language
|
||||
- `update-tasks-from-id` - Update multiple tasks from a starting point
|
||||
- `update-single-task` - Update specific task
|
||||
|
||||
### `/project:tm/add-task`
|
||||
- `add-task` - Add new task with AI assistance
|
||||
|
||||
### `/project:tm/remove-task`
|
||||
- `remove-task` - Remove task with confirmation
|
||||
|
||||
## Subtask Management
|
||||
|
||||
### `/project:tm/add-subtask`
|
||||
- `add-subtask` - Add new subtask to parent
|
||||
- `convert-task-to-subtask` - Convert existing task to subtask
|
||||
|
||||
### `/project:tm/remove-subtask`
|
||||
- `remove-subtask` - Remove subtask (with optional conversion)
|
||||
|
||||
### `/project:tm/clear-subtasks`
|
||||
- `clear-subtasks` - Clear subtasks from specific task
|
||||
- `clear-all-subtasks` - Clear all subtasks globally
|
||||
|
||||
## Task Analysis & Breakdown
|
||||
|
||||
### `/project:tm/analyze-complexity`
|
||||
- `analyze-complexity` - Analyze and generate expansion recommendations
|
||||
|
||||
### `/project:tm/complexity-report`
|
||||
- `complexity-report` - Display complexity analysis report
|
||||
|
||||
### `/project:tm/expand`
|
||||
- `expand-task` - Break down specific task
|
||||
- `expand-all-tasks` - Expand all eligible tasks
|
||||
- `with-research` - Enhanced expansion
|
||||
|
||||
## Task Navigation
|
||||
|
||||
### `/project:tm/next`
|
||||
- `next-task` - Intelligent next task recommendation
|
||||
|
||||
### `/project:tm/show`
|
||||
- `show-task` - Display detailed task information
|
||||
|
||||
### `/project:tm/status`
|
||||
- `project-status` - Comprehensive project dashboard
|
||||
|
||||
## Dependency Management
|
||||
|
||||
### `/project:tm/add-dependency`
|
||||
- `add-dependency` - Add task dependency
|
||||
|
||||
### `/project:tm/remove-dependency`
|
||||
- `remove-dependency` - Remove task dependency
|
||||
|
||||
### `/project:tm/validate-dependencies`
|
||||
- `validate-dependencies` - Check for dependency issues
|
||||
|
||||
### `/project:tm/fix-dependencies`
|
||||
- `fix-dependencies` - Automatically fix dependency problems
|
||||
|
||||
## Workflows & Automation
|
||||
|
||||
### `/project:tm/workflows`
|
||||
- `smart-workflow` - Context-aware intelligent workflow execution
|
||||
- `command-pipeline` - Chain multiple commands together
|
||||
- `auto-implement-tasks` - Advanced auto-implementation with code generation
|
||||
|
||||
## Utilities
|
||||
|
||||
### `/project:tm/utils`
|
||||
- `analyze-project` - Deep project analysis and insights
|
||||
|
||||
### `/project:tm/setup`
|
||||
- `install-taskmaster` - Comprehensive installation guide
|
||||
- `quick-install-taskmaster` - One-line global installation
|
||||
|
||||
## Usage Patterns
|
||||
|
||||
### Natural Language
|
||||
Most commands accept natural language arguments:
|
||||
```
|
||||
/project:tm/add-task create user authentication system
|
||||
/project:tm/update mark all API tasks as high priority
|
||||
/project:tm/list show blocked tasks
|
||||
```
|
||||
|
||||
### ID-Based Commands
|
||||
Commands requiring IDs intelligently parse from $ARGUMENTS:
|
||||
```
|
||||
/project:tm/show 45
|
||||
/project:tm/expand 23
|
||||
/project:tm/set-status/to-done 67
|
||||
```
|
||||
|
||||
### Smart Defaults
|
||||
Commands provide intelligent defaults and suggestions based on context.
|
||||
119
assets/claude/commands/tm/update/update-single-task.md
Normal file
119
assets/claude/commands/tm/update/update-single-task.md
Normal file
@@ -0,0 +1,119 @@
|
||||
Update a single specific task with new information.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse task ID and update details.
|
||||
|
||||
## Single Task Update
|
||||
|
||||
Precisely update one task with AI assistance to maintain consistency.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
Natural language updates:
|
||||
- "5: add caching requirement"
|
||||
- "update 5 to include error handling"
|
||||
- "task 5 needs rate limiting"
|
||||
- "5 change priority to high"
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master update-task --id=<id> --prompt="<context>"
|
||||
```
|
||||
|
||||
## Update Types
|
||||
|
||||
### 1. **Content Updates**
|
||||
- Enhance description
|
||||
- Add requirements
|
||||
- Clarify details
|
||||
- Update acceptance criteria
|
||||
|
||||
### 2. **Metadata Updates**
|
||||
- Change priority
|
||||
- Adjust time estimates
|
||||
- Update complexity
|
||||
- Modify dependencies
|
||||
|
||||
### 3. **Strategic Updates**
|
||||
- Revise approach
|
||||
- Change test strategy
|
||||
- Update implementation notes
|
||||
- Adjust subtask needs
|
||||
|
||||
## AI-Powered Updates
|
||||
|
||||
The AI:
|
||||
1. **Understands Context**
|
||||
- Reads current task state
|
||||
- Identifies update intent
|
||||
- Maintains consistency
|
||||
- Preserves important info
|
||||
|
||||
2. **Applies Changes**
|
||||
- Updates relevant fields
|
||||
- Keeps style consistent
|
||||
- Adds without removing
|
||||
- Enhances clarity
|
||||
|
||||
3. **Validates Results**
|
||||
- Checks coherence
|
||||
- Verifies completeness
|
||||
- Maintains relationships
|
||||
- Suggests related updates
|
||||
|
||||
## Example Updates
|
||||
|
||||
```
|
||||
/project:tm/update/single 5: add rate limiting
|
||||
→ Updating Task #5: "Implement API endpoints"
|
||||
|
||||
Current: Basic CRUD endpoints
|
||||
Adding: Rate limiting requirements
|
||||
|
||||
Updated sections:
|
||||
✓ Description: Added rate limiting mention
|
||||
✓ Details: Added specific limits (100/min)
|
||||
✓ Test Strategy: Added rate limit tests
|
||||
✓ Complexity: Increased from 5 to 6
|
||||
✓ Time Estimate: Increased by 2 hours
|
||||
|
||||
Suggestion: Also update task #6 (API Gateway) for consistency?
|
||||
```
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Incremental Updates**
|
||||
- Adds without overwriting
|
||||
- Preserves work history
|
||||
- Tracks what changed
|
||||
- Shows diff view
|
||||
|
||||
2. **Consistency Checks**
|
||||
- Related task alignment
|
||||
- Subtask compatibility
|
||||
- Dependency validity
|
||||
- Timeline impact
|
||||
|
||||
3. **Update History**
|
||||
- Timestamp changes
|
||||
- Track who/what updated
|
||||
- Reason for update
|
||||
- Previous versions
|
||||
|
||||
## Field-Specific Updates
|
||||
|
||||
Quick syntax for specific fields:
|
||||
- "5 priority:high" → Update priority only
|
||||
- "5 add-time:4h" → Add to time estimate
|
||||
- "5 status:review" → Change status
|
||||
- "5 depends:3,4" → Add dependencies
|
||||
|
||||
## Post-Update
|
||||
|
||||
- Show updated task
|
||||
- Highlight changes
|
||||
- Check related tasks
|
||||
- Update suggestions
|
||||
- Timeline adjustments
|
||||
72
assets/claude/commands/tm/update/update-task.md
Normal file
72
assets/claude/commands/tm/update/update-task.md
Normal file
@@ -0,0 +1,72 @@
|
||||
Update tasks with intelligent field detection and bulk operations.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Task Updates
|
||||
|
||||
Parse arguments to determine update intent and execute smartly.
|
||||
|
||||
### 1. **Natural Language Processing**
|
||||
|
||||
Understand update requests like:
|
||||
- "mark 23 as done" → Update status to done
|
||||
- "increase priority of 45" → Set priority to high
|
||||
- "add dependency on 12 to task 34" → Add dependency
|
||||
- "tasks 20-25 need review" → Bulk status update
|
||||
- "all API tasks high priority" → Pattern-based update
|
||||
|
||||
### 2. **Smart Field Detection**
|
||||
|
||||
Automatically detect what to update:
|
||||
- Status keywords: done, complete, start, pause, review
|
||||
- Priority changes: urgent, high, low, deprioritize
|
||||
- Dependency updates: depends on, blocks, after
|
||||
- Assignment: assign to, owner, responsible
|
||||
- Time: estimate, spent, deadline
|
||||
|
||||
### 3. **Bulk Operations**
|
||||
|
||||
Support for multiple task updates:
|
||||
```
|
||||
Examples:
|
||||
- "complete tasks 12, 15, 18"
|
||||
- "all pending auth tasks to in-progress"
|
||||
- "increase priority for tasks blocking 45"
|
||||
- "defer all documentation tasks"
|
||||
```
|
||||
|
||||
### 4. **Contextual Validation**
|
||||
|
||||
Before updating, check:
|
||||
- Status transitions are valid
|
||||
- Dependencies don't create cycles
|
||||
- Priority changes make sense
|
||||
- Bulk updates won't break project flow
|
||||
|
||||
Show preview:
|
||||
```
|
||||
Update Preview:
|
||||
─────────────────
|
||||
Tasks to update: #23, #24, #25
|
||||
Change: status → in-progress
|
||||
Impact: Will unblock tasks #30, #31
|
||||
Warning: Task #24 has unmet dependencies
|
||||
```
|
||||
|
||||
### 5. **Smart Suggestions**
|
||||
|
||||
Based on update:
|
||||
- Completing task? → Show newly unblocked tasks
|
||||
- Changing priority? → Show impact on sprint
|
||||
- Adding dependency? → Check for conflicts
|
||||
- Bulk update? → Show summary of changes
|
||||
|
||||
### 6. **Workflow Integration**
|
||||
|
||||
After updates:
|
||||
- Auto-update dependent task states
|
||||
- Trigger status recalculation
|
||||
- Update sprint/milestone progress
|
||||
- Log changes with context
|
||||
|
||||
Result: Flexible, intelligent task updates with safety checks.
|
||||
108
assets/claude/commands/tm/update/update-tasks-from-id.md
Normal file
108
assets/claude/commands/tm/update/update-tasks-from-id.md
Normal file
@@ -0,0 +1,108 @@
|
||||
Update multiple tasks starting from a specific ID.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
Parse starting task ID and update context.
|
||||
|
||||
## Bulk Task Updates
|
||||
|
||||
Update multiple related tasks based on new requirements or context changes.
|
||||
|
||||
## Argument Parsing
|
||||
|
||||
- "from 5: add security requirements"
|
||||
- "5 onwards: update API endpoints"
|
||||
- "starting at 5: change to use new framework"
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master update --from=<id> --prompt="<context>"
|
||||
```
|
||||
|
||||
## Update Process
|
||||
|
||||
### 1. **Task Selection**
|
||||
Starting from specified ID:
|
||||
- Include the task itself
|
||||
- Include all dependent tasks
|
||||
- Include related subtasks
|
||||
- Smart boundary detection
|
||||
|
||||
### 2. **Context Application**
|
||||
AI analyzes the update context and:
|
||||
- Identifies what needs changing
|
||||
- Maintains consistency
|
||||
- Preserves completed work
|
||||
- Updates related information
|
||||
|
||||
### 3. **Intelligent Updates**
|
||||
- Modify descriptions appropriately
|
||||
- Update test strategies
|
||||
- Adjust time estimates
|
||||
- Revise dependencies if needed
|
||||
|
||||
## Smart Features
|
||||
|
||||
1. **Scope Detection**
|
||||
- Find natural task groupings
|
||||
- Identify related features
|
||||
- Stop at logical boundaries
|
||||
- Avoid over-updating
|
||||
|
||||
2. **Consistency Maintenance**
|
||||
- Keep naming conventions
|
||||
- Preserve relationships
|
||||
- Update cross-references
|
||||
- Maintain task flow
|
||||
|
||||
3. **Change Preview**
|
||||
```
|
||||
Bulk Update Preview
|
||||
━━━━━━━━━━━━━━━━━━
|
||||
Starting from: Task #5
|
||||
Tasks to update: 8 tasks + 12 subtasks
|
||||
|
||||
Context: "add security requirements"
|
||||
|
||||
Changes will include:
|
||||
- Add security sections to descriptions
|
||||
- Update test strategies for security
|
||||
- Add security-related subtasks where needed
|
||||
- Adjust time estimates (+20% average)
|
||||
|
||||
Continue? (y/n)
|
||||
```
|
||||
|
||||
## Example Updates
|
||||
|
||||
```
|
||||
/project:tm/update/from-id 5: change database to PostgreSQL
|
||||
→ Analyzing impact starting from task #5
|
||||
→ Found 6 related tasks to update
|
||||
→ Updates will maintain consistency
|
||||
→ Preview changes? (y/n)
|
||||
|
||||
Applied updates:
|
||||
✓ Task #5: Updated connection logic references
|
||||
✓ Task #6: Changed migration approach
|
||||
✓ Task #7: Updated query syntax notes
|
||||
✓ Task #8: Revised testing strategy
|
||||
✓ Task #9: Updated deployment steps
|
||||
✓ Task #12: Changed backup procedures
|
||||
```
|
||||
|
||||
## Safety Features
|
||||
|
||||
- Preview all changes
|
||||
- Selective confirmation
|
||||
- Rollback capability
|
||||
- Change logging
|
||||
- Validation checks
|
||||
|
||||
## Post-Update
|
||||
|
||||
- Summary of changes
|
||||
- Consistency verification
|
||||
- Suggest review tasks
|
||||
- Update timeline if needed
|
||||
97
assets/claude/commands/tm/utils/analyze-project.md
Normal file
97
assets/claude/commands/tm/utils/analyze-project.md
Normal file
@@ -0,0 +1,97 @@
|
||||
Advanced project analysis with actionable insights and recommendations.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Comprehensive Project Analysis
|
||||
|
||||
Multi-dimensional analysis based on requested focus area.
|
||||
|
||||
### 1. **Analysis Modes**
|
||||
|
||||
Based on $ARGUMENTS:
|
||||
- "velocity" → Sprint velocity and trends
|
||||
- "quality" → Code quality metrics
|
||||
- "risk" → Risk assessment and mitigation
|
||||
- "dependencies" → Dependency graph analysis
|
||||
- "team" → Workload and skill distribution
|
||||
- "architecture" → System design coherence
|
||||
- Default → Full spectrum analysis
|
||||
|
||||
### 2. **Velocity Analytics**
|
||||
|
||||
```
|
||||
📊 Velocity Analysis
|
||||
━━━━━━━━━━━━━━━━━━━
|
||||
Current Sprint: 24 points/week ↗️ +20%
|
||||
Rolling Average: 20 points/week
|
||||
Efficiency: 85% (17/20 tasks on time)
|
||||
|
||||
Bottlenecks Detected:
|
||||
- Code review delays (avg 4h wait)
|
||||
- Test environment availability
|
||||
- Dependency on external team
|
||||
|
||||
Recommendations:
|
||||
1. Implement parallel review process
|
||||
2. Add staging environment
|
||||
3. Mock external dependencies
|
||||
```
|
||||
|
||||
### 3. **Risk Assessment**
|
||||
|
||||
**Technical Risks**
|
||||
- High complexity tasks without backup assignee
|
||||
- Single points of failure in architecture
|
||||
- Insufficient test coverage in critical paths
|
||||
- Technical debt accumulation rate
|
||||
|
||||
**Project Risks**
|
||||
- Critical path dependencies
|
||||
- Resource availability gaps
|
||||
- Deadline feasibility analysis
|
||||
- Scope creep indicators
|
||||
|
||||
### 4. **Dependency Intelligence**
|
||||
|
||||
Visual dependency analysis:
|
||||
```
|
||||
Critical Path:
|
||||
#12 → #15 → #23 → #45 → #50 (20 days)
|
||||
↘ #24 → #46 ↗
|
||||
|
||||
Optimization: Parallelize #15 and #24
|
||||
Time Saved: 3 days
|
||||
```
|
||||
|
||||
### 5. **Quality Metrics**
|
||||
|
||||
**Code Quality**
|
||||
- Test coverage trends
|
||||
- Complexity scores
|
||||
- Technical debt ratio
|
||||
- Review feedback patterns
|
||||
|
||||
**Process Quality**
|
||||
- Rework frequency
|
||||
- Bug introduction rate
|
||||
- Time to resolution
|
||||
- Knowledge distribution
|
||||
|
||||
### 6. **Predictive Insights**
|
||||
|
||||
Based on patterns:
|
||||
- Completion probability by deadline
|
||||
- Resource needs projection
|
||||
- Risk materialization likelihood
|
||||
- Suggested interventions
|
||||
|
||||
### 7. **Executive Dashboard**
|
||||
|
||||
High-level summary with:
|
||||
- Health score (0-100)
|
||||
- Top 3 risks
|
||||
- Top 3 opportunities
|
||||
- Recommended actions
|
||||
- Success probability
|
||||
|
||||
Result: Data-driven decisions with clear action paths.
|
||||
@@ -0,0 +1,71 @@
|
||||
Validate all task dependencies for issues.
|
||||
|
||||
## Dependency Validation
|
||||
|
||||
Comprehensive check for dependency problems across the entire project.
|
||||
|
||||
## Execution
|
||||
|
||||
```bash
|
||||
task-master validate-dependencies
|
||||
```
|
||||
|
||||
## Validation Checks
|
||||
|
||||
1. **Circular Dependencies**
|
||||
- A depends on B, B depends on A
|
||||
- Complex circular chains
|
||||
- Self-dependencies
|
||||
|
||||
2. **Missing Dependencies**
|
||||
- References to non-existent tasks
|
||||
- Deleted task references
|
||||
- Invalid task IDs
|
||||
|
||||
3. **Logical Issues**
|
||||
- Completed tasks depending on pending
|
||||
- Cancelled tasks in dependency chains
|
||||
- Impossible sequences
|
||||
|
||||
4. **Complexity Warnings**
|
||||
- Over-complex dependency chains
|
||||
- Too many dependencies per task
|
||||
- Bottleneck tasks
|
||||
|
||||
## Smart Analysis
|
||||
|
||||
The validation provides:
|
||||
- Visual dependency graph
|
||||
- Critical path analysis
|
||||
- Bottleneck identification
|
||||
- Suggested optimizations
|
||||
|
||||
## Report Format
|
||||
|
||||
```
|
||||
Dependency Validation Report
|
||||
━━━━━━━━━━━━━━━━━━━━━━━━━━
|
||||
✅ No circular dependencies found
|
||||
⚠️ 2 warnings found:
|
||||
- Task #23 has 7 dependencies (consider breaking down)
|
||||
- Task #45 blocks 5 other tasks (potential bottleneck)
|
||||
❌ 1 error found:
|
||||
- Task #67 depends on deleted task #66
|
||||
|
||||
Critical Path: #1 → #5 → #23 → #45 → #50 (15 days)
|
||||
```
|
||||
|
||||
## Actionable Output
|
||||
|
||||
For each issue found:
|
||||
- Clear description
|
||||
- Impact assessment
|
||||
- Suggested fix
|
||||
- Command to resolve
|
||||
|
||||
## Next Steps
|
||||
|
||||
After validation:
|
||||
- Run `/project:tm/fix-dependencies` to auto-fix
|
||||
- Manually adjust problematic dependencies
|
||||
- Rerun to verify fixes
|
||||
97
assets/claude/commands/tm/workflows/auto-implement-tasks.md
Normal file
97
assets/claude/commands/tm/workflows/auto-implement-tasks.md
Normal file
@@ -0,0 +1,97 @@
|
||||
Enhanced auto-implementation with intelligent code generation and testing.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Auto-Implementation
|
||||
|
||||
Advanced implementation with context awareness and quality checks.
|
||||
|
||||
### 1. **Pre-Implementation Analysis**
|
||||
|
||||
Before starting:
|
||||
- Analyze task complexity and requirements
|
||||
- Check codebase patterns and conventions
|
||||
- Identify similar completed tasks
|
||||
- Assess test coverage needs
|
||||
- Detect potential risks
|
||||
|
||||
### 2. **Smart Implementation Strategy**
|
||||
|
||||
Based on task type and context:
|
||||
|
||||
**Feature Tasks**
|
||||
1. Research existing patterns
|
||||
2. Design component architecture
|
||||
3. Implement with tests
|
||||
4. Integrate with system
|
||||
5. Update documentation
|
||||
|
||||
**Bug Fix Tasks**
|
||||
1. Reproduce issue
|
||||
2. Identify root cause
|
||||
3. Implement minimal fix
|
||||
4. Add regression tests
|
||||
5. Verify side effects
|
||||
|
||||
**Refactoring Tasks**
|
||||
1. Analyze current structure
|
||||
2. Plan incremental changes
|
||||
3. Maintain test coverage
|
||||
4. Refactor step-by-step
|
||||
5. Verify behavior unchanged
|
||||
|
||||
### 3. **Code Intelligence**
|
||||
|
||||
**Pattern Recognition**
|
||||
- Learn from existing code
|
||||
- Follow team conventions
|
||||
- Use preferred libraries
|
||||
- Match style guidelines
|
||||
|
||||
**Test-Driven Approach**
|
||||
- Write tests first when possible
|
||||
- Ensure comprehensive coverage
|
||||
- Include edge cases
|
||||
- Performance considerations
|
||||
|
||||
### 4. **Progressive Implementation**
|
||||
|
||||
Step-by-step with validation:
|
||||
```
|
||||
Step 1/5: Setting up component structure ✓
|
||||
Step 2/5: Implementing core logic ✓
|
||||
Step 3/5: Adding error handling ⚡ (in progress)
|
||||
Step 4/5: Writing tests ⏳
|
||||
Step 5/5: Integration testing ⏳
|
||||
|
||||
Current: Adding try-catch blocks and validation...
|
||||
```
|
||||
|
||||
### 5. **Quality Assurance**
|
||||
|
||||
Automated checks:
|
||||
- Linting and formatting
|
||||
- Test execution
|
||||
- Type checking
|
||||
- Dependency validation
|
||||
- Performance analysis
|
||||
|
||||
### 6. **Smart Recovery**
|
||||
|
||||
If issues arise:
|
||||
- Diagnostic analysis
|
||||
- Suggestion generation
|
||||
- Fallback strategies
|
||||
- Manual intervention points
|
||||
- Learning from failures
|
||||
|
||||
### 7. **Post-Implementation**
|
||||
|
||||
After completion:
|
||||
- Generate PR description
|
||||
- Update documentation
|
||||
- Log lessons learned
|
||||
- Suggest follow-up tasks
|
||||
- Update task relationships
|
||||
|
||||
Result: High-quality, production-ready implementations.
|
||||
77
assets/claude/commands/tm/workflows/command-pipeline.md
Normal file
77
assets/claude/commands/tm/workflows/command-pipeline.md
Normal file
@@ -0,0 +1,77 @@
|
||||
Execute a pipeline of commands based on a specification.
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Command Pipeline Execution
|
||||
|
||||
Parse pipeline specification from arguments. Supported formats:
|
||||
|
||||
### Simple Pipeline
|
||||
`init → expand-all → sprint-plan`
|
||||
|
||||
### Conditional Pipeline
|
||||
`status → if:pending>10 → sprint-plan → else → next`
|
||||
|
||||
### Iterative Pipeline
|
||||
`for:pending-tasks → expand → complexity-check`
|
||||
|
||||
### Smart Pipeline Patterns
|
||||
|
||||
**1. Project Setup Pipeline**
|
||||
```
|
||||
init [prd] →
|
||||
expand-all →
|
||||
complexity-report →
|
||||
sprint-plan →
|
||||
show first-sprint
|
||||
```
|
||||
|
||||
**2. Daily Work Pipeline**
|
||||
```
|
||||
standup →
|
||||
if:in-progress → continue →
|
||||
else → next → start
|
||||
```
|
||||
|
||||
**3. Task Completion Pipeline**
|
||||
```
|
||||
complete [id] →
|
||||
git-commit →
|
||||
if:blocked-tasks-freed → show-freed →
|
||||
next
|
||||
```
|
||||
|
||||
**4. Quality Check Pipeline**
|
||||
```
|
||||
list in-progress →
|
||||
for:each → check-idle-time →
|
||||
if:idle>1day → prompt-update
|
||||
```
|
||||
|
||||
### Pipeline Features
|
||||
|
||||
**Variables**
|
||||
- Store results: `status → $count=pending-count`
|
||||
- Use in conditions: `if:$count>10`
|
||||
- Pass between commands: `expand $high-priority-tasks`
|
||||
|
||||
**Error Handling**
|
||||
- On failure: `try:complete → catch:show-blockers`
|
||||
- Skip on error: `optional:test-run`
|
||||
- Retry logic: `retry:3:commit`
|
||||
|
||||
**Parallel Execution**
|
||||
- Parallel branches: `[analyze | test | lint]`
|
||||
- Join results: `parallel → join:report`
|
||||
|
||||
### Execution Flow
|
||||
|
||||
1. Parse pipeline specification
|
||||
2. Validate command sequence
|
||||
3. Execute with state passing
|
||||
4. Handle conditions and loops
|
||||
5. Aggregate results
|
||||
6. Show summary
|
||||
|
||||
This enables complex workflows like:
|
||||
`parse-prd → expand-all → filter:complex>70 → assign:senior → sprint-plan:weighted`
|
||||
55
assets/claude/commands/tm/workflows/smart-workflow.md
Normal file
55
assets/claude/commands/tm/workflows/smart-workflow.md
Normal file
@@ -0,0 +1,55 @@
|
||||
Execute an intelligent workflow based on current project state and recent commands.
|
||||
|
||||
This command analyzes:
|
||||
1. Recent commands you've run
|
||||
2. Current project state
|
||||
3. Time of day / day of week
|
||||
4. Your working patterns
|
||||
|
||||
Arguments: $ARGUMENTS
|
||||
|
||||
## Intelligent Workflow Selection
|
||||
|
||||
Based on context, I'll determine the best workflow:
|
||||
|
||||
### Context Analysis
|
||||
- Previous command executed
|
||||
- Current task states
|
||||
- Unfinished work from last session
|
||||
- Your typical patterns
|
||||
|
||||
### Smart Execution
|
||||
|
||||
If last command was:
|
||||
- `status` → Likely starting work → Run daily standup
|
||||
- `complete` → Task finished → Find next task
|
||||
- `list pending` → Planning → Suggest sprint planning
|
||||
- `expand` → Breaking down work → Show complexity analysis
|
||||
- `init` → New project → Show onboarding workflow
|
||||
|
||||
If no recent commands:
|
||||
- Morning? → Daily standup workflow
|
||||
- Many pending tasks? → Sprint planning
|
||||
- Tasks blocked? → Dependency resolution
|
||||
- Friday? → Weekly review
|
||||
|
||||
### Workflow Composition
|
||||
|
||||
I'll chain appropriate commands:
|
||||
1. Analyze current state
|
||||
2. Execute primary workflow
|
||||
3. Suggest follow-up actions
|
||||
4. Prepare environment for coding
|
||||
|
||||
### Learning Mode
|
||||
|
||||
This command learns from your patterns:
|
||||
- Track command sequences
|
||||
- Note time preferences
|
||||
- Remember common workflows
|
||||
- Adapt to your style
|
||||
|
||||
Example flows detected:
|
||||
- Morning: standup → next → start
|
||||
- After lunch: status → continue task
|
||||
- End of day: complete → commit → status
|
||||
@@ -11,10 +11,11 @@ Welcome to the Task Master documentation. Use the links below to navigate to the
|
||||
|
||||
- [Command Reference](command-reference.md) - Complete list of all available commands (including research and multi-task viewing)
|
||||
- [Task Structure](task-structure.md) - Understanding the task format and features
|
||||
- [Available Models](models.md) - Complete list of supported AI models and providers
|
||||
|
||||
## Examples & Licensing
|
||||
|
||||
- [Example Interactions](examples.md) - Common Cursor AI interaction examples
|
||||
- [Example Interactions](examples.md) - Common Cursor AI interaction examples
|
||||
- [Licensing Information](licensing.md) - Detailed information about the license
|
||||
|
||||
## Need More Help?
|
||||
|
||||
@@ -4,7 +4,30 @@ Taskmaster uses two primary methods for configuration:
|
||||
|
||||
1. **`.taskmaster/config.json` File (Recommended - New Structure)**
|
||||
|
||||
- This JSON file stores most configuration settings, including AI model selections, parameters, logging levels, and project defaults.
|
||||
- This JSON file stores most configuration settings, including A5. **Usage Requirements**:
|
||||
8. **Troubleshooting**:
|
||||
- "MCP provider requires session context" → Ensure running in MCP environment
|
||||
- See the [MCP Provider Guide](./mcp-provider-guide.md) for detailed troubleshootingust be running in an MCP context (session must be available)
|
||||
- Session must provide `clientCapabilities.sampling` capability
|
||||
|
||||
6. **Best Practices**:
|
||||
- Always configure a non-MCP fallback provider
|
||||
- Use `mcp` for main/research roles when in MCP environments
|
||||
- Test sampling capability before production use
|
||||
|
||||
7. **Setup Commands**:
|
||||
```bash
|
||||
# Set MCP provider for main role
|
||||
task-master models set-main --provider mcp --model claude-3-5-sonnet-20241022
|
||||
|
||||
# Set MCP provider for research role
|
||||
task-master models set-research --provider mcp --model claude-3-opus-20240229
|
||||
|
||||
# Verify configuration
|
||||
task-master models list
|
||||
```
|
||||
|
||||
8. **Troubleshooting**:lections, parameters, logging levels, and project defaults.
|
||||
- **Location:** This file is created in the `.taskmaster/` directory when you run the `task-master models --setup` interactive setup or initialize a new project with `task-master init`.
|
||||
- **Migration:** Existing projects with `.taskmasterconfig` in the root will continue to work, but should be migrated to the new structure using `task-master migrate`.
|
||||
- **Management:** Use the `task-master models --setup` command (or `models` MCP tool) to interactively create and manage this file. You can also set specific models directly using `task-master models --set-<role>=<model_id>`, adding `--ollama` or `--openrouter` flags for custom models. Manual editing is possible but not recommended unless you understand the structure.
|
||||
@@ -173,6 +196,57 @@ node scripts/init.js
|
||||
|
||||
## Provider-Specific Configuration
|
||||
|
||||
### MCP (Model Context Protocol) Provider
|
||||
|
||||
The MCP provider enables Task Master to use MCP servers as AI providers. This is particularly useful when running Task Master within MCP-compatible development environments like Claude Desktop or Cursor.
|
||||
|
||||
1. **Prerequisites**:
|
||||
- An active MCP session with sampling capability
|
||||
- MCP client with sampling support (e.g. VS Code)
|
||||
- No API keys required (uses session-based authentication)
|
||||
|
||||
2. **Configuration**:
|
||||
```json
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "mcp",
|
||||
"modelId": "mcp-sampling"
|
||||
},
|
||||
"research": {
|
||||
"provider": "mcp",
|
||||
"modelId": "mcp-sampling"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
3. **Available Model IDs**:
|
||||
- `mcp-sampling` - General text generation using MCP client sampling (supports all roles)
|
||||
- `claude-3-5-sonnet-20241022` - High-performance model for general tasks (supports all roles)
|
||||
- `claude-3-opus-20240229` - Enhanced reasoning model for complex tasks (supports all roles)
|
||||
|
||||
4. **Features**:
|
||||
- ✅ **Text Generation**: Standard AI text generation via MCP sampling
|
||||
- ✅ **Object Generation**: Full schema-driven structured output generation
|
||||
- ✅ **PRD Parsing**: Parse Product Requirements Documents into structured tasks
|
||||
- ✅ **Task Creation**: AI-powered task creation with validation
|
||||
- ✅ **Session Management**: Automatic session detection and context handling
|
||||
- ✅ **Error Recovery**: Robust error handling and fallback mechanisms
|
||||
|
||||
5. **Usage Requirements**:
|
||||
- Must be running in an MCP context (session must be available)
|
||||
- Session must provide `clientCapabilities.sampling` capability
|
||||
|
||||
5. **Best Practices**:
|
||||
- Always configure a non-MCP fallback provider
|
||||
- Use `mcp` for main/research roles when in MCP environments
|
||||
- Test sampling capability before production use
|
||||
|
||||
6. **Troubleshooting**:
|
||||
- "MCP provider requires session context" → Ensure running in MCP environment
|
||||
- See the [MCP Provider Guide](./mcp-provider-guide.md) for detailed troubleshooting
|
||||
|
||||
### Google Vertex AI Configuration
|
||||
|
||||
Google Vertex AI is Google Cloud's enterprise AI platform and requires specific configuration:
|
||||
|
||||
564
docs/mcp-provider-guide.md
Normal file
564
docs/mcp-provider-guide.md
Normal file
@@ -0,0 +1,564 @@
|
||||
# MCP Provider Integration Guide
|
||||
|
||||
## Overview
|
||||
|
||||
Task Master provides a **unified MCP provider** for AI operations:
|
||||
|
||||
**MCP Provider** (`mcp`) - Modern AI SDK-compatible provider with full structured object generation support
|
||||
|
||||
The MCP provider enables Task Master to act as an MCP client, using MCP servers as AI providers alongside traditional API-based providers. This integration follows the existing provider pattern and supports all standard AI operations including structured object generation for PRD parsing and task creation.
|
||||
|
||||
## MCP Provider Features
|
||||
|
||||
The **MCP Provider** (`mcp`) provides:
|
||||
|
||||
✅ **Full AI SDK Compatibility** - Complete LanguageModelV1 interface implementation
|
||||
✅ **Structured Object Generation** - Schema-driven outputs for PRD parsing and task creation
|
||||
✅ **Enhanced Error Handling** - Robust JSON extraction and validation
|
||||
✅ **Session Management** - Automatic session detection and context handling
|
||||
✅ **Schema Validation** - Type-safe object generation with Zod validation
|
||||
|
||||
### Quick Setup
|
||||
|
||||
```bash
|
||||
# Set MCP provider for main role
|
||||
task-master models set-main --provider mcp --model claude-3-5-sonnet-20241022
|
||||
```
|
||||
|
||||
For detailed information, see [MCP Provider Documentation](mcp-provider.md).
|
||||
|
||||
## What is MCP Provider?
|
||||
|
||||
The MCP provider allows Task Master to:
|
||||
- Connect to MCP servers/tools as AI providers
|
||||
- Use session-based authentication instead of API keys
|
||||
- Map AI operations to MCP tool calls
|
||||
- Integrate with existing role-based provider assignment
|
||||
- Maintain compatibility with fallback chains
|
||||
- Support structured object generation for schema-driven features
|
||||
|
||||
## Configuration
|
||||
|
||||
### MCP Provider Setup
|
||||
|
||||
Add MCP provider to your `.taskmaster/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "mcp",
|
||||
"modelId": "claude-3-5-sonnet-20241022",
|
||||
"maxTokens": 50000,
|
||||
"temperature": 0.2
|
||||
},
|
||||
"research": {
|
||||
"provider": "mcp",
|
||||
"modelId": "claude-3-5-sonnet-20241022",
|
||||
"maxTokens": 8700,
|
||||
"temperature": 0.1
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-5-sonnet-20241022"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Available Models
|
||||
|
||||
**MCP Provider Models:**
|
||||
|
||||
- **`claude-3-5-sonnet-20241022`** - High-performance model for general tasks
|
||||
- **SWE Score**: 0.49
|
||||
- **Features**: Text + Object generation
|
||||
|
||||
- **`claude-3-opus-20240229`** - Enhanced reasoning model for complex tasks
|
||||
- **SWE Score**: 0.725
|
||||
- **Features**: Text + Object generation
|
||||
|
||||
- **`mcp-sampling`** - General text generation using MCP client sampling
|
||||
- **SWE Score**: null
|
||||
- **Roles**: Supports main, research, and fallback roles
|
||||
- **SWE Score**: 0.49
|
||||
- **Cost**: $0 (session-based)
|
||||
- **Max Tokens**: 200,000
|
||||
- **Supported Roles**: main, research, fallback
|
||||
- **Features**: Text + Object generation
|
||||
|
||||
- **`claude-3-opus-20240229`** - Enhanced reasoning model for complex tasks
|
||||
- **SWE Score**: 0.725
|
||||
- **Cost**: $0 (session-based)
|
||||
- **Max Tokens**: 200,000
|
||||
- **Supported Roles**: main, research, fallback
|
||||
- **Features**: Text + Object generation
|
||||
|
||||
**Basic MCP Provider Models:**
|
||||
|
||||
- **`mcp-sampling`** - General text generation using MCP client sampling
|
||||
- **`mcp-sampling`** - General text generation using MCP client sampling
|
||||
- **SWE Score**: null
|
||||
- **Roles**: Supports main, research, and fallback roles
|
||||
|
||||
### Model ID Format
|
||||
|
||||
MCP model IDs use a simple format:
|
||||
|
||||
- **`claude-3-5-sonnet-20241022`** - Uses Claude 3.5 Sonnet via MCP sampling
|
||||
- **`claude-3-opus-20240229`** - Uses Claude 3 Opus via MCP sampling
|
||||
- **`mcp-sampling`** - Uses MCP client's sampling capability for text generation
|
||||
|
||||
## Session Requirements
|
||||
|
||||
The MCP provider requires an active MCP session with sampling capabilities:
|
||||
|
||||
```javascript
|
||||
session: {
|
||||
clientCapabilities: {
|
||||
sampling: {} // Client supports sampling requests
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Text Generation
|
||||
|
||||
```javascript
|
||||
import { generateTextService } from './scripts/modules/ai-services-unified.js';
|
||||
|
||||
const result = await generateTextService({
|
||||
role: 'main',
|
||||
session: mcpSession, // Required for MCP provider
|
||||
prompt: 'Explain MCP integration',
|
||||
systemPrompt: 'You are a helpful AI assistant'
|
||||
});
|
||||
|
||||
console.log(result.text);
|
||||
```
|
||||
|
||||
### Structured Object Generation
|
||||
|
||||
```javascript
|
||||
import { generateObjectService } from './scripts/modules/ai-services-unified.js';
|
||||
|
||||
const result = await generateObjectService({
|
||||
role: 'main',
|
||||
session: mcpSession,
|
||||
prompt: 'Create a task breakdown',
|
||||
schema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
tasks: {
|
||||
type: 'array',
|
||||
items: { type: 'string' }
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
console.log(result.object);
|
||||
```
|
||||
|
||||
### Research Operations
|
||||
|
||||
```javascript
|
||||
const research = await generateTextService({
|
||||
role: 'research',
|
||||
session: mcpSession,
|
||||
prompt: 'Research the latest developments in AI',
|
||||
systemPrompt: 'You are a research assistant'
|
||||
});
|
||||
```
|
||||
|
||||
## CLI Integration
|
||||
|
||||
The MCP provider works seamlessly with Task Master CLI commands when running in an MCP context:
|
||||
|
||||
```bash
|
||||
# Generate tasks using MCP provider (if configured as main)
|
||||
task-master add-task "Implement user authentication"
|
||||
|
||||
# Research using MCP provider (if configured as research)
|
||||
task-master research "OAuth 2.0 best practices"
|
||||
|
||||
# Parse PRD using MCP provider
|
||||
task-master parse-prd requirements.txt
|
||||
```
|
||||
|
||||
## Architecture Details
|
||||
|
||||
### Provider Architecture
|
||||
**MCPProvider** (`mcp-server/src/providers/mcp-provider.js`)
|
||||
- Modern AI SDK-compliant provider for Task Master's MCP server
|
||||
- Auto-registers when MCP sessions connect to Task Master
|
||||
- Enables Task Master to use MCP sessions for AI operations
|
||||
- Supports both text generation and structured object generation
|
||||
|
||||
### Auto-Registration Process
|
||||
|
||||
When running as an MCP server, Task Master automatically:
|
||||
|
||||
```javascript
|
||||
// On MCP session connect
|
||||
server.on("connect", (event) => {
|
||||
// Check session capabilities
|
||||
if (session.clientCapabilities?.sampling) {
|
||||
// Create and register MCP provider
|
||||
const mcpProvider = new MCPProvider();
|
||||
mcpProvider.setSession(session);
|
||||
|
||||
// Auto-register with provider registry
|
||||
providerRegistry.registerProvider('mcp', mcpProvider);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
This enables seamless self-referential AI operations within MCP contexts.
|
||||
|
||||
### Provider Pattern Integration
|
||||
|
||||
The MCP provider follows the same pattern as other providers:
|
||||
|
||||
```javascript
|
||||
class MCPProvider extends BaseAIProvider {
|
||||
// Implements generateText, generateObject
|
||||
// Uses session context instead of API keys
|
||||
// Maps operations to MCP sampling requests
|
||||
}
|
||||
```
|
||||
|
||||
### Session Detection
|
||||
|
||||
The provider automatically detects MCP sampling capability when sessions connect:
|
||||
|
||||
```javascript
|
||||
// On MCP session connect
|
||||
if (session.clientCapabilities?.sampling) {
|
||||
// Auto-register MCP provider for use
|
||||
const mcpProvider = new MCPProvider();
|
||||
mcpProvider.setSession(session);
|
||||
}
|
||||
```
|
||||
|
||||
### Sampling Integration
|
||||
|
||||
AI operations use MCP sampling with different levels of support:
|
||||
|
||||
- `generateText()` → MCP `requestSampling()` with messages (2-minute timeout) ✅ **Full Support**
|
||||
- `streamText()` → **Limited/No Support** ⚠️ See streaming limitations below
|
||||
- `generateObject()` → MCP `requestSampling()` with JSON schema instructions (2-minute timeout) ✅ **Full Support**
|
||||
|
||||
**Timeout Configuration**: All MCP sampling requests use a 2-minute (120,000ms) timeout to accommodate complex AI operations.
|
||||
|
||||
#### Streaming Text Limitations ⚠️
|
||||
|
||||
**Important**: The MCP provider has **no support** for text streaming:
|
||||
|
||||
**MCPProvider**:
|
||||
- **❌ No Streaming Support**: Throws error "MCP Provider does not support streaming text, use generateText instead"
|
||||
- **Solution**: Always use `generateText()` instead of `streamText()` with this provider
|
||||
|
||||
**Recommendation**: For streaming functionality, configure a non-MCP fallback provider (like Anthropic or OpenAI) in your fallback role.
|
||||
|
||||
### Error Handling
|
||||
|
||||
The MCP provider includes comprehensive error handling:
|
||||
|
||||
- Session validation errors (checks for `clientCapabilities.sampling`)
|
||||
- MCP sampling request failures
|
||||
- JSON parsing errors (for structured output)
|
||||
- Automatic fallback to other providers
|
||||
|
||||
### Best Practices
|
||||
|
||||
### 1. Configure Fallbacks
|
||||
|
||||
Always configure a non-MCP fallback provider, especially for streaming operations:
|
||||
|
||||
```json
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "mcp",
|
||||
"modelId": "mcp-sampling"
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-3-5-sonnet-20241022"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Avoid Streaming with MCP
|
||||
|
||||
**Do not use `streamTextService()` with MCP provider**. Use `generateTextService()` instead:
|
||||
|
||||
```javascript
|
||||
// ❌ Don't do this with MCP provider
|
||||
const result = await streamTextService({
|
||||
role: 'main', // MCP provider
|
||||
session: mcpSession,
|
||||
prompt: 'Generate content'
|
||||
});
|
||||
|
||||
// ✅ Do this instead
|
||||
const result = await generateTextService({
|
||||
role: 'main', // MCP provider
|
||||
session: mcpSession,
|
||||
prompt: 'Generate content'
|
||||
});
|
||||
```
|
||||
|
||||
### 3. Session Management
|
||||
|
||||
Ensure your MCP session remains active throughout Task Master operations:
|
||||
|
||||
```javascript
|
||||
// Check session health before operations
|
||||
if (!session || !session.capabilities) {
|
||||
throw new Error('MCP session not available');
|
||||
}
|
||||
```
|
||||
|
||||
### 4. Tool Availability
|
||||
|
||||
Verify required capabilities are available in your MCP session:
|
||||
|
||||
```javascript
|
||||
// Check session health and capabilities
|
||||
if (session && session.clientCapabilities && session.clientCapabilities.sampling) {
|
||||
console.log('MCP sampling available');
|
||||
} else {
|
||||
console.log('MCP sampling not available');
|
||||
}
|
||||
```
|
||||
|
||||
### 5. Error Recovery
|
||||
|
||||
Handle MCP-specific errors gracefully:
|
||||
|
||||
```javascript
|
||||
try {
|
||||
const result = await generateTextService({
|
||||
role: 'main',
|
||||
session: mcpSession,
|
||||
prompt: 'Generate content'
|
||||
});
|
||||
} catch (error) {
|
||||
if (error.message.includes('MCP')) {
|
||||
// Handle MCP-specific error
|
||||
console.log('MCP error, falling back to alternate provider');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
1. **"MCP provider requires session context"**
|
||||
- Ensure `session` parameter is passed to service calls
|
||||
- Verify session has proper structure
|
||||
- Check that you're running in an MCP environment
|
||||
|
||||
2. **"MCP session must have client sampling capabilities"**
|
||||
- Check that `session.clientCapabilities.sampling` exists
|
||||
- Verify session has `requestSampling()` method
|
||||
- Ensure MCP client supports sampling feature
|
||||
|
||||
3. **"MCP Provider does not support streaming text, use generateText instead"**
|
||||
- **Common Error**: Occurs when calling `streamTextService()` with MCP provider
|
||||
- **Solution**: Use `generateTextService()` instead of `streamTextService()`
|
||||
- **Alternative**: Configure a non-MCP fallback provider for streaming operations
|
||||
|
||||
4. **"MCP sampling failed"** or **Timeout errors**
|
||||
- Check MCP client is responding to sampling requests
|
||||
- Verify session is still active and connected
|
||||
- Consider if request complexity requires longer processing time
|
||||
- Check for network connectivity issues
|
||||
|
||||
5. **"Model ID is required for MCP Remote Provider"**
|
||||
- Ensure `modelId` is specified in configuration
|
||||
- Use `mcp-sampling` as the standard model ID
|
||||
- Verify provider configuration is properly loaded
|
||||
|
||||
6. **Auto-registration failures**
|
||||
- Check that MCP session has required sampling capabilities
|
||||
- Verify server event listeners are properly configured
|
||||
- Look for provider registry initialization issues
|
||||
|
||||
### Streaming-Related Issues
|
||||
|
||||
**Error**: `streamTextService()` calls fail with MCP provider
|
||||
**Cause**: MCP provider has no streaming support
|
||||
**Solutions**:
|
||||
- Use `generateTextService()` for all MCP-based text generation
|
||||
- Configure non-MCP fallback providers for streaming requirements
|
||||
- Check your provider configuration to ensure fallback chain includes streaming-capable providers
|
||||
|
||||
### Debug Mode
|
||||
|
||||
Enable debug logging to see MCP provider operations:
|
||||
|
||||
```javascript
|
||||
// Set debug flag in config or environment
|
||||
process.env.DEBUG = 'true';
|
||||
|
||||
// Or in .taskmasterconfig
|
||||
{
|
||||
"debug": true,
|
||||
"models": { /* ... */ }
|
||||
}
|
||||
```
|
||||
|
||||
### Testing MCP Integration
|
||||
|
||||
Test MCP provider functionality:
|
||||
|
||||
```javascript
|
||||
// Check if MCP provider is properly registered
|
||||
import { MCPProvider } from './mcp-server/src/providers/mcp-provider.js';
|
||||
|
||||
// Test session capabilities
|
||||
if (session && session.clientCapabilities && session.clientCapabilities.sampling) {
|
||||
console.log('MCP sampling available');
|
||||
|
||||
// Test provider creation
|
||||
const provider = new MCPProvider();
|
||||
provider.setSession(session);
|
||||
console.log('MCP provider created successfully');
|
||||
} else {
|
||||
console.log('MCP session lacks required capabilities');
|
||||
}
|
||||
```
|
||||
|
||||
## Integration with Development Tools
|
||||
|
||||
### VS Code with MCP Extension
|
||||
|
||||
When using Task Master in VS Code with MCP support:
|
||||
|
||||
1. Configure Task Master MCP server in your `.vscode/mcp.json`
|
||||
2. Set MCP provider as main/research in `.taskmaster/config.json`
|
||||
3. Benefit from integrated AI assistance within your development workflow
|
||||
4. Use Task Master tools directly from VS Code's MCP interface
|
||||
|
||||
**Example VS Code MCP Configuration:**
|
||||
```json
|
||||
{
|
||||
"servers": {
|
||||
"task-master-dev": {
|
||||
"command": "node",
|
||||
"args": ["mcp-server/server.js"],
|
||||
"cwd": "/path/to/your/task-master-project",
|
||||
"env": {
|
||||
"NODE_ENV": "development",
|
||||
"ANTHROPIC_API_KEY": "${env:ANTHROPIC_API_KEY}",
|
||||
"TASK_MASTER_PROJECT_ROOT": "/path/to/your/project"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Claude Desktop
|
||||
|
||||
When using Task Master through Claude Desktop's MCP integration:
|
||||
|
||||
1. Configure Task Master as MCP provider in Claude Desktop
|
||||
2. Use MCP provider for AI operations within Task Master
|
||||
3. Benefit from nested MCP tool calling capabilities
|
||||
|
||||
### Cursor and Other MCP Clients
|
||||
|
||||
The MCP provider works with any MCP-compatible development environment:
|
||||
|
||||
1. Ensure your IDE has MCP client capabilities
|
||||
2. Configure Task Master MCP server endpoint
|
||||
3. Use MCP provider for enhanced AI-driven development
|
||||
|
||||
## Advanced Configuration
|
||||
|
||||
### Custom Tool Mapping
|
||||
|
||||
Advanced users can use MCP sampling for all roles:
|
||||
|
||||
```javascript
|
||||
// MCP sampling for all roles
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "mcp",
|
||||
"modelId": "mcp-sampling"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Role-Specific Configuration
|
||||
|
||||
Configure MCP sampling for different roles:
|
||||
|
||||
```json
|
||||
{
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "mcp",
|
||||
"modelId": "mcp-sampling"
|
||||
},
|
||||
"research": {
|
||||
"provider": "mcp",
|
||||
"modelId": "mcp-sampling"
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "mcp",
|
||||
"modelId": "backup-server:simple-generation"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### API Reference
|
||||
|
||||
### MCPProvider Methods
|
||||
|
||||
- `generateText(params)` - Generate text using MCP sampling ✅ **Supported**
|
||||
- `streamText(params)` - Stream text ❌ **Not supported** (throws error)
|
||||
- `generateObject(params)` - Generate structured objects ✅ **Supported**
|
||||
- `setSession(session)` - Update provider session
|
||||
- `validateAuth(params)` - Validate session capabilities
|
||||
- `getClient()` - Returns null (not applicable for MCP)
|
||||
|
||||
### Required Parameters
|
||||
|
||||
All MCP operations require:
|
||||
- `session` - Active MCP session object (auto-provided when registered)
|
||||
- `modelId` - MCP model identifier (typically "mcp-sampling")
|
||||
- `messages` - Array of message objects
|
||||
|
||||
### Optional Parameters
|
||||
|
||||
- `temperature` - Creativity control (if supported by MCP client)
|
||||
- `maxTokens` - Maximum response length (if supported)
|
||||
- `schema` - JSON schema for structured output (generateObject only)
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Session Security**: MCP sessions should be properly authenticated
|
||||
2. **Server Validation**: Only connect to trusted MCP servers
|
||||
3. **Data Privacy**: Ensure MCP clients handle data according to your privacy requirements
|
||||
4. **Error Exposure**: Be careful not to expose sensitive session information in error messages
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Planned improvements for MCP provider:
|
||||
|
||||
1. **Native Streaming Support** - True streaming for compatible MCP clients (requires MCP protocol updates)
|
||||
2. **Enhanced Session Monitoring** - Automatic session validation and recovery
|
||||
3. **Performance Optimization** - Caching and connection pooling
|
||||
4. **Advanced Error Recovery** - Intelligent retry and fallback strategies
|
||||
|
||||
**Note**: True streaming support depends on future MCP protocol enhancements. Current implementation provides text generation without streaming capabilities.
|
||||
350
docs/mcp-provider.md
Normal file
350
docs/mcp-provider.md
Normal file
@@ -0,0 +1,350 @@
|
||||
# MCP Provider Implementation
|
||||
|
||||
## Overview
|
||||
|
||||
The MCP Provider creates a modern AI SDK-compliant custom provider that integrates with the existing Task Master MCP server infrastructure. This provider enables AI operations through MCP session sampling while following modern AI SDK patterns and **includes full support for structured object generation (generateObject)** for schema-driven features like PRD parsing and task creation.
|
||||
|
||||
## Architecture
|
||||
|
||||
### Components
|
||||
|
||||
1. **MCPProvider** (`mcp-server/src/providers/mcp-provider.js`)
|
||||
- Main provider class following Claude Code pattern
|
||||
- Session-based provider (no API key required)
|
||||
- Registers with provider registry on MCP server connect
|
||||
|
||||
2. **AI SDK Implementation** (`mcp-server/src/custom-sdk/`)
|
||||
- `index.js` - Provider factory function
|
||||
- `language-model.js` - LanguageModelV1 implementation with **doGenerateObject support**
|
||||
- `message-converter.js` - Format conversion utilities
|
||||
- `json-extractor.js` - **NEW**: Robust JSON extraction from AI responses
|
||||
- `schema-converter.js` - **NEW**: Schema-to-instructions conversion utility
|
||||
- `errors.js` - Error handling and mapping
|
||||
|
||||
3. **Integration Points**
|
||||
- MCP Server registration (`mcp-server/src/index.js`)
|
||||
- AI Services integration (`scripts/modules/ai-services-unified.js`)
|
||||
- Model configuration (`scripts/modules/supported-models.json`)
|
||||
|
||||
### Session Flow
|
||||
|
||||
```
|
||||
MCP Client Connect → MCP Server → registerRemoteProvider()
|
||||
↓
|
||||
MCPRemoteProvider (existing)
|
||||
MCPProvider
|
||||
↓
|
||||
Provider Registry
|
||||
↓
|
||||
AI Services Layer
|
||||
↓
|
||||
Text Generation + Object Generation
|
||||
```
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Provider Registration
|
||||
|
||||
The MCP server registers **both** providers when a client connects:
|
||||
|
||||
```javascript
|
||||
// mcp-server/src/index.js
|
||||
registerRemoteProvider(session) {
|
||||
if (session?.clientCapabilities?.sampling) {
|
||||
// Register existing provider
|
||||
// Register unified MCP provider
|
||||
const mcpProvider = new MCPProvider();
|
||||
mcpProvider.setSession(session);
|
||||
|
||||
const providerRegistry = ProviderRegistry.getInstance();
|
||||
providerRegistry.registerProvider('mcp', mcpProvider);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### AI Services Integration
|
||||
|
||||
The AI services layer includes the new provider:
|
||||
|
||||
```javascript
|
||||
// scripts/modules/ai-services-unified.js
|
||||
const PROVIDERS = {
|
||||
// ... other providers
|
||||
'mcp': () => {
|
||||
const providerRegistry = ProviderRegistry.getInstance();
|
||||
return providerRegistry.getProvider('mcp');
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### Message Conversion
|
||||
|
||||
The provider converts between AI SDK and MCP formats:
|
||||
|
||||
```javascript
|
||||
// AI SDK prompt → MCP sampling format
|
||||
const { messages, systemPrompt } = convertToMCPFormat(options.prompt);
|
||||
|
||||
// MCP response → AI SDK format
|
||||
const result = convertFromMCPFormat(response);
|
||||
```
|
||||
|
||||
## Structured Object Generation (generateObject)
|
||||
|
||||
### Overview
|
||||
|
||||
The MCP Provider includes full support for structured object generation, enabling schema-driven features like PRD parsing, task creation, and any operations requiring validated JSON outputs.
|
||||
|
||||
### Architecture
|
||||
|
||||
The generateObject implementation includes:
|
||||
|
||||
1. **Schema-to-Instructions Conversion** (`schema-converter.js`)
|
||||
- Converts Zod schemas to natural language instructions
|
||||
- Generates example outputs to guide AI responses
|
||||
- Handles complex nested schemas and validation requirements
|
||||
|
||||
2. **JSON Extraction Pipeline** (`json-extractor.js`)
|
||||
- Multiple extraction strategies for robust JSON parsing
|
||||
- Handles code blocks, malformed JSON, and various response formats
|
||||
- Fallback mechanisms for maximum reliability
|
||||
|
||||
3. **Validation System**
|
||||
- Complete schema validation using Zod
|
||||
- Detailed error reporting for failed validations
|
||||
- Type-safe object generation
|
||||
|
||||
### Implementation Details
|
||||
|
||||
#### doGenerateObject Method
|
||||
|
||||
The `MCPLanguageModel` class implements the AI SDK's `doGenerateObject` method:
|
||||
|
||||
```javascript
|
||||
async doGenerateObject({ schema, objectName, prompt, ...options }) {
|
||||
// Convert schema to instructions
|
||||
const instructions = convertSchemaToInstructions(schema, objectName);
|
||||
|
||||
// Enhance prompt with structured output requirements
|
||||
const enhancedPrompt = enhancePromptForObjectGeneration(prompt, instructions);
|
||||
|
||||
// Generate response via MCP sampling
|
||||
const response = await this.doGenerate({ prompt: enhancedPrompt, ...options });
|
||||
|
||||
// Extract and validate JSON
|
||||
const extractedJson = extractJsonFromResponse(response.text);
|
||||
const validatedObject = schema.parse(extractedJson);
|
||||
|
||||
return {
|
||||
object: validatedObject,
|
||||
usage: response.usage,
|
||||
finishReason: response.finishReason
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
#### AI SDK Compatibility
|
||||
|
||||
The provider includes required properties for AI SDK object generation:
|
||||
|
||||
```javascript
|
||||
class MCPLanguageModel {
|
||||
get defaultObjectGenerationMode() {
|
||||
return 'tool';
|
||||
}
|
||||
|
||||
get supportsStructuredOutputs() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// ... doGenerateObject implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Usage Examples
|
||||
|
||||
#### PRD Parsing
|
||||
|
||||
```javascript
|
||||
import { z } from 'zod';
|
||||
|
||||
const taskSchema = z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
priority: z.enum(['high', 'medium', 'low']),
|
||||
dependencies: z.array(z.number()).optional()
|
||||
});
|
||||
|
||||
const result = await generateObject({
|
||||
model: mcpModel,
|
||||
schema: taskSchema,
|
||||
prompt: 'Parse this PRD section into a task: [PRD content]'
|
||||
});
|
||||
|
||||
console.log(result.object); // Validated task object
|
||||
```
|
||||
|
||||
#### Task Creation
|
||||
|
||||
```javascript
|
||||
const taskCreationSchema = z.object({
|
||||
task: z.object({
|
||||
title: z.string(),
|
||||
description: z.string(),
|
||||
details: z.string(),
|
||||
testStrategy: z.string(),
|
||||
priority: z.enum(['high', 'medium', 'low']),
|
||||
dependencies: z.array(z.number()).optional()
|
||||
})
|
||||
});
|
||||
|
||||
const result = await generateObject({
|
||||
model: mcpModel,
|
||||
schema: taskCreationSchema,
|
||||
prompt: 'Create a comprehensive task for implementing user authentication'
|
||||
});
|
||||
```
|
||||
|
||||
### Error Handling
|
||||
|
||||
The implementation provides comprehensive error handling:
|
||||
|
||||
- **Schema Validation Errors**: Detailed Zod validation messages
|
||||
- **JSON Extraction Failures**: Fallback strategies and clear error reporting
|
||||
- **MCP Communication Errors**: Proper error mapping and recovery
|
||||
- **Timeout Handling**: Configurable timeouts for long-running operations
|
||||
|
||||
### Testing
|
||||
|
||||
The generateObject functionality is fully tested:
|
||||
|
||||
```bash
|
||||
# Test object generation
|
||||
npm test -- --grep "generateObject"
|
||||
|
||||
# Test with actual MCP session
|
||||
node test-object-generation.js
|
||||
```
|
||||
|
||||
### Supported Features
|
||||
|
||||
✅ **Schema Conversion**: Zod schemas → Natural language instructions
|
||||
✅ **JSON Extraction**: Multiple strategies for robust parsing
|
||||
✅ **Validation**: Complete schema validation with error reporting
|
||||
✅ **Error Recovery**: Fallback mechanisms for failed extractions
|
||||
✅ **Type Safety**: Full TypeScript support with inferred types
|
||||
✅ **AI SDK Compliance**: Complete LanguageModelV1 interface implementation
|
||||
|
||||
## Usage
|
||||
|
||||
### Configuration
|
||||
|
||||
Add to supported models configuration:
|
||||
|
||||
```json
|
||||
{
|
||||
"mcp": [
|
||||
{
|
||||
"id": "claude-3-5-sonnet-20241022",
|
||||
"swe_score": 0.623,
|
||||
"cost_per_1m_tokens": { "input": 0, "output": 0 },
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 200000
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### CLI Usage
|
||||
|
||||
```bash
|
||||
# Set provider for main role
|
||||
tm models set-main --provider mcp --model claude-3-5-sonnet-20241022
|
||||
|
||||
# Use in task operations
|
||||
tm add-task "Create user authentication system"
|
||||
```
|
||||
|
||||
### Programmatic Usage
|
||||
|
||||
```javascript
|
||||
const provider = registry.getProvider('mcp');
|
||||
if (provider && provider.hasValidSession()) {
|
||||
const client = provider.getClient({ temperature: 0.7 });
|
||||
const model = client({ modelId: 'claude-3-5-sonnet-20241022' });
|
||||
|
||||
const result = await model.doGenerate({
|
||||
prompt: [
|
||||
{ role: 'user', content: 'Hello!' }
|
||||
]
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Component Tests
|
||||
|
||||
```bash
|
||||
# Test individual components
|
||||
node test-mcp-components.js
|
||||
```
|
||||
|
||||
### Integration Testing
|
||||
|
||||
1. Start MCP server
|
||||
2. Connect Claude client
|
||||
3. Verify both providers are registered
|
||||
4. Test AI operations through mcp provider
|
||||
|
||||
### Validation Checklist
|
||||
|
||||
- ✅ Provider creation and initialization
|
||||
- ✅ Registry integration
|
||||
- ✅ Session management
|
||||
- ✅ Message conversion
|
||||
- ✅ Error handling
|
||||
- ✅ AI Services integration
|
||||
- ✅ Model configuration
|
||||
|
||||
## Key Benefits
|
||||
|
||||
1. **AI SDK Compliance** - Full LanguageModelV1 implementation
|
||||
2. **Session Integration** - Leverages existing MCP session infrastructure
|
||||
3. **Registry Pattern** - Uses provider registry for discovery
|
||||
4. **Backward Compatibility** - Coexists with existing MCPRemoteProvider
|
||||
5. **Future Ready** - Supports AI SDK features and patterns
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Provider Not Found
|
||||
|
||||
```
|
||||
Error: Provider "mcp" not found in registry
|
||||
```
|
||||
|
||||
**Solution**: Ensure MCP server is running and client is connected
|
||||
|
||||
### Session Errors
|
||||
|
||||
```
|
||||
Error: MCP Provider requires active MCP session
|
||||
```
|
||||
|
||||
**Solution**: Check MCP client connection and session capabilities
|
||||
|
||||
### Sampling Errors
|
||||
|
||||
```
|
||||
Error: MCP session must have client sampling capabilities
|
||||
```
|
||||
|
||||
**Solution**: Verify MCP client supports sampling operations
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Performance Optimization** - Add caching and connection pooling
|
||||
2. **Enhanced Streaming** - Implement native streaming if MCP supports it
|
||||
3. **Tool Integration** - Add support for function calling through MCP tools
|
||||
4. **Monitoring** - Add metrics and logging for provider usage
|
||||
5. **Documentation** - Update user guides and API documentation
|
||||
169
docs/models.md
169
docs/models.md
@@ -1,24 +1,18 @@
|
||||
# Available Models as of July 2, 2025
|
||||
# Available Models as of July 10, 2025
|
||||
|
||||
## Main Models
|
||||
|
||||
| Provider | Model Name | SWE Score | Input Cost | Output Cost |
|
||||
| ----------- | ---------------------------------------------- | --------- | ---------- | ----------- |
|
||||
| bedrock | us.anthropic.claude-3-haiku-20240307-v1:0 | 0.4 | 0.25 | 1.25 |
|
||||
| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20241022-v2:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-7-sonnet-20250219-v1:0 | 0.623 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-5-haiku-20241022-v1:0 | 0.4 | 0.8 | 4 |
|
||||
| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 |
|
||||
| anthropic | claude-sonnet-4-20250514 | 0.727 | 3 | 15 |
|
||||
| anthropic | claude-opus-4-20250514 | 0.725 | 15 | 75 |
|
||||
| anthropic | claude-3-7-sonnet-20250219 | 0.623 | 3 | 15 |
|
||||
| anthropic | claude-3-5-sonnet-20241022 | 0.49 | 3 | 15 |
|
||||
| azure | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| azure | gpt-4o-mini | 0.3 | 0.15 | 0.6 |
|
||||
| azure | gpt-4-1 | — | 2 | 10 |
|
||||
| claude-code | opus | 0.725 | 0 | 0 |
|
||||
| claude-code | sonnet | 0.727 | 0 | 0 |
|
||||
| mcp | mcp-sampling | — | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 |
|
||||
| openai | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| openai | o1 | 0.489 | 15 | 60 |
|
||||
| openai | o3 | 0.5 | 2 | 8 |
|
||||
@@ -35,18 +29,21 @@
|
||||
| google | gemini-2.5-flash-preview-04-17 | 0.604 | — | — |
|
||||
| google | gemini-2.0-flash | 0.518 | 0.15 | 0.6 |
|
||||
| google | gemini-2.0-flash-lite | — | — | — |
|
||||
| xai | grok-3 | — | 3 | 15 |
|
||||
| xai | grok-3-fast | — | 5 | 25 |
|
||||
| xai | grok-4 | — | 3 | 15 |
|
||||
| groq | llama-3.3-70b-versatile | 0.55 | 0.59 | 0.79 |
|
||||
| groq | llama-3.1-8b-instant | 0.32 | 0.05 | 0.08 |
|
||||
| groq | llama-4-scout | 0.45 | 0.11 | 0.34 |
|
||||
| groq | llama-4-maverick | 0.52 | 0.5 | 0.77 |
|
||||
| groq | mixtral-8x7b-32768 | 0.35 | 0.24 | 0.24 |
|
||||
| groq | qwen-qwq-32b-preview | 0.4 | 0.18 | 0.18 |
|
||||
| groq | deepseek-r1-distill-llama-70b | 0.52 | 0.75 | 0.99 |
|
||||
| groq | gemma2-9b-it | 0.3 | 0.2 | 0.2 |
|
||||
| groq | whisper-large-v3 | — | 0.11 | 0 |
|
||||
| perplexity | sonar-pro | — | 3 | 15 |
|
||||
| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning | 0.211 | 1 | 5 |
|
||||
| xai | grok-3 | — | 3 | 15 |
|
||||
| xai | grok-3-fast | — | 5 | 25 |
|
||||
| ollama | devstral:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:14b | — | 0 | 0 |
|
||||
| ollama | qwen3:32b | — | 0 | 0 |
|
||||
| ollama | mistral-small3.1:latest | — | 0 | 0 |
|
||||
| ollama | llama3.3:latest | — | 0 | 0 |
|
||||
| ollama | phi4:latest | — | 0 | 0 |
|
||||
| openrouter | google/gemini-2.5-flash-preview-05-20 | — | 0.15 | 0.6 |
|
||||
| openrouter | google/gemini-2.5-flash-preview-05-20:thinking | — | 0.15 | 3.5 |
|
||||
| openrouter | google/gemini-2.5-pro-exp-03-25 | — | 0 | 0 |
|
||||
@@ -72,40 +69,16 @@
|
||||
| openrouter | mistralai/devstral-small | — | 0.1 | 0.3 |
|
||||
| openrouter | mistralai/mistral-nemo | — | 0.03 | 0.07 |
|
||||
| openrouter | thudm/glm-4-32b:free | — | 0 | 0 |
|
||||
| claude-code | opus | 0.725 | 0 | 0 |
|
||||
| claude-code | sonnet | 0.727 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 |
|
||||
|
||||
## Research Models
|
||||
|
||||
| Provider | Model Name | SWE Score | Input Cost | Output Cost |
|
||||
| ----------- | -------------------------------------------- | --------- | ---------- | ----------- |
|
||||
| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20241022-v2:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-7-sonnet-20250219-v1:0 | 0.623 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 |
|
||||
| bedrock | us.deepseek.r1-v1:0 | — | 1.35 | 5.4 |
|
||||
| openai | gpt-4o-search-preview | 0.33 | 2.5 | 10 |
|
||||
| openai | gpt-4o-mini-search-preview | 0.3 | 0.15 | 0.6 |
|
||||
| perplexity | sonar-pro | — | 3 | 15 |
|
||||
| perplexity | sonar | — | 1 | 1 |
|
||||
| perplexity | deep-research | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning | 0.211 | 1 | 5 |
|
||||
| xai | grok-3 | — | 3 | 15 |
|
||||
| xai | grok-3-fast | — | 5 | 25 |
|
||||
| claude-code | opus | 0.725 | 0 | 0 |
|
||||
| claude-code | sonnet | 0.727 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 |
|
||||
|
||||
## Fallback Models
|
||||
|
||||
| Provider | Model Name | SWE Score | Input Cost | Output Cost |
|
||||
| ----------- | ---------------------------------------------- | --------- | ---------- | ----------- |
|
||||
| ollama | devstral:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:14b | — | 0 | 0 |
|
||||
| ollama | qwen3:32b | — | 0 | 0 |
|
||||
| ollama | mistral-small3.1:latest | — | 0 | 0 |
|
||||
| ollama | llama3.3:latest | — | 0 | 0 |
|
||||
| ollama | phi4:latest | — | 0 | 0 |
|
||||
| azure | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| azure | gpt-4o-mini | 0.3 | 0.15 | 0.6 |
|
||||
| azure | gpt-4-1 | — | 2 | 10 |
|
||||
| bedrock | us.anthropic.claude-3-haiku-20240307-v1:0 | 0.4 | 0.25 | 1.25 |
|
||||
| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 |
|
||||
@@ -114,13 +87,52 @@
|
||||
| bedrock | us.anthropic.claude-3-5-haiku-20241022-v1:0 | 0.4 | 0.8 | 4 |
|
||||
| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 |
|
||||
|
||||
## Research Models
|
||||
|
||||
| Provider | Model Name | SWE Score | Input Cost | Output Cost |
|
||||
| ----------- | -------------------------------------------- | --------- | ---------- | ----------- |
|
||||
| claude-code | opus | 0.725 | 0 | 0 |
|
||||
| claude-code | sonnet | 0.727 | 0 | 0 |
|
||||
| mcp | mcp-sampling | — | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 |
|
||||
| openai | gpt-4o-search-preview | 0.33 | 2.5 | 10 |
|
||||
| openai | gpt-4o-mini-search-preview | 0.3 | 0.15 | 0.6 |
|
||||
| xai | grok-3 | — | 3 | 15 |
|
||||
| xai | grok-3-fast | — | 5 | 25 |
|
||||
| xai | grok-4 | — | 3 | 15 |
|
||||
| groq | llama-3.3-70b-versatile | 0.55 | 0.59 | 0.79 |
|
||||
| groq | llama-4-scout | 0.45 | 0.11 | 0.34 |
|
||||
| groq | llama-4-maverick | 0.52 | 0.5 | 0.77 |
|
||||
| groq | qwen-qwq-32b-preview | 0.4 | 0.18 | 0.18 |
|
||||
| groq | deepseek-r1-distill-llama-70b | 0.52 | 0.75 | 0.99 |
|
||||
| perplexity | sonar-pro | — | 3 | 15 |
|
||||
| perplexity | sonar | — | 1 | 1 |
|
||||
| perplexity | deep-research | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning | 0.211 | 1 | 5 |
|
||||
| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20241022-v2:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-7-sonnet-20250219-v1:0 | 0.623 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 |
|
||||
| bedrock | us.deepseek.r1-v1:0 | — | 1.35 | 5.4 |
|
||||
|
||||
## Fallback Models
|
||||
|
||||
| Provider | Model Name | SWE Score | Input Cost | Output Cost |
|
||||
| ----------- | ---------------------------------------------- | --------- | ---------- | ----------- |
|
||||
| anthropic | claude-sonnet-4-20250514 | 0.727 | 3 | 15 |
|
||||
| anthropic | claude-opus-4-20250514 | 0.725 | 15 | 75 |
|
||||
| anthropic | claude-3-7-sonnet-20250219 | 0.623 | 3 | 15 |
|
||||
| anthropic | claude-3-5-sonnet-20241022 | 0.49 | 3 | 15 |
|
||||
| azure | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| azure | gpt-4o-mini | 0.3 | 0.15 | 0.6 |
|
||||
| azure | gpt-4-1 | — | 2 | 10 |
|
||||
| claude-code | opus | 0.725 | 0 | 0 |
|
||||
| claude-code | sonnet | 0.727 | 0 | 0 |
|
||||
| mcp | mcp-sampling | — | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 |
|
||||
| openai | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| openai | o3 | 0.5 | 2 | 8 |
|
||||
| openai | o4-mini | 0.45 | 1.1 | 4.4 |
|
||||
@@ -129,17 +141,18 @@
|
||||
| google | gemini-2.5-flash-preview-04-17 | 0.604 | — | — |
|
||||
| google | gemini-2.0-flash | 0.518 | 0.15 | 0.6 |
|
||||
| google | gemini-2.0-flash-lite | — | — | — |
|
||||
| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning | 0.211 | 1 | 5 |
|
||||
| xai | grok-3 | — | 3 | 15 |
|
||||
| xai | grok-3-fast | — | 5 | 25 |
|
||||
| ollama | devstral:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:14b | — | 0 | 0 |
|
||||
| ollama | qwen3:32b | — | 0 | 0 |
|
||||
| ollama | mistral-small3.1:latest | — | 0 | 0 |
|
||||
| ollama | llama3.3:latest | — | 0 | 0 |
|
||||
| ollama | phi4:latest | — | 0 | 0 |
|
||||
| xai | grok-4 | — | 3 | 15 |
|
||||
| groq | llama-3.3-70b-versatile | 0.55 | 0.59 | 0.79 |
|
||||
| groq | llama-3.1-8b-instant | 0.32 | 0.05 | 0.08 |
|
||||
| groq | llama-4-scout | 0.45 | 0.11 | 0.34 |
|
||||
| groq | llama-4-maverick | 0.52 | 0.5 | 0.77 |
|
||||
| groq | mixtral-8x7b-32768 | 0.35 | 0.24 | 0.24 |
|
||||
| groq | qwen-qwq-32b-preview | 0.4 | 0.18 | 0.18 |
|
||||
| groq | gemma2-9b-it | 0.3 | 0.2 | 0.2 |
|
||||
| perplexity | sonar-reasoning-pro | 0.211 | 2 | 8 |
|
||||
| perplexity | sonar-reasoning | 0.211 | 1 | 5 |
|
||||
| openrouter | google/gemini-2.5-flash-preview-05-20 | — | 0.15 | 0.6 |
|
||||
| openrouter | google/gemini-2.5-flash-preview-05-20:thinking | — | 0.15 | 3.5 |
|
||||
| openrouter | google/gemini-2.5-pro-exp-03-25 | — | 0 | 0 |
|
||||
@@ -163,7 +176,21 @@
|
||||
| openrouter | mistralai/mistral-small-3.1-24b-instruct | — | 0.1 | 0.3 |
|
||||
| openrouter | mistralai/mistral-nemo | — | 0.03 | 0.07 |
|
||||
| openrouter | thudm/glm-4-32b:free | — | 0 | 0 |
|
||||
| claude-code | opus | 0.725 | 0 | 0 |
|
||||
| claude-code | sonnet | 0.727 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-pro | 0.72 | 0 | 0 |
|
||||
| gemini-cli | gemini-2.5-flash | 0.71 | 0 | 0 |
|
||||
| ollama | devstral:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:latest | — | 0 | 0 |
|
||||
| ollama | qwen3:14b | — | 0 | 0 |
|
||||
| ollama | qwen3:32b | — | 0 | 0 |
|
||||
| ollama | mistral-small3.1:latest | — | 0 | 0 |
|
||||
| ollama | llama3.3:latest | — | 0 | 0 |
|
||||
| ollama | phi4:latest | — | 0 | 0 |
|
||||
| azure | gpt-4o | 0.332 | 2.5 | 10 |
|
||||
| azure | gpt-4o-mini | 0.3 | 0.15 | 0.6 |
|
||||
| azure | gpt-4-1 | — | 2 | 10 |
|
||||
| bedrock | us.anthropic.claude-3-haiku-20240307-v1:0 | 0.4 | 0.25 | 1.25 |
|
||||
| bedrock | us.anthropic.claude-3-opus-20240229-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20240620-v1:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-5-sonnet-20241022-v2:0 | 0.49 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-7-sonnet-20250219-v1:0 | 0.623 | 3 | 15 |
|
||||
| bedrock | us.anthropic.claude-3-5-haiku-20241022-v1:0 | 0.4 | 0.8 | 4 |
|
||||
| bedrock | us.anthropic.claude-opus-4-20250514-v1:0 | 0.725 | 15 | 75 |
|
||||
| bedrock | us.anthropic.claude-sonnet-4-20250514-v1:0 | 0.727 | 3 | 15 |
|
||||
|
||||
@@ -4,11 +4,11 @@ The Gemini CLI provider allows you to use Google's Gemini models through the Gem
|
||||
|
||||
## Why Use Gemini CLI?
|
||||
|
||||
The primary benefit of using the `gemini-cli` provider is to leverage your existing Gemini Pro subscription or OAuth authentication configured through the Gemini CLI. This is ideal for users who:
|
||||
The primary benefit of using the `gemini-cli` provider is to leverage your existing Personal Gemini Code Assist license/usage Google offers for free, or Gemini Code Assist Standard/Enterprise subscription you may already have, via OAuth configured through the Gemini CLI. This is ideal for users who:
|
||||
|
||||
- Have an active Gemini subscription
|
||||
- Have an active Gemini Code Assist license (including those using the free tier offere by Google)
|
||||
- Want to use OAuth authentication instead of managing API keys
|
||||
- Have already configured authentication via `gemini auth login`
|
||||
- Have already configured authentication via `gemini` OAuth login
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -26,11 +26,11 @@ npm install -g @google/gemini-cli
|
||||
The Gemini CLI provider is designed to use your pre-configured OAuth authentication:
|
||||
|
||||
```bash
|
||||
# Authenticate with your Google account
|
||||
gemini auth login
|
||||
# Launch Gemini CLI and go through the authentication procedure
|
||||
gemini
|
||||
```
|
||||
|
||||
This will open a browser window for OAuth authentication. Once authenticated, Task Master will automatically use these credentials when you select the `gemini-cli` provider.
|
||||
For OAuth use, select `Login with Google` - This will open a browser window for OAuth authentication. Once authenticated, Task Master will automatically use these credentials when you select the `gemini-cli` provider and models.
|
||||
|
||||
### Alternative Method: API Key
|
||||
|
||||
@@ -42,8 +42,18 @@ export GEMINI_API_KEY="your-gemini-api-key"
|
||||
|
||||
**Note:** If you want to use API keys, consider using the standard `google` provider instead, as `gemini-cli` is specifically designed for OAuth/subscription users.
|
||||
|
||||
More details on authentication steps and options can be found in the [gemini-cli GitHub README](https://github.com/google-gemini/gemini-cli).
|
||||
|
||||
## Configuration
|
||||
|
||||
Use the `task-master init` command to run through the guided initialization:
|
||||
|
||||
```bash
|
||||
task-master init
|
||||
```
|
||||
|
||||
**OR**
|
||||
|
||||
Configure `gemini-cli` as a provider using the Task Master models command:
|
||||
|
||||
```bash
|
||||
@@ -54,14 +64,44 @@ task-master models --set-main gemini-2.5-pro --gemini-cli
|
||||
task-master models --set-main gemini-2.5-flash --gemini-cli
|
||||
```
|
||||
|
||||
You can also manually edit your `.taskmaster/config/providers.json`:
|
||||
You can also manually edit your `.taskmaster/config.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"main": {
|
||||
"provider": "gemini-cli",
|
||||
"model": "gemini-2.5-flash"
|
||||
}
|
||||
"models": {
|
||||
"main": {
|
||||
"provider": "gemini-cli",
|
||||
"modelId": "gemini-2.5-pro",
|
||||
"maxTokens": 65536,
|
||||
"temperature": 0.2
|
||||
},
|
||||
"research": {
|
||||
"provider": "gemini-cli",
|
||||
"modelId": "gemini-2.5-pro",
|
||||
"maxTokens": 65536,
|
||||
"temperature": 0.1
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "gemini-cli",
|
||||
"modelId": "gemini-2.5-flash",
|
||||
"maxTokens": 65536,
|
||||
"temperature": 0.2
|
||||
}
|
||||
},
|
||||
"global": {
|
||||
"logLevel": "info",
|
||||
"debug": false,
|
||||
"defaultNumTasks": 10,
|
||||
"defaultSubtasks": 5,
|
||||
"defaultPriority": "medium",
|
||||
"projectName": "Taskmaster",
|
||||
"ollamaBaseURL": "http://localhost:11434/api",
|
||||
"bedrockBaseURL": "https://bedrock.us-east-1.amazonaws.com",
|
||||
"responseLanguage": "English",
|
||||
"defaultTag": "master",
|
||||
"azureOpenaiBaseURL": "https://your-endpoint.openai.azure.com/"
|
||||
},
|
||||
"claudeCode": {}
|
||||
}
|
||||
```
|
||||
|
||||
@@ -75,45 +115,11 @@ The gemini-cli provider supports only two models:
|
||||
|
||||
### Basic Usage
|
||||
|
||||
Once authenticated with `gemini auth login` and configured, simply use Task Master as normal:
|
||||
Once gemini-cli is installed and authenticated, and Task Master simply use Task Master as normal:
|
||||
|
||||
```bash
|
||||
# The provider will automatically use your OAuth credentials
|
||||
task-master new "Create a hello world function"
|
||||
```
|
||||
|
||||
### With Specific Parameters
|
||||
|
||||
Configure model parameters in your providers.json:
|
||||
|
||||
```json
|
||||
{
|
||||
"main": {
|
||||
"provider": "gemini-cli",
|
||||
"model": "gemini-2.5-pro",
|
||||
"parameters": {
|
||||
"maxTokens": 65536,
|
||||
"temperature": 0.7
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### As Fallback Provider
|
||||
|
||||
Use gemini-cli as a fallback when your primary provider is unavailable:
|
||||
|
||||
```json
|
||||
{
|
||||
"main": {
|
||||
"provider": "anthropic",
|
||||
"model": "claude-3-5-sonnet-latest"
|
||||
},
|
||||
"fallback": {
|
||||
"provider": "gemini-cli",
|
||||
"model": "gemini-2.5-flash"
|
||||
}
|
||||
}
|
||||
task-master parse-prd my-prd.txt
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
@@ -122,9 +128,9 @@ Use gemini-cli as a fallback when your primary provider is unavailable:
|
||||
|
||||
If you get an authentication error:
|
||||
|
||||
1. **Primary solution**: Run `gemini auth login` to authenticate with your Google account
|
||||
2. **Check authentication status**: Run `gemini auth status` to verify you're logged in
|
||||
3. **If using API key** (not recommended): Ensure `GEMINI_API_KEY` is set correctly
|
||||
1. **Primary solution**: Run `gemini` to authenticate with your Google account - use `/auth` slash command in **gemini-cli** to change authentication method if desired.
|
||||
2. **Check authentication status**: Run `gemini` and use `/about` to verify your Auth Method and GCP Project if applicable.
|
||||
3. **If using API key** (not recommended): Ensure `GEMINI_API_KEY` env variable is set correctly, see the gemini-cli README.md for more info.
|
||||
|
||||
### "Model not found" Error
|
||||
|
||||
@@ -146,23 +152,9 @@ npm install -g @google/gemini-cli
|
||||
gemini --version
|
||||
```
|
||||
|
||||
### Custom Endpoints
|
||||
|
||||
Custom endpoints can be configured if needed:
|
||||
|
||||
```json
|
||||
{
|
||||
"main": {
|
||||
"provider": "gemini-cli",
|
||||
"model": "gemini-2.5-pro",
|
||||
"baseURL": "https://custom-endpoint.example.com"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Important Notes
|
||||
|
||||
- **OAuth vs API Key**: This provider is specifically designed for users who want to use OAuth authentication via `gemini auth login`. If you prefer using API keys, consider using the standard `google` provider instead.
|
||||
- **OAuth vs API Key**: This provider is specifically designed for users who want to use OAuth authentication via gemini-cli. If you prefer using API keys, consider using the standard `google` provider instead.
|
||||
- **Limited Model Support**: Only `gemini-2.5-pro` and `gemini-2.5-flash` are available through gemini-cli.
|
||||
- **Subscription Benefits**: Using OAuth authentication allows you to leverage any subscription benefits associated with your Google account.
|
||||
- The provider uses the `ai-sdk-provider-gemini-cli` npm package internally.
|
||||
|
||||
106
mcp-server/src/custom-sdk/errors.js
Normal file
106
mcp-server/src/custom-sdk/errors.js
Normal file
@@ -0,0 +1,106 @@
|
||||
/**
|
||||
* src/ai-providers/custom-sdk/mcp/errors.js
|
||||
*
|
||||
* Error handling utilities for MCP AI SDK provider.
|
||||
* Maps MCP errors to AI SDK compatible error types.
|
||||
*/
|
||||
|
||||
/**
|
||||
* MCP-specific error class
|
||||
*/
|
||||
export class MCPError extends Error {
|
||||
constructor(message, options = {}) {
|
||||
super(message);
|
||||
this.name = 'MCPError';
|
||||
this.code = options.code;
|
||||
this.cause = options.cause;
|
||||
this.mcpResponse = options.mcpResponse;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Session-related error
|
||||
*/
|
||||
export class MCPSessionError extends MCPError {
|
||||
constructor(message, options = {}) {
|
||||
super(message, options);
|
||||
this.name = 'MCPSessionError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sampling-related error
|
||||
*/
|
||||
export class MCPSamplingError extends MCPError {
|
||||
constructor(message, options = {}) {
|
||||
super(message, options);
|
||||
this.name = 'MCPSamplingError';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Map MCP errors to AI SDK compatible error types
|
||||
* @param {Error} error - Original error
|
||||
* @returns {Error} Mapped error
|
||||
*/
|
||||
export function mapMCPError(error) {
|
||||
// If already an MCP error, return as-is
|
||||
if (error instanceof MCPError) {
|
||||
return error;
|
||||
}
|
||||
|
||||
const message = error.message || 'Unknown MCP error';
|
||||
const originalError = error;
|
||||
|
||||
// Map common error patterns
|
||||
if (message.includes('session') || message.includes('connection')) {
|
||||
return new MCPSessionError(message, {
|
||||
cause: originalError,
|
||||
code: 'SESSION_ERROR'
|
||||
});
|
||||
}
|
||||
|
||||
if (message.includes('sampling') || message.includes('timeout')) {
|
||||
return new MCPSamplingError(message, {
|
||||
cause: originalError,
|
||||
code: 'SAMPLING_ERROR'
|
||||
});
|
||||
}
|
||||
|
||||
if (message.includes('capabilities') || message.includes('not supported')) {
|
||||
return new MCPSessionError(message, {
|
||||
cause: originalError,
|
||||
code: 'CAPABILITY_ERROR'
|
||||
});
|
||||
}
|
||||
|
||||
// Default to generic MCP error
|
||||
return new MCPError(message, {
|
||||
cause: originalError,
|
||||
code: 'UNKNOWN_ERROR'
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if error is retryable
|
||||
* @param {Error} error - Error to check
|
||||
* @returns {boolean} True if error might be retryable
|
||||
*/
|
||||
export function isRetryableError(error) {
|
||||
if (error instanceof MCPSamplingError && error.code === 'SAMPLING_ERROR') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (error instanceof MCPSessionError && error.code === 'SESSION_ERROR') {
|
||||
// Session errors are generally not retryable
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check for common retryable patterns
|
||||
const message = error.message?.toLowerCase() || '';
|
||||
return (
|
||||
message.includes('timeout') ||
|
||||
message.includes('network') ||
|
||||
message.includes('temporary')
|
||||
);
|
||||
}
|
||||
47
mcp-server/src/custom-sdk/index.js
Normal file
47
mcp-server/src/custom-sdk/index.js
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* src/ai-providers/custom-sdk/mcp/index.js
|
||||
*
|
||||
* AI SDK factory function for MCP provider.
|
||||
* Creates MCP language model instances with session-based AI operations.
|
||||
*/
|
||||
|
||||
import { MCPLanguageModel } from './language-model.js';
|
||||
|
||||
/**
|
||||
* Create MCP provider factory function following AI SDK patterns
|
||||
* @param {object} options - Provider options
|
||||
* @param {object} options.session - MCP session object
|
||||
* @param {object} options.defaultSettings - Default settings for the provider
|
||||
* @returns {Function} Provider factory function
|
||||
*/
|
||||
export function createMCP(options = {}) {
|
||||
if (!options.session) {
|
||||
throw new Error('MCP provider requires session object');
|
||||
}
|
||||
|
||||
// Return the provider factory function that AI SDK expects
|
||||
const provider = function (modelId, settings = {}) {
|
||||
if (new.target) {
|
||||
throw new Error(
|
||||
'The MCP model function cannot be called with the new keyword.'
|
||||
);
|
||||
}
|
||||
|
||||
return new MCPLanguageModel({
|
||||
session: options.session,
|
||||
modelId: modelId || 'claude-3-5-sonnet-20241022',
|
||||
settings: {
|
||||
temperature: settings.temperature,
|
||||
maxTokens: settings.maxTokens,
|
||||
...options.defaultSettings,
|
||||
...settings
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Add required methods for AI SDK compatibility
|
||||
provider.languageModel = (modelId, settings) => provider(modelId, settings);
|
||||
provider.chat = (modelId, settings) => provider(modelId, settings);
|
||||
|
||||
return provider;
|
||||
}
|
||||
109
mcp-server/src/custom-sdk/json-extractor.js
Normal file
109
mcp-server/src/custom-sdk/json-extractor.js
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* @fileoverview Extract JSON from MCP response, handling markdown blocks and other formatting
|
||||
*/
|
||||
|
||||
/**
|
||||
* Extract JSON from MCP AI response
|
||||
* @param {string} text - The text to extract JSON from
|
||||
* @returns {string} - The extracted JSON string
|
||||
*/
|
||||
export function extractJson(text) {
|
||||
// Remove markdown code blocks if present
|
||||
let jsonText = text.trim();
|
||||
|
||||
// Remove ```json blocks
|
||||
jsonText = jsonText.replace(/^```json\s*/gm, '');
|
||||
jsonText = jsonText.replace(/^```\s*/gm, '');
|
||||
jsonText = jsonText.replace(/```\s*$/gm, '');
|
||||
|
||||
// Remove common TypeScript/JavaScript patterns
|
||||
jsonText = jsonText.replace(/^const\s+\w+\s*=\s*/, ''); // Remove "const varName = "
|
||||
jsonText = jsonText.replace(/^let\s+\w+\s*=\s*/, ''); // Remove "let varName = "
|
||||
jsonText = jsonText.replace(/^var\s+\w+\s*=\s*/, ''); // Remove "var varName = "
|
||||
jsonText = jsonText.replace(/;?\s*$/, ''); // Remove trailing semicolons
|
||||
|
||||
// Remove explanatory text before JSON (common with AI responses)
|
||||
jsonText = jsonText.replace(/^.*?(?=\{|\[)/s, '');
|
||||
|
||||
// Remove explanatory text after JSON
|
||||
const lines = jsonText.split('\n');
|
||||
let jsonEndIndex = -1;
|
||||
let braceCount = 0;
|
||||
let inString = false;
|
||||
let escapeNext = false;
|
||||
|
||||
// Find the end of the JSON by tracking braces
|
||||
for (let i = 0; i < jsonText.length; i++) {
|
||||
const char = jsonText[i];
|
||||
|
||||
if (escapeNext) {
|
||||
escapeNext = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (char === '\\') {
|
||||
escapeNext = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (char === '"' && !escapeNext) {
|
||||
inString = !inString;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!inString) {
|
||||
if (char === '{' || char === '[') {
|
||||
braceCount++;
|
||||
} else if (char === '}' || char === ']') {
|
||||
braceCount--;
|
||||
if (braceCount === 0) {
|
||||
jsonEndIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (jsonEndIndex > -1) {
|
||||
jsonText = jsonText.substring(0, jsonEndIndex + 1);
|
||||
}
|
||||
|
||||
// Try to extract JSON object or array if previous method didn't work
|
||||
if (jsonEndIndex === -1) {
|
||||
const objectMatch = jsonText.match(/{[\s\S]*}/);
|
||||
const arrayMatch = jsonText.match(/\[[\s\S]*\]/);
|
||||
|
||||
if (objectMatch) {
|
||||
jsonText = objectMatch[0];
|
||||
} else if (arrayMatch) {
|
||||
jsonText = arrayMatch[0];
|
||||
}
|
||||
}
|
||||
|
||||
// First try to parse as valid JSON
|
||||
try {
|
||||
JSON.parse(jsonText);
|
||||
return jsonText;
|
||||
} catch {
|
||||
// If it's not valid JSON, it might be a JavaScript object literal
|
||||
// Try to convert it to valid JSON
|
||||
try {
|
||||
// This is a simple conversion that handles basic cases
|
||||
// Replace unquoted keys with quoted keys
|
||||
const converted = jsonText
|
||||
.replace(/([{,]\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:/g, '$1"$2":')
|
||||
// Replace single quotes with double quotes
|
||||
.replace(/'/g, '"')
|
||||
// Handle trailing commas
|
||||
.replace(/,\s*([}\]])/g, '$1');
|
||||
|
||||
// Validate the converted JSON
|
||||
JSON.parse(converted);
|
||||
return converted;
|
||||
} catch {
|
||||
// If all else fails, return the original text
|
||||
// The calling code will handle the error appropriately
|
||||
return text;
|
||||
}
|
||||
}
|
||||
}
|
||||
230
mcp-server/src/custom-sdk/language-model.js
Normal file
230
mcp-server/src/custom-sdk/language-model.js
Normal file
@@ -0,0 +1,230 @@
|
||||
/**
|
||||
* src/ai-providers/custom-sdk/mcp/language-model.js
|
||||
*
|
||||
* MCP Language Model implementation following AI SDK LanguageModelV1 interface.
|
||||
* Uses MCP session.requestSampling() for AI operations.
|
||||
*/
|
||||
|
||||
import {
|
||||
convertToMCPFormat,
|
||||
convertFromMCPFormat
|
||||
} from './message-converter.js';
|
||||
import { MCPError, mapMCPError } from './errors.js';
|
||||
import { extractJson } from './json-extractor.js';
|
||||
import {
|
||||
convertSchemaToInstructions,
|
||||
enhancePromptForJSON
|
||||
} from './schema-converter.js';
|
||||
|
||||
/**
|
||||
* MCP Language Model implementing AI SDK LanguageModelV1 interface
|
||||
*/
|
||||
export class MCPLanguageModel {
|
||||
specificationVersion = 'v1';
|
||||
defaultObjectGenerationMode = 'json';
|
||||
supportsImageUrls = false;
|
||||
supportsStructuredOutputs = true;
|
||||
|
||||
constructor(options) {
|
||||
this.session = options.session; // MCP session object
|
||||
this.modelId = options.modelId;
|
||||
this.settings = options.settings || {};
|
||||
this.provider = 'mcp-ai-sdk';
|
||||
this.maxTokens = this.settings.maxTokens;
|
||||
this.temperature = this.settings.temperature;
|
||||
|
||||
this.validateSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate that the MCP session has required capabilities
|
||||
*/
|
||||
validateSession() {
|
||||
if (!this.session?.clientCapabilities?.sampling) {
|
||||
throw new MCPError('MCP session must have client sampling capabilities');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate text using MCP session sampling
|
||||
* @param {object} options - Generation options
|
||||
* @param {Array} options.prompt - AI SDK prompt format
|
||||
* @param {AbortSignal} options.abortSignal - Abort signal
|
||||
* @returns {Promise<object>} Generation result in AI SDK format
|
||||
*/
|
||||
async doGenerate(options) {
|
||||
try {
|
||||
// Convert AI SDK prompt to MCP format
|
||||
const { messages, systemPrompt } = convertToMCPFormat(options.prompt);
|
||||
|
||||
// Use MCP session.requestSampling (same as MCPRemoteProvider)
|
||||
const response = await this.session.requestSampling(
|
||||
{
|
||||
messages,
|
||||
systemPrompt,
|
||||
temperature: this.settings.temperature,
|
||||
maxTokens: this.settings.maxTokens,
|
||||
includeContext: 'thisServer'
|
||||
},
|
||||
{
|
||||
// signal: options.abortSignal,
|
||||
timeout: 240000 // 4 minutes timeout
|
||||
}
|
||||
);
|
||||
|
||||
// Convert MCP response back to AI SDK format
|
||||
const result = convertFromMCPFormat(response);
|
||||
|
||||
return {
|
||||
text: result.text,
|
||||
finishReason: result.finishReason || 'stop',
|
||||
usage: {
|
||||
promptTokens: result.usage?.inputTokens || 0,
|
||||
completionTokens: result.usage?.outputTokens || 0,
|
||||
totalTokens:
|
||||
(result.usage?.inputTokens || 0) + (result.usage?.outputTokens || 0)
|
||||
},
|
||||
rawResponse: response,
|
||||
warnings: result.warnings
|
||||
};
|
||||
} catch (error) {
|
||||
throw mapMCPError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate structured object using MCP session sampling
|
||||
* @param {object} options - Generation options
|
||||
* @param {Array} options.prompt - AI SDK prompt format
|
||||
* @param {import('zod').ZodSchema} options.schema - Zod schema for validation
|
||||
* @param {string} [options.mode='json'] - Generation mode ('json' or 'tool')
|
||||
* @param {AbortSignal} options.abortSignal - Abort signal
|
||||
* @returns {Promise<object>} Generation result with structured object
|
||||
*/
|
||||
async doGenerateObject(options) {
|
||||
try {
|
||||
const { schema, mode = 'json', ...restOptions } = options;
|
||||
|
||||
if (!schema) {
|
||||
throw new MCPError('Schema is required for object generation');
|
||||
}
|
||||
|
||||
// Convert schema to JSON instructions
|
||||
const objectName = restOptions.objectName || 'generated_object';
|
||||
const jsonInstructions = convertSchemaToInstructions(schema, objectName);
|
||||
|
||||
// Enhance prompt with JSON generation instructions
|
||||
const enhancedPrompt = enhancePromptForJSON(
|
||||
options.prompt,
|
||||
jsonInstructions
|
||||
);
|
||||
|
||||
// Convert enhanced prompt to MCP format
|
||||
const { messages, systemPrompt } = convertToMCPFormat(enhancedPrompt);
|
||||
|
||||
// Use MCP session.requestSampling with enhanced prompt
|
||||
const response = await this.session.requestSampling(
|
||||
{
|
||||
messages,
|
||||
systemPrompt,
|
||||
temperature: this.settings.temperature,
|
||||
maxTokens: this.settings.maxTokens,
|
||||
includeContext: 'thisServer'
|
||||
},
|
||||
{
|
||||
timeout: 240000 // 4 minutes timeout
|
||||
}
|
||||
);
|
||||
|
||||
// Convert MCP response back to AI SDK format
|
||||
const result = convertFromMCPFormat(response);
|
||||
|
||||
// Extract JSON from the response text
|
||||
const jsonText = extractJson(result.text);
|
||||
|
||||
// Parse and validate JSON
|
||||
let parsedObject;
|
||||
try {
|
||||
parsedObject = JSON.parse(jsonText);
|
||||
} catch (parseError) {
|
||||
throw new MCPError(
|
||||
`Failed to parse JSON response: ${parseError.message}. Response: ${result.text.substring(0, 200)}...`
|
||||
);
|
||||
}
|
||||
|
||||
// Validate against schema
|
||||
try {
|
||||
const validatedObject = schema.parse(parsedObject);
|
||||
|
||||
return {
|
||||
object: validatedObject,
|
||||
finishReason: result.finishReason || 'stop',
|
||||
usage: {
|
||||
promptTokens: result.usage?.inputTokens || 0,
|
||||
completionTokens: result.usage?.outputTokens || 0,
|
||||
totalTokens:
|
||||
(result.usage?.inputTokens || 0) +
|
||||
(result.usage?.outputTokens || 0)
|
||||
},
|
||||
rawResponse: response,
|
||||
warnings: result.warnings
|
||||
};
|
||||
} catch (validationError) {
|
||||
throw new MCPError(
|
||||
`Generated object does not match schema: ${validationError.message}. Generated: ${JSON.stringify(parsedObject, null, 2)}`
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
throw mapMCPError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream text generation using MCP session sampling
|
||||
* Note: MCP may not support native streaming, so this may simulate streaming
|
||||
* @param {object} options - Generation options
|
||||
* @returns {AsyncIterable} Stream of generation chunks
|
||||
*/
|
||||
async doStream(options) {
|
||||
try {
|
||||
// For now, simulate streaming by chunking the complete response
|
||||
// TODO: Implement native streaming if MCP supports it
|
||||
const result = await this.doGenerate(options);
|
||||
|
||||
// Create async generator that yields chunks
|
||||
return this.simulateStreaming(result);
|
||||
} catch (error) {
|
||||
throw mapMCPError(error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Simulate streaming by chunking a complete response
|
||||
* @param {object} result - Complete generation result
|
||||
* @returns {AsyncIterable} Simulated stream chunks
|
||||
*/
|
||||
async *simulateStreaming(result) {
|
||||
const text = result.text;
|
||||
const chunkSize = Math.max(1, Math.floor(text.length / 10)); // 10 chunks
|
||||
|
||||
for (let i = 0; i < text.length; i += chunkSize) {
|
||||
const chunk = text.slice(i, i + chunkSize);
|
||||
const isLast = i + chunkSize >= text.length;
|
||||
|
||||
yield {
|
||||
type: 'text-delta',
|
||||
textDelta: chunk
|
||||
};
|
||||
|
||||
// Small delay to simulate streaming
|
||||
await new Promise((resolve) => setTimeout(resolve, 50));
|
||||
}
|
||||
|
||||
// Final chunk with finish reason and usage
|
||||
yield {
|
||||
type: 'finish',
|
||||
finishReason: result.finishReason,
|
||||
usage: result.usage
|
||||
};
|
||||
}
|
||||
}
|
||||
116
mcp-server/src/custom-sdk/message-converter.js
Normal file
116
mcp-server/src/custom-sdk/message-converter.js
Normal file
@@ -0,0 +1,116 @@
|
||||
/**
|
||||
* src/ai-providers/custom-sdk/mcp/message-converter.js
|
||||
*
|
||||
* Message conversion utilities for converting between AI SDK prompt format
|
||||
* and MCP sampling format.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert AI SDK prompt format to MCP sampling format
|
||||
* @param {Array} prompt - AI SDK prompt array
|
||||
* @returns {object} MCP format with messages and systemPrompt
|
||||
*/
|
||||
export function convertToMCPFormat(prompt) {
|
||||
const messages = [];
|
||||
let systemPrompt = '';
|
||||
|
||||
for (const message of prompt) {
|
||||
if (message.role === 'system') {
|
||||
// Extract system prompt
|
||||
systemPrompt = extractTextContent(message.content);
|
||||
} else if (message.role === 'user' || message.role === 'assistant') {
|
||||
// Convert user/assistant messages
|
||||
messages.push({
|
||||
role: message.role,
|
||||
content: {
|
||||
type: 'text',
|
||||
text: extractTextContent(message.content)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
messages,
|
||||
systemPrompt
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert MCP response format to AI SDK format
|
||||
* @param {object} response - MCP sampling response
|
||||
* @returns {object} AI SDK compatible result
|
||||
*/
|
||||
export function convertFromMCPFormat(response) {
|
||||
// Handle different possible response formats
|
||||
let text = '';
|
||||
let usage = null;
|
||||
let finishReason = 'stop';
|
||||
let warnings = [];
|
||||
|
||||
if (typeof response === 'string') {
|
||||
text = response;
|
||||
} else if (response.content) {
|
||||
text = extractTextContent(response.content);
|
||||
usage = response.usage;
|
||||
finishReason = response.finishReason || 'stop';
|
||||
} else if (response.text) {
|
||||
text = response.text;
|
||||
usage = response.usage;
|
||||
finishReason = response.finishReason || 'stop';
|
||||
} else {
|
||||
// Fallback: try to extract text from response
|
||||
text = JSON.stringify(response);
|
||||
warnings.push('Unexpected MCP response format, used JSON fallback');
|
||||
}
|
||||
|
||||
return {
|
||||
text,
|
||||
usage,
|
||||
finishReason,
|
||||
warnings
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract text content from various content formats
|
||||
* @param {string|Array|object} content - Content in various formats
|
||||
* @returns {string} Extracted text
|
||||
*/
|
||||
function extractTextContent(content) {
|
||||
if (typeof content === 'string') {
|
||||
return content;
|
||||
}
|
||||
|
||||
if (Array.isArray(content)) {
|
||||
// Handle array of content parts
|
||||
return content
|
||||
.map((part) => {
|
||||
if (typeof part === 'string') {
|
||||
return part;
|
||||
}
|
||||
if (part.type === 'text' && part.text) {
|
||||
return part.text;
|
||||
}
|
||||
if (part.text) {
|
||||
return part.text;
|
||||
}
|
||||
// Skip non-text content (images, etc.)
|
||||
return '';
|
||||
})
|
||||
.filter((text) => text.length > 0)
|
||||
.join(' ');
|
||||
}
|
||||
|
||||
if (content && typeof content === 'object') {
|
||||
if (content.type === 'text' && content.text) {
|
||||
return content.text;
|
||||
}
|
||||
if (content.text) {
|
||||
return content.text;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return String(content || '');
|
||||
}
|
||||
150
mcp-server/src/custom-sdk/schema-converter.js
Normal file
150
mcp-server/src/custom-sdk/schema-converter.js
Normal file
@@ -0,0 +1,150 @@
|
||||
/**
|
||||
* @fileoverview Schema conversion utilities for MCP AI SDK provider
|
||||
*/
|
||||
|
||||
/**
|
||||
* Convert Zod schema to human-readable JSON instructions
|
||||
* @param {import('zod').ZodSchema} schema - Zod schema object
|
||||
* @param {string} [objectName='result'] - Name of the object being generated
|
||||
* @returns {string} Instructions for JSON generation
|
||||
*/
|
||||
export function convertSchemaToInstructions(schema, objectName = 'result') {
|
||||
try {
|
||||
// Generate example structure from schema
|
||||
const exampleStructure = generateExampleFromSchema(schema);
|
||||
|
||||
return `
|
||||
CRITICAL JSON GENERATION INSTRUCTIONS:
|
||||
|
||||
You must respond with ONLY valid JSON that matches this exact structure for "${objectName}":
|
||||
|
||||
${JSON.stringify(exampleStructure, null, 2)}
|
||||
|
||||
STRICT REQUIREMENTS:
|
||||
1. Response must start with { and end with }
|
||||
2. Use double quotes for all strings and property names
|
||||
3. Do not include any text before or after the JSON
|
||||
4. Do not wrap in markdown code blocks
|
||||
5. Do not include explanations or comments
|
||||
6. Follow the exact property names and types shown above
|
||||
7. All required fields must be present
|
||||
|
||||
Begin your response immediately with the opening brace {`;
|
||||
} catch (error) {
|
||||
// Fallback to basic JSON instructions if schema parsing fails
|
||||
return `
|
||||
CRITICAL JSON GENERATION INSTRUCTIONS:
|
||||
|
||||
You must respond with ONLY valid JSON for "${objectName}".
|
||||
|
||||
STRICT REQUIREMENTS:
|
||||
1. Response must start with { and end with }
|
||||
2. Use double quotes for all strings and property names
|
||||
3. Do not include any text before or after the JSON
|
||||
4. Do not wrap in markdown code blocks
|
||||
5. Do not include explanations or comments
|
||||
|
||||
Begin your response immediately with the opening brace {`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate example structure from Zod schema
|
||||
* @param {import('zod').ZodSchema} schema - Zod schema
|
||||
* @returns {any} Example object matching the schema
|
||||
*/
|
||||
function generateExampleFromSchema(schema) {
|
||||
// This is a simplified schema-to-example converter
|
||||
// For production, you might want to use a more sophisticated library
|
||||
|
||||
if (!schema || typeof schema._def === 'undefined') {
|
||||
return {};
|
||||
}
|
||||
|
||||
const def = schema._def;
|
||||
|
||||
switch (def.typeName) {
|
||||
case 'ZodObject':
|
||||
const result = {};
|
||||
const shape = def.shape();
|
||||
|
||||
for (const [key, fieldSchema] of Object.entries(shape)) {
|
||||
result[key] = generateExampleFromSchema(fieldSchema);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
case 'ZodString':
|
||||
return 'string';
|
||||
|
||||
case 'ZodNumber':
|
||||
return 0;
|
||||
|
||||
case 'ZodBoolean':
|
||||
return false;
|
||||
|
||||
case 'ZodArray':
|
||||
const elementExample = generateExampleFromSchema(def.type);
|
||||
return [elementExample];
|
||||
|
||||
case 'ZodOptional':
|
||||
return generateExampleFromSchema(def.innerType);
|
||||
|
||||
case 'ZodNullable':
|
||||
return generateExampleFromSchema(def.innerType);
|
||||
|
||||
case 'ZodEnum':
|
||||
return def.values[0] || 'enum_value';
|
||||
|
||||
case 'ZodLiteral':
|
||||
return def.value;
|
||||
|
||||
case 'ZodUnion':
|
||||
// Use the first option from the union
|
||||
if (def.options && def.options.length > 0) {
|
||||
return generateExampleFromSchema(def.options[0]);
|
||||
}
|
||||
return 'union_value';
|
||||
|
||||
case 'ZodRecord':
|
||||
return {
|
||||
key: generateExampleFromSchema(def.valueType)
|
||||
};
|
||||
|
||||
default:
|
||||
// For unknown types, return a placeholder
|
||||
return `<${def.typeName || 'unknown'}>`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enhance prompt with JSON generation instructions
|
||||
* @param {Array} prompt - AI SDK prompt array
|
||||
* @param {string} jsonInstructions - JSON generation instructions
|
||||
* @returns {Array} Enhanced prompt array
|
||||
*/
|
||||
export function enhancePromptForJSON(prompt, jsonInstructions) {
|
||||
const enhancedPrompt = [...prompt];
|
||||
|
||||
// Find system message or create one
|
||||
let systemMessageIndex = enhancedPrompt.findIndex(
|
||||
(msg) => msg.role === 'system'
|
||||
);
|
||||
|
||||
if (systemMessageIndex >= 0) {
|
||||
// Append to existing system message
|
||||
const currentContent = enhancedPrompt[systemMessageIndex].content;
|
||||
enhancedPrompt[systemMessageIndex] = {
|
||||
...enhancedPrompt[systemMessageIndex],
|
||||
content: currentContent + '\n\n' + jsonInstructions
|
||||
};
|
||||
} else {
|
||||
// Add new system message at the beginning
|
||||
enhancedPrompt.unshift({
|
||||
role: 'system',
|
||||
content: jsonInstructions
|
||||
});
|
||||
}
|
||||
|
||||
return enhancedPrompt;
|
||||
}
|
||||
@@ -5,6 +5,8 @@ import { fileURLToPath } from 'url';
|
||||
import fs from 'fs';
|
||||
import logger from './logger.js';
|
||||
import { registerTaskMasterTools } from './tools/index.js';
|
||||
import ProviderRegistry from '../../src/provider-registry/index.js';
|
||||
import { MCPProvider } from './providers/mcp-provider.js';
|
||||
|
||||
// Load environment variables
|
||||
dotenv.config();
|
||||
@@ -65,6 +67,17 @@ class TaskMasterMCPServer {
|
||||
await this.init();
|
||||
}
|
||||
|
||||
this.server.on('connect', (event) => {
|
||||
event.session.server.sendLoggingMessage({
|
||||
data: {
|
||||
context: event.session.context,
|
||||
message: `MCP Server connected: ${event.session.name}`
|
||||
},
|
||||
level: 'info'
|
||||
});
|
||||
this.registerRemoteProvider(event.session);
|
||||
});
|
||||
|
||||
// Start the FastMCP server with increased timeout
|
||||
await this.server.start({
|
||||
transportType: 'stdio',
|
||||
@@ -74,6 +87,52 @@ class TaskMasterMCPServer {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register both MCP providers with the provider registry
|
||||
*/
|
||||
registerRemoteProvider(session) {
|
||||
// Check if the server has at least one session
|
||||
if (session) {
|
||||
// Make sure session has required capabilities
|
||||
if (!session.clientCapabilities || !session.clientCapabilities.sampling) {
|
||||
session.server.sendLoggingMessage({
|
||||
data: {
|
||||
context: session.context,
|
||||
message: `MCP session missing required sampling capabilities, providers not registered`
|
||||
},
|
||||
level: 'info'
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Register MCP provider with the Provider Registry
|
||||
|
||||
// Register the unified MCP provider
|
||||
const mcpProvider = new MCPProvider();
|
||||
mcpProvider.setSession(session);
|
||||
|
||||
// Register provider with the registry
|
||||
const providerRegistry = ProviderRegistry.getInstance();
|
||||
providerRegistry.registerProvider('mcp', mcpProvider);
|
||||
|
||||
session.server.sendLoggingMessage({
|
||||
data: {
|
||||
context: session.context,
|
||||
message: `MCP Server connected`
|
||||
},
|
||||
level: 'info'
|
||||
});
|
||||
} else {
|
||||
session.server.sendLoggingMessage({
|
||||
data: {
|
||||
context: session.context,
|
||||
message: `No MCP sessions available, providers not registered`
|
||||
},
|
||||
level: 'warn'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the MCP server
|
||||
*/
|
||||
|
||||
84
mcp-server/src/providers/mcp-provider.js
Normal file
84
mcp-server/src/providers/mcp-provider.js
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* mcp-server/src/providers/mcp-provider.js
|
||||
*
|
||||
* Implementation for MCP custom AI SDK provider that integrates with
|
||||
* the existing MCP server infrastructure and provider registry.
|
||||
* Follows the Claude Code provider pattern for session-based providers.
|
||||
*/
|
||||
|
||||
import { createMCP } from '../custom-sdk/index.js';
|
||||
import { BaseAIProvider } from '../../../src/ai-providers/base-provider.js';
|
||||
|
||||
export class MCPProvider extends BaseAIProvider {
|
||||
constructor() {
|
||||
super();
|
||||
this.name = 'mcp';
|
||||
this.session = null; // MCP server session object
|
||||
}
|
||||
|
||||
getRequiredApiKeyName() {
|
||||
return 'MCP_API_KEY';
|
||||
}
|
||||
|
||||
isRequiredApiKey() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override validateAuth to validate MCP session instead of API key
|
||||
* @param {object} params - Parameters to validate
|
||||
*/
|
||||
validateAuth(params) {
|
||||
// Validate MCP session instead of API key
|
||||
if (!this.session) {
|
||||
throw new Error('MCP Provider requires active MCP session');
|
||||
}
|
||||
|
||||
if (!this.session.clientCapabilities?.sampling) {
|
||||
throw new Error('MCP session must have client sampling capabilities');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns an MCP AI SDK client instance.
|
||||
* @param {object} params - Parameters for client initialization
|
||||
* @returns {Function} MCP AI SDK client function
|
||||
* @throws {Error} If initialization fails
|
||||
*/
|
||||
getClient(params) {
|
||||
try {
|
||||
// Pass MCP session to AI SDK implementation
|
||||
return createMCP({
|
||||
session: this.session,
|
||||
defaultSettings: {
|
||||
temperature: params.temperature,
|
||||
maxTokens: params.maxTokens
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
this.handleError('client initialization', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method called by MCP server on connect events
|
||||
* @param {object} session - MCP session object
|
||||
*/
|
||||
setSession(session) {
|
||||
this.session = session;
|
||||
|
||||
if (!session) {
|
||||
this.logger?.warn('Set null session on MCP Provider');
|
||||
} else {
|
||||
this.logger?.debug('Updated MCP Provider session');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current session status
|
||||
* @returns {boolean} True if session is available and valid
|
||||
*/
|
||||
hasValidSession() {
|
||||
return !!(this.session && this.session.clientCapabilities?.sampling);
|
||||
}
|
||||
}
|
||||
2653
package-lock.json
generated
2653
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
11
package.json
11
package.json
@@ -44,6 +44,7 @@
|
||||
"@ai-sdk/azure": "^1.3.17",
|
||||
"@ai-sdk/google": "^1.2.13",
|
||||
"@ai-sdk/google-vertex": "^2.2.23",
|
||||
"@ai-sdk/groq": "^1.2.9",
|
||||
"@ai-sdk/mistral": "^1.2.7",
|
||||
"@ai-sdk/openai": "^1.3.20",
|
||||
"@ai-sdk/perplexity": "^1.1.7",
|
||||
@@ -53,6 +54,8 @@
|
||||
"@inquirer/search": "^3.0.15",
|
||||
"@openrouter/ai-sdk-provider": "^0.4.5",
|
||||
"ai": "^4.3.10",
|
||||
"ajv": "^8.17.1",
|
||||
"ajv-formats": "^3.0.1",
|
||||
"boxen": "^8.0.1",
|
||||
"chalk": "^5.4.1",
|
||||
"cli-highlight": "^2.1.11",
|
||||
@@ -61,7 +64,7 @@
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.3.1",
|
||||
"express": "^4.21.2",
|
||||
"fastmcp": "^2.2.2",
|
||||
"fastmcp": "^3.5.0",
|
||||
"figlet": "^1.8.0",
|
||||
"fuse.js": "^7.1.0",
|
||||
"gpt-tokens": "^1.3.14",
|
||||
@@ -75,11 +78,13 @@
|
||||
"openai": "^4.89.0",
|
||||
"ora": "^8.2.0",
|
||||
"uuid": "^11.1.0",
|
||||
"zod": "^3.23.8"
|
||||
"zod": "^3.23.8",
|
||||
"zod-to-json-schema": "^3.24.5"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@anthropic-ai/claude-code": "^1.0.25",
|
||||
"ai-sdk-provider-gemini-cli": "^0.0.3"
|
||||
"ai-sdk-provider-gemini-cli": "^0.0.4",
|
||||
"@biomejs/cli-linux-x64": "^1.9.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
|
||||
@@ -51,6 +51,9 @@ import {
|
||||
GeminiCliProvider
|
||||
} from '../../src/ai-providers/index.js';
|
||||
|
||||
// Import the provider registry
|
||||
import ProviderRegistry from '../../src/provider-registry/index.js';
|
||||
|
||||
// Create provider instances
|
||||
const PROVIDERS = {
|
||||
anthropic: new AnthropicAIProvider(),
|
||||
@@ -67,6 +70,23 @@ const PROVIDERS = {
|
||||
'gemini-cli': new GeminiCliProvider()
|
||||
};
|
||||
|
||||
function _getProvider(providerName) {
|
||||
// First check the static PROVIDERS object
|
||||
if (PROVIDERS[providerName]) {
|
||||
return PROVIDERS[providerName];
|
||||
}
|
||||
|
||||
// If not found, check the provider registry
|
||||
const providerRegistry = ProviderRegistry.getInstance();
|
||||
if (providerRegistry.hasProvider(providerName)) {
|
||||
log('debug', `Provider "${providerName}" found in dynamic registry`);
|
||||
return providerRegistry.getProvider(providerName);
|
||||
}
|
||||
|
||||
// Provider not found in either location
|
||||
return null;
|
||||
}
|
||||
|
||||
// Helper function to get cost for a specific model
|
||||
function _getCostForModel(providerName, modelId) {
|
||||
if (!MODEL_MAP || !MODEL_MAP[providerName]) {
|
||||
@@ -231,44 +251,26 @@ function _extractErrorMessage(error) {
|
||||
* @throws {Error} If a required API key is missing.
|
||||
*/
|
||||
function _resolveApiKey(providerName, session, projectRoot = null) {
|
||||
// Claude Code doesn't require an API key
|
||||
if (providerName === 'claude-code') {
|
||||
return 'claude-code-no-key-required';
|
||||
}
|
||||
|
||||
// Gemini CLI can work without an API key (uses CLI auth)
|
||||
if (providerName === 'gemini-cli') {
|
||||
const apiKey = resolveEnvVariable('GEMINI_API_KEY', session, projectRoot);
|
||||
return apiKey || 'gemini-cli-no-key-required';
|
||||
}
|
||||
|
||||
const keyMap = {
|
||||
openai: 'OPENAI_API_KEY',
|
||||
anthropic: 'ANTHROPIC_API_KEY',
|
||||
google: 'GOOGLE_API_KEY',
|
||||
perplexity: 'PERPLEXITY_API_KEY',
|
||||
mistral: 'MISTRAL_API_KEY',
|
||||
azure: 'AZURE_OPENAI_API_KEY',
|
||||
openrouter: 'OPENROUTER_API_KEY',
|
||||
xai: 'XAI_API_KEY',
|
||||
ollama: 'OLLAMA_API_KEY',
|
||||
bedrock: 'AWS_ACCESS_KEY_ID',
|
||||
vertex: 'GOOGLE_API_KEY',
|
||||
'claude-code': 'CLAUDE_CODE_API_KEY', // Not actually used, but included for consistency
|
||||
'gemini-cli': 'GEMINI_API_KEY'
|
||||
};
|
||||
|
||||
const envVarName = keyMap[providerName];
|
||||
if (!envVarName) {
|
||||
// Get provider instance
|
||||
const provider = _getProvider(providerName);
|
||||
if (!provider) {
|
||||
throw new Error(
|
||||
`Unknown provider '${providerName}' for API key resolution.`
|
||||
);
|
||||
}
|
||||
|
||||
// All providers must implement getRequiredApiKeyName()
|
||||
const envVarName = provider.getRequiredApiKeyName();
|
||||
|
||||
// If envVarName is null (like for MCP), return null directly
|
||||
if (envVarName === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const apiKey = resolveEnvVariable(envVarName, session, projectRoot);
|
||||
|
||||
// Special handling for providers that can use alternative auth
|
||||
if (providersWithoutApiKeys.includes(providerName?.toLowerCase())) {
|
||||
// Special handling for providers that can use alternative auth or no API key
|
||||
if (!provider.isRequiredApiKey()) {
|
||||
return apiKey || null;
|
||||
}
|
||||
|
||||
@@ -455,7 +457,7 @@ async function _unifiedServiceRunner(serviceType, params) {
|
||||
}
|
||||
|
||||
// Get provider instance
|
||||
provider = PROVIDERS[providerName?.toLowerCase()];
|
||||
provider = _getProvider(providerName?.toLowerCase());
|
||||
if (!provider) {
|
||||
log(
|
||||
'warn',
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,10 @@ import chalk from 'chalk';
|
||||
import { z } from 'zod';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { log, findProjectRoot, resolveEnvVariable, isEmpty } from './utils.js';
|
||||
import { LEGACY_CONFIG_FILE } from '../../src/constants/paths.js';
|
||||
import {
|
||||
LEGACY_CONFIG_FILE,
|
||||
TASKMASTER_DIR
|
||||
} from '../../src/constants/paths.js';
|
||||
import { findConfigPath } from '../../src/utils/path-utils.js';
|
||||
import {
|
||||
VALIDATED_PROVIDERS,
|
||||
@@ -99,17 +102,30 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
||||
if (rootToUse) {
|
||||
configSource = `found root (${rootToUse})`;
|
||||
} else {
|
||||
// No root found, return defaults immediately
|
||||
return defaults;
|
||||
// No root found, use current working directory as fallback
|
||||
// This prevents infinite loops during initialization
|
||||
rootToUse = process.cwd();
|
||||
configSource = `current directory (${rootToUse}) - no project markers found`;
|
||||
}
|
||||
}
|
||||
// ---> End find project root logic <---
|
||||
|
||||
// --- Find configuration file using centralized path utility ---
|
||||
const configPath = findConfigPath(null, { projectRoot: rootToUse });
|
||||
// --- Find configuration file ---
|
||||
let configPath = null;
|
||||
let config = { ...defaults }; // Start with a deep copy of defaults
|
||||
let configExists = false;
|
||||
|
||||
// During initialization (no project markers), skip config file search entirely
|
||||
const hasProjectMarkers =
|
||||
fs.existsSync(path.join(rootToUse, TASKMASTER_DIR)) ||
|
||||
fs.existsSync(path.join(rootToUse, LEGACY_CONFIG_FILE));
|
||||
|
||||
if (hasProjectMarkers) {
|
||||
// Only try to find config if we have project markers
|
||||
// This prevents the repeated warnings during init
|
||||
configPath = findConfigPath(null, { projectRoot: rootToUse });
|
||||
}
|
||||
|
||||
if (configPath) {
|
||||
configExists = true;
|
||||
const isLegacy = configPath.endsWith(LEGACY_CONFIG_FILE);
|
||||
@@ -199,11 +215,22 @@ function _loadAndValidateConfig(explicitRoot = null) {
|
||||
)
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`Warning: Configuration file not found at derived root (${rootToUse}). Using defaults.`
|
||||
)
|
||||
// Don't warn about missing config during initialization
|
||||
// Only warn if this looks like an existing project (has .taskmaster dir or legacy config marker)
|
||||
const hasTaskmasterDir = fs.existsSync(
|
||||
path.join(rootToUse, TASKMASTER_DIR)
|
||||
);
|
||||
const hasLegacyMarker = fs.existsSync(
|
||||
path.join(rootToUse, LEGACY_CONFIG_FILE)
|
||||
);
|
||||
|
||||
if (hasTaskmasterDir || hasLegacyMarker) {
|
||||
console.warn(
|
||||
chalk.yellow(
|
||||
`Warning: Configuration file not found at derived root (${rootToUse}). Using defaults.`
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
// Keep config as defaults
|
||||
config = { ...defaults };
|
||||
@@ -592,6 +619,7 @@ function isApiKeySet(providerName, session = null, projectRoot = null) {
|
||||
const providersWithoutApiKeys = [
|
||||
CUSTOM_PROVIDERS.OLLAMA,
|
||||
CUSTOM_PROVIDERS.BEDROCK,
|
||||
CUSTOM_PROVIDERS.MCP,
|
||||
CUSTOM_PROVIDERS.GEMINI_CLI
|
||||
];
|
||||
|
||||
@@ -890,7 +918,8 @@ function getBaseUrlForRole(role, explicitRoot = null) {
|
||||
export const providersWithoutApiKeys = [
|
||||
CUSTOM_PROVIDERS.OLLAMA,
|
||||
CUSTOM_PROVIDERS.BEDROCK,
|
||||
CUSTOM_PROVIDERS.GEMINI_CLI
|
||||
CUSTOM_PROVIDERS.GEMINI_CLI,
|
||||
CUSTOM_PROVIDERS.MCP
|
||||
];
|
||||
|
||||
export {
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
*/
|
||||
|
||||
// Export all modules
|
||||
export * from './utils.js';
|
||||
export * from './ui.js';
|
||||
export * from './task-manager.js';
|
||||
export * from './utils.js';
|
||||
export * from './commands.js';
|
||||
export * from './task-manager.js';
|
||||
export * from './prompt-manager.js';
|
||||
|
||||
509
scripts/modules/prompt-manager.js
Normal file
509
scripts/modules/prompt-manager.js
Normal file
@@ -0,0 +1,509 @@
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { log } from './utils.js';
|
||||
import Ajv from 'ajv';
|
||||
import addFormats from 'ajv-formats';
|
||||
|
||||
/**
|
||||
* Manages prompt templates for AI interactions
|
||||
*/
|
||||
export class PromptManager {
|
||||
constructor() {
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
this.promptsDir = path.join(__dirname, '..', '..', 'src', 'prompts');
|
||||
this.cache = new Map();
|
||||
this.setupValidation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up JSON schema validation
|
||||
* @private
|
||||
*/
|
||||
setupValidation() {
|
||||
this.ajv = new Ajv({ allErrors: true, strict: false });
|
||||
addFormats(this.ajv);
|
||||
|
||||
try {
|
||||
// Load schema from src/prompts/schemas
|
||||
const schemaPath = path.join(
|
||||
this.promptsDir,
|
||||
'schemas',
|
||||
'prompt-template.schema.json'
|
||||
);
|
||||
const schemaContent = fs.readFileSync(schemaPath, 'utf-8');
|
||||
const schema = JSON.parse(schemaContent);
|
||||
|
||||
this.validatePrompt = this.ajv.compile(schema);
|
||||
log('info', '✓ JSON schema validation enabled');
|
||||
} catch (error) {
|
||||
log('warn', `⚠ Schema validation disabled: ${error.message}`);
|
||||
this.validatePrompt = () => true; // Fallback to no validation
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a prompt template and render it with variables
|
||||
* @param {string} promptId - The prompt template ID
|
||||
* @param {Object} variables - Variables to inject into the template
|
||||
* @param {string} [variantKey] - Optional specific variant to use
|
||||
* @returns {{systemPrompt: string, userPrompt: string, metadata: Object}}
|
||||
*/
|
||||
loadPrompt(promptId, variables = {}, variantKey = null) {
|
||||
try {
|
||||
// Check cache first
|
||||
const cacheKey = `${promptId}-${JSON.stringify(variables)}-${variantKey}`;
|
||||
if (this.cache.has(cacheKey)) {
|
||||
return this.cache.get(cacheKey);
|
||||
}
|
||||
|
||||
// Load template
|
||||
const template = this.loadTemplate(promptId);
|
||||
|
||||
// Validate parameters if schema validation is available
|
||||
if (this.validatePrompt && this.validatePrompt !== true) {
|
||||
this.validateParameters(template, variables);
|
||||
}
|
||||
|
||||
// Select the variant - use specified key or select based on conditions
|
||||
const variant = variantKey
|
||||
? { ...template.prompts[variantKey], name: variantKey }
|
||||
: this.selectVariant(template, variables);
|
||||
|
||||
// Render the prompts with variables
|
||||
const rendered = {
|
||||
systemPrompt: this.renderTemplate(variant.system, variables),
|
||||
userPrompt: this.renderTemplate(variant.user, variables),
|
||||
metadata: {
|
||||
templateId: template.id,
|
||||
version: template.version,
|
||||
variant: variant.name || 'default',
|
||||
parameters: variables
|
||||
}
|
||||
};
|
||||
|
||||
// Cache the result
|
||||
this.cache.set(cacheKey, rendered);
|
||||
|
||||
return rendered;
|
||||
} catch (error) {
|
||||
log('error', `Failed to load prompt ${promptId}: ${error.message}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a prompt template from disk
|
||||
* @private
|
||||
*/
|
||||
loadTemplate(promptId) {
|
||||
const templatePath = path.join(this.promptsDir, `${promptId}.json`);
|
||||
|
||||
try {
|
||||
const content = fs.readFileSync(templatePath, 'utf-8');
|
||||
const template = JSON.parse(content);
|
||||
|
||||
// Schema validation if available (do this first for detailed errors)
|
||||
if (this.validatePrompt && this.validatePrompt !== true) {
|
||||
const valid = this.validatePrompt(template);
|
||||
if (!valid) {
|
||||
const errors = this.validatePrompt.errors
|
||||
.map((err) => `${err.instancePath || 'root'}: ${err.message}`)
|
||||
.join(', ');
|
||||
throw new Error(`Schema validation failed: ${errors}`);
|
||||
}
|
||||
} else {
|
||||
// Fallback basic validation if no schema validation available
|
||||
if (!template.id || !template.prompts || !template.prompts.default) {
|
||||
throw new Error(
|
||||
'Invalid template structure: missing required fields (id, prompts.default)'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return template;
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
throw new Error(`Prompt template '${promptId}' not found`);
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate parameters against template schema
|
||||
* @private
|
||||
*/
|
||||
validateParameters(template, variables) {
|
||||
if (!template.parameters) return;
|
||||
|
||||
const errors = [];
|
||||
|
||||
for (const [paramName, paramConfig] of Object.entries(
|
||||
template.parameters
|
||||
)) {
|
||||
const value = variables[paramName];
|
||||
|
||||
// Check required parameters
|
||||
if (paramConfig.required && value === undefined) {
|
||||
errors.push(`Required parameter '${paramName}' missing`);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip validation for undefined optional parameters
|
||||
if (value === undefined) continue;
|
||||
|
||||
// Type validation
|
||||
if (!this.validateParameterType(value, paramConfig.type)) {
|
||||
errors.push(
|
||||
`Parameter '${paramName}' expected ${paramConfig.type}, got ${typeof value}`
|
||||
);
|
||||
}
|
||||
|
||||
// Enum validation
|
||||
if (paramConfig.enum && !paramConfig.enum.includes(value)) {
|
||||
errors.push(
|
||||
`Parameter '${paramName}' must be one of: ${paramConfig.enum.join(', ')}`
|
||||
);
|
||||
}
|
||||
|
||||
// Pattern validation for strings
|
||||
if (paramConfig.pattern && typeof value === 'string') {
|
||||
const regex = new RegExp(paramConfig.pattern);
|
||||
if (!regex.test(value)) {
|
||||
errors.push(
|
||||
`Parameter '${paramName}' does not match required pattern: ${paramConfig.pattern}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Range validation for numbers
|
||||
if (typeof value === 'number') {
|
||||
if (paramConfig.minimum !== undefined && value < paramConfig.minimum) {
|
||||
errors.push(
|
||||
`Parameter '${paramName}' must be >= ${paramConfig.minimum}`
|
||||
);
|
||||
}
|
||||
if (paramConfig.maximum !== undefined && value > paramConfig.maximum) {
|
||||
errors.push(
|
||||
`Parameter '${paramName}' must be <= ${paramConfig.maximum}`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
throw new Error(`Parameter validation failed: ${errors.join('; ')}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate parameter type
|
||||
* @private
|
||||
*/
|
||||
validateParameterType(value, expectedType) {
|
||||
switch (expectedType) {
|
||||
case 'string':
|
||||
return typeof value === 'string';
|
||||
case 'number':
|
||||
return typeof value === 'number';
|
||||
case 'boolean':
|
||||
return typeof value === 'boolean';
|
||||
case 'array':
|
||||
return Array.isArray(value);
|
||||
case 'object':
|
||||
return (
|
||||
typeof value === 'object' && value !== null && !Array.isArray(value)
|
||||
);
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select the best variant based on conditions
|
||||
* @private
|
||||
*/
|
||||
selectVariant(template, variables) {
|
||||
// Check each variant's condition
|
||||
for (const [name, variant] of Object.entries(template.prompts)) {
|
||||
if (name === 'default') continue;
|
||||
|
||||
if (
|
||||
variant.condition &&
|
||||
this.evaluateCondition(variant.condition, variables)
|
||||
) {
|
||||
return { ...variant, name };
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to default
|
||||
return { ...template.prompts.default, name: 'default' };
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate a condition string
|
||||
* @private
|
||||
*/
|
||||
evaluateCondition(condition, variables) {
|
||||
try {
|
||||
// Create a safe evaluation context
|
||||
const context = { ...variables };
|
||||
|
||||
// Simple condition evaluation (can be enhanced)
|
||||
// For now, supports basic comparisons
|
||||
const func = new Function(...Object.keys(context), `return ${condition}`);
|
||||
return func(...Object.values(context));
|
||||
} catch (error) {
|
||||
log('warn', `Failed to evaluate condition: ${condition}`);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Render a template string with variables
|
||||
* @private
|
||||
*/
|
||||
renderTemplate(template, variables) {
|
||||
let rendered = template;
|
||||
|
||||
// Handle helper functions like (eq variable "value")
|
||||
rendered = rendered.replace(
|
||||
/\(eq\s+(\w+(?:\.\w+)*)\s+"([^"]+)"\)/g,
|
||||
(match, path, compareValue) => {
|
||||
const value = this.getNestedValue(variables, path);
|
||||
return value === compareValue ? 'true' : 'false';
|
||||
}
|
||||
);
|
||||
|
||||
// Handle not helper function like (not variable)
|
||||
rendered = rendered.replace(/\(not\s+(\w+(?:\.\w+)*)\)/g, (match, path) => {
|
||||
const value = this.getNestedValue(variables, path);
|
||||
return !value ? 'true' : 'false';
|
||||
});
|
||||
|
||||
// Handle gt (greater than) helper function like (gt variable 0)
|
||||
rendered = rendered.replace(
|
||||
/\(gt\s+(\w+(?:\.\w+)*)\s+(\d+(?:\.\d+)?)\)/g,
|
||||
(match, path, compareValue) => {
|
||||
const value = this.getNestedValue(variables, path);
|
||||
const numValue = parseFloat(compareValue);
|
||||
return typeof value === 'number' && value > numValue ? 'true' : 'false';
|
||||
}
|
||||
);
|
||||
|
||||
// Handle gte (greater than or equal) helper function like (gte variable 0)
|
||||
rendered = rendered.replace(
|
||||
/\(gte\s+(\w+(?:\.\w+)*)\s+(\d+(?:\.\d+)?)\)/g,
|
||||
(match, path, compareValue) => {
|
||||
const value = this.getNestedValue(variables, path);
|
||||
const numValue = parseFloat(compareValue);
|
||||
return typeof value === 'number' && value >= numValue
|
||||
? 'true'
|
||||
: 'false';
|
||||
}
|
||||
);
|
||||
|
||||
// Handle conditionals with else {{#if variable}}...{{else}}...{{/if}}
|
||||
rendered = rendered.replace(
|
||||
/\{\{#if\s+([^}]+)\}\}([\s\S]*?)(?:\{\{else\}\}([\s\S]*?))?\{\{\/if\}\}/g,
|
||||
(match, condition, trueContent, falseContent = '') => {
|
||||
// Handle boolean values and helper function results
|
||||
let value;
|
||||
if (condition === 'true') {
|
||||
value = true;
|
||||
} else if (condition === 'false') {
|
||||
value = false;
|
||||
} else {
|
||||
value = this.getNestedValue(variables, condition);
|
||||
}
|
||||
return value ? trueContent : falseContent;
|
||||
}
|
||||
);
|
||||
|
||||
// Handle each loops {{#each array}}...{{/each}}
|
||||
rendered = rendered.replace(
|
||||
/\{\{#each\s+(\w+(?:\.\w+)*)\}\}([\s\S]*?)\{\{\/each\}\}/g,
|
||||
(match, path, content) => {
|
||||
const array = this.getNestedValue(variables, path);
|
||||
if (!Array.isArray(array)) return '';
|
||||
|
||||
return array
|
||||
.map((item, index) => {
|
||||
// Create a context with item properties and special variables
|
||||
const itemContext = {
|
||||
...variables,
|
||||
...item,
|
||||
'@index': index,
|
||||
'@first': index === 0,
|
||||
'@last': index === array.length - 1
|
||||
};
|
||||
|
||||
// Recursively render the content with item context
|
||||
return this.renderTemplate(content, itemContext);
|
||||
})
|
||||
.join('');
|
||||
}
|
||||
);
|
||||
|
||||
// Handle json helper {{{json variable}}} (triple braces for raw output)
|
||||
rendered = rendered.replace(
|
||||
/\{\{\{json\s+(\w+(?:\.\w+)*)\}\}\}/g,
|
||||
(match, path) => {
|
||||
const value = this.getNestedValue(variables, path);
|
||||
return value !== undefined ? JSON.stringify(value, null, 2) : '';
|
||||
}
|
||||
);
|
||||
|
||||
// Handle variable substitution {{variable}}
|
||||
rendered = rendered.replace(/\{\{(\w+(?:\.\w+)*)\}\}/g, (match, path) => {
|
||||
const value = this.getNestedValue(variables, path);
|
||||
return value !== undefined ? value : '';
|
||||
});
|
||||
|
||||
return rendered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nested value from object using dot notation
|
||||
* @private
|
||||
*/
|
||||
getNestedValue(obj, path) {
|
||||
return path
|
||||
.split('.')
|
||||
.reduce(
|
||||
(current, key) =>
|
||||
current && current[key] !== undefined ? current[key] : undefined,
|
||||
obj
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate all prompt templates
|
||||
*/
|
||||
validateAllPrompts() {
|
||||
const results = { total: 0, errors: [], valid: [] };
|
||||
|
||||
try {
|
||||
const files = fs.readdirSync(this.promptsDir);
|
||||
const promptFiles = files.filter((file) => file.endsWith('.json'));
|
||||
|
||||
for (const file of promptFiles) {
|
||||
const promptId = file.replace('.json', '');
|
||||
results.total++;
|
||||
|
||||
try {
|
||||
this.loadTemplate(promptId);
|
||||
results.valid.push(promptId);
|
||||
} catch (error) {
|
||||
results.errors.push(`${promptId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
results.errors.push(
|
||||
`Failed to read templates directory: ${error.message}`
|
||||
);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all available prompt templates
|
||||
*/
|
||||
listPrompts() {
|
||||
try {
|
||||
const files = fs.readdirSync(this.promptsDir);
|
||||
const prompts = [];
|
||||
|
||||
for (const file of files) {
|
||||
if (!file.endsWith('.json')) continue;
|
||||
|
||||
const promptId = file.replace('.json', '');
|
||||
try {
|
||||
const template = this.loadTemplate(promptId);
|
||||
prompts.push({
|
||||
id: template.id,
|
||||
description: template.description,
|
||||
version: template.version,
|
||||
parameters: template.parameters,
|
||||
tags: template.metadata?.tags || []
|
||||
});
|
||||
} catch (error) {
|
||||
log('warn', `Failed to load template ${promptId}: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
return prompts;
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
// Templates directory doesn't exist yet
|
||||
return [];
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate template structure
|
||||
*/
|
||||
validateTemplate(templatePath) {
|
||||
try {
|
||||
const content = fs.readFileSync(templatePath, 'utf-8');
|
||||
const template = JSON.parse(content);
|
||||
|
||||
// Check required fields
|
||||
const required = ['id', 'version', 'description', 'prompts'];
|
||||
for (const field of required) {
|
||||
if (!template[field]) {
|
||||
return { valid: false, error: `Missing required field: ${field}` };
|
||||
}
|
||||
}
|
||||
|
||||
// Check default prompt exists
|
||||
if (!template.prompts.default) {
|
||||
return { valid: false, error: 'Missing default prompt variant' };
|
||||
}
|
||||
|
||||
// Check each variant has required fields
|
||||
for (const [name, variant] of Object.entries(template.prompts)) {
|
||||
if (!variant.system || !variant.user) {
|
||||
return {
|
||||
valid: false,
|
||||
error: `Variant '${name}' missing system or user prompt`
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Schema validation if available
|
||||
if (this.validatePrompt && this.validatePrompt !== true) {
|
||||
const valid = this.validatePrompt(template);
|
||||
if (!valid) {
|
||||
const errors = this.validatePrompt.errors
|
||||
.map((err) => `${err.instancePath || 'root'}: ${err.message}`)
|
||||
.join(', ');
|
||||
return { valid: false, error: `Schema validation failed: ${errors}` };
|
||||
}
|
||||
}
|
||||
|
||||
return { valid: true };
|
||||
} catch (error) {
|
||||
return { valid: false, error: error.message };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Singleton instance
|
||||
let promptManager = null;
|
||||
|
||||
/**
|
||||
* Get or create the prompt manager instance
|
||||
* @returns {PromptManager}
|
||||
*/
|
||||
export function getPromptManager() {
|
||||
if (!promptManager) {
|
||||
promptManager = new PromptManager();
|
||||
}
|
||||
return promptManager;
|
||||
}
|
||||
@@ -1,68 +1,4 @@
|
||||
{
|
||||
"bedrock": [
|
||||
{
|
||||
"id": "us.anthropic.claude-3-haiku-20240307-v1:0",
|
||||
"swe_score": 0.4,
|
||||
"cost_per_1m_tokens": { "input": 0.25, "output": 1.25 },
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-opus-20240229-v1:0",
|
||||
"swe_score": 0.725,
|
||||
"cost_per_1m_tokens": { "input": 15, "output": 75 },
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-5-sonnet-20240620-v1:0",
|
||||
"swe_score": 0.49,
|
||||
"cost_per_1m_tokens": { "input": 3, "output": 15 },
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
|
||||
"swe_score": 0.49,
|
||||
"cost_per_1m_tokens": { "input": 3, "output": 15 },
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-7-sonnet-20250219-v1:0",
|
||||
"swe_score": 0.623,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 65536
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-5-haiku-20241022-v1:0",
|
||||
"swe_score": 0.4,
|
||||
"cost_per_1m_tokens": { "input": 0.8, "output": 4 },
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-opus-4-20250514-v1:0",
|
||||
"swe_score": 0.725,
|
||||
"cost_per_1m_tokens": { "input": 15, "output": 75 },
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-sonnet-4-20250514-v1:0",
|
||||
"swe_score": 0.727,
|
||||
"cost_per_1m_tokens": { "input": 3, "output": 15 },
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.deepseek.r1-v1:0",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 1.35,
|
||||
"output": 5.4
|
||||
},
|
||||
"allowed_roles": ["research"],
|
||||
"max_tokens": 65536
|
||||
}
|
||||
],
|
||||
"anthropic": [
|
||||
{
|
||||
"id": "claude-sonnet-4-20250514",
|
||||
@@ -105,36 +41,60 @@
|
||||
"max_tokens": 8192
|
||||
}
|
||||
],
|
||||
"azure": [
|
||||
"claude-code": [
|
||||
{
|
||||
"id": "gpt-4o",
|
||||
"swe_score": 0.332,
|
||||
"id": "opus",
|
||||
"swe_score": 0.725,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 2.5,
|
||||
"output": 10.0
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 16384
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 32000
|
||||
},
|
||||
{
|
||||
"id": "gpt-4o-mini",
|
||||
"swe_score": 0.3,
|
||||
"id": "sonnet",
|
||||
"swe_score": 0.727,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.15,
|
||||
"output": 0.6
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 16384
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 64000
|
||||
}
|
||||
],
|
||||
"mcp": [
|
||||
{
|
||||
"id": "mcp-sampling",
|
||||
"swe_score": null,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 100000
|
||||
}
|
||||
],
|
||||
"gemini-cli": [
|
||||
{
|
||||
"id": "gemini-2.5-pro",
|
||||
"swe_score": 0.72,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 65536
|
||||
},
|
||||
{
|
||||
"id": "gpt-4-1",
|
||||
"swe_score": 0,
|
||||
"id": "gemini-2.5-flash",
|
||||
"swe_score": 0.71,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 2.0,
|
||||
"output": 10.0
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 16384
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 65536
|
||||
}
|
||||
],
|
||||
"openai": [
|
||||
@@ -299,6 +259,133 @@
|
||||
"max_tokens": 1048000
|
||||
}
|
||||
],
|
||||
"xai": [
|
||||
{
|
||||
"id": "grok-3",
|
||||
"name": "Grok 3",
|
||||
"swe_score": null,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 131072
|
||||
},
|
||||
{
|
||||
"id": "grok-3-fast",
|
||||
"name": "Grok 3 Fast",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 5,
|
||||
"output": 25
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 131072
|
||||
},
|
||||
{
|
||||
"id": "grok-4",
|
||||
"name": "Grok 4",
|
||||
"swe_score": null,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 131072
|
||||
}
|
||||
],
|
||||
"groq": [
|
||||
{
|
||||
"id": "llama-3.3-70b-versatile",
|
||||
"swe_score": 0.55,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.59,
|
||||
"output": 0.79
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 32768
|
||||
},
|
||||
{
|
||||
"id": "llama-3.1-8b-instant",
|
||||
"swe_score": 0.32,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.05,
|
||||
"output": 0.08
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 131072
|
||||
},
|
||||
{
|
||||
"id": "llama-4-scout",
|
||||
"swe_score": 0.45,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.11,
|
||||
"output": 0.34
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 32768
|
||||
},
|
||||
{
|
||||
"id": "llama-4-maverick",
|
||||
"swe_score": 0.52,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.5,
|
||||
"output": 0.77
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 32768
|
||||
},
|
||||
{
|
||||
"id": "mixtral-8x7b-32768",
|
||||
"swe_score": 0.35,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.24,
|
||||
"output": 0.24
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 32768
|
||||
},
|
||||
{
|
||||
"id": "qwen-qwq-32b-preview",
|
||||
"swe_score": 0.4,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.18,
|
||||
"output": 0.18
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 32768
|
||||
},
|
||||
{
|
||||
"id": "deepseek-r1-distill-llama-70b",
|
||||
"swe_score": 0.52,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.75,
|
||||
"output": 0.99
|
||||
},
|
||||
"allowed_roles": ["main", "research"],
|
||||
"max_tokens": 8192
|
||||
},
|
||||
{
|
||||
"id": "gemma2-9b-it",
|
||||
"swe_score": 0.3,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.2,
|
||||
"output": 0.2
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 8192
|
||||
},
|
||||
{
|
||||
"id": "whisper-large-v3",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.11,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main"],
|
||||
"max_tokens": 0
|
||||
}
|
||||
],
|
||||
"perplexity": [
|
||||
{
|
||||
"id": "sonar-pro",
|
||||
@@ -351,95 +438,6 @@
|
||||
"max_tokens": 8700
|
||||
}
|
||||
],
|
||||
"xai": [
|
||||
{
|
||||
"id": "grok-3",
|
||||
"name": "Grok 3",
|
||||
"swe_score": null,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 131072
|
||||
},
|
||||
{
|
||||
"id": "grok-3-fast",
|
||||
"name": "Grok 3 Fast",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 5,
|
||||
"output": 25
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 131072
|
||||
}
|
||||
],
|
||||
"ollama": [
|
||||
{
|
||||
"id": "devstral:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "qwen3:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "qwen3:14b",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "qwen3:32b",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "mistral-small3.1:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "llama3.3:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "phi4:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
}
|
||||
],
|
||||
"openrouter": [
|
||||
{
|
||||
"id": "google/gemini-2.5-flash-preview-05-20",
|
||||
@@ -692,47 +690,185 @@
|
||||
"max_tokens": 32768
|
||||
}
|
||||
],
|
||||
"claude-code": [
|
||||
"ollama": [
|
||||
{
|
||||
"id": "opus",
|
||||
"swe_score": 0.725,
|
||||
"id": "devstral:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 32000
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "sonnet",
|
||||
"swe_score": 0.727,
|
||||
"id": "qwen3:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 64000
|
||||
}
|
||||
],
|
||||
"gemini-cli": [
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "gemini-2.5-pro",
|
||||
"swe_score": 0.72,
|
||||
"id": "qwen3:14b",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "qwen3:32b",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "mistral-small3.1:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "llama3.3:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "phi4:latest",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
}
|
||||
],
|
||||
"azure": [
|
||||
{
|
||||
"id": "gpt-4o",
|
||||
"swe_score": 0.332,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 2.5,
|
||||
"output": 10.0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 16384
|
||||
},
|
||||
{
|
||||
"id": "gpt-4o-mini",
|
||||
"swe_score": 0.3,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.15,
|
||||
"output": 0.6
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 16384
|
||||
},
|
||||
{
|
||||
"id": "gpt-4-1",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 2.0,
|
||||
"output": 10.0
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"],
|
||||
"max_tokens": 16384
|
||||
}
|
||||
],
|
||||
"bedrock": [
|
||||
{
|
||||
"id": "us.anthropic.claude-3-haiku-20240307-v1:0",
|
||||
"swe_score": 0.4,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0.25,
|
||||
"output": 1.25
|
||||
},
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-opus-20240229-v1:0",
|
||||
"swe_score": 0.725,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 15,
|
||||
"output": 75
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-5-sonnet-20240620-v1:0",
|
||||
"swe_score": 0.49,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-5-sonnet-20241022-v2:0",
|
||||
"swe_score": 0.49,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-3-7-sonnet-20250219-v1:0",
|
||||
"swe_score": 0.623,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"max_tokens": 65536
|
||||
},
|
||||
{
|
||||
"id": "gemini-2.5-flash",
|
||||
"swe_score": 0.71,
|
||||
"id": "us.anthropic.claude-3-5-haiku-20241022-v1:0",
|
||||
"swe_score": 0.4,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 0,
|
||||
"output": 0
|
||||
"input": 0.8,
|
||||
"output": 4
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"],
|
||||
"allowed_roles": ["main", "fallback"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-opus-4-20250514-v1:0",
|
||||
"swe_score": 0.725,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 15,
|
||||
"output": 75
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.anthropic.claude-sonnet-4-20250514-v1:0",
|
||||
"swe_score": 0.727,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 3,
|
||||
"output": 15
|
||||
},
|
||||
"allowed_roles": ["main", "fallback", "research"]
|
||||
},
|
||||
{
|
||||
"id": "us.deepseek.r1-v1:0",
|
||||
"swe_score": 0,
|
||||
"cost_per_1m_tokens": {
|
||||
"input": 1.35,
|
||||
"output": 5.4
|
||||
},
|
||||
"allowed_roles": ["research"],
|
||||
"max_tokens": 65536
|
||||
}
|
||||
]
|
||||
|
||||
@@ -27,8 +27,15 @@ import {
|
||||
} from '../utils.js';
|
||||
import { generateObjectService } from '../ai-services-unified.js';
|
||||
import { getDefaultPriority } from '../config-manager.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import ContextGatherer from '../utils/contextGatherer.js';
|
||||
import generateTaskFiles from './generate-task-files.js';
|
||||
import {
|
||||
TASK_PRIORITY_OPTIONS,
|
||||
DEFAULT_TASK_PRIORITY,
|
||||
isValidTaskPriority,
|
||||
normalizeTaskPriority
|
||||
} from '../../../src/constants/task-priority.js';
|
||||
|
||||
// Define Zod schema for the expected AI output object
|
||||
const AiTaskDataSchema = z.object({
|
||||
@@ -115,7 +122,25 @@ async function addTask(
|
||||
success: (...args) => consoleLog('success', ...args)
|
||||
};
|
||||
|
||||
const effectivePriority = priority || getDefaultPriority(projectRoot);
|
||||
// Validate priority - only accept high, medium, or low
|
||||
let effectivePriority =
|
||||
priority || getDefaultPriority(projectRoot) || DEFAULT_TASK_PRIORITY;
|
||||
|
||||
// If priority is provided, validate and normalize it
|
||||
if (priority) {
|
||||
const normalizedPriority = normalizeTaskPriority(priority);
|
||||
if (normalizedPriority) {
|
||||
effectivePriority = normalizedPriority;
|
||||
} else {
|
||||
if (outputFormat === 'text') {
|
||||
consoleLog(
|
||||
'warn',
|
||||
`Invalid priority "${priority}". Using default priority "${DEFAULT_TASK_PRIORITY}".`
|
||||
);
|
||||
}
|
||||
effectivePriority = DEFAULT_TASK_PRIORITY;
|
||||
}
|
||||
}
|
||||
|
||||
logFn.info(
|
||||
`Adding new task with prompt: "${prompt}", Priority: ${effectivePriority}, Dependencies: ${dependencies.join(', ') || 'None'}, Research: ${useResearch}, ProjectRoot: ${projectRoot}`
|
||||
@@ -379,30 +404,6 @@ async function addTask(
|
||||
displayContextAnalysis(analysisData, prompt, gatheredContext.length);
|
||||
}
|
||||
|
||||
// System Prompt - Enhanced for dependency awareness
|
||||
const systemPrompt =
|
||||
"You are a helpful assistant that creates well-structured tasks for a software development project. Generate a single new task based on the user's description, adhering strictly to the provided JSON schema. Pay special attention to dependencies between tasks, ensuring the new task correctly references any tasks it depends on.\n\n" +
|
||||
'When determining dependencies for a new task, follow these principles:\n' +
|
||||
'1. Select dependencies based on logical requirements - what must be completed before this task can begin.\n' +
|
||||
'2. Prioritize task dependencies that are semantically related to the functionality being built.\n' +
|
||||
'3. Consider both direct dependencies (immediately prerequisite) and indirect dependencies.\n' +
|
||||
'4. Avoid adding unnecessary dependencies - only include tasks that are genuinely prerequisite.\n' +
|
||||
'5. Consider the current status of tasks - prefer completed tasks as dependencies when possible.\n' +
|
||||
"6. Pay special attention to foundation tasks (1-5) but don't automatically include them without reason.\n" +
|
||||
'7. Recent tasks (higher ID numbers) may be more relevant for newer functionality.\n\n' +
|
||||
'The dependencies array should contain task IDs (numbers) of prerequisite tasks.\n';
|
||||
|
||||
// Task Structure Description (for user prompt)
|
||||
const taskStructureDesc = `
|
||||
{
|
||||
"title": "Task title goes here",
|
||||
"description": "A concise one or two sentence description of what the task involves",
|
||||
"details": "Detailed implementation steps, considerations, code examples, or technical approach",
|
||||
"testStrategy": "Specific steps to verify correct implementation and functionality",
|
||||
"dependencies": [1, 3] // Example: IDs of tasks that must be completed before this task
|
||||
}
|
||||
`;
|
||||
|
||||
// Add any manually provided details to the prompt for context
|
||||
let contextFromArgs = '';
|
||||
if (manualTaskData?.title)
|
||||
@@ -414,18 +415,21 @@ async function addTask(
|
||||
if (manualTaskData?.testStrategy)
|
||||
contextFromArgs += `\n- Additional Test Strategy Context: "${manualTaskData.testStrategy}"`;
|
||||
|
||||
// User Prompt
|
||||
const userPrompt = `You are generating the details for Task #${newTaskId}. Based on the user's request: "${prompt}", create a comprehensive new task for a software development project.
|
||||
|
||||
${gatheredContext}
|
||||
|
||||
Based on the information about existing tasks provided above, include appropriate dependencies in the "dependencies" array. Only include task IDs that this new task directly depends on.
|
||||
|
||||
Return your answer as a single JSON object matching the schema precisely:
|
||||
${taskStructureDesc}
|
||||
|
||||
Make sure the details and test strategy are comprehensive and specific. DO NOT include the task ID in the title.
|
||||
`;
|
||||
// Load prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
const { systemPrompt, userPrompt } = await promptManager.loadPrompt(
|
||||
'add-task',
|
||||
{
|
||||
prompt,
|
||||
newTaskId,
|
||||
existingTasks: allTasks,
|
||||
gatheredContext,
|
||||
contextFromArgs,
|
||||
useResearch,
|
||||
priority: effectivePriority,
|
||||
dependencies: numericDependencies
|
||||
}
|
||||
);
|
||||
|
||||
// Start the loading indicator - only for text mode
|
||||
if (outputFormat === 'text') {
|
||||
|
||||
@@ -14,6 +14,7 @@ import {
|
||||
import { generateTextService } from '../ai-services-unified.js';
|
||||
|
||||
import { getDebugFlag, getProjectName } from '../config-manager.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import {
|
||||
COMPLEXITY_REPORT_FILE,
|
||||
LEGACY_TASKS_FILE
|
||||
@@ -239,7 +240,7 @@ async function analyzeTaskComplexity(options, context = {}) {
|
||||
tasks: relevantTaskIds,
|
||||
format: 'research'
|
||||
});
|
||||
gatheredContext = contextResult;
|
||||
gatheredContext = contextResult.context || '';
|
||||
}
|
||||
} catch (contextError) {
|
||||
reportLog(
|
||||
@@ -396,12 +397,20 @@ async function analyzeTaskComplexity(options, context = {}) {
|
||||
}
|
||||
|
||||
// Continue with regular analysis path
|
||||
const prompt = generateInternalComplexityAnalysisPrompt(
|
||||
tasksData,
|
||||
gatheredContext
|
||||
// Load prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
|
||||
const promptParams = {
|
||||
tasks: tasksData.tasks,
|
||||
gatheredContext: gatheredContext || '',
|
||||
useResearch: useResearch
|
||||
};
|
||||
|
||||
const { systemPrompt, userPrompt: prompt } = await promptManager.loadPrompt(
|
||||
'analyze-complexity',
|
||||
promptParams,
|
||||
'default'
|
||||
);
|
||||
const systemPrompt =
|
||||
'You are an expert software architect and project manager analyzing task complexity. Respond only with the requested valid JSON array.';
|
||||
|
||||
let loadingIndicator = null;
|
||||
if (outputFormat === 'text') {
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
import { generateTextService } from '../ai-services-unified.js';
|
||||
|
||||
import { getDefaultSubtasks, getDebugFlag } from '../config-manager.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import generateTaskFiles from './generate-task-files.js';
|
||||
import { COMPLEXITY_REPORT_FILE } from '../../../src/constants/paths.js';
|
||||
import { ContextGatherer } from '../utils/contextGatherer.js';
|
||||
@@ -60,128 +61,6 @@ const subtaskWrapperSchema = z.object({
|
||||
});
|
||||
// --- End Zod Schemas ---
|
||||
|
||||
/**
|
||||
* Generates the system prompt for the main AI role (e.g., Claude).
|
||||
* @param {number} subtaskCount - The target number of subtasks.
|
||||
* @returns {string} The system prompt.
|
||||
*/
|
||||
function generateMainSystemPrompt(subtaskCount) {
|
||||
return `You are an AI assistant helping with task breakdown for software development.
|
||||
You need to break down a high-level task into ${subtaskCount > 0 ? subtaskCount : 'an appropriate number of'} specific subtasks that can be implemented one by one.
|
||||
|
||||
Subtasks should:
|
||||
1. Be specific and actionable implementation steps
|
||||
2. Follow a logical sequence
|
||||
3. Each handle a distinct part of the parent task
|
||||
4. Include clear guidance on implementation approach
|
||||
5. Have appropriate dependency chains between subtasks (using the new sequential IDs)
|
||||
6. Collectively cover all aspects of the parent task
|
||||
|
||||
For each subtask, provide:
|
||||
- id: Sequential integer starting from the provided nextSubtaskId
|
||||
- title: Clear, specific title
|
||||
- description: Detailed description
|
||||
- dependencies: Array of prerequisite subtask IDs (use the new sequential IDs)
|
||||
- details: Implementation details, the output should be in string
|
||||
- testStrategy: Optional testing approach
|
||||
|
||||
|
||||
Respond ONLY with a valid JSON object containing a single key "subtasks" whose value is an array matching the structure described. Do not include any explanatory text, markdown formatting, or code block markers.`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the user prompt for the main AI role (e.g., Claude).
|
||||
* @param {Object} task - The parent task object.
|
||||
* @param {number} subtaskCount - The target number of subtasks.
|
||||
* @param {string} additionalContext - Optional additional context.
|
||||
* @param {number} nextSubtaskId - The starting ID for the new subtasks.
|
||||
* @returns {string} The user prompt.
|
||||
*/
|
||||
function generateMainUserPrompt(
|
||||
task,
|
||||
subtaskCount,
|
||||
additionalContext,
|
||||
nextSubtaskId
|
||||
) {
|
||||
const contextPrompt = additionalContext
|
||||
? `\n\nAdditional context: ${additionalContext}`
|
||||
: '';
|
||||
const schemaDescription = `
|
||||
{
|
||||
"subtasks": [
|
||||
{
|
||||
"id": ${nextSubtaskId}, // First subtask ID
|
||||
"title": "Specific subtask title",
|
||||
"description": "Detailed description",
|
||||
"dependencies": [], // e.g., [${nextSubtaskId + 1}] if it depends on the next
|
||||
"details": "Implementation guidance",
|
||||
"testStrategy": "Optional testing approach"
|
||||
},
|
||||
// ... (repeat for ${subtaskCount ? 'a total of ' + subtaskCount : 'each of the'} subtasks with sequential IDs)
|
||||
]
|
||||
}`;
|
||||
|
||||
return `Break down this task into ${subtaskCount > 0 ? 'exactly ' + subtaskCount : 'an appropriate number of'} specific subtasks:
|
||||
|
||||
Task ID: ${task.id}
|
||||
Title: ${task.title}
|
||||
Description: ${task.description}
|
||||
Current details: ${task.details || 'None'}
|
||||
${contextPrompt}
|
||||
|
||||
Return ONLY the JSON object containing the "subtasks" array, matching this structure:
|
||||
${schemaDescription}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the user prompt for the research AI role (e.g., Perplexity).
|
||||
* @param {Object} task - The parent task object.
|
||||
* @param {number} subtaskCount - The target number of subtasks.
|
||||
* @param {string} additionalContext - Optional additional context.
|
||||
* @param {number} nextSubtaskId - The starting ID for the new subtasks.
|
||||
* @returns {string} The user prompt.
|
||||
*/
|
||||
function generateResearchUserPrompt(
|
||||
task,
|
||||
subtaskCount,
|
||||
additionalContext,
|
||||
nextSubtaskId
|
||||
) {
|
||||
const contextPrompt = additionalContext
|
||||
? `\n\nConsider this context: ${additionalContext}`
|
||||
: '';
|
||||
const schemaDescription = `
|
||||
{
|
||||
"subtasks": [
|
||||
{
|
||||
"id": <number>, // Sequential ID starting from ${nextSubtaskId}
|
||||
"title": "<string>",
|
||||
"description": "<string>",
|
||||
"dependencies": [<number>], // e.g., [${nextSubtaskId + 1}]. If no dependencies, use an empty array [].
|
||||
"details": "<string>",
|
||||
"testStrategy": "<string>" // Optional
|
||||
},
|
||||
// ... (repeat for ${subtaskCount} subtasks)
|
||||
]
|
||||
}`;
|
||||
|
||||
return `Analyze the following task and break it down into ${subtaskCount > 0 ? 'exactly ' + subtaskCount : 'an appropriate number of'} specific subtasks using your research capabilities. Assign sequential IDs starting from ${nextSubtaskId}.
|
||||
|
||||
Parent Task:
|
||||
ID: ${task.id}
|
||||
Title: ${task.title}
|
||||
Description: ${task.description}
|
||||
Current details: ${task.details || 'None'}
|
||||
${contextPrompt}
|
||||
|
||||
CRITICAL: Respond ONLY with a valid JSON object containing a single key "subtasks". The value must be an array of the generated subtasks, strictly matching this structure:
|
||||
${schemaDescription}
|
||||
|
||||
Important: For the 'dependencies' field, if a subtask has no dependencies, you MUST use an empty array, for example: "dependencies": []. Do not use null or omit the field.
|
||||
|
||||
Do not include ANY explanatory text, markdown, or code block markers. Just the JSON object.`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse subtasks from AI's text response. Includes basic cleanup.
|
||||
* @param {string} text - Response text from AI.
|
||||
@@ -490,7 +369,7 @@ async function expandTask(
|
||||
tasks: finalTaskIds,
|
||||
format: 'research'
|
||||
});
|
||||
gatheredContext = contextResult;
|
||||
gatheredContext = contextResult.context || '';
|
||||
}
|
||||
} catch (contextError) {
|
||||
logger.warn(`Could not gather context: ${contextError.message}`);
|
||||
@@ -499,9 +378,7 @@ async function expandTask(
|
||||
|
||||
// --- Complexity Report Integration ---
|
||||
let finalSubtaskCount;
|
||||
let promptContent = '';
|
||||
let complexityReasoningContext = '';
|
||||
let systemPrompt; // Declare systemPrompt here
|
||||
|
||||
// Use tag-aware complexity report path
|
||||
const complexityReportPath = getTagAwareFilePath(
|
||||
@@ -570,52 +447,71 @@ async function expandTask(
|
||||
// Determine prompt content AND system prompt
|
||||
const nextSubtaskId = (task.subtasks?.length || 0) + 1;
|
||||
|
||||
// Load prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
|
||||
// Combine all context sources into a single additionalContext parameter
|
||||
let combinedAdditionalContext = '';
|
||||
if (additionalContext || complexityReasoningContext) {
|
||||
combinedAdditionalContext =
|
||||
`\n\n${additionalContext}${complexityReasoningContext}`.trim();
|
||||
}
|
||||
if (gatheredContext) {
|
||||
combinedAdditionalContext =
|
||||
`${combinedAdditionalContext}\n\n# Project Context\n\n${gatheredContext}`.trim();
|
||||
}
|
||||
|
||||
// Ensure expansionPrompt is a string (handle both string and object formats)
|
||||
let expansionPromptText = undefined;
|
||||
if (taskAnalysis?.expansionPrompt) {
|
||||
// Use prompt from complexity report
|
||||
promptContent = taskAnalysis.expansionPrompt;
|
||||
// Append additional context and reasoning
|
||||
promptContent += `\n\n${additionalContext}`.trim();
|
||||
promptContent += `${complexityReasoningContext}`.trim();
|
||||
if (gatheredContext) {
|
||||
promptContent += `\n\n# Project Context\n\n${gatheredContext}`;
|
||||
if (typeof taskAnalysis.expansionPrompt === 'string') {
|
||||
expansionPromptText = taskAnalysis.expansionPrompt;
|
||||
} else if (
|
||||
typeof taskAnalysis.expansionPrompt === 'object' &&
|
||||
taskAnalysis.expansionPrompt.text
|
||||
) {
|
||||
expansionPromptText = taskAnalysis.expansionPrompt.text;
|
||||
}
|
||||
}
|
||||
|
||||
// --- Use Simplified System Prompt for Report Prompts ---
|
||||
systemPrompt = `You are an AI assistant helping with task breakdown. Generate ${finalSubtaskCount > 0 ? 'exactly ' + finalSubtaskCount : 'an appropriate number of'} subtasks based on the provided prompt and context. Respond ONLY with a valid JSON object containing a single key "subtasks" whose value is an array of the generated subtask objects. Each subtask object in the array must have keys: "id", "title", "description", "dependencies", "details", "status". Ensure the 'id' starts from ${nextSubtaskId} and is sequential. Ensure 'dependencies' only reference valid prior subtask IDs generated in this response (starting from ${nextSubtaskId}). Ensure 'status' is 'pending'. Do not include any other text or explanation.`;
|
||||
logger.info(
|
||||
`Using expansion prompt from complexity report and simplified system prompt for task ${task.id}.`
|
||||
);
|
||||
// --- End Simplified System Prompt ---
|
||||
} else {
|
||||
// Use standard prompt generation
|
||||
let combinedAdditionalContext =
|
||||
`${additionalContext}${complexityReasoningContext}`.trim();
|
||||
if (gatheredContext) {
|
||||
combinedAdditionalContext =
|
||||
`${combinedAdditionalContext}\n\n# Project Context\n\n${gatheredContext}`.trim();
|
||||
}
|
||||
|
||||
if (useResearch) {
|
||||
promptContent = generateResearchUserPrompt(
|
||||
task,
|
||||
finalSubtaskCount,
|
||||
combinedAdditionalContext,
|
||||
nextSubtaskId
|
||||
);
|
||||
// Use the specific research system prompt if needed, or a standard one
|
||||
systemPrompt = `You are an AI assistant that responds ONLY with valid JSON objects as requested. The object should contain a 'subtasks' array.`; // Or keep generateResearchSystemPrompt if it exists
|
||||
// Ensure gatheredContext is a string (handle both string and object formats)
|
||||
let gatheredContextText = gatheredContext;
|
||||
if (typeof gatheredContext === 'object' && gatheredContext !== null) {
|
||||
if (gatheredContext.data) {
|
||||
gatheredContextText = gatheredContext.data;
|
||||
} else if (gatheredContext.text) {
|
||||
gatheredContextText = gatheredContext.text;
|
||||
} else {
|
||||
promptContent = generateMainUserPrompt(
|
||||
task,
|
||||
finalSubtaskCount,
|
||||
combinedAdditionalContext,
|
||||
nextSubtaskId
|
||||
);
|
||||
// Use the original detailed system prompt for standard generation
|
||||
systemPrompt = generateMainSystemPrompt(finalSubtaskCount);
|
||||
gatheredContextText = JSON.stringify(gatheredContext);
|
||||
}
|
||||
}
|
||||
|
||||
const promptParams = {
|
||||
task: task,
|
||||
subtaskCount: finalSubtaskCount,
|
||||
nextSubtaskId: nextSubtaskId,
|
||||
additionalContext: additionalContext,
|
||||
complexityReasoningContext: complexityReasoningContext,
|
||||
gatheredContext: gatheredContextText || '',
|
||||
useResearch: useResearch,
|
||||
expansionPrompt: expansionPromptText || undefined
|
||||
};
|
||||
|
||||
let variantKey = 'default';
|
||||
if (expansionPromptText) {
|
||||
variantKey = 'complexity-report';
|
||||
logger.info(
|
||||
`Using expansion prompt from complexity report for task ${task.id}.`
|
||||
);
|
||||
} else if (useResearch) {
|
||||
variantKey = 'research';
|
||||
logger.info(`Using research variant for task ${task.id}.`);
|
||||
} else {
|
||||
logger.info(`Using standard prompt generation for task ${task.id}.`);
|
||||
}
|
||||
|
||||
const { systemPrompt, userPrompt: promptContent } =
|
||||
await promptManager.loadPrompt('expand-task', promptParams, variantKey);
|
||||
// --- End Complexity Report / Prompt Logic ---
|
||||
|
||||
// --- AI Subtask Generation using generateTextService ---
|
||||
|
||||
@@ -864,64 +864,54 @@ function generateMarkdownOutput(data, filteredTasks, stats) {
|
||||
return '█'.repeat(filled) + '░'.repeat(empty);
|
||||
};
|
||||
|
||||
const taskProgressBar = createMarkdownProgressBar(completionPercentage, 20);
|
||||
const subtaskProgressBar = createMarkdownProgressBar(
|
||||
subtaskCompletionPercentage,
|
||||
20
|
||||
);
|
||||
|
||||
// Dashboard section
|
||||
markdown += '```\n';
|
||||
markdown +=
|
||||
'╭─────────────────────────────────────────────────────────╮╭─────────────────────────────────────────────────────────╮\n';
|
||||
markdown +=
|
||||
'│ ││ │\n';
|
||||
markdown +=
|
||||
'│ Project Dashboard ││ Dependency Status & Next Task │\n';
|
||||
markdown += `│ Tasks Progress: ${createMarkdownProgressBar(completionPercentage, 20)} ${Math.round(completionPercentage)}% ││ Dependency Metrics: │\n`;
|
||||
markdown += `│ ${Math.round(completionPercentage)}% ││ • Tasks with no dependencies: ${tasksWithNoDeps} │\n`;
|
||||
markdown += `│ Done: ${doneCount} In Progress: ${inProgressCount} Pending: ${pendingCount} Blocked: ${blockedCount} ││ • Tasks ready to work on: ${tasksReadyToWork} │\n`;
|
||||
markdown += `│ Deferred: ${deferredCount} Cancelled: ${cancelledCount} ││ • Tasks blocked by dependencies: ${tasksWithUnsatisfiedDeps} │\n`;
|
||||
markdown += `│ ││ • Most depended-on task: #${mostDependedOnTaskId} (${maxDependents} dependents) │\n`;
|
||||
markdown += `│ Subtasks Progress: ${createMarkdownProgressBar(subtaskCompletionPercentage, 20)} ││ • Avg dependencies per task: ${avgDependenciesPerTask.toFixed(1)} │\n`;
|
||||
markdown += `│ ${Math.round(subtaskCompletionPercentage)}% ${Math.round(subtaskCompletionPercentage)}% ││ │\n`;
|
||||
markdown += `│ Completed: ${completedSubtasks}/${totalSubtasks} In Progress: ${inProgressSubtasks} Pending: ${pendingSubtasks} ││ Next Task to Work On: │\n`;
|
||||
// markdown += '```\n';
|
||||
markdown += '| Project Dashboard | |\n';
|
||||
markdown += '| :- |:-|\n';
|
||||
markdown += `| Task Progress | ${taskProgressBar} ${Math.round(completionPercentage)}% |\n`;
|
||||
markdown += `| Done | ${doneCount} |\n`;
|
||||
markdown += `| In Progress | ${inProgressCount} |\n`;
|
||||
markdown += `| Pending | ${pendingCount} |\n`;
|
||||
markdown += `| Deferred | ${deferredCount} |\n`;
|
||||
markdown += `| Cancelled | ${cancelledCount} |\n`;
|
||||
markdown += `|-|-|\n`;
|
||||
markdown += `| Subtask Progress | ${subtaskProgressBar} ${Math.round(subtaskCompletionPercentage)}% |\n`;
|
||||
markdown += `| Completed | ${completedSubtasks} |\n`;
|
||||
markdown += `| In Progress | ${inProgressSubtasks} |\n`;
|
||||
markdown += `| Pending | ${pendingSubtasks} |\n`;
|
||||
|
||||
const nextTaskTitle = nextItem
|
||||
? nextItem.title.length > 40
|
||||
? nextItem.title.substring(0, 37) + '...'
|
||||
: nextItem.title
|
||||
: 'No task available';
|
||||
|
||||
markdown += `│ Blocked: ${blockedSubtasks} Deferred: ${deferredSubtasks} Cancelled: ${cancelledSubtasks} ││ ID: ${nextItem ? nextItem.id : 'N/A'} - ${nextTaskTitle} │\n`;
|
||||
markdown += `│ ││ Priority: ${nextItem ? nextItem.priority || 'medium' : ''} Dependencies: ${nextItem && nextItem.dependencies && nextItem.dependencies.length > 0 ? 'Some' : 'None'} │\n`;
|
||||
markdown += `│ Priority Breakdown: ││ Complexity: ${nextItem && nextItem.complexityScore ? '● ' + nextItem.complexityScore : 'N/A'} │\n`;
|
||||
markdown += `│ • High priority: ${data.tasks.filter((t) => t.priority === 'high').length} │╰─────────────────────────────────────────────────────────╯\n`;
|
||||
markdown += `│ • Medium priority: ${data.tasks.filter((t) => t.priority === 'medium').length} │\n`;
|
||||
markdown += `│ • Low priority: ${data.tasks.filter((t) => t.priority === 'low').length} │\n`;
|
||||
markdown += '│ │\n';
|
||||
markdown += '╰─────────────────────────────────────────────────────────╯\n';
|
||||
markdown += '\n\n';
|
||||
|
||||
// Tasks table
|
||||
markdown +=
|
||||
'┌───────────┬──────────────────────────────────────┬─────────────────┬──────────────┬───────────────────────┬───────────┐\n';
|
||||
'| ID | Title | Status | Priority | Dependencies | Complexity |\n';
|
||||
markdown +=
|
||||
'│ ID │ Title │ Status │ Priority │ Dependencies │ Complexi… │\n';
|
||||
markdown +=
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n';
|
||||
'| :- | :- | :- | :- | :- | :- |\n';
|
||||
|
||||
// Helper function to format status with symbols
|
||||
const getStatusSymbol = (status) => {
|
||||
switch (status) {
|
||||
case 'done':
|
||||
case 'completed':
|
||||
return '✓ done';
|
||||
return '✓ done';
|
||||
case 'in-progress':
|
||||
return '► in-progress';
|
||||
return '► in-progress';
|
||||
case 'pending':
|
||||
return '○ pending';
|
||||
return '○ pending';
|
||||
case 'blocked':
|
||||
return '⭕ blocked';
|
||||
return '⭕ blocked';
|
||||
case 'deferred':
|
||||
return 'x deferred';
|
||||
return 'x deferred';
|
||||
case 'cancelled':
|
||||
return 'x cancelled';
|
||||
return 'x cancelled';
|
||||
case 'review':
|
||||
return '? review';
|
||||
return '? review';
|
||||
default:
|
||||
return status || 'pending';
|
||||
}
|
||||
@@ -948,12 +938,12 @@ function generateMarkdownOutput(data, filteredTasks, stats) {
|
||||
? `● ${task.complexityScore}`
|
||||
: 'N/A';
|
||||
|
||||
markdown += `│ ${task.id.toString().padEnd(9)} │ ${taskTitle.substring(0, 36).padEnd(36)} │ ${statusSymbol.padEnd(15)} │ ${priority.padEnd(12)} │ ${deps.substring(0, 21).padEnd(21)} │ ${complexity.padEnd(9)} │\n`;
|
||||
markdown += `| ${task.id} | ${taskTitle} | ${statusSymbol} | ${priority} | ${deps} | ${complexity} |\n`;
|
||||
|
||||
// Add subtasks if requested
|
||||
if (withSubtasks && task.subtasks && task.subtasks.length > 0) {
|
||||
task.subtasks.forEach((subtask) => {
|
||||
const subtaskTitle = `└─ ${subtask.title}`; // No truncation
|
||||
const subtaskTitle = `${subtask.title}`; // No truncation
|
||||
const subtaskStatus = getStatusSymbol(subtask.status);
|
||||
const subtaskDeps = formatDependenciesForMarkdown(
|
||||
subtask.dependencies,
|
||||
@@ -963,85 +953,11 @@ function generateMarkdownOutput(data, filteredTasks, stats) {
|
||||
? subtask.complexityScore.toString()
|
||||
: 'N/A';
|
||||
|
||||
markdown +=
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n';
|
||||
markdown += `│ ${task.id}.${subtask.id}${' '.padEnd(6)} │ ${subtaskTitle.substring(0, 36).padEnd(36)} │ ${subtaskStatus.padEnd(15)} │ - │ ${subtaskDeps.substring(0, 21).padEnd(21)} │ ${subtaskComplexity.padEnd(9)} │\n`;
|
||||
markdown += `| ${task.id}.${subtask.id} | ${subtaskTitle} | ${subtaskStatus} | - | ${subtaskDeps} | ${subtaskComplexity} |\n`;
|
||||
});
|
||||
}
|
||||
|
||||
markdown +=
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n';
|
||||
});
|
||||
|
||||
// Close the table
|
||||
markdown = markdown.slice(
|
||||
0,
|
||||
-1 *
|
||||
'├───────────┼──────────────────────────────────────┼─────────────────┼──────────────┼───────────────────────┼───────────┤\n'
|
||||
.length
|
||||
);
|
||||
markdown +=
|
||||
'└───────────┴──────────────────────────────────────┴─────────────────┴──────────────┴───────────────────────┴───────────┘\n';
|
||||
markdown += '```\n\n';
|
||||
|
||||
// Next task recommendation
|
||||
if (nextItem) {
|
||||
markdown +=
|
||||
'╭────────────────────────────────────────────── ⚡ RECOMMENDED NEXT TASK ⚡ ──────────────────────────────────────────────╮\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown += `│ 🔥 Next Task to Work On: #${nextItem.id} - ${nextItem.title} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown += `│ Priority: ${nextItem.priority || 'medium'} Status: ${getStatusSymbol(nextItem.status)} │\n`;
|
||||
markdown += `│ Dependencies: ${nextItem.dependencies && nextItem.dependencies.length > 0 ? formatDependenciesForMarkdown(nextItem.dependencies, data.tasks) : 'None'} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown += `│ Description: ${getWorkItemDescription(nextItem, data.tasks)} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
|
||||
// Add subtasks if they exist
|
||||
const parentTask = data.tasks.find((t) => t.id === nextItem.id);
|
||||
if (parentTask && parentTask.subtasks && parentTask.subtasks.length > 0) {
|
||||
markdown +=
|
||||
'│ Subtasks: │\n';
|
||||
parentTask.subtasks.forEach((subtask) => {
|
||||
markdown += `│ ${nextItem.id}.${subtask.id} [${subtask.status || 'pending'}] ${subtask.title} │\n`;
|
||||
});
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
}
|
||||
|
||||
markdown += `│ Start working: task-master set-status --id=${nextItem.id} --status=in-progress │\n`;
|
||||
markdown += `│ View details: task-master show ${nextItem.id} │\n`;
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯\n\n';
|
||||
}
|
||||
|
||||
// Suggested next steps
|
||||
markdown += '\n';
|
||||
markdown +=
|
||||
'╭──────────────────────────────────────────────────────────────────────────────────────╮\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'│ Suggested Next Steps: │\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'│ 1. Run task-master next to see what to work on next │\n';
|
||||
markdown +=
|
||||
'│ 2. Run task-master expand --id=<id> to break down a task into subtasks │\n';
|
||||
markdown +=
|
||||
'│ 3. Run task-master set-status --id=<id> --status=done to mark a task as complete │\n';
|
||||
markdown +=
|
||||
'│ │\n';
|
||||
markdown +=
|
||||
'╰──────────────────────────────────────────────────────────────────────────────────────╯\n';
|
||||
|
||||
return markdown;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
|
||||
import { generateObjectService } from '../ai-services-unified.js';
|
||||
import { getDebugFlag } from '../config-manager.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import generateTaskFiles from './generate-task-files.js';
|
||||
import { displayAiUsageSummary } from '../ui.js';
|
||||
|
||||
@@ -147,10 +148,8 @@ async function parsePRD(prdPath, tasksPath, numTasks, options = {}) {
|
||||
report(overwriteError.message, 'error');
|
||||
if (outputFormat === 'text') {
|
||||
console.error(chalk.red(overwriteError.message));
|
||||
process.exit(1);
|
||||
} else {
|
||||
throw overwriteError;
|
||||
}
|
||||
throw overwriteError;
|
||||
} else {
|
||||
// Force overwrite is true
|
||||
report(
|
||||
@@ -172,74 +171,24 @@ async function parsePRD(prdPath, tasksPath, numTasks, options = {}) {
|
||||
throw new Error(`Input file ${prdPath} is empty or could not be read.`);
|
||||
}
|
||||
|
||||
// Research-specific enhancements to the system prompt
|
||||
const researchPromptAddition = research
|
||||
? `\nBefore breaking down the PRD into tasks, you will:
|
||||
1. Research and analyze the latest technologies, libraries, frameworks, and best practices that would be appropriate for this project
|
||||
2. Identify any potential technical challenges, security concerns, or scalability issues not explicitly mentioned in the PRD without discarding any explicit requirements or going overboard with complexity -- always aim to provide the most direct path to implementation, avoiding over-engineering or roundabout approaches
|
||||
3. Consider current industry standards and evolving trends relevant to this project (this step aims to solve LLM hallucinations and out of date information due to training data cutoff dates)
|
||||
4. Evaluate alternative implementation approaches and recommend the most efficient path
|
||||
5. Include specific library versions, helpful APIs, and concrete implementation guidance based on your research
|
||||
6. Always aim to provide the most direct path to implementation, avoiding over-engineering or roundabout approaches
|
||||
// Load prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
|
||||
Your task breakdown should incorporate this research, resulting in more detailed implementation guidance, more accurate dependency mapping, and more precise technology recommendations than would be possible from the PRD text alone, while maintaining all explicit requirements and best practices and all details and nuances of the PRD.`
|
||||
: '';
|
||||
// Get defaultTaskPriority from config
|
||||
const { getDefaultPriority } = await import('../config-manager.js');
|
||||
const defaultTaskPriority = getDefaultPriority(projectRoot) || 'medium';
|
||||
|
||||
// Base system prompt for PRD parsing
|
||||
const systemPrompt = `You are an AI assistant specialized in analyzing Product Requirements Documents (PRDs) and generating a structured, logically ordered, dependency-aware and sequenced list of development tasks in JSON format.${researchPromptAddition}
|
||||
|
||||
Analyze the provided PRD content and generate ${numTasks > 0 ? 'approximately ' + numTasks : 'an appropriate number of'} top-level development tasks. If the complexity or the level of detail of the PRD is high, generate more tasks relative to the complexity of the PRD
|
||||
Each task should represent a logical unit of work needed to implement the requirements and focus on the most direct and effective way to implement the requirements without unnecessary complexity or overengineering. Include pseudo-code, implementation details, and test strategy for each task. Find the most up to date information to implement each task.
|
||||
Assign sequential IDs starting from ${nextId}. Infer title, description, details, and test strategy for each task based *only* on the PRD content.
|
||||
Set status to 'pending', dependencies to an empty array [], and priority to 'medium' initially for all tasks.
|
||||
Respond ONLY with a valid JSON object containing a single key "tasks", where the value is an array of task objects adhering to the provided Zod schema. Do not include any explanation or markdown formatting.
|
||||
|
||||
Each task should follow this JSON structure:
|
||||
{
|
||||
"id": number,
|
||||
"title": string,
|
||||
"description": string,
|
||||
"status": "pending",
|
||||
"dependencies": number[] (IDs of tasks this depends on),
|
||||
"priority": "high" | "medium" | "low",
|
||||
"details": string (implementation details),
|
||||
"testStrategy": string (validation approach)
|
||||
}
|
||||
|
||||
Guidelines:
|
||||
1. ${numTasks > 0 ? 'Unless complexity warrants otherwise' : 'Depending on the complexity'}, create ${numTasks > 0 ? 'exactly ' + numTasks : 'an appropriate number of'} tasks, numbered sequentially starting from ${nextId}
|
||||
2. Each task should be atomic and focused on a single responsibility following the most up to date best practices and standards
|
||||
3. Order tasks logically - consider dependencies and implementation sequence
|
||||
4. Early tasks should focus on setup, core functionality first, then advanced features
|
||||
5. Include clear validation/testing approach for each task
|
||||
6. Set appropriate dependency IDs (a task can only depend on tasks with lower IDs, potentially including existing tasks with IDs less than ${nextId} if applicable)
|
||||
7. Assign priority (high/medium/low) based on criticality and dependency order
|
||||
8. Include detailed implementation guidance in the "details" field${research ? ', with specific libraries and version recommendations based on your research' : ''}
|
||||
9. If the PRD contains specific requirements for libraries, database schemas, frameworks, tech stacks, or any other implementation details, STRICTLY ADHERE to these requirements in your task breakdown and do not discard them under any circumstance
|
||||
10. Focus on filling in any gaps left by the PRD or areas that aren't fully specified, while preserving all explicit requirements
|
||||
11. Always aim to provide the most direct path to implementation, avoiding over-engineering or roundabout approaches${research ? '\n12. For each task, include specific, actionable guidance based on current industry standards and best practices discovered through research' : ''}`;
|
||||
|
||||
// Build user prompt with PRD content
|
||||
const userPrompt = `Here's the Product Requirements Document (PRD) to break down into approximately ${numTasks > 0 ? 'approximately ' + numTasks : 'an appropriate number of'} tasks, starting IDs from ${nextId}:${research ? '\n\nRemember to thoroughly research current best practices and technologies before task breakdown to provide specific, actionable implementation details.' : ''}\n\n${prdContent}\n\n
|
||||
|
||||
Return your response in this format:
|
||||
{
|
||||
"tasks": [
|
||||
{
|
||||
"id": 1,
|
||||
"title": "Setup Project Repository",
|
||||
"description": "...",
|
||||
...
|
||||
},
|
||||
...
|
||||
],
|
||||
"metadata": {
|
||||
"projectName": "PRD Implementation",
|
||||
"totalTasks": {number of tasks},
|
||||
"sourceFile": "${prdPath}",
|
||||
"generatedAt": "YYYY-MM-DD"
|
||||
}
|
||||
}`;
|
||||
const { systemPrompt, userPrompt } = await promptManager.loadPrompt(
|
||||
'parse-prd',
|
||||
{
|
||||
research,
|
||||
numTasks,
|
||||
nextId,
|
||||
prdContent,
|
||||
prdPath,
|
||||
defaultTaskPriority
|
||||
}
|
||||
);
|
||||
|
||||
// Call the unified AI service
|
||||
report(
|
||||
@@ -420,11 +369,9 @@ Guidelines:
|
||||
// Use projectRoot for debug flag check
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
process.exit(1);
|
||||
} else {
|
||||
throw error; // Re-throw for JSON output
|
||||
}
|
||||
|
||||
throw error; // Always re-throw for proper error handling
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import { highlight } from 'cli-highlight';
|
||||
import { ContextGatherer } from '../utils/contextGatherer.js';
|
||||
import { FuzzyTaskSearch } from '../utils/fuzzyTaskSearch.js';
|
||||
import { generateTextService } from '../ai-services-unified.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import {
|
||||
log as consoleLog,
|
||||
findProjectRoot,
|
||||
@@ -190,14 +191,24 @@ async function performResearch(
|
||||
const gatheredContext = contextResult.context;
|
||||
const tokenBreakdown = contextResult.tokenBreakdown;
|
||||
|
||||
// Build system prompt based on detail level
|
||||
const systemPrompt = buildResearchSystemPrompt(detailLevel, projectRoot);
|
||||
// Load prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
|
||||
// Build user prompt with context
|
||||
const userPrompt = buildResearchUserPrompt(
|
||||
query,
|
||||
gatheredContext,
|
||||
detailLevel
|
||||
const promptParams = {
|
||||
query: query,
|
||||
gatheredContext: gatheredContext || '',
|
||||
detailLevel: detailLevel,
|
||||
projectInfo: {
|
||||
root: projectRoot,
|
||||
taskCount: finalTaskIds.length,
|
||||
fileCount: filePaths.length
|
||||
}
|
||||
};
|
||||
|
||||
// Load prompts - the research template handles detail level internally
|
||||
const { systemPrompt, userPrompt } = await promptManager.loadPrompt(
|
||||
'research',
|
||||
promptParams
|
||||
);
|
||||
|
||||
// Count tokens for system and user prompts
|
||||
@@ -349,94 +360,6 @@ async function performResearch(
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build system prompt for research based on detail level
|
||||
* @param {string} detailLevel - Detail level: 'low', 'medium', 'high'
|
||||
* @param {string} projectRoot - Project root for context
|
||||
* @returns {string} System prompt
|
||||
*/
|
||||
function buildResearchSystemPrompt(detailLevel, projectRoot) {
|
||||
const basePrompt = `You are an expert AI research assistant helping with a software development project. You have access to project context including tasks, files, and project structure.
|
||||
|
||||
Your role is to provide comprehensive, accurate, and actionable research responses based on the user's query and the provided project context.`;
|
||||
|
||||
const detailInstructions = {
|
||||
low: `
|
||||
**Response Style: Concise & Direct**
|
||||
- Provide brief, focused answers (2-4 paragraphs maximum)
|
||||
- Focus on the most essential information
|
||||
- Use bullet points for key takeaways
|
||||
- Avoid lengthy explanations unless critical
|
||||
- Skip pleasantries, introductions, and conclusions
|
||||
- No phrases like "Based on your project context" or "I'll provide guidance"
|
||||
- No summary outros or alignment statements
|
||||
- Get straight to the actionable information
|
||||
- Use simple, direct language - users want info, not explanation`,
|
||||
|
||||
medium: `
|
||||
**Response Style: Balanced & Comprehensive**
|
||||
- Provide thorough but well-structured responses (4-8 paragraphs)
|
||||
- Include relevant examples and explanations
|
||||
- Balance depth with readability
|
||||
- Use headings and bullet points for organization`,
|
||||
|
||||
high: `
|
||||
**Response Style: Detailed & Exhaustive**
|
||||
- Provide comprehensive, in-depth analysis (8+ paragraphs)
|
||||
- Include multiple perspectives and approaches
|
||||
- Provide detailed examples, code snippets, and step-by-step guidance
|
||||
- Cover edge cases and potential pitfalls
|
||||
- Use clear structure with headings, subheadings, and lists`
|
||||
};
|
||||
|
||||
return `${basePrompt}
|
||||
|
||||
${detailInstructions[detailLevel]}
|
||||
|
||||
**Guidelines:**
|
||||
- Always consider the project context when formulating responses
|
||||
- Reference specific tasks, files, or project elements when relevant
|
||||
- Provide actionable insights that can be applied to the project
|
||||
- If the query relates to existing project tasks, suggest how the research applies to those tasks
|
||||
- Use markdown formatting for better readability
|
||||
- Be precise and avoid speculation unless clearly marked as such
|
||||
|
||||
**For LOW detail level specifically:**
|
||||
- Start immediately with the core information
|
||||
- No introductory phrases or context acknowledgments
|
||||
- No concluding summaries or project alignment statements
|
||||
- Focus purely on facts, steps, and actionable items`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build user prompt with query and context
|
||||
* @param {string} query - User's research query
|
||||
* @param {string} gatheredContext - Gathered project context
|
||||
* @param {string} detailLevel - Detail level for response guidance
|
||||
* @returns {string} Complete user prompt
|
||||
*/
|
||||
function buildResearchUserPrompt(query, gatheredContext, detailLevel) {
|
||||
let prompt = `# Research Query
|
||||
|
||||
${query}`;
|
||||
|
||||
if (gatheredContext && gatheredContext.trim()) {
|
||||
prompt += `
|
||||
|
||||
# Project Context
|
||||
|
||||
${gatheredContext}`;
|
||||
}
|
||||
|
||||
prompt += `
|
||||
|
||||
# Instructions
|
||||
|
||||
Please research and provide a ${detailLevel}-detail response to the query above. Consider the project context provided and make your response as relevant and actionable as possible for this specific project.`;
|
||||
|
||||
return prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display detailed token breakdown for context and prompts
|
||||
* @param {Object} tokenBreakdown - Token breakdown from context gatherer
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
} from '../utils.js';
|
||||
import { generateTextService } from '../ai-services-unified.js';
|
||||
import { getDebugFlag } from '../config-manager.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import generateTaskFiles from './generate-task-files.js';
|
||||
import { ContextGatherer } from '../utils/contextGatherer.js';
|
||||
import { FuzzyTaskSearch } from '../utils/fuzzyTaskSearch.js';
|
||||
@@ -160,7 +161,7 @@ async function updateSubtaskById(
|
||||
tasks: finalTaskIds,
|
||||
format: 'research'
|
||||
});
|
||||
gatheredContext = contextResult;
|
||||
gatheredContext = contextResult.context || '';
|
||||
}
|
||||
} catch (contextError) {
|
||||
report('warn', `Could not gather context: ${contextError.message}`);
|
||||
@@ -213,7 +214,7 @@ async function updateSubtaskById(
|
||||
title: parentTask.subtasks[subtaskIndex - 1].title,
|
||||
status: parentTask.subtasks[subtaskIndex - 1].status
|
||||
}
|
||||
: null;
|
||||
: undefined;
|
||||
const nextSubtask =
|
||||
subtaskIndex < parentTask.subtasks.length - 1
|
||||
? {
|
||||
@@ -221,32 +222,27 @@ async function updateSubtaskById(
|
||||
title: parentTask.subtasks[subtaskIndex + 1].title,
|
||||
status: parentTask.subtasks[subtaskIndex + 1].status
|
||||
}
|
||||
: null;
|
||||
: undefined;
|
||||
|
||||
const contextString = `
|
||||
Parent Task: ${JSON.stringify(parentContext)}
|
||||
${prevSubtask ? `Previous Subtask: ${JSON.stringify(prevSubtask)}` : ''}
|
||||
${nextSubtask ? `Next Subtask: ${JSON.stringify(nextSubtask)}` : ''}
|
||||
Current Subtask Details (for context only):\n${subtask.details || '(No existing details)'}
|
||||
`;
|
||||
// Build prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
|
||||
const systemPrompt = `You are an AI assistant helping to update a subtask. You will be provided with the subtask's existing details, context about its parent and sibling tasks, and a user request string.
|
||||
const promptParams = {
|
||||
parentTask: parentContext,
|
||||
prevSubtask: prevSubtask,
|
||||
nextSubtask: nextSubtask,
|
||||
currentDetails: subtask.details || '(No existing details)',
|
||||
updatePrompt: prompt,
|
||||
useResearch: useResearch,
|
||||
gatheredContext: gatheredContext || ''
|
||||
};
|
||||
|
||||
Your Goal: Based *only* on the user's request and all the provided context (including existing details if relevant to the request), GENERATE the new text content that should be added to the subtask's details.
|
||||
Focus *only* on generating the substance of the update.
|
||||
|
||||
Output Requirements:
|
||||
1. Return *only* the newly generated text content as a plain string. Do NOT return a JSON object or any other structured data.
|
||||
2. Your string response should NOT include any of the subtask's original details, unless the user's request explicitly asks to rephrase, summarize, or directly modify existing text.
|
||||
3. Do NOT include any timestamps, XML-like tags, markdown, or any other special formatting in your string response.
|
||||
4. Ensure the generated text is concise yet complete for the update based on the user request. Avoid conversational fillers or explanations about what you are doing (e.g., do not start with "Okay, here's the update...").`;
|
||||
|
||||
// Pass the existing subtask.details in the user prompt for the AI's context.
|
||||
let userPrompt = `Task Context:\n${contextString}\n\nUser Request: "${prompt}"\n\nBased on the User Request and all the Task Context (including current subtask details provided above), what is the new information or text that should be appended to this subtask's details? Return ONLY this new text as a plain string.`;
|
||||
|
||||
if (gatheredContext) {
|
||||
userPrompt += `\n\n# Additional Project Context\n\n${gatheredContext}`;
|
||||
}
|
||||
const variantKey = useResearch ? 'research' : 'default';
|
||||
const { systemPrompt, userPrompt } = await promptManager.loadPrompt(
|
||||
'update-subtask',
|
||||
promptParams,
|
||||
variantKey
|
||||
);
|
||||
|
||||
const role = useResearch ? 'research' : 'main';
|
||||
report('info', `Using AI text service with role: ${role}`);
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
|
||||
import { generateTextService } from '../ai-services-unified.js';
|
||||
import { getDebugFlag, isApiKeySet } from '../config-manager.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import { ContextGatherer } from '../utils/contextGatherer.js';
|
||||
import { FuzzyTaskSearch } from '../utils/fuzzyTaskSearch.js';
|
||||
|
||||
@@ -345,7 +346,7 @@ async function updateTaskById(
|
||||
tasks: finalTaskIds,
|
||||
format: 'research'
|
||||
});
|
||||
gatheredContext = contextResult;
|
||||
gatheredContext = contextResult.context || '';
|
||||
}
|
||||
} catch (contextError) {
|
||||
report('warn', `Could not gather context: ${contextError.message}`);
|
||||
@@ -408,69 +409,61 @@ async function updateTaskById(
|
||||
);
|
||||
}
|
||||
|
||||
// --- Build Prompts (Different for append vs full update) ---
|
||||
// --- Build Prompts using PromptManager ---
|
||||
const promptManager = getPromptManager();
|
||||
|
||||
const promptParams = {
|
||||
task: taskToUpdate,
|
||||
taskJson: JSON.stringify(taskToUpdate, null, 2),
|
||||
updatePrompt: prompt,
|
||||
appendMode: appendMode,
|
||||
useResearch: useResearch,
|
||||
currentDetails: taskToUpdate.details || '(No existing details)',
|
||||
gatheredContext: gatheredContext || ''
|
||||
};
|
||||
|
||||
const variantKey = appendMode
|
||||
? 'append'
|
||||
: useResearch
|
||||
? 'research'
|
||||
: 'default';
|
||||
|
||||
report(
|
||||
'info',
|
||||
`Loading prompt template with variant: ${variantKey}, appendMode: ${appendMode}, useResearch: ${useResearch}`
|
||||
);
|
||||
|
||||
let systemPrompt;
|
||||
let userPrompt;
|
||||
try {
|
||||
const promptResult = await promptManager.loadPrompt(
|
||||
'update-task',
|
||||
promptParams,
|
||||
variantKey
|
||||
);
|
||||
report(
|
||||
'info',
|
||||
`Prompt result type: ${typeof promptResult}, keys: ${promptResult ? Object.keys(promptResult).join(', ') : 'null'}`
|
||||
);
|
||||
|
||||
if (appendMode) {
|
||||
// Append mode: generate new content to add to task details
|
||||
systemPrompt = `You are an AI assistant helping to append additional information to a software development task. You will be provided with the task's existing details, context, and a user request string.
|
||||
// Extract prompts - loadPrompt returns { systemPrompt, userPrompt, metadata }
|
||||
systemPrompt = promptResult.systemPrompt;
|
||||
userPrompt = promptResult.userPrompt;
|
||||
|
||||
Your Goal: Based *only* on the user's request and all the provided context (including existing details if relevant to the request), GENERATE the new text content that should be added to the task's details.
|
||||
Focus *only* on generating the substance of the update.
|
||||
report(
|
||||
'info',
|
||||
`Loaded prompts - systemPrompt length: ${systemPrompt?.length}, userPrompt length: ${userPrompt?.length}`
|
||||
);
|
||||
} catch (error) {
|
||||
report('error', `Failed to load prompt template: ${error.message}`);
|
||||
throw new Error(`Failed to load prompt template: ${error.message}`);
|
||||
}
|
||||
|
||||
Output Requirements:
|
||||
1. Return *only* the newly generated text content as a plain string. Do NOT return a JSON object or any other structured data.
|
||||
2. Your string response should NOT include any of the task's original details, unless the user's request explicitly asks to rephrase, summarize, or directly modify existing text.
|
||||
3. Do NOT include any timestamps, XML-like tags, markdown, or any other special formatting in your string response.
|
||||
4. Ensure the generated text is concise yet complete for the update based on the user request. Avoid conversational fillers or explanations about what you are doing (e.g., do not start with "Okay, here's the update...").`;
|
||||
|
||||
const taskContext = `
|
||||
Task: ${JSON.stringify({
|
||||
id: taskToUpdate.id,
|
||||
title: taskToUpdate.title,
|
||||
description: taskToUpdate.description,
|
||||
status: taskToUpdate.status
|
||||
})}
|
||||
Current Task Details (for context only):\n${taskToUpdate.details || '(No existing details)'}
|
||||
`;
|
||||
|
||||
userPrompt = `Task Context:\n${taskContext}\n\nUser Request: "${prompt}"\n\nBased on the User Request and all the Task Context (including current task details provided above), what is the new information or text that should be appended to this task's details? Return ONLY this new text as a plain string.`;
|
||||
|
||||
if (gatheredContext) {
|
||||
userPrompt += `\n\n# Additional Project Context\n\n${gatheredContext}`;
|
||||
}
|
||||
} else {
|
||||
// Full update mode: use original prompts
|
||||
systemPrompt = `You are an AI assistant helping to update a software development task based on new context.
|
||||
You will be given a task and a prompt describing changes or new implementation details.
|
||||
Your job is to update the task to reflect these changes, while preserving its basic structure.
|
||||
|
||||
Guidelines:
|
||||
1. VERY IMPORTANT: NEVER change the title of the task - keep it exactly as is
|
||||
2. Maintain the same ID, status, and dependencies unless specifically mentioned in the prompt
|
||||
3. Update the description, details, and test strategy to reflect the new information
|
||||
4. Do not change anything unnecessarily - just adapt what needs to change based on the prompt
|
||||
5. Return a complete valid JSON object representing the updated task
|
||||
6. VERY IMPORTANT: Preserve all subtasks marked as "done" or "completed" - do not modify their content
|
||||
7. For tasks with completed subtasks, build upon what has already been done rather than rewriting everything
|
||||
8. If an existing completed subtask needs to be changed/undone based on the new context, DO NOT modify it directly
|
||||
9. Instead, add a new subtask that clearly indicates what needs to be changed or replaced
|
||||
10. Use the existence of completed subtasks as an opportunity to make new subtasks more specific and targeted
|
||||
11. Ensure any new subtasks have unique IDs that don't conflict with existing ones
|
||||
12. CRITICAL: For subtask IDs, use ONLY numeric values (1, 2, 3, etc.) NOT strings ("1", "2", "3")
|
||||
13. CRITICAL: Subtask IDs should start from 1 and increment sequentially (1, 2, 3...) - do NOT use parent task ID as prefix
|
||||
|
||||
The changes described in the prompt should be thoughtfully applied to make the task more accurate and actionable.`;
|
||||
|
||||
const taskDataString = JSON.stringify(taskToUpdate, null, 2);
|
||||
userPrompt = `Here is the task to update:\n${taskDataString}\n\nPlease update this task based on the following new context:\n${prompt}\n\nIMPORTANT: In the task JSON above, any subtasks with "status": "done" or "status": "completed" should be preserved exactly as is. Build your changes around these completed items.`;
|
||||
|
||||
if (gatheredContext) {
|
||||
userPrompt += `\n\n# Project Context\n\n${gatheredContext}`;
|
||||
}
|
||||
|
||||
userPrompt += `\n\nReturn only the updated task as a valid JSON object.`;
|
||||
// If prompts are still not set, throw an error
|
||||
if (!systemPrompt || !userPrompt) {
|
||||
throw new Error(
|
||||
`Failed to load prompts: systemPrompt=${!!systemPrompt}, userPrompt=${!!userPrompt}`
|
||||
);
|
||||
}
|
||||
// --- End Build Prompts ---
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
} from '../ui.js';
|
||||
|
||||
import { getDebugFlag } from '../config-manager.js';
|
||||
import { getPromptManager } from '../prompt-manager.js';
|
||||
import generateTaskFiles from './generate-task-files.js';
|
||||
import { generateTextService } from '../ai-services-unified.js';
|
||||
import { getModelConfiguration } from './models.js';
|
||||
@@ -299,7 +300,7 @@ async function updateTasks(
|
||||
tasks: finalTaskIds,
|
||||
format: 'research'
|
||||
});
|
||||
gatheredContext = contextResult; // contextResult is a string
|
||||
gatheredContext = contextResult.context || '';
|
||||
}
|
||||
} catch (contextError) {
|
||||
logFn(
|
||||
@@ -368,35 +369,18 @@ async function updateTasks(
|
||||
}
|
||||
// --- End Display Tasks ---
|
||||
|
||||
// --- Build Prompts (Unchanged Core Logic) ---
|
||||
// Keep the original system prompt logic
|
||||
const systemPrompt = `You are an AI assistant helping to update software development tasks based on new context.
|
||||
You will be given a set of tasks and a prompt describing changes or new implementation details.
|
||||
Your job is to update the tasks to reflect these changes, while preserving their basic structure.
|
||||
|
||||
Guidelines:
|
||||
1. Maintain the same IDs, statuses, and dependencies unless specifically mentioned in the prompt
|
||||
2. Update titles, descriptions, details, and test strategies to reflect the new information
|
||||
3. Do not change anything unnecessarily - just adapt what needs to change based on the prompt
|
||||
4. You should return ALL the tasks in order, not just the modified ones
|
||||
5. Return a complete valid JSON object with the updated tasks array
|
||||
6. VERY IMPORTANT: Preserve all subtasks marked as "done" or "completed" - do not modify their content
|
||||
7. For tasks with completed subtasks, build upon what has already been done rather than rewriting everything
|
||||
8. If an existing completed subtask needs to be changed/undone based on the new context, DO NOT modify it directly
|
||||
9. Instead, add a new subtask that clearly indicates what needs to be changed or replaced
|
||||
10. Use the existence of completed subtasks as an opportunity to make new subtasks more specific and targeted
|
||||
|
||||
The changes described in the prompt should be applied to ALL tasks in the list.`;
|
||||
|
||||
// Keep the original user prompt logic
|
||||
const taskDataString = JSON.stringify(tasksToUpdate, null, 2);
|
||||
let userPrompt = `Here are the tasks to update:\n${taskDataString}\n\nPlease update these tasks based on the following new context:\n${prompt}\n\nIMPORTANT: In the tasks JSON above, any subtasks with "status": "done" or "status": "completed" should be preserved exactly as is. Build your changes around these completed items.`;
|
||||
|
||||
if (gatheredContext) {
|
||||
userPrompt += `\n\n# Project Context\n\n${gatheredContext}`;
|
||||
}
|
||||
|
||||
userPrompt += `\n\nReturn only the updated tasks as a valid JSON array.`;
|
||||
// --- Build Prompts (Using PromptManager) ---
|
||||
// Load prompts using PromptManager
|
||||
const promptManager = getPromptManager();
|
||||
const { systemPrompt, userPrompt } = await promptManager.loadPrompt(
|
||||
'update-tasks',
|
||||
{
|
||||
tasks: tasksToUpdate,
|
||||
updatePrompt: prompt,
|
||||
useResearch,
|
||||
projectContext: gatheredContext
|
||||
}
|
||||
);
|
||||
// --- End Build Prompts ---
|
||||
|
||||
// --- AI Call ---
|
||||
|
||||
@@ -23,6 +23,14 @@ export class AnthropicAIProvider extends BaseAIProvider {
|
||||
this.name = 'Anthropic';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the environment variable name required for this provider's API key.
|
||||
* @returns {string} The environment variable name for the Anthropic API key
|
||||
*/
|
||||
getRequiredApiKeyName() {
|
||||
return 'ANTHROPIC_API_KEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns an Anthropic client instance.
|
||||
* @param {object} params - Parameters for client initialization
|
||||
|
||||
@@ -12,6 +12,14 @@ export class AzureProvider extends BaseAIProvider {
|
||||
this.name = 'Azure OpenAI';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the environment variable name required for this provider's API key.
|
||||
* @returns {string} The environment variable name for the Azure OpenAI API key
|
||||
*/
|
||||
getRequiredApiKeyName() {
|
||||
return 'AZURE_OPENAI_API_KEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates Azure-specific authentication parameters
|
||||
* @param {object} params - Parameters to validate
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { generateObject, generateText, streamText } from 'ai';
|
||||
import { log } from '../../scripts/modules/index.js';
|
||||
import { log } from '../../scripts/modules/utils.js';
|
||||
|
||||
/**
|
||||
* Base class for all AI providers
|
||||
@@ -96,6 +96,24 @@ export class BaseAIProvider {
|
||||
throw new Error('getClient must be implemented by provider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if the API key is required
|
||||
* @abstract
|
||||
* @returns {boolean} if the API key is required, defaults to true
|
||||
*/
|
||||
isRequiredApiKey() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required API key environment variable name
|
||||
* @abstract
|
||||
* @returns {string|null} The environment variable name, or null if no API key is required
|
||||
*/
|
||||
getRequiredApiKeyName() {
|
||||
throw new Error('getRequiredApiKeyName must be implemented by provider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates text using the provider's model
|
||||
*/
|
||||
|
||||
@@ -8,6 +8,19 @@ export class BedrockAIProvider extends BaseAIProvider {
|
||||
this.name = 'Bedrock';
|
||||
}
|
||||
|
||||
isRequiredApiKey() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required API key environment variable name for Bedrock.
|
||||
* Bedrock uses AWS credentials, so we return the AWS access key identifier.
|
||||
* @returns {string} The environment variable name
|
||||
*/
|
||||
getRequiredApiKeyName() {
|
||||
return 'AWS_ACCESS_KEY_ID';
|
||||
}
|
||||
|
||||
/**
|
||||
* Override auth validation - Bedrock uses AWS credentials instead of API keys
|
||||
* @param {object} params - Parameters to validate
|
||||
|
||||
@@ -15,6 +15,14 @@ export class ClaudeCodeProvider extends BaseAIProvider {
|
||||
this.name = 'Claude Code';
|
||||
}
|
||||
|
||||
getRequiredApiKeyName() {
|
||||
return 'CLAUDE_CODE_API_KEY';
|
||||
}
|
||||
|
||||
isRequiredApiKey() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override validateAuth to skip API key validation for Claude Code
|
||||
* @param {object} params - Parameters to validate
|
||||
|
||||
@@ -205,32 +205,57 @@ export class ClaudeCodeLanguageModel {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
if (error instanceof AbortError) {
|
||||
throw options.abortSignal?.aborted ? options.abortSignal.reason : error;
|
||||
}
|
||||
// -------------------------------------------------------------
|
||||
// Work-around for Claude-Code CLI/SDK JSON truncation bug (#913)
|
||||
// -------------------------------------------------------------
|
||||
// If the SDK throws a JSON SyntaxError *but* we already hold some
|
||||
// buffered text, assume the response was truncated by the CLI.
|
||||
// We keep the accumulated text, mark the finish reason, push a
|
||||
// provider-warning and *skip* the normal error handling so Task
|
||||
// Master can continue processing.
|
||||
const isJsonTruncation =
|
||||
error instanceof SyntaxError &&
|
||||
/JSON/i.test(error.message || '') &&
|
||||
(error.message.includes('position') ||
|
||||
error.message.includes('Unexpected end'));
|
||||
if (isJsonTruncation && text && text.length > 0) {
|
||||
warnings.push({
|
||||
type: 'provider-warning',
|
||||
details:
|
||||
'Claude Code SDK emitted a JSON parse error but Task Master recovered buffered text (possible CLI truncation).'
|
||||
});
|
||||
finishReason = 'truncated';
|
||||
// Skip re-throwing: fall through so the caller receives usable data
|
||||
} else {
|
||||
if (error instanceof AbortError) {
|
||||
throw options.abortSignal?.aborted
|
||||
? options.abortSignal.reason
|
||||
: error;
|
||||
}
|
||||
|
||||
// Check for authentication errors
|
||||
if (
|
||||
error.message?.includes('not logged in') ||
|
||||
error.message?.includes('authentication') ||
|
||||
error.exitCode === 401
|
||||
) {
|
||||
throw createAuthenticationError({
|
||||
message:
|
||||
error.message ||
|
||||
'Authentication failed. Please ensure Claude Code CLI is properly authenticated.'
|
||||
// Check for authentication errors
|
||||
if (
|
||||
error.message?.includes('not logged in') ||
|
||||
error.message?.includes('authentication') ||
|
||||
error.exitCode === 401
|
||||
) {
|
||||
throw createAuthenticationError({
|
||||
message:
|
||||
error.message ||
|
||||
'Authentication failed. Please ensure Claude Code CLI is properly authenticated.'
|
||||
});
|
||||
}
|
||||
|
||||
// Wrap other errors with API call error
|
||||
throw createAPICallError({
|
||||
message: error.message || 'Claude Code CLI error',
|
||||
code: error.code,
|
||||
exitCode: error.exitCode,
|
||||
stderr: error.stderr,
|
||||
promptExcerpt: messagesPrompt.substring(0, 200),
|
||||
isRetryable: error.code === 'ENOENT' || error.code === 'ECONNREFUSED'
|
||||
});
|
||||
}
|
||||
|
||||
// Wrap other errors with API call error
|
||||
throw createAPICallError({
|
||||
message: error.message || 'Claude Code CLI error',
|
||||
code: error.code,
|
||||
exitCode: error.exitCode,
|
||||
stderr: error.stderr,
|
||||
promptExcerpt: messagesPrompt.substring(0, 200),
|
||||
isRetryable: error.code === 'ENOENT' || error.code === 'ECONNREFUSED'
|
||||
});
|
||||
}
|
||||
|
||||
// Extract JSON if in object-json mode
|
||||
@@ -402,6 +427,53 @@ export class ClaudeCodeLanguageModel {
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------
|
||||
// Work-around for Claude-Code CLI/SDK JSON truncation bug (#913)
|
||||
// -------------------------------------------------------------
|
||||
// If we hit the SDK JSON SyntaxError but have buffered text, finalize
|
||||
// the stream gracefully instead of emitting an error.
|
||||
const isJsonTruncation =
|
||||
error instanceof SyntaxError &&
|
||||
/JSON/i.test(error.message || '') &&
|
||||
(error.message.includes('position') ||
|
||||
error.message.includes('Unexpected end'));
|
||||
|
||||
if (
|
||||
isJsonTruncation &&
|
||||
accumulatedText &&
|
||||
accumulatedText.length > 0
|
||||
) {
|
||||
// Prepare final text payload
|
||||
const finalText =
|
||||
options.mode?.type === 'object-json'
|
||||
? extractJson(accumulatedText)
|
||||
: accumulatedText;
|
||||
|
||||
// Emit any remaining text
|
||||
controller.enqueue({
|
||||
type: 'text-delta',
|
||||
textDelta: finalText
|
||||
});
|
||||
|
||||
// Emit finish with truncated reason and warning
|
||||
controller.enqueue({
|
||||
type: 'finish',
|
||||
finishReason: 'truncated',
|
||||
usage,
|
||||
providerMetadata: { 'claude-code': { truncated: true } },
|
||||
warnings: [
|
||||
{
|
||||
type: 'provider-warning',
|
||||
details:
|
||||
'Claude Code SDK JSON truncation detected; stream recovered.'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
controller.close();
|
||||
return; // Skip normal error path
|
||||
}
|
||||
|
||||
controller.close();
|
||||
} catch (error) {
|
||||
let errorToEmit;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
import { generateObject, generateText, streamText } from 'ai';
|
||||
import { parse } from 'jsonc-parser';
|
||||
import { BaseAIProvider } from './base-provider.js';
|
||||
import { log } from '../../scripts/modules/index.js';
|
||||
import { log } from '../../scripts/modules/utils.js';
|
||||
|
||||
let createGeminiProvider;
|
||||
|
||||
@@ -67,8 +67,7 @@ export class GeminiCliProvider extends BaseAIProvider {
|
||||
apiKey: params.apiKey
|
||||
};
|
||||
} else {
|
||||
// Expected case: Use gemini CLI authentication
|
||||
// Requires: gemini auth login (pre-configured)
|
||||
// Expected case: Use gemini CLI authentication via OAuth
|
||||
authOptions = {
|
||||
authType: 'oauth-personal'
|
||||
};
|
||||
@@ -653,4 +652,12 @@ Generate ${subtaskCount} subtasks based on the original task context. Return ONL
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
getRequiredApiKeyName() {
|
||||
return 'GEMINI_API_KEY';
|
||||
}
|
||||
|
||||
isRequiredApiKey() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,14 @@ export class VertexAIProvider extends BaseAIProvider {
|
||||
this.name = 'Google Vertex AI';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the required API key environment variable name for Google Vertex AI.
|
||||
* @returns {string} The environment variable name
|
||||
*/
|
||||
getRequiredApiKeyName() {
|
||||
return 'GOOGLE_API_KEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates Vertex AI-specific authentication parameters
|
||||
* @param {object} params - Parameters to validate
|
||||
|
||||
@@ -12,6 +12,14 @@ export class GoogleAIProvider extends BaseAIProvider {
|
||||
this.name = 'Google';
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the environment variable name required for this provider's API key.
|
||||
* @returns {string} The environment variable name for the Google API key
|
||||
*/
|
||||
getRequiredApiKeyName() {
|
||||
return 'GOOGLE_API_KEY';
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a Google AI client instance.
|
||||
* @param {object} params - Parameters for client initialization
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user