feat: Enhance Claude Code AI SDK integration with comprehensive improvements#1113
feat: Enhance Claude Code AI SDK integration with comprehensive improvements#1113tommy-ca wants to merge 2 commits intoeyaltoledano:nextfrom
Conversation
|
WalkthroughA new integration for Claude Code was added, including documentation, direct test scripts, and refactored provider logic to use the external Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant TaskMaster
participant ClaudeCodeProvider
participant ClaudeCodeCLI
User->>TaskMaster: Request AI task (e.g., generate text)
TaskMaster->>ClaudeCodeProvider: getClient(commandName)
ClaudeCodeProvider->>ClaudeCodeCLI: Authenticate (OAuth token or env var)
ClaudeCodeCLI-->>ClaudeCodeProvider: Token/Failure
ClaudeCodeProvider->>TaskMaster: Claude Code client or error
TaskMaster->>ClaudeCodeProvider: generateText / streamText
ClaudeCodeProvider->>ClaudeCodeCLI: Run model (sonnet/opus)
ClaudeCodeCLI-->>ClaudeCodeProvider: AI response (text/stream)
ClaudeCodeProvider-->>TaskMaster: Result
TaskMaster-->>User: Return AI result
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Note 🔌 MCP (Model Context Protocol) integration is now available in Early Access!Pro users can now connect to remote MCP servers under the Integrations page to get reviews and chat conversations that understand additional development context. ✨ Finishing Touches🧪 Generate unit tests
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 30
🔭 Outside diff range comments (2)
package.json (1)
13-27: Add the required test scripts (unit/integration/e2e/ci) per repository guidelines.Current scripts miss test:unit, test:integration, and test:ci.
Apply:
"scripts": { - "test": "node --experimental-vm-modules node_modules/.bin/jest", + "test": "node --experimental-vm-modules node_modules/.bin/jest", "test:fails": "node --experimental-vm-modules node_modules/.bin/jest --onlyFailures", "test:watch": "node --experimental-vm-modules node_modules/.bin/jest --watch", "test:coverage": "node --experimental-vm-modules node_modules/.bin/jest --coverage", - "test:e2e": "./tests/e2e/run_e2e.sh", + "test:unit": "node --experimental-vm-modules node_modules/.bin/jest --selectProjects unit", + "test:integration": "node --experimental-vm-modules node_modules/.bin/jest --selectProjects integration", + "test:e2e": "./tests/e2e/run_e2e.sh", "test:e2e-report": "./tests/e2e/run_e2e.sh --analyze-log", + "test:ci": "npm run format-check && npm run test:coverage && npm run test:integration && npm run test:e2e", "prepare": "chmod +x bin/task-master.js mcp-server/server.js", "changeset": "changeset", "release": "changeset publish", "inspector": "npx @modelcontextprotocol/inspector node mcp-server/server.js", "mcp-server": "node mcp-server/server.js", "format-check": "biome format .", "format": "biome format . --write" },If you don’t use Jest projects, we can adapt commands to your structure.
tests/integration/claude-code-optional.test.js (1)
71-82: Refactor stream failure test to sync throw checksMirror the same change for doStream.
-it('should fail streaming when Claude Code CLI is not available', async () => { +it('should fail streaming when Claude Code CLI is not available', () => { const provider = new ClaudeCodeProvider(); const client = provider.getClient({}); const model = client('sonnet'); - await expect( - model.doStream({ - prompt: [{ role: 'user', content: 'Hello' }], - mode: { type: 'regular' } - }) - ).rejects.toThrow('Claude Code executable not found'); + expect(() => + model.doStream({ + prompt: [{ role: 'user', content: 'Hello' }], + mode: { type: 'regular' } + }) + ).toThrow('Claude Code executable not found'); });
.claude/agents/task-executor.md
Outdated
| - Use `Edit` tool to modify existing files | ||
| - Use `Bash` tool to run commands (mkdir, npm install, etc.) | ||
| - Use `Read` tool to verify your implementations | ||
| 3. **Focused Execution**: |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Trim trailing spaces to satisfy MD009 (safe for agent format)
Remove trailing spaces at these lines; it won’t affect Claude agent parsing and keeps linters quiet.
-3. **Focused Execution**:
+3. **Focused Execution**:
@@
-4. **Progress Documentation**:
+4. **Progress Documentation**:Also applies to: 25-25
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)
19-19: Trailing spaces
Expected: 0 or 2; Actual: 1
(MD009, no-trailing-spaces)
🤖 Prompt for AI Agents
In .claude/agents/task-executor.md at lines 19 and 25, there are trailing spaces
that violate MD009 linting rules. Remove any trailing spaces at the end of these
lines to satisfy the linter and maintain clean formatting without affecting
Claude agent parsing.
.claude/agents/task-orchestrator.md
Outdated
| --- | ||
| name: task-orchestrator | ||
| description: Use this agent FREQUENTLY throughout task execution to analyze and coordinate parallel work at the SUBTASK level. Invoke the orchestrator: (1) at session start to plan execution, (2) after EACH subtask completes to identify next parallel batch, (3) whenever executors finish to find newly unblocked work. ALWAYS provide FULL CONTEXT including project root, package location, what files ACTUALLY exist vs task status, and specific implementation details. The orchestrator breaks work into SUBTASK-LEVEL units for short-lived, focused executors. Maximum 3 parallel executors at once.\n\n<example>\nContext: Starting work with existing code\nuser: "Work on tm-core tasks. Files exist: types/index.ts, storage/file-storage.ts. Task 118 says in-progress but BaseProvider not created."\nassistant: "I'll invoke orchestrator with full context about actual vs reported state to plan subtask execution"\n<commentary>\nProvide complete context about file existence and task reality.\n</commentary>\n</example>\n\n<example>\nContext: Subtask completion\nuser: "Subtask 118.2 done. What subtasks can run in parallel now?"\nassistant: "Invoking orchestrator to analyze dependencies and identify next 3 parallel subtasks"\n<commentary>\nFrequent orchestration after each subtask ensures maximum parallelization.\n</commentary>\n</example>\n\n<example>\nContext: Breaking down tasks\nuser: "Task 118 has 5 subtasks, how to parallelize?"\nassistant: "Orchestrator will analyze which specific subtasks (118.1, 118.2, etc.) can run simultaneously"\n<commentary>\nFocus on subtask-level parallelization, not full tasks.\n</commentary>\n</example> | ||
| description: Use this agent when you need to coordinate and manage the execution of Task Master tasks, especially when dealing with complex task dependencies and parallel execution opportunities. This agent should be invoked at the beginning of a work session to analyze the task queue, identify parallelizable work, and orchestrate the deployment of task-executor agents. It should also be used when tasks complete to reassess the dependency graph and deploy new executors as needed.\n\n<example>\nContext: User wants to start working on their project tasks using Task Master\nuser: "Let's work on the next available tasks in the project"\nassistant: "I'll use the task-orchestrator agent to analyze the task queue and coordinate execution"\n<commentary>\nThe user wants to work on tasks, so the task-orchestrator should be deployed to analyze dependencies and coordinate execution.\n</commentary>\n</example>\n\n<example>\nContext: Multiple independent tasks are available in the queue\nuser: "Can we work on multiple tasks at once?"\nassistant: "Let me deploy the task-orchestrator to analyze task dependencies and parallelize the work"\n<commentary>\nWhen parallelization is mentioned or multiple tasks could be worked on, the orchestrator should coordinate the effort.\n</commentary>\n</example>\n\n<example>\nContext: A complex feature with many subtasks needs implementation\nuser: "Implement the authentication system tasks"\nassistant: "I'll use the task-orchestrator to break down the authentication tasks and coordinate their execution"\n<commentary>\nFor complex multi-task features, the orchestrator manages the overall execution strategy.\n</commentary>\n</example> |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Use YAML block scalar for multi-line description (avoid literal "\n")
Literal “\n” sequences may not render as intended. Prefer a block scalar for multi-line content to match agent file conventions.
-name: task-orchestrator
-description: Use this agent when you need to coordinate and manage the execution of Task Master tasks, especially when dealing with complex task dependencies and parallel execution opportunities. This agent should be invoked at the beginning of a work session to analyze the task queue, identify parallelizable work, and orchestrate the deployment of task-executor agents. It should also be used when tasks complete to reassess the dependency graph and deploy new executors as needed.\n\n<example>\nContext: User wants to start working on their project tasks using Task Master\nuser: "Let's work on the next available tasks in the project"\nassistant: "I'll use the task-orchestrator agent to analyze the task queue and coordinate execution"\n<commentary>\nThe user wants to work on tasks, so the task-orchestrator should be deployed to analyze dependencies and coordinate execution.\n</commentary>\n</example>\n\n<example>\nContext: Multiple independent tasks are available in the queue\nuser: "Can we work on multiple tasks at once?"\nassistant: "Let me deploy the task-orchestrator to analyze task dependencies and parallelize the work"\n<commentary>\nWhen parallelization is mentioned or multiple tasks could be worked on, the orchestrator should coordinate the effort.\n</commentary>\n</example>\n\n<example>\nContext: A complex feature with many subtasks needs implementation\nuser: "Implement the authentication system tasks"\nassistant: "I'll use the task-orchestrator to break down the authentication tasks and coordinate their execution"\n<commentary>\nFor complex multi-task features, the orchestrator manages the overall execution strategy.\n</commentary>\n</example>
+name: task-orchestrator
+description: |
+ Use this agent when you need to coordinate and manage the execution of Task Master tasks, especially when dealing with complex task dependencies and parallel execution opportunities. This agent should be invoked at the beginning of a work session to analyze the task queue, identify parallelizable work, and orchestrate the deployment of task-executor agents. It should also be used when tasks complete to reassess the dependency graph and deploy new executors as needed.
+
+ <example>
+ Context: User wants to start working on their project tasks using Task Master
+ user: "Let's work on the next available tasks in the project"
+ assistant: "I'll use the task-orchestrator agent to analyze the task queue and coordinate execution"
+ <commentary>
+ The user wants to work on tasks, so the task-orchestrator should be deployed to analyze dependencies and coordinate execution.
+ </commentary>
+ </example>
+
+ <example>
+ Context: Multiple independent tasks are available in the queue
+ user: "Can we work on multiple tasks at once?"
+ assistant: "Let me deploy the task-orchestrator to analyze task dependencies and parallelize the work"
+ <commentary>
+ When parallelization is mentioned or multiple tasks could be worked on, the orchestrator should coordinate the effort.
+ </commentary>
+ </example>
+
+ <example>
+ Context: A complex feature with many subtasks needs implementation
+ user: "Implement the authentication system tasks"
+ assistant: "I'll use the task-orchestrator to break down the authentication tasks and coordinate their execution"
+ <commentary>
+ For complex multi-task features, the orchestrator manages the overall execution strategy.
+ </commentary>
+ </example>📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| description: Use this agent when you need to coordinate and manage the execution of Task Master tasks, especially when dealing with complex task dependencies and parallel execution opportunities. This agent should be invoked at the beginning of a work session to analyze the task queue, identify parallelizable work, and orchestrate the deployment of task-executor agents. It should also be used when tasks complete to reassess the dependency graph and deploy new executors as needed.\n\n<example>\nContext: User wants to start working on their project tasks using Task Master\nuser: "Let's work on the next available tasks in the project"\nassistant: "I'll use the task-orchestrator agent to analyze the task queue and coordinate execution"\n<commentary>\nThe user wants to work on tasks, so the task-orchestrator should be deployed to analyze dependencies and coordinate execution.\n</commentary>\n</example>\n\n<example>\nContext: Multiple independent tasks are available in the queue\nuser: "Can we work on multiple tasks at once?"\nassistant: "Let me deploy the task-orchestrator to analyze task dependencies and parallelize the work"\n<commentary>\nWhen parallelization is mentioned or multiple tasks could be worked on, the orchestrator should coordinate the effort.\n</commentary>\n</example>\n\n<example>\nContext: A complex feature with many subtasks needs implementation\nuser: "Implement the authentication system tasks"\nassistant: "I'll use the task-orchestrator to break down the authentication tasks and coordinate their execution"\n<commentary>\nFor complex multi-task features, the orchestrator manages the overall execution strategy.\n</commentary>\n</example> | |
| name: task-orchestrator | |
| description: | | |
| Use this agent when you need to coordinate and manage the execution of Task Master tasks, especially when dealing with complex task dependencies and parallel execution opportunities. This agent should be invoked at the beginning of a work session to analyze the task queue, identify parallelizable work, and orchestrate the deployment of task-executor agents. It should also be used when tasks complete to reassess the dependency graph and deploy new executors as needed. | |
| <example> | |
| Context: User wants to start working on their project tasks using Task Master | |
| user: "Let's work on the next available tasks in the project" | |
| assistant: "I'll use the task-orchestrator agent to analyze the task queue and coordinate execution" | |
| <commentary> | |
| The user wants to work on tasks, so the task-orchestrator should be deployed to analyze dependencies and coordinate execution. | |
| </commentary> | |
| </example> | |
| <example> | |
| Context: Multiple independent tasks are available in the queue | |
| user: "Can we work on multiple tasks at once?" | |
| assistant: "Let me deploy the task-orchestrator to analyze task dependencies and parallelize the work" | |
| <commentary> | |
| When parallelization is mentioned or multiple tasks could be worked on, the orchestrator should coordinate the effort. | |
| </commentary> | |
| </example> | |
| <example> | |
| Context: A complex feature with many subtasks needs implementation | |
| user: "Implement the authentication system tasks" | |
| assistant: "I'll use the task-orchestrator agent to break down the authentication tasks and coordinate their execution" | |
| <commentary> | |
| For complex multi-task features, the orchestrator manages the overall execution strategy. | |
| </commentary> | |
| </example> |
🤖 Prompt for AI Agents
In .claude/agents/task-orchestrator.md at line 3, the multi-line description
uses literal "\n" characters which may not render correctly. Replace the literal
"\n" sequences with a YAML block scalar style (using | or >) to properly format
the multi-line description and examples according to YAML conventions and
maintain consistency with other agent files.
.gitignore
Outdated
| apps/extension/vsix-build/ | ||
|
|
||
| # OS specific | ||
|
|
||
| # Task files | ||
| # tasks.json | ||
| # tasks/ |
There was a problem hiding this comment.
💡 Verification agent
❓ Verification inconclusive
Only comments added; consider clarifying intent and avoid ignoring tracked task files.
- Good: ignoring apps/extension/vsix-build/.
- The OS/Task files sections are placeholders without patterns. Either add concrete entries or remove to avoid confusion.
- Do not ignore tasks.json or .taskmaster/tasks unless this repo’s policy changes—these are intentionally tracked per Taskmaster workflow.
If you want typical OS entries, consider:
# OS specific
+.Spotlight-V100
+.Trashes
+Thumbs.db
+
# Task files
-# tasks.json
-# tasks/
+# Intentionally tracked by Taskmaster – do not ignoreClarify .gitignore tail entries
The final lines currently read as commented placeholders with no actual ignore patterns. To avoid confusion and ensure you don’t accidentally ignore tracked Taskmaster files, please:
- Replace the “OS specific” section’s placeholder with real patterns or remove it:
# OS specific -.Spotlight-V100 -.Trashes -Thumbs.db +.Spotlight-V100 +.Trashes +Thumbs.db
- Remove or clarify the “Task files” placeholder so it doesn’t suggest you should ignore real files:
# Task files -# tasks.json -# tasks/ +# Intentionally tracked by Taskmaster – do not ignore tasks.json or tasks/
These changes will make the intent clear and prevent accidentally hiding files that must remain under version control.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In the .gitignore file around lines 96 to 102, the "OS specific" and "Task
files" sections contain only commented placeholders without actual ignore
patterns, which can cause confusion. Remove these placeholder comments or
replace them with real ignore patterns if needed. Ensure that no important
tracked files like Taskmaster files are accidentally ignored by clarifying or
deleting these sections.
.mcp.json
Outdated
| "args": [ | ||
| "-y", | ||
| "task-master-ai" | ||
| ] |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Align npx args with VS Code settings for consistency.
VS Code uses args [-y, --package=task-master-ai, task-master-ai], while here it’s [-y, task-master-ai]. Add --package for parity and predictable resolution.
Proposed tweak:
- "args": [
- "-y",
- "task-master-ai"
- ]
+ "args": [
+ "-y",
+ "--package=task-master-ai",
+ "task-master-ai"
+ ]Alternatively, to avoid npx variability you can run the server directly:
{ "type": "stdio", "command": "node", "args": ["mcp-server/server.js"] }🏁 Script executed:
#!/bin/bash
# Show the args in .mcp.json and compare with VS Code settings.json usage
echo ">>> .mcp.json (around args):"
rg -n '"args"' -C2 .mcp.json || true
echo
echo ">>> .vscode/settings.json (around task-master-ai):"
rg -n 'task-master-ai' -C2 .vscode/settings.json || trueLength of output: 541
Align npx args in .mcp.json with VS Code settings
The args array in .mcp.json (lines 6–9) currently omits the --package flag, causing it to drift from the configuration in .vscode/settings.json. Add --package=task-master-ai for parity and consistent package resolution:
In .mcp.json (around lines 6–9):
"args": [
- "-y",
- "task-master-ai"
+ "-y",
+ "--package=task-master-ai",
+ "task-master-ai"
]Alternatively, to bypass npx variability, you can invoke the server directly:
{ "type": "stdio", "command": "node", "args": ["mcp-server/server.js"] }🤖 Prompt for AI Agents
In .mcp.json around lines 6 to 9, the args array for npx is missing the
--package=task-master-ai flag, causing inconsistency with the VS Code settings.
Update the args array to include "--package=task-master-ai" before
"task-master-ai" to align with the VS Code configuration. Alternatively, replace
the entire command with a direct node invocation of the server by setting
command to "node" and args to ["mcp-server/server.js"] for more consistent
behavior.
.taskmaster/config.json
Outdated
| "models": { | ||
| "main": { | ||
| "provider": "claude-code", | ||
| "modelId": "sonnet", | ||
| "maxTokens": 64000, | ||
| "temperature": 0.2 | ||
| }, | ||
| "research": { | ||
| "provider": "claude-code", | ||
| "modelId": "opus", | ||
| "maxTokens": 32000, | ||
| "temperature": 0.1 | ||
| }, | ||
| "fallback": { | ||
| "provider": "claude-code", | ||
| "modelId": "sonnet", | ||
| "maxTokens": 64000, | ||
| "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", | ||
| "userId": "1234567890", | ||
| "azureBaseURL": "https://your-endpoint.azure.com/", | ||
| "defaultTag": "master" | ||
| }, | ||
| "claudeCode": {} | ||
| } No newline at end of file |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Do not manually edit .taskmaster/config.json; update via CLI or MCP tools.
Per repository rules, this file must be managed by Taskmaster commands. Manual edits risk drift and break workflows.
Please revert this manual change and apply via CLI:
- Main:
task-master models set --role main --provider claude-code --model sonnet --maxTokens 64000 --temperature 0.2 - Research:
task-master models set --role research --provider claude-code --model opus --maxTokens 32000 --temperature 0.1 - Fallback:
task-master models set --role fallback --provider claude-code --model sonnet --maxTokens 64000 --temperature 0.2
Validate model IDs and limits exist in supported-models and provider code:
If aliases aren’t defined (e.g., need full IDs), adjust the set commands accordingly.
🏁 Script executed:
#!/bin/bash
# Verify claude-code models and aliases in repo configs
rg -n "supported-models\.json|claude-code" -A 5
rg -n '"provider": "claude-code"|sonnet|opus' scripts/modules/supported-models.json -A 2 || trueLength of output: 65969
Revert manual edits to .taskmaster/config.json and use Taskmaster CLI/MCP commands
Manual changes to .taskmaster/config.json violate the repository’s configuration rules. Instead, configure your Claude Code models via Taskmaster commands (model IDs sonnet and opus are confirmed valid in scripts/modules/supported-models.json):
• Set main:
task-master models --set-main sonnet --claude-code• Set research:
task-master models --set-research opus --claude-code• Set fallback:
task-master models --set-fallback sonnet --claude-codeIf you need to override the default maxTokens or temperature, include the flags in the same command:
task-master models --set-main sonnet --claude-code \
--set-max-tokens 64000 --set-temperature 0.2🤖 Prompt for AI Agents
In .taskmaster/config.json from lines 2 to 37, manual edits to configure Claude
Code models violate repository rules. Revert all manual changes in this file and
instead use the Taskmaster CLI commands to set the main, research, and fallback
models with the appropriate model IDs (sonnet and opus). Use commands like
"task-master models --set-main sonnet --claude-code" and include flags for
maxTokens and temperature if needed to override defaults.
| it('should fail when Claude Code CLI is not available', async () => { | ||
| const provider = new ClaudeCodeProvider(); | ||
| const client = provider.getClient({}); | ||
| const model = client('opus'); | ||
|
|
||
| // The actual usage should fail with the lazy loading error | ||
| // The mock simulates Claude Code CLI not being available | ||
| await expect( | ||
| model.doGenerate({ | ||
| prompt: [{ role: 'user', content: 'Hello' }], | ||
| mode: { type: 'regular' } | ||
| }) | ||
| ).rejects.toThrow( | ||
| "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider." | ||
| ); | ||
| ).rejects.toThrow('Claude Code executable not found'); | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Refactor to sync throw checks (no async/await)
With sync-throwing mocks, simplify to a synchronous test using toThrow.
-it('should fail when Claude Code CLI is not available', async () => {
+it('should fail when Claude Code CLI is not available', () => {
const provider = new ClaudeCodeProvider();
const client = provider.getClient({});
const model = client('opus');
- // The mock simulates Claude Code CLI not being available
- await expect(
- model.doGenerate({
- prompt: [{ role: 'user', content: 'Hello' }],
- mode: { type: 'regular' }
- })
- ).rejects.toThrow('Claude Code executable not found');
+ // The mock simulates Claude Code CLI not being available
+ expect(() =>
+ model.doGenerate({
+ prompt: [{ role: 'user', content: 'Hello' }],
+ mode: { type: 'regular' }
+ })
+ ).toThrow('Claude Code executable not found');
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it('should fail when Claude Code CLI is not available', async () => { | |
| const provider = new ClaudeCodeProvider(); | |
| const client = provider.getClient({}); | |
| const model = client('opus'); | |
| // The actual usage should fail with the lazy loading error | |
| // The mock simulates Claude Code CLI not being available | |
| await expect( | |
| model.doGenerate({ | |
| prompt: [{ role: 'user', content: 'Hello' }], | |
| mode: { type: 'regular' } | |
| }) | |
| ).rejects.toThrow( | |
| "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider." | |
| ); | |
| ).rejects.toThrow('Claude Code executable not found'); | |
| }); | |
| it('should fail when Claude Code CLI is not available', () => { | |
| const provider = new ClaudeCodeProvider(); | |
| const client = provider.getClient({}); | |
| const model = client('opus'); | |
| // The mock simulates Claude Code CLI not being available | |
| expect(() => | |
| model.doGenerate({ | |
| prompt: [{ role: 'user', content: 'Hello' }], | |
| mode: { type: 'regular' } | |
| }) | |
| ).toThrow('Claude Code executable not found'); | |
| }); |
🤖 Prompt for AI Agents
In tests/integration/claude-code-optional.test.js around lines 57 to 69, the
test currently uses async/await with rejects.toThrow to check for an error
thrown synchronously. Refactor the test to remove async/await and use a
synchronous function call inside expect with toThrow, since the error is thrown
synchronously. This means wrapping the call to model.doGenerate in a function
passed to expect and using toThrow directly without awaiting.
| @@ -1,21 +1,20 @@ | |||
| import { jest } from '@jest/globals'; | |||
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Add a changeset for this feature PR
Per repo standards, feature PRs must include a changeset. Please add one describing the provider migration, auth fallback, tests, and docs.
Example new file:
.changeset/enhance-claude-code-integration.md
---
task-master-ai: minor
---
feat(claude-code): migrate to ai-sdk-provider-claude-code v5.0.0-beta.34, add intelligent auth fallback (ENV/CLI), improve error handling and model support checks, expand unit/integration tests, and add integration docs.
🤖 Prompt for AI Agents
In tests/unit/ai-providers/claude-code.test.js at line 1, a changeset file is
missing for this feature PR. Create a new changeset markdown file in the
.changeset directory with a descriptive name like
enhance-claude-code-integration.md. Inside, include the YAML frontmatter
specifying the package and version impact, followed by a concise summary of the
migration to ai-sdk-provider-claude-code v5.0.0-beta.34, the addition of
intelligent auth fallback, improved error handling, expanded tests, and added
docs as shown in the example. This will comply with repo standards for feature
PRs.
| // Mock the ai-sdk-provider-claude-code package | ||
| jest.unstable_mockModule('ai-sdk-provider-claude-code', () => ({ | ||
| createClaudeCode: jest.fn(() => { | ||
| const provider = (modelId, settings) => ({ | ||
| // Minimal mock language model surface | ||
| id: modelId, | ||
| settings, | ||
| doGenerate: jest.fn(async () => ({ text: 'ok', usage: {} })), | ||
| doStream: jest.fn(async () => ({ stream: true })) | ||
| }); | ||
| provider.languageModel = jest.fn((id, settings) => ({ id, settings })); | ||
| provider.chat = provider.languageModel; | ||
| return provider; | ||
| }) | ||
| })); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Make mock methods synchronous to comply with test rules
Repo guideline forbids async in tests. Make mock returns synchronous to simplify tests and avoid async flows.
jest.unstable_mockModule('ai-sdk-provider-claude-code', () => ({
createClaudeCode: jest.fn(() => {
const provider = (modelId, settings) => ({
// Minimal mock language model surface
id: modelId,
settings,
- doGenerate: jest.fn(async () => ({ text: 'ok', usage: {} })),
- doStream: jest.fn(async () => ({ stream: true }))
+ doGenerate: jest.fn(() => ({ text: 'ok', usage: {} })),
+ doStream: jest.fn(() => ({ stream: true }))
});
provider.languageModel = jest.fn((id, settings) => ({ id, settings }));
provider.chat = provider.languageModel;
return provider;
})
}));📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // Mock the ai-sdk-provider-claude-code package | |
| jest.unstable_mockModule('ai-sdk-provider-claude-code', () => ({ | |
| createClaudeCode: jest.fn(() => { | |
| const provider = (modelId, settings) => ({ | |
| // Minimal mock language model surface | |
| id: modelId, | |
| settings, | |
| doGenerate: jest.fn(async () => ({ text: 'ok', usage: {} })), | |
| doStream: jest.fn(async () => ({ stream: true })) | |
| }); | |
| provider.languageModel = jest.fn((id, settings) => ({ id, settings })); | |
| provider.chat = provider.languageModel; | |
| return provider; | |
| }) | |
| })); | |
| // Mock the ai-sdk-provider-claude-code package | |
| jest.unstable_mockModule('ai-sdk-provider-claude-code', () => ({ | |
| createClaudeCode: jest.fn(() => { | |
| const provider = (modelId, settings) => ({ | |
| // Minimal mock language model surface | |
| id: modelId, | |
| settings, | |
| doGenerate: jest.fn(() => ({ text: 'ok', usage: {} })), | |
| doStream: jest.fn(() => ({ stream: true })) | |
| }); | |
| provider.languageModel = jest.fn((id, settings) => ({ id, settings })); | |
| provider.chat = provider.languageModel; | |
| return provider; | |
| }) | |
| })); |
🤖 Prompt for AI Agents
In tests/unit/ai-providers/claude-code.test.js between lines 3 and 17, the mock
methods doGenerate and doStream are currently asynchronous, which violates the
repo guideline against async in tests. Change these mock methods to return
synchronous values instead of async functions by removing the async keyword and
returning the resolved values directly. This will simplify the tests and comply
with the test rules.
| it('should handle commandName parameter', () => { | ||
| const client = provider.getClient({ | ||
| commandName: 'test-command' | ||
| }); | ||
| expect(client).toBeDefined(); | ||
| }); |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Option: Assert createClaudeCode receives commandName
You can strengthen this by asserting createClaudeCode was called with settings including the provided commandName.
it('should handle commandName parameter', () => {
const client = provider.getClient({
commandName: 'test-command'
});
expect(client).toBeDefined();
+ // Optionally verify createClaudeCode received the option
+ // const { createClaudeCode } = await import('ai-sdk-provider-claude-code');
+ // expect(createClaudeCode).toHaveBeenCalledWith(expect.objectContaining({
+ // commandName: 'test-command'
+ // }));
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it('should handle commandName parameter', () => { | |
| const client = provider.getClient({ | |
| commandName: 'test-command' | |
| }); | |
| expect(client).toBeDefined(); | |
| }); | |
| it('should handle commandName parameter', () => { | |
| const client = provider.getClient({ | |
| commandName: 'test-command' | |
| }); | |
| expect(client).toBeDefined(); | |
| // Optionally verify createClaudeCode received the option | |
| // const { createClaudeCode } = await import('ai-sdk-provider-claude-code'); | |
| // expect(createClaudeCode).toHaveBeenCalledWith(expect.objectContaining({ | |
| // commandName: 'test-command' | |
| // })); | |
| }); |
🤖 Prompt for AI Agents
In tests/unit/ai-providers/claude-code.test.js around lines 81 to 86, the test
checks if the client is defined when passing commandName but does not verify
that createClaudeCode was called with the correct settings. Modify the test to
spy on or mock createClaudeCode and add an assertion that it was called with an
argument object containing the commandName 'test-command' to ensure the
parameter is properly forwarded.
| it('should handle client initialization errors', async () => { | ||
| // Force an error by making createClaudeCode throw | ||
| const { createClaudeCode } = await import( | ||
| '../../../src/ai-providers/custom-sdk/claude-code/index.js' | ||
| 'ai-sdk-provider-claude-code' | ||
| ); | ||
| createClaudeCode.mockImplementationOnce(() => { | ||
| throw new Error('Mock initialization error'); | ||
| }); | ||
|
|
||
| // Create a new provider instance to use the mocked createClaudeCode | ||
| const errorProvider = new ClaudeCodeProvider(); | ||
| expect(() => errorProvider.getClient({})).toThrow( | ||
| 'Mock initialization error' | ||
| ); | ||
| expect(() => errorProvider.getClient({})).toThrow('Mock initialization error'); | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Remove async from the test; import the mock at module scope
Avoid async tests per repo rule. Move the import of the mocked module to module scope and make the test sync.
- it('should handle client initialization errors', async () => {
- // Force an error by making createClaudeCode throw
- const { createClaudeCode } = await import(
- 'ai-sdk-provider-claude-code'
- );
+ // Import after mocking (at module scope, near other imports):
+ // const { createClaudeCode } = await import('ai-sdk-provider-claude-code');
+
+ it('should handle client initialization errors', () => {
+ // Force an error by making createClaudeCode throw
createClaudeCode.mockImplementationOnce(() => {
throw new Error('Mock initialization error');
});
// Create a new provider instance to use the mocked createClaudeCode
const errorProvider = new ClaudeCodeProvider();
expect(() => errorProvider.getClient({})).toThrow('Mock initialization error');
});And add this import once at top-level (after the mockModule blocks, before using it):
+const { createClaudeCode } = await import('ai-sdk-provider-claude-code');Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In tests/unit/ai-providers/claude-code.test.js around lines 111 to 123, the test
is marked async and imports the mocked module inside the test, which violates
repo rules. Move the import of 'createClaudeCode' from
'ai-sdk-provider-claude-code' to the top-level module scope after any mockModule
blocks, remove the async keyword from the test function, and make the test
synchronous. This ensures the mock is imported once and the test runs
synchronously as required.
- Update AI SDK from v4.3.16 to v5.0.0-beta.34 - Add ai-sdk-provider-claude-code integration - Replace custom SDK with official ai-sdk-provider-claude-code package - Add OAuth token authentication via Claude Code CLI - Support for 'sonnet' and 'opus' models - Comprehensive integration tests and documentation - Direct integration test script for verification 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
655125c to
b52ac33
Compare
- Updates @anthropic-ai/claude-code to latest version - Ensures compatibility with latest Claude Code CLI features - Maintains optional dependency status for graceful degradation 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
Actionable comments posted: 7
♻️ Duplicate comments (12)
package.json (1)
57-58: Add a Changeset for dependency upgrades and provider additionPer repository policy, feature and dependency updates require a .changeset entry. Please add one documenting the ai 5.0.0-beta.34 upgrade and the new ai-sdk-provider-claude-code dependency.
Example:
--- "task-master-ai": minor --- feat(claude-code): migrate to ai-sdk-provider-claude-code, upgrade ai to 5.0.0-beta.34; improve auth fallback and error handling; expand tests and docs.tests/unit/ai-providers/claude-code.test.js (3)
3-17: Make mock methods synchronous to comply with test rulesRepo forbids async in tests where possible. Change doGenerate/doStream mocks to return sync values.
- doGenerate: jest.fn(async () => ({ text: 'ok', usage: {} })), - doStream: jest.fn(async () => ({ stream: true })) + doGenerate: jest.fn(() => ({ text: 'ok', usage: {} })), + doStream: jest.fn(() => ({ stream: true }))
81-86: Optionally assert createClaudeCode receives commandNameStrengthen this test by asserting the commandName is forwarded into createClaudeCode options.
it('should handle commandName parameter', () => { const client = provider.getClient({ commandName: 'test-command' }); expect(client).toBeDefined(); + // Optional: verify forwarding + // const { createClaudeCode } = await import('ai-sdk-provider-claude-code'); + // expect(createClaudeCode).toHaveBeenCalledWith( + // expect.objectContaining({ defaultSettings: expect.any(Object) }) + // ); });
111-123: Remove async from the test; import the mock at module scopeAvoid async tests and dynamic imports inside tests. Import createClaudeCode once at module scope (after mockModule), then make the test synchronous.
- it('should handle client initialization errors', async () => { - // Force an error by making createClaudeCode throw - const { createClaudeCode } = await import( - 'ai-sdk-provider-claude-code' - ); + // Add at module scope (after jest.unstable_mockModule blocks): + // const { createClaudeCode } = await import('ai-sdk-provider-claude-code'); + + it('should handle client initialization errors', () => { createClaudeCode.mockImplementationOnce(() => { throw new Error('Mock initialization error'); }); // Create a new provider instance to use the mocked createClaudeCode const errorProvider = new ClaudeCodeProvider(); expect(() => errorProvider.getClient({})).toThrow('Mock initialization error'); });Add this import at module scope:
const { createClaudeCode } = await import('ai-sdk-provider-claude-code');scripts/test-claude-code-direct.js (1)
43-51: Optional: surface streaming usage details if availableIf the stream result exposes usage or finish reasons, log them to aid diagnostics.
console.log('\n✅ Streaming completed'); - console.log('📊 Final usage:', await streamResult.usage); + console.log('📊 Final usage:', await streamResult.usage); + if (streamResult.finishReason) { + console.log('🏁 Finish reason:', streamResult.finishReason); + }tests/integration/claude-code-optional.test.js (1)
82-106: Refactor streamText test to be synchronous (mock returns sync object)Provide a sync mock result and remove async/await.
- it('should integrate with AI SDK streamText', async () => { + it('should integrate with AI SDK streamText', () => { const provider = new ClaudeCodeProvider(); const client = provider.getClient(); // Mock successful streaming const mockStream = { - textStream: (async function* () { - yield 'Hello '; - yield 'from '; - yield 'Claude Code!'; - })() + textStream: { + // You can keep this as a simple iterable if you don’t consume it in test + [Symbol.asyncIterator]: async function* () { + yield 'Hello '; + yield 'from '; + yield 'Claude Code!'; + } + } }; - streamText.mockResolvedValueOnce(mockStream); + streamText.mockReturnValueOnce(mockStream); - const result = await streamText({ + const result = streamText({ model: client('sonnet'), messages: [{ role: 'user', content: 'Hello' }] }); expect(result.textStream).toBeDefined(); expect(streamText).toHaveBeenCalledWith({ model: expect.any(Object), messages: [{ role: 'user', content: 'Hello' }] }); });docs/claude-code-integration.md (1)
205-219: Add “Migration Notes” to document the provider switchSummarize the move from custom SDK to the external provider.
## Security Notes ... ## Getting Help ... 4. Open an issue with both Task Master and Claude Code version information + +## Migration Notes + +- Replaced the legacy custom SDK (src/ai-providers/custom-sdk/claude-code/) with the external ai-sdk-provider-claude-code +- No breaking changes: existing Task Master model selections continue to work via claude-code/{sonnet|opus} +- Authentication now uses CLI-managed OAuth; API keys are not required +- For automation, CLAUDE_CODE_OAUTH_TOKEN can override CLI-managed tokensrc/ai-providers/claude-code.js (5)
97-98: Export generate/stream/object wrapper functions per repo conventionConsumers and tests expect function exports alongside the class. Add thin wrappers using a singleton.
} +// Convenience exports per repository convention: +// generateClaudeCodeText, streamClaudeCodeText, generateClaudeCodeObject +const _claudeCodeProviderSingleton = new ClaudeCodeProvider(); + +export const generateClaudeCodeText = (params) => + _claudeCodeProviderSingleton.generateText(params); + +export const streamClaudeCodeText = (params) => + _claudeCodeProviderSingleton.streamText(params); + +export const generateClaudeCodeObject = (params) => + _claudeCodeProviderSingleton.generateObject(params);
29-30: Freeze supportedModels to prevent accidental mutationMake the supported models immutable and safe to expose.
- this.supportedModels = ['sonnet', 'opus']; + this.supportedModels = Object.freeze(['sonnet', 'opus']);
35-37: Return null for API key name since API keys aren’t requiredisRequiredApiKey() returns false; returning a name is misleading.
- getRequiredApiKeyName() { - return 'CLAUDE_CODE_API_KEY'; - } + getRequiredApiKeyName() { + // No API key required for Claude Code CLI-based auth + return null; + }
46-52: Rename unused param to underscore to appease lintersClarifies intent and avoids unused-var warnings.
- * @param {object} params - Parameters (ignored) + * @param {object} _params - Parameters (ignored) @@ - validateAuth(params) { + validateAuth(_params) {
82-96: Fail fast on unsupported model IDs via validateParams overrideYou added isModelSupported(), but it’s not enforced. Validate early with a precise error.
export class ClaudeCodeProvider extends BaseAIProvider { @@ } + /** + * Validate required/common params + supported model IDs + * @param {object} params + */ + validateParams(params) { + super.validateParams(params); + if (!this.isModelSupported(params.modelId)) { + throw new Error( + `${this.name} unsupported model ID: '${params.modelId}'. Supported: ${this.supportedModels.join(', ')}` + ); + } + }
| 1. **Install Claude Code CLI** (if not already installed): | ||
| ```bash | ||
| # Installation method depends on your system | ||
| # Follow Claude Code documentation for installation | ||
| ``` | ||
|
|
||
| 2. **Set up OAuth token** using Claude Code CLI: |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Fix markdownlint issues: surround fences with blank lines and specify languages
Add blank lines around fenced blocks (MD031) and ensure a language is specified (MD040). Example fixes:
-1. **Install Claude Code CLI** (if not already installed):
- ```bash
+1. **Install Claude Code CLI** (if not already installed):
+
+ ```bash
# Installation method depends on your system
# Follow Claude Code documentation for installation
```
-2. **Set up OAuth token** using Claude Code CLI:
- ```bash
+2. **Set up OAuth token** using Claude Code CLI:
+
+ ```bash
claude setup-token
```
1. **Test Claude Code CLI directly**:
- ```bash
+
+ ```bash
claude --help
# Should show help without errors
```
2. **Test authentication**:
- ```bash
+
+ ```bash
claude setup-token --verify
# Should confirm token is valid
```
3. **Test Task Master integration**:
- ```bash
+
+ ```bash
task-master models --test claude-code:sonnet
# Should successfully connect and test the model
```
2. Set up authentication via environment variable:
- ```dockerfile
+
+ ```dockerfile
ENV CLAUDE_CODE_OAUTH_TOKEN="your_token_here"
```Also applies to: 21-25, 133-141, 141-147, 147-152, 165-168
🧰 Tools
🪛 LanguageTool
[grammar] ~15-~15: Use correct spacing
Context: ...stall Claude Code CLI** (if not already installed): bash # Installation method depends on your system # Follow Claude Code documentation for installation 2. Set up OAuth token using Claude Code C...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~21-~21: There might be a mistake here.
Context: ...Set up OAuth token* using Claude Code CLI: bash claude setup-token This command will: - Guide you th...
(QB_NEW_EN_OTHER)
🪛 markdownlint-cli2 (0.17.2)
16-16: Fenced code blocks should be surrounded by blank lines
(MD031, blanks-around-fences)
🤖 Prompt for AI Agents
In docs/claude-code-integration.md around lines 15 to 21 and also lines 21-25,
133-141, 141-147, 147-152, and 165-168, the fenced code blocks lack surrounding
blank lines and do not consistently specify the language, causing markdownlint
errors MD031 and MD040. Fix this by adding a blank line before and after each
fenced code block and ensure the language is specified immediately after the
opening triple backticks, such as ```bash or ```dockerfile, to comply with
markdownlint rules.
| Add Claude Code to your Task Master configuration: | ||
|
|
||
| ```javascript | ||
| // In your .taskmaster/config.json or via task-master models command | ||
| { | ||
| "models": { | ||
| "main": "claude-code:sonnet", // Use Claude Code with Sonnet | ||
| "research": "perplexity-llama-3.1-sonar-large-128k-online", | ||
| "fallback": "claude-code:opus" // Use Claude Code with Opus as fallback | ||
| } | ||
| } | ||
| ``` |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Unify model ID notation across docs
The repo often uses “claude-code/sonnet” format; this doc uses “claude-code:sonnet”. Please align to the canonical format used by Task Master’s config parser and README.
If “/” is canonical, apply:
- "main": "claude-code:sonnet",
- "fallback": "claude-code:opus"
+ "main": "claude-code/sonnet",
+ "fallback": "claude-code/opus"And update references:
-- `claude-code:sonnet`
-- `claude-code:opus`
+- `claude-code/sonnet`
+- `claude-code/opus`-# Set Claude Code as main model
-task-master models --set-main claude-code:sonnet
+# Set Claude Code as main model
+task-master models --set-main claude-code/sonnetAlso applies to: 62-66, 93-100
🏁 Script executed:
#!/bin/bash
# Search for all usages of "claude-code" across the repository to inspect notation
rg -n "claude-code" -C2 .Length of output: 34893
Unify model ID notation in docs/claude-code-integration.md to use “claude-code/...”
Please replace all occurrences of the colon-style shorthand with the canonical slash-style notation:
• docs/claude-code-integration.md (lines 55–59)
• docs/claude-code-integration.md (lines 64–66)
• docs/claude-code-integration.md (line 95)
• docs/claude-code-integration.md (line 149)
Suggested changes:
@@ docs/claude-code-integration.md:55
- "main": "claude-code:sonnet", // Use Claude Code with Sonnet
+ "main": "claude-code/sonnet", // Use Claude Code with Sonnet
@@ docs/claude-code-integration.md:57
- "fallback": "claude-code:opus" // Use Claude Code with Opus as fallback
+ "fallback": "claude-code/opus" // Use Claude Code with Opus as fallback
@@ docs/claude-code-integration.md:64
-- `claude-code:sonnet` - Claude 3.5 Sonnet via Claude Code CLI
-- `claude-code:opus` - Claude 3 Opus via Claude Code CLI
+- `claude-code/sonnet` - Claude 3.5 Sonnet via Claude Code CLI
+- `claude-code/opus` - Claude 3 Opus via Claude Code CLI
@@ docs/claude-code-integration.md:95
-task-master models --set-main claude-code:sonnet
+task-master models --set-main claude-code/sonnet
@@ docs/claude-code-integration.md:149
- task-master models --test claude-code:sonnet
+ task-master models --test claude-code/sonnet📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| Add Claude Code to your Task Master configuration: | |
| ```javascript | |
| // In your .taskmaster/config.json or via task-master models command | |
| { | |
| "models": { | |
| "main": "claude-code:sonnet", // Use Claude Code with Sonnet | |
| "research": "perplexity-llama-3.1-sonar-large-128k-online", | |
| "fallback": "claude-code:opus" // Use Claude Code with Opus as fallback | |
| } | |
| } | |
| ``` | |
| Add Claude Code to your Task Master configuration: | |
🧰 Tools
🪛 LanguageTool
[grammar] ~49-~49: There might be a mistake here.
Context: ...on Add Claude Code to your Task Master configuration: javascript // In your .taskmaster/config.json or via task-master models command { "models": { "main": "claude-code:sonnet", // Use Claude Code with Sonnet "research": "perplexity-llama-3.1-sonar-large-128k-online", "fallback": "claude-code:opus" // Use Claude Code with Opus as fallback } } ### Supported Models - `claude-...
(QB_NEW_EN_OTHER)
🤖 Prompt for AI Agents
In docs/claude-code-integration.md around lines 49 to 60, replace all instances
of the model ID notation using a colon (e.g., "claude-code:sonnet") with the
canonical slash-style notation (e.g., "claude-code/sonnet"). Apply this change
consistently to all similar occurrences in the specified line ranges (55–59,
64–66, 95, and 149) to unify the model ID format throughout the document.
| ```javascript | ||
| import { generateText } from 'ai'; | ||
| import { ClaudeCodeProvider } from './src/ai-providers/claude-code.js'; | ||
|
|
||
| const provider = new ClaudeCodeProvider(); | ||
| const client = provider.getClient(); | ||
|
|
||
| const result = await generateText({ | ||
| model: client('sonnet'), | ||
| messages: [ | ||
| { role: 'user', content: 'Hello Claude!' } | ||
| ] | ||
| }); | ||
|
|
||
| console.log(result.text); | ||
| ``` |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Use public import path in examples (avoid repo-internal paths)
For user-facing docs, import from the installed package rather than a repo-local path.
-import { ClaudeCodeProvider } from './src/ai-providers/claude-code.js';
+import { ClaudeCodeProvider } from 'task-master-ai/src/ai-providers/claude-code.js';If a top-level export exists, prefer that:
import { ClaudeCodeProvider } from 'task-master-ai';🏁 Script executed:
#!/bin/bash
set -e
echo "==== Listing all package.json files ===="
fd --type f package.json
echo
echo "==== Root package.json (first 200 lines) ===="
sed -n '1,200p' package.json
echo
echo "==== Subpackage package.json files containing 'task-master-ai' in name ===="
rg -l '"name":.*task-master-ai' -g '**/package.json'
echo
echo "==== 'exports' field in root package.json ===="
jq '.exports' package.json || echo "→ No exports field found"
echo
echo "==== Locating claude-code.js ===="
fd 'claude-code.js'
echo
echo "==== claude-code.js head (first 50 lines) ===="
sed -n '1,50p' $(fd 'claude-code.js' | head -n1)
echo
echo "==== Searching for ClaudeCodeProvider in source ===="
grep -R "ClaudeCodeProvider" -n srcLength of output: 7225
🏁 Script executed:
#!/bin/bash
set -e
echo "==== Root index.js (first 200 lines) ===="
sed -n '1,200p' index.js
echo
echo "==== src/ai-providers/index.js (first 200 lines) ===="
sed -n '1,200p' src/ai-providers/index.jsLength of output: 5623
Use public package import instead of relative path in docs
- File: docs/claude-code-integration.md (lines 188–203)
- Replace the repo-internal import with the published package subpath:
-import { ClaudeCodeProvider } from './src/ai-providers/claude-code.js';
+import { ClaudeCodeProvider } from 'task-master-ai/src/ai-providers/claude-code.js';Note: the package’s root entrypoint (index.js) doesn’t currently re-export ClaudeCodeProvider. If you’d like to support a top-level import (import { ClaudeCodeProvider } from 'task-master-ai'), add a re-export in index.js and update the exports field in package.json.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In docs/claude-code-integration.md around lines 188 to 203, replace the relative
import of ClaudeCodeProvider from './src/ai-providers/claude-code.js' with the
public package import path from 'task-master-ai/ai-providers/claude-code'. If
you want to support importing ClaudeCodeProvider directly from the package root,
add a re-export for it in the package's index.js and update the exports field in
package.json accordingly.
| getClient(params = {}) { | ||
| try { | ||
| // Claude Code doesn't use API keys or base URLs | ||
| // Just return the provider factory | ||
| const settings = getClaudeCodeSettingsForCommand(params.commandName); | ||
|
|
||
| return createClaudeCode({ | ||
| defaultSettings: getClaudeCodeSettingsForCommand(params?.commandName) | ||
| defaultSettings: settings | ||
| }); | ||
| } catch (error) { | ||
| this.handleError('client initialization', error); | ||
| // Provide more helpful error message | ||
| if (error.message.includes('Claude Code') || error.message.includes('claude')) { | ||
| const enhancedError = new Error( | ||
| `Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${error.message}` | ||
| ); | ||
| enhancedError.cause = error; | ||
| this.handleError('Claude Code CLI initialization', enhancedError); | ||
| } else { | ||
| this.handleError('client initialization', error); | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Do not swallow errors; harden missing-CLI detection and rethrow
Guard error.message, detect ENOENT deterministically, and rethrow to match JSDoc “throws”.
} catch (error) {
- // Provide more helpful error message
- if (error.message.includes('Claude Code') || error.message.includes('claude')) {
- const enhancedError = new Error(
- `Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${error.message}`
- );
- enhancedError.cause = error;
- this.handleError('Claude Code CLI initialization', enhancedError);
- } else {
- this.handleError('client initialization', error);
- }
+ // Provide more helpful error message and deterministic missing-CLI detection
+ const msg = typeof error?.message === 'string' ? error.message : '';
+ const isMissingCli =
+ error?.code === 'ENOENT' || // spawned process not found
+ msg.toLowerCase().includes('claude code') ||
+ msg.toLowerCase().includes('claude');
+ if (isMissingCli) {
+ const enhancedError = new Error(
+ `Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${msg || 'Unknown'}`
+ );
+ enhancedError.cause = error;
+ this.handleError('Claude Code CLI initialization', enhancedError);
+ throw enhancedError;
+ } else {
+ this.handleError('client initialization', error);
+ throw error;
+ }
}📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| getClient(params = {}) { | |
| try { | |
| // Claude Code doesn't use API keys or base URLs | |
| // Just return the provider factory | |
| const settings = getClaudeCodeSettingsForCommand(params.commandName); | |
| return createClaudeCode({ | |
| defaultSettings: getClaudeCodeSettingsForCommand(params?.commandName) | |
| defaultSettings: settings | |
| }); | |
| } catch (error) { | |
| this.handleError('client initialization', error); | |
| // Provide more helpful error message | |
| if (error.message.includes('Claude Code') || error.message.includes('claude')) { | |
| const enhancedError = new Error( | |
| `Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${error.message}` | |
| ); | |
| enhancedError.cause = error; | |
| this.handleError('Claude Code CLI initialization', enhancedError); | |
| } else { | |
| this.handleError('client initialization', error); | |
| } | |
| } | |
| getClient(params = {}) { | |
| try { | |
| const settings = getClaudeCodeSettingsForCommand(params.commandName); | |
| return createClaudeCode({ | |
| defaultSettings: settings | |
| }); | |
| } catch (error) { | |
| // Provide more helpful error message and deterministic missing-CLI detection | |
| const msg = typeof error?.message === 'string' ? error.message : ''; | |
| const isMissingCli = | |
| error?.code === 'ENOENT' || // spawned process not found | |
| msg.toLowerCase().includes('claude code') || | |
| msg.toLowerCase().includes('claude'); | |
| if (isMissingCli) { | |
| const enhancedError = new Error( | |
| `Claude Code CLI not available. Please install Claude Code CLI first. Original error: ${msg || 'Unknown'}` | |
| ); | |
| enhancedError.cause = error; | |
| this.handleError('Claude Code CLI initialization', enhancedError); | |
| throw enhancedError; | |
| } else { | |
| this.handleError('client initialization', error); | |
| throw error; | |
| } | |
| } | |
| } |
🤖 Prompt for AI Agents
In src/ai-providers/claude-code.js lines 61 to 79, the current error handling
swallows errors and relies on error.message string checks which is fragile.
Update the catch block to first check if error is defined and has a message
property before accessing it. Also, detect missing CLI errors deterministically
by checking if error.code equals 'ENOENT'. After handling the error with this
improved detection, rethrow the error to comply with the JSDoc “throws” contract
instead of swallowing it.
| it('should handle missing claude code CLI gracefully', async () => { | ||
| // Mock the provider to throw when CLI is not available | ||
| jest.unstable_mockModule('ai-sdk-provider-claude-code', () => ({ | ||
| createClaudeCode: jest.fn(() => { | ||
| throw new Error('Claude Code CLI not found'); | ||
| }) | ||
| })); | ||
|
|
||
| it('should allow client creation', () => { | ||
| const provider = new ClaudeCodeProvider(); | ||
| // Client creation should work | ||
| const client = provider.getClient({}); | ||
| expect(client).toBeDefined(); | ||
| expect(typeof client).toBe('function'); | ||
| }); | ||
| const { ClaudeCodeProvider } = await import('../../src/ai-providers/claude-code.js'); | ||
| const provider = new ClaudeCodeProvider(); | ||
|
|
||
| it('should fail with clear error when trying to use the model', async () => { | ||
| const provider = new ClaudeCodeProvider(); | ||
| const client = provider.getClient({}); | ||
| const model = client('opus'); | ||
| expect(() => provider.getClient()).toThrow(/Claude Code CLI not available/); | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Make this test synchronous (no async/await needed)
The path under test throws synchronously. Drop async and dynamic import remains OK.
-it('should handle missing claude code CLI gracefully', async () => {
+it('should handle missing claude code CLI gracefully', () => {
// (rest unchanged)
});Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In tests/integration/claude-code-optional.test.js around lines 23 to 35, the
test is marked async and uses await for dynamic import, but since the code under
test throws synchronously, remove the async keyword from the test function and
drop the await before the dynamic import. This will make the test synchronous
while keeping the dynamic import intact.
| it('should integrate with AI SDK generateText', async () => { | ||
| const provider = new ClaudeCodeProvider(); | ||
| // Should not throw | ||
| expect(() => provider.validateAuth()).not.toThrow(); | ||
| expect(() => provider.validateAuth({ apiKey: null })).not.toThrow(); | ||
| const client = provider.getClient(); | ||
|
|
||
| // Mock successful generation | ||
| generateText.mockResolvedValueOnce({ | ||
| text: 'Hello from Claude Code!', | ||
| usage: { totalTokens: 10 } | ||
| }); | ||
|
|
||
| const result = await generateText({ | ||
| model: client('sonnet'), | ||
| messages: [{ role: 'user', content: 'Hello' }] | ||
| }); | ||
|
|
||
| expect(result.text).toBe('Hello from Claude Code!'); | ||
| expect(generateText).toHaveBeenCalledWith({ | ||
| model: expect.any(Object), | ||
| messages: [{ role: 'user', content: 'Hello' }] | ||
| }); | ||
| }); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Refactor generateText integration test to be synchronous
Mocks can return sync values; remove async/await to comply with repo rules.
- it('should integrate with AI SDK generateText', async () => {
+ it('should integrate with AI SDK generateText', () => {
const provider = new ClaudeCodeProvider();
const client = provider.getClient();
// Mock successful generation
- generateText.mockResolvedValueOnce({
+ generateText.mockReturnValueOnce({
text: 'Hello from Claude Code!',
usage: { totalTokens: 10 }
});
- const result = await generateText({
+ const result = generateText({
model: client('sonnet'),
messages: [{ role: 'user', content: 'Hello' }]
});
expect(result.text).toBe('Hello from Claude Code!');
expect(generateText).toHaveBeenCalledWith({
model: expect.any(Object),
messages: [{ role: 'user', content: 'Hello' }]
});
});📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it('should integrate with AI SDK generateText', async () => { | |
| const provider = new ClaudeCodeProvider(); | |
| // Should not throw | |
| expect(() => provider.validateAuth()).not.toThrow(); | |
| expect(() => provider.validateAuth({ apiKey: null })).not.toThrow(); | |
| const client = provider.getClient(); | |
| // Mock successful generation | |
| generateText.mockResolvedValueOnce({ | |
| text: 'Hello from Claude Code!', | |
| usage: { totalTokens: 10 } | |
| }); | |
| const result = await generateText({ | |
| model: client('sonnet'), | |
| messages: [{ role: 'user', content: 'Hello' }] | |
| }); | |
| expect(result.text).toBe('Hello from Claude Code!'); | |
| expect(generateText).toHaveBeenCalledWith({ | |
| model: expect.any(Object), | |
| messages: [{ role: 'user', content: 'Hello' }] | |
| }); | |
| }); | |
| it('should integrate with AI SDK generateText', () => { | |
| const provider = new ClaudeCodeProvider(); | |
| const client = provider.getClient(); | |
| // Mock successful generation | |
| generateText.mockReturnValueOnce({ | |
| text: 'Hello from Claude Code!', | |
| usage: { totalTokens: 10 } | |
| }); | |
| const result = generateText({ | |
| model: client('sonnet'), | |
| messages: [{ role: 'user', content: 'Hello' }] | |
| }); | |
| expect(result.text).toBe('Hello from Claude Code!'); | |
| expect(generateText).toHaveBeenCalledWith({ | |
| model: expect.any(Object), | |
| messages: [{ role: 'user', content: 'Hello' }] | |
| }); | |
| }); |
🤖 Prompt for AI Agents
In tests/integration/claude-code-optional.test.js between lines 60 and 80, the
generateText integration test uses async/await with a mocked function that can
return synchronous values. Refactor the test to remove async/await by returning
the mock value synchronously and adjusting the test accordingly to comply with
repo rules against unnecessary async usage.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (2)
package.json (2)
57-58: Add a Changeset entry for these dependency upgradesUpgrading
aito 5.0.0-beta.34 and introducingai-sdk-provider-claude-coderequires a.changesetentry per repo policy. Reuse the prior suggestion; it still applies.Example:
--- "task-master-ai": minor --- Enhance Claude Code integration: migrate to ai-sdk-provider-claude-code and upgrade ai to 5.0.0-beta.34. Improves model support, auth fallback, and error handling.
13-27: Add required test scripts (unit/integration/ci) to comply with repo workflowPer guidelines, include test:unit, test:integration, and test:ci. This was flagged earlier; reiterating here.
"scripts": { "test": "node --experimental-vm-modules node_modules/.bin/jest", "test:fails": "node --experimental-vm-modules node_modules/.bin/jest --onlyFailures", "test:watch": "node --experimental-vm-modules node_modules/.bin/jest --watch", "test:coverage": "node --experimental-vm-modules node_modules/.bin/jest --coverage", + "test:unit": "node --experimental-vm-modules node_modules/.bin/jest tests/unit", + "test:integration": "node --experimental-vm-modules node_modules/.bin/jest tests/integration", + "test:ci": "node --experimental-vm-modules node_modules/.bin/jest --ci --runInBand", "test:e2e": "./tests/e2e/run_e2e.sh", "test:e2e-report": "./tests/e2e/run_e2e.sh --analyze-log", "prepare": "chmod +x bin/task-master.js mcp-server/server.js", "changeset": "changeset", "release": "changeset publish",
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (1)
package.json(2 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
package.json
📄 CodeRabbit Inference Engine (.cursor/rules/test_workflow.mdc)
Add and update test scripts in package.json to include test, test:watch, test:coverage, test:unit, test:integration, test:e2e, and test:ci
Files:
package.json
🧠 Learnings (31)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/changeset.mdc:0-0
Timestamp: 2025-07-18T17:07:53.100Z
Learning: Every pull request containing new features, bug fixes, breaking changes, performance improvements, significant refactoring, user-facing documentation updates, dependency updates, or impactful build/tooling changes should include a changeset file.
Learnt from: rtmcrc
PR: eyaltoledano/claude-task-master#933
File: scripts/modules/supported-models.json:238-238
Timestamp: 2025-07-21T14:14:48.694Z
Learning: Model version updates in scripts/modules/supported-models.json may be included in feature PRs if they provide practical improvements like reduced error rates, even if not directly related to the main feature being implemented.
Learnt from: eyaltoledano
PR: eyaltoledano/claude-task-master#1069
File: .changeset/floppy-news-buy.md:7-38
Timestamp: 2025-08-02T14:54:52.216Z
Learning: For major feature additions like new CLI commands, eyaltoledano prefers detailed changesets with comprehensive descriptions, usage examples, and feature explanations rather than minimal single-line summaries.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to tests/unit/ai-providers/*.test.js : Create unit tests for the new provider in tests/unit/ai-providers/<provider-name>.test.js, mocking ai-sdk/<provider-name> and core ai module functions, and testing all exported functions for correct behavior and error handling.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to scripts/modules/ai-services-unified.js : Integrate the new provider module with scripts/modules/ai-services-unified.js by importing it and adding an entry to the PROVIDER_FUNCTIONS map.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to scripts/modules/config-manager.js : Update scripts/modules/config-manager.js to add the new provider to MODEL_MAP, ensure it is included in VALID_PROVIDERS, and update API key handling logic.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Update relevant documentation files (such as README.md) to mention the new provider and its configuration.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must import the provider's create<ProviderName> function from ai-sdk/<provider-name>, and import generateText, streamText, generateObject from the core ai package, as well as the log utility from ../../scripts/modules/utils.js.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to src/ai-providers/*.js : Provider-specific wrappers for Vercel AI SDK functions must be implemented in src/ai-providers/*.js, each file corresponding to a provider.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Create a new provider module file in src/ai-providers/ named <provider-name>.js when adding a new AI provider.
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Implement generate<ProviderName>Text, stream<ProviderName>Text, and generate<ProviderName>Object functions in provider modules with basic validation and try/catch error handling.
📚 Learning: 2025-08-07T13:00:22.923Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1090
File: apps/extension/package.json:241-243
Timestamp: 2025-08-07T13:00:22.923Z
Learning: In monorepos, local packages should use "*" as the version constraint in package.json dependencies, as recommended by npm. This ensures the local version from within the same workspace is always used, rather than attempting to resolve from external registries. This applies to packages like task-master-ai within the eyaltoledano/claude-task-master monorepo.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must import the provider's create<ProviderName> function from ai-sdk/<provider-name>, and import generateText, streamText, generateObject from the core ai package, as well as the log utility from ../../scripts/modules/utils.js.
Applied to files:
package.json
📚 Learning: 2025-07-17T21:33:57.585Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1002
File: .changeset/puny-friends-give.md:2-3
Timestamp: 2025-07-17T21:33:57.585Z
Learning: In the eyaltoledano/claude-task-master repository, the MCP server code in mcp-server/src/ is part of the main "task-master-ai" package, not a separate "mcp-server" package. When creating changesets for MCP server changes, use "task-master-ai" as the package name.
Applied to files:
package.json
📚 Learning: 2025-08-03T12:13:33.875Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/test_workflow.mdc:0-0
Timestamp: 2025-08-03T12:13:33.875Z
Learning: Applies to package.json : Add and update test scripts in package.json to include test, test:watch, test:coverage, test:unit, test:integration, test:e2e, and test:ci
Applied to files:
package.json
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Do not import real AI service clients in tests; create fully mocked versions that return predictable responses.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/commands.js : Do not import or call anything from the old `ai-services.js`, `ai-client-factory.js`, or `ai-client-utils.js` files.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:06:57.833Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_services.mdc:0-0
Timestamp: 2025-07-18T17:06:57.833Z
Learning: Applies to scripts/modules/task-manager/*.js : Do not import or call anything from the old `ai-services.js`, `ai-client-factory.js`, or `ai-client-utils.js` files.
Applied to files:
package.json
📚 Learning: 2025-07-31T20:49:04.638Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#997
File: apps/extension/package.publish.json:2-8
Timestamp: 2025-07-31T20:49:04.638Z
Learning: In the eyaltoledano/claude-task-master repository, the VS Code extension uses a 3-file packaging system where package.json (with name "extension") is for development within the monorepo, while package.publish.json (with name "task-master-hamster") contains the clean manifest for VS Code marketplace publishing. The different names are intentional and serve distinct purposes in the build and publishing workflow.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to src/ai-providers/*.js : Provider-specific wrappers for Vercel AI SDK functions must be implemented in src/ai-providers/*.js, each file corresponding to a provider.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to tests/unit/ai-providers/*.test.js : Create unit tests for the new provider in tests/unit/ai-providers/<provider-name>.test.js, mocking ai-sdk/<provider-name> and core ai module functions, and testing all exported functions for correct behavior and error handling.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to .changeset/* : Create appropriate changesets for new features, use semantic versioning, include tagged system information in release notes, and document breaking changes if any.
Applied to files:
package.json
📚 Learning: 2025-08-06T21:12:43.673Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1091
File: assets/claude/agents/task-orchestrator.md:1-6
Timestamp: 2025-08-06T21:12:43.673Z
Learning: In the eyaltoledano/claude-task-master repository, agent files are intentionally duplicated between `.claude/agents/` (for internal project use) and `assets/claude/agents/` (as template files for users to copy). This duplication serves different purposes and should be maintained to support both internal development and user distribution needs.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:10:53.657Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/glossary.mdc:0-0
Timestamp: 2025-07-18T17:10:53.657Z
Learning: Guidelines for using Changesets (npm run changeset) to manage versioning and changelogs (changeset.mdc).
Applied to files:
package.json
📚 Learning: 2025-07-18T17:07:53.100Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/changeset.mdc:0-0
Timestamp: 2025-07-18T17:07:53.100Z
Learning: Applies to .changeset/*.md : When running `npm run changeset` or `npx changeset add`, provide a concise summary of the changes for the `CHANGELOG.md` in imperative mood, typically a single line, and not a detailed Git commit message.
Applied to files:
package.json
📚 Learning: 2025-08-06T21:12:20.956Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1091
File: assets/claude/agents/task-executor.md:1-6
Timestamp: 2025-08-06T21:12:20.956Z
Learning: In the eyaltoledano/claude-task-master repository, agent files in assets/claude/agents/ are intended for distribution to users (for copying), while identical files in .claude/agents/ are for internal project use. This intentional duplication serves different purposes and is not a DRY violation.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:07:53.100Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/changeset.mdc:0-0
Timestamp: 2025-07-18T17:07:53.100Z
Learning: Every pull request containing new features, bug fixes, breaking changes, performance improvements, significant refactoring, user-facing documentation updates, dependency updates, or impactful build/tooling changes should include a changeset file.
Applied to files:
package.json
📚 Learning: 2025-08-06T21:13:05.213Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1091
File: assets/claude/agents/task-orchestrator.md:69-78
Timestamp: 2025-08-06T21:13:05.213Z
Learning: For Claude agent instruction files in .claude/agents/ and assets/claude/agents/ directories, ignore markdownlint issues (like MD031 blanks-around-fences, MD040 fenced-code-language, MD041 missing top-level heading) as these files follow Claude's specific agent format requirements rather than standard markdown documentation conventions.
Applied to files:
package.json
📚 Learning: 2025-08-06T21:16:02.249Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1095
File: .github/scripts/check-pre-release-mode.mjs:33-34
Timestamp: 2025-08-06T21:16:02.249Z
Learning: In the claude-task-master project, the .changeset directory is guaranteed to exist as part of the fundamental project structure, so validation checks for its existence are unnecessary.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Explicitly handle all options, including defaults and shorthand flags (e.g., -p for --prompt), and include null/undefined checks in test implementations for parameters that might be optional.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Every new feature must include comprehensive tests following the guidelines in 'tests.mdc', including unit tests, integration tests, edge cases, and at least 80% coverage.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test CLI and MCP interfaces with real task data, verify end-to-end workflows across tag contexts, and test error scenarios and recovery in integration tests.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:07:39.336Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/architecture.mdc:0-0
Timestamp: 2025-07-18T17:07:39.336Z
Learning: Applies to tests/{unit,integration,e2e,fixtures}/**/*.js : Test files must be organized as follows: unit tests in tests/unit/, integration tests in tests/integration/, end-to-end tests in tests/e2e/, and test fixtures in tests/fixtures/.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to **/*.test.js : Do not use real AI client initialization logic in tests; create test-specific paths that bypass client initialization.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/**/*.test.js : Test core logic independently with both data formats, mock file system operations, test tag resolution behavior, and verify migration compatibility in unit tests.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:16:13.793Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tests.mdc:0-0
Timestamp: 2025-07-18T17:16:13.793Z
Learning: Applies to tests/{unit,integration,e2e}/**/*.test.js : Do not try to use the real action implementation without proper mocking, and do not mock Commander partially—either mock it completely or test the action directly.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Provider modules must export three functions: generate<ProviderName>Text, stream<ProviderName>Text, and generate<ProviderName>Object.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Create a new provider module file in src/ai-providers/ named <provider-name>.js when adding a new AI provider.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:06:04.909Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/ai_providers.mdc:0-0
Timestamp: 2025-07-18T17:06:04.909Z
Learning: Applies to src/ai-providers/*.js : Implement generate<ProviderName>Text, stream<ProviderName>Text, and generate<ProviderName>Object functions in provider modules with basic validation and try/catch error handling.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:12:57.903Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/new_features.mdc:0-0
Timestamp: 2025-07-18T17:12:57.903Z
Learning: Applies to scripts/modules/ai-services.js : Features that use AI models belong in 'scripts/modules/ai-services.js'.
Applied to files:
package.json
🔇 Additional comments (1)
package.json (1)
88-88: Optional dependency bump LGTMKeeping
@anthropic-ai/claude-codeas an optional dependency aligns with the new provider’s CLI fallback behavior.
| "ai": "^5.0.0-beta.34", | ||
| "ai-sdk-provider-claude-code": "^1.0.0-beta.1", |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Avoid caret range on beta releases to prevent unexpected breakage
Pin beta versions exactly to keep CI stable.
- "ai": "^5.0.0-beta.34",
- "ai-sdk-provider-claude-code": "^1.0.0-beta.1",
+ "ai": "5.0.0-beta.34",
+ "ai-sdk-provider-claude-code": "1.0.0-beta.1",📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "ai": "^5.0.0-beta.34", | |
| "ai-sdk-provider-claude-code": "^1.0.0-beta.1", | |
| "ai": "5.0.0-beta.34", | |
| "ai-sdk-provider-claude-code": "1.0.0-beta.1", |
🤖 Prompt for AI Agents
In package.json at lines 57 to 58, the dependencies "ai" and
"ai-sdk-provider-claude-code" use caret (^) version ranges on beta releases,
which can cause unexpected breakage. Change the version specifications to exact
versions by removing the caret (^) prefix to pin the beta versions exactly and
ensure CI stability.
|
Closing to recreate PR targeting upstream/next instead of origin/next |
Summary
This PR enhances the Claude Code AI SDK integration with comprehensive improvements, updated dependencies, better error handling, and thorough documentation.
Key Changes
🆙 Dependencies Updated
🔧 Provider Enhancement (
src/ai-providers/claude-code.js)getSupportedModels,isModelSupported)✅ Testing Improvements
📚 Documentation (
docs/claude-code-integration.md)claude setup-token🔐 Authentication Features
CLAUDE_CODE_OAUTH_TOKENenv var → CLI-stored token → errorclaude setup-token)Testing Verified
generateTextandstreamTextconfirmedFiles Changed
Enhanced
src/ai-providers/claude-code.js- Enhanced provider with better error handlingtests/unit/ai-providers/claude-code.test.js- Updated tests with model supporttests/integration/claude-code-optional.test.js- Improved integration testingpackage.json- Updated AI SDK dependenciesAdded
docs/claude-code-integration.md- Comprehensive integration documentationscripts/test-claude-code-direct.js- Integration test scriptRemoved
src/ai-providers/custom-sdk/claude-code/- Deprecated custom implementationtests/unit/ai-providers/custom-sdk/claude-code/- Associated testsBreaking Changes
None - maintains full backward compatibility while enhancing functionality.
Production Impact
This PR significantly improves the Claude Code integration quality while maintaining complete backward compatibility.
🤖 Generated with Claude Code
Co-Authored-By: Claude noreply@anthropic.com
Summary by CodeRabbit
New Features
Dependency Updates
aipackage to a newer beta version.ai-sdk-provider-claude-codeas a new dependency.@anthropic-ai/claude-code.Refactor
Tests