Conversation
…ject" when SDK missing; improve CLI stability (#1146) * fix: handle missing @anthropic-ai/claude-code SDK gracefully Add defensive checks to prevent "Right-hand side of 'instanceof' is not an object" errors when the optional Claude Code SDK is not installed. Changes: - Check if AbortError exists before using instanceof - Check if query function exists before calling it - Provide clear error messages when SDK is missing This fixes the issue reported by users in v0.24.0 and v0.25.0 where Task Master would crash with instanceof errors when using the claude-code provider without the SDK installed. * chore: bump @anthropic-ai/claude-code to ^1.0.88 and regenerate lockfile
* fix: temporarily disable streaming
🦋 Changeset detectedLatest commit: db720a9 The changes in this PR will be included in the next version bump. Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
WalkthroughDisables streaming in PRD parsing via a feature flag and updates tests accordingly. Adds runtime guards and safer AbortError handling in the Claude Code language model. Updates optional dependency version and formats JSON files. Adds changeset entries and updates a documentation attribution line. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant CLI/Caller as Caller
participant Config as PrdParseConfig
participant Parser as Parse PRD Service
participant Gen as generateObjectService
participant Stream as streamObjectService
User->>CLI/Caller: parse PRD
CLI/Caller->>Config: new PrdParseConfig(...)
Note right of Config: ENABLE_STREAMING=false<br/>(temporary gate)
Config-->>CLI/Caller: useStreaming=false
CLI/Caller->>Parser: parse(input, useStreaming=false)
alt useStreaming=false
Parser->>Gen: generateObject(...)
Gen-->>Parser: result
else useStreaming=true
Parser->>Stream: streamObject(...)
Stream-->>Parser: stream events
end
Parser-->>CLI/Caller: parsed result
CLI/Caller-->>User: output
sequenceDiagram
autonumber
participant Caller
participant LM as ClaudeCodeLanguageModel
participant SDK as Claude Code SDK (query)
Caller->>LM: doGenerate(request)
LM->>LM: if (!query) throw Error("SDK not loaded")
LM->>SDK: query(request)
SDK-->>LM: response
LM-->>Caller: result
rect rgba(255,235,205,0.3)
note right of LM: Error handling (guarded)
Caller->>LM: doGenerate(...) / doStream(...)
LM->>LM: try { ... } catch (e) {<br/>if (AbortError && e instanceof AbortError) handleAbort()<br/>else throw e }
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested reviewers
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ 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/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (7)
src/ai-providers/custom-sdk/claude-code/language-model.js (1)
440-486: Bug: ‘error’ is referenced outside a catch block in streaming path (unbound identifier).Within
doStream()you attempt JSON-truncation recovery usingerrorinside the try body, buterroris not defined there. This will throw a ReferenceError and bypass the intended recovery path.Fix by moving the truncation handling into the
catch (error)block and hoistingusage/accumulatedTextso they’re visible in the catch:@@ - let usage = { promptTokens: 0, completionTokens: 0 }; - let accumulatedText = ''; + // Hoist so they are visible to the catch block + let usage = { promptTokens: 0, completionTokens: 0 }; + let accumulatedText = ''; @@ - // ------------------------------------------------------------- - // 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 - } + // Truncation handling moved to catch block @@ - } catch (error) { - let errorToEmit; + } catch (error) { + // JSON truncation recovery (mirrors doGenerate) + 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) { + const finalText = + options.mode?.type === 'object-json' + ? extractJson(accumulatedText) + : accumulatedText; + controller.enqueue({ type: 'text-delta', textDelta: finalText }); + 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; + } + let errorToEmit;tests/unit/scripts/modules/task-manager/parse-prd.test.js (6)
798-839: Non-streaming with reportProgress (streaming disabled) is asserted correctly; add telemetry UI assertion.Good pivot to non-streaming. Given guidelines require showing AI usage in CLI/text when telemetry exists, assert
displayAiUsageSummaryis invoked when applicable.Apply this diff to import the UI helper and assert it:
@@ -jest.unstable_mockModule('../../../../../scripts/modules/ui.js', () => ({ +jest.unstable_mockModule('../../../../../scripts/modules/ui.js', () => ({ getStatusWithColor: jest.fn((status) => status), startLoadingIndicator: jest.fn(), stopLoadingIndicator: jest.fn(), displayAiUsageSummary: jest.fn() })); @@ -const { JSONParser } = await import('@streamparser/json'); +const { JSONParser } = await import('@streamparser/json'); +const { displayAiUsageSummary } = await import( + '../../../../../scripts/modules/ui.js' +); @@ -// With streaming disabled, should use generateObjectService instead +// With streaming disabled, should use generateObjectService instead expect(generateObjectService).toHaveBeenCalled(); @@ -// Verify progress reporting was still called +// Verify progress reporting was still called expect(mockReportProgress).toHaveBeenCalled(); +// If CLI/text path is used and telemetry is available, summarize usage +expect(displayAiUsageSummary).toHaveBeenCalledWith({}, 'cli');
1009-1032: CLI text mode (streaming disabled) checks are good; also assert progress tracker creation.You already note tracker components may still be used. Add an explicit assertion so regressions are caught.
@@ -// Progress tracker components may still be called for CLI mode display -// but the actual parsing uses non-streaming +// Tracker still created for CLI display even if parsing is non-streaming +expect(createParsePrdTracker).toHaveBeenCalledWith( + expect.objectContaining({ numUnits: 3, unitName: 'task' }) +);
28-68: Normalize generateObjectService mock return shape across tests.Return shapes vary between
{ tasks: [...] },{ mainResult: sample }, and{ mainResult: { object } }. This obscures contract regressions and forces defensive branching. Standardize on one shape (recommended:{ mainResult: { object }, telemetryData }).Apply this diff to the initial mock and adjust individual tests to override only the payload, not the shape:
@@ -jest.unstable_mockModule( - '../../../../../scripts/modules/ai-services-unified.js', - () => ({ - generateObjectService: jest.fn().mockResolvedValue({ - tasks: [ - { id: 1, title: 'Test Task 1', priority: 'high', description: 'Test description 1', status: 'pending', dependencies: [] }, - { id: 2, title: 'Test Task 2', priority: 'medium', description: 'Test description 2', status: 'pending', dependencies: [] }, - { id: 3, title: 'Test Task 3', priority: 'low', description: 'Test description 3', status: 'pending', dependencies: [] } - ] - }), +jest.unstable_mockModule( + '../../../../../scripts/modules/ai-services-unified.js', + () => ({ + generateObjectService: jest.fn().mockResolvedValue({ + mainResult: { + object: { + tasks: [ + { id: 1, title: 'Test Task 1', priority: 'high', description: 'Test description 1', status: 'pending', dependencies: [] }, + { id: 2, title: 'Test Task 2', priority: 'medium', description: 'Test description 2', status: 'pending', dependencies: [] }, + { id: 3, title: 'Test Task 3', priority: 'low', description: 'Test description 3', status: 'pending', dependencies: [] } + ], + metadata: { projectName: 'Fixture', totalTasks: 3, sourceFile: 'fixture.prd', generatedAt: '2025-01-01T00:00:00Z' } + } + }, + telemetryData: {} + }),
568-593: Avoid matching exact error messages; assert on error types or patterns.Per test guidelines, don’t lock tests to exact strings. Use regex or general properties to keep tests robust.
@@ -).rejects.toThrow('Test error in AI API call'); +).rejects.toThrow(/AI API call/i); @@ -).rejects.toThrow('already contains'); +).rejects.toThrow(/already contains/i); @@ -).rejects.toThrow('process.exit was called with code 1'); +).rejects.toThrow(/process\.exit was called with code \d+/);Also applies to: 649-676, 678-693
236-251: Prefer mock-fs for FS ops to align with repo test standards.You’re manually mocking
fs; switching tomock-fsimproves isolation (e.g., path joins, encodings) and aligns with guidance.If you adopt
mock-fs, ensure restoration inafterEach:@@ -jest.unstable_mockModule('fs', () => ({ - default: { /* ... */ }, - readFileSync: jest.fn(), - existsSync: jest.fn(), - mkdirSync: jest.fn(), - writeFileSync: jest.fn() -})); +import mockFs from 'mock-fs'; @@ -beforeEach(() => { +beforeEach(() => { + mockFs({ + path: { 'to': { 'prd.txt': '# Sample PRD for Testing' } }, + tasks: {} + }); // existing spies/mocks... }); @@ -afterEach(() => { +afterEach(() => { + mockFs.restore(); jest.restoreAllMocks(); });
471-479: Spying on console is fine; ensure restoration even on failure.You restore spies in
afterEach, good. Consider also restoringprocess.exitspy there to avoid bleed-over if a test throws before hitting your manual restore.@@ - afterEach(() => { - // Restore all mocks after each test - jest.restoreAllMocks(); - }); +afterEach(() => { + jest.restoreAllMocks(); + if (process.exit.mockRestore) process.exit.mockRestore(); +});
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (8)
.changeset/quiet-owls-fix-cli-sdk.md(1 hunks).changeset/rich-emus-say.md(1 hunks).claude/commands/dedupe.md(1 hunks)apps/extension/package.json(3 hunks)package.json(2 hunks)scripts/modules/task-manager/parse-prd/parse-prd-config.js(1 hunks)src/ai-providers/custom-sdk/claude-code/language-model.js(4 hunks)tests/unit/scripts/modules/task-manager/parse-prd.test.js(7 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
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
.changeset/*.md
📄 CodeRabbit inference engine (.cursor/rules/changeset.mdc)
.changeset/*.md: When runningnpm run changesetornpx changeset add, provide a concise summary of the changes for theCHANGELOG.mdin imperative mood, typically a single line, and not a detailed Git commit message.
The changeset summary should be user-facing, describing what changed in the released version that is relevant to users or consumers of the package.
Do not use your detailed Git commit message body as the changeset summary.
Files:
.changeset/quiet-owls-fix-cli-sdk.md.changeset/rich-emus-say.md
.changeset/*
📄 CodeRabbit inference engine (.cursor/rules/new_features.mdc)
Create appropriate changesets for new features, use semantic versioning, include tagged system information in release notes, and document breaking changes if any.
Files:
.changeset/quiet-owls-fix-cli-sdk.md.changeset/rich-emus-say.md
scripts/modules/**
📄 CodeRabbit inference engine (.cursor/rules/dev_workflow.mdc)
When using the MCP server, restart it if core logic in
scripts/modulesor MCP tool/direct function definitions change.
Files:
scripts/modules/task-manager/parse-prd/parse-prd-config.js
scripts/modules/task-manager/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/telemetry.mdc)
scripts/modules/task-manager/**/*.js: Functions in scripts/modules/task-manager/ that invoke AI services must call the appropriate AI service function (e.g., generateObjectService), passing commandName and outputType in the params object.
Core logic functions in scripts/modules/task-manager/ must return an object that includes aiServiceResponse.telemetryData.
If the core logic function handles CLI output (outputFormat === 'text' or 'cli'), and aiServiceResponse.telemetryData is available, it must call displayAiUsageSummary(aiServiceResponse.telemetryData, 'cli') from scripts/modules/ui.js.Do not call AI-specific getters (like
getMainModelId,getMainMaxTokens) from core logic functions inscripts/modules/task-manager/*; instead, pass theroleto the unified AI service.
Files:
scripts/modules/task-manager/parse-prd/parse-prd-config.js
**/*.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.js: Declare and initialize global variables at the top of modules to avoid hoisting issues.
Use proper function declarations to avoid hoisting issues and initialize variables before they are referenced.
Do not reference variables before their declaration in module scope.
Use dynamic imports (import()) to avoid initialization order issues in modules.
Files:
scripts/modules/task-manager/parse-prd/parse-prd-config.jstests/unit/scripts/modules/task-manager/parse-prd.test.jssrc/ai-providers/custom-sdk/claude-code/language-model.js
tests/{unit,integration,e2e,fixtures}/**/*.js
📄 CodeRabbit inference engine (.cursor/rules/architecture.mdc)
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/.
Files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
**/*.{test,spec}.{js,ts,jsx,tsx}
📄 CodeRabbit inference engine (.cursor/rules/git_workflow.mdc)
**/*.{test,spec}.{js,ts,jsx,tsx}: Create a test file and ensure all tests pass when all subtasks are complete; commit tests if added or modified
When all subtasks are complete, run final testing using the appropriate test runner (e.g., npm test, jest, or manual testing)
Files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
**/*.test.js: Never use asynchronous operations in tests. Make all mocks return synchronous values when possible.
Always mock tests properly based on the way the tested functions are defined and used.
Follow the test file organization: mocks must be set up before importing modules under test, and spies on mocked modules should be set up after imports.
Use fixtures from tests/fixtures/ for consistent sample data across tests.
Always declare mocks before importing the modules being tested in Jest test files.
Use jest.spyOn() after imports to create spies on mock functions and reference these spies in test assertions.
When testing functions with callbacks, get the callback from your mock's call arguments, execute it directly with test inputs, and verify the results.
For ES modules, use jest.mock() before static imports and jest.unstable_mockModule() before dynamic imports to mock dependencies.
Reset mock functions (mockFn.mockReset()) before dynamic imports if they might have been called previously.
When verifying console assertions, assert against the actual arguments passed (single formatted string), not multiple arguments.
Use mock-fs to mock file system operations in tests, and restore the file system after each test.
Mock API calls (e.g., Anthropic/Claude) by mocking the entire module and providing predictable responses.
Set mock environment variables in test setup and restore them after each test.
Maintain test fixtures separate from test logic.
Follow the mock-first-then-import pattern for all Jest mocks.
Do not define mock variables before jest.mock() calls (they won't be accessible due to hoisting).
Use test-specific file paths (e.g., 'test-tasks.json') for all file operations in tests.
Mock readJSON and writeJSON to avoid real file system interactions in tests.
Verify file operations use the correct paths in expect statements.
Use different file paths for each test to avoid test interdependence.
Verify modifications on the in-memory task objects passed to w...
Files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
tests/unit/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
tests/unit/**/*.test.js: Unit tests must be located in tests/unit/, test individual functions and utilities in isolation, mock all external dependencies, and keep tests small, focused, and fast.
Do not include actual command execution in unit tests.
Files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
tests/{unit,integration,e2e}/**/*.test.js
📄 CodeRabbit inference engine (.cursor/rules/tests.mdc)
tests/{unit,integration,e2e}/**/*.test.js: When testing CLI commands built with Commander.js, test the command action handlers directly rather than trying to mock the entire Commander.js chain.
When mocking the Commander.js chain, mock ALL chainable methods (option, argument, action, on, etc.) and return this (or the mock object) from all chainable method mocks.
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.
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.
Mock the action handlers for CLI commands and verify they're called with correct arguments.
Use sample task fixtures for consistent test data, mock file system operations, and test both success and error paths for task operations.
Mock console output and verify correct formatting in UI function tests. Use flexible assertions like toContain() or toMatch() for formatted output.
Mock chalk functions to return the input text to make testing easier while still verifying correct function calls.
Files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
**/*.{test,spec}.*
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
Test files should follow naming conventions: .test., .spec., or _test. depending on the language
Files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
tests/{unit,integration,e2e}/**
📄 CodeRabbit inference engine (.cursor/rules/test_workflow.mdc)
Organize test directories by test type (unit, integration, e2e) and mirror source structure where possible
Files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
🧠 Learnings (27)
📓 Common learnings
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/git_workflow.mdc:0-0
Timestamp: 2025-07-18T17:10:31.810Z
Learning: Pull Request descriptions must use the provided template, including Task Overview, Subtasks Completed, Implementation Details, Testing, Breaking Changes, and Related Tasks
📚 Learning: 2025-08-07T13:00:22.966Z
Learnt from: Crunchyman-ralph
PR: eyaltoledano/claude-task-master#1090
File: apps/extension/package.json:241-243
Timestamp: 2025-08-07T13:00:22.966Z
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: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.jsontests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 modify real task files (tasks.json) during tests.
Applied to files:
package.json
📚 Learning: 2025-07-18T17:18:17.759Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/utilities.mdc:0-0
Timestamp: 2025-07-18T17:18:17.759Z
Learning: Applies to mcp-server/src/{core/utils,tools}/**/*.js : Place utilities specifically designed to support the MCP server implementation into the appropriate subdirectories within `mcp-server/src/` (e.g., path/core logic helpers in `mcp-server/src/core/utils/`, tool execution/response helpers in `mcp-server/src/tools/utils.js`).
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:
apps/extension/package.json
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Use consistent formatting for task files, include all task properties in text files, and format dependencies with status indicators.
Applied to files:
apps/extension/package.json
📚 Learning: 2025-08-11T12:30:23.843Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-11T12:30:23.843Z
Learning: Import Task Master's development workflow commands and guidelines; treat the contents of ./.taskmaster/CLAUDE.md as if included in the main CLAUDE.md
Applied to files:
.claude/commands/dedupe.md
📚 Learning: 2025-08-06T21:12:43.715Z
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.715Z
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:
.claude/commands/dedupe.md
📚 Learning: 2025-07-20T01:35:05.831Z
Learnt from: rtmcrc
PR: eyaltoledano/claude-task-master#933
File: scripts/modules/task-manager/parse-prd.js:226-226
Timestamp: 2025-07-20T01:35:05.831Z
Learning: The parsePRD function in scripts/modules/task-manager/parse-prd.js has a different parameter structure than other task-manager functions - it uses `options` parameter instead of `context` parameter because it generates tasks from PRD documents rather than operating on existing tasks.
Applied to files:
scripts/modules/task-manager/parse-prd/parse-prd-config.jstests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 Learning: 2025-07-18T17:14:29.399Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/tasks.mdc:0-0
Timestamp: 2025-07-18T17:14:29.399Z
Learning: Applies to scripts/modules/task-manager.js : Generate task files from the current tag context, include tag information in generated files, and do not mix tasks from different tags in file generation.
Applied to files:
scripts/modules/task-manager/parse-prd/parse-prd-config.js
📚 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 : Verify modifications on the in-memory task objects passed to writeJSON.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : Use `generateTextService` and implement robust manual JSON parsing (with Zod validation after parsing) when structured output is needed, as `generateObjectService` has shown unreliability with some providers/schemas.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : Never use asynchronous operations in tests. Make all mocks return synchronous values when possible.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : Mock readJSON and writeJSON to avoid real file system interactions in tests.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : Mock console output and verify correct formatting in UI function tests. Use flexible assertions like toContain() or toMatch() for formatted output.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 Learning: 2025-07-18T17:11:36.732Z
Learnt from: CR
PR: eyaltoledano/claude-task-master#0
File: .cursor/rules/mcp.mdc:0-0
Timestamp: 2025-07-18T17:11:36.732Z
Learning: Applies to mcp-server/src/core/direct-functions/*.js : Do not use or pass reportProgress within *Direct functions.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : Use mock-fs to mock file system operations in tests, and restore the file system after each test.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 test exact error messages; test for error presence and general properties instead.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : Mock the action handlers for CLI commands and verify they're called with correct arguments.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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/**/*.test.js : Do not include actual command execution in unit tests.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : When testing CLI commands built with Commander.js, test the command action handlers directly rather than trying to mock the entire Commander.js chain.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
📚 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 : Mock chalk functions to return the input text to make testing easier while still verifying correct function calls.
Applied to files:
tests/unit/scripts/modules/task-manager/parse-prd.test.js
🧬 Code graph analysis (1)
tests/unit/scripts/modules/task-manager/parse-prd.test.js (3)
mcp-server/src/core/direct-functions/parse-prd.js (1)
result(155-172)scripts/modules/task-manager/parse-prd/parse-prd-streaming.js (1)
result(559-568)tests/unit/parse-prd.test.js (1)
parsePRD(211-213)
🪛 LanguageTool
.changeset/quiet-owls-fix-cli-sdk.md
[grammar] ~5-~5: Use correct spacing
Context: ...1.0.88` for improved export consistency. Related to JSON truncation handling in #...
(QB_NEW_EN_OTHER_ERROR_IDS_5)
[grammar] ~7-~7: There might be a mistake here.
Context: ...Related to JSON truncation handling in #920; this change addresses a separate error-...
(QB_NEW_EN_OTHER)
[grammar] ~7-~7: Use correct spacing
Context: ...rate error-path crash reported in #1142.
(QB_NEW_EN_OTHER_ERROR_IDS_5)
.changeset/rich-emus-say.md
[typographical] ~5-~5: To join two clauses or set off examples, consider using an em dash.
Context: ...ly disable streaming for improved model compatibility - will be re-enabled in upcoming release
(QB_NEW_EN_DASH_RULE_EM)
[grammar] ~5-~5: There might be a mistake here.
Context: ...- will be re-enabled in upcoming release
(QB_NEW_EN_OTHER)
🪛 markdownlint-cli2 (0.17.2)
.changeset/quiet-owls-fix-cli-sdk.md
5-5: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
.changeset/rich-emus-say.md
5-5: First line in a file should be a top-level heading
(MD041, first-line-heading, first-line-h1)
🔇 Additional comments (11)
.changeset/rich-emus-say.md (1)
5-5: Polish the changeset summary for style and clarity (imperative + punctuation).Keep it user-facing and single-line. Replace the hyphen with a semicolon and end with a period per our changeset guidance.
Apply this diff:
-Temporarily disable streaming for improved model compatibility - will be re-enabled in upcoming release +Temporarily disable streaming for improved model compatibility; re-enable in a future release.Note: markdownlint MD041 (top-level heading) is a false positive for changeset files; safe to ignore here.
package.json (1)
89-92: Please manually verify the next version bump to 0.25.1I attempted to run
npx changeset status --verbosebut encountered an error (could not determine executable to run). To ensure the release will be version 0.25.1 as per the PR title, please:
- Inspect your
.changeset/*.mdfront-matter to confirm it specifies a patch bump.- Verify that the current
versioninpackage.json(e.g. 0.25.0) plus this patch bump equals 0.25.1.- Optionally run locally (with dependencies installed)
yarn changeset versionornpx changeset versionto preview the new version..claude/commands/dedupe.md (1)
36-36: Attribution tweak acknowledged; verify intent to remove the hyperlink.The new attribution “Generated with [Task Master Bot]” (escaped) is fine. Confirm that removing the external link is intentional and consistent across other command docs.
.changeset/quiet-owls-fix-cli-sdk.md (1)
5-8: Condense changeset text to a single, user-facing line (avoid commit-style body).Changeset entries should be concise and imperative. Move deep technical detail and issue cross-links to the PR description or commit body.
Apply this diff:
-fix(claude-code): prevent crash/hang when the optional `@anthropic-ai/claude-code` SDK is missing by guarding `AbortError instanceof` checks and adding explicit SDK presence checks in `doGenerate`/`doStream`. Also bump the optional dependency to `^1.0.88` for improved export consistency. - -Related to JSON truncation handling in #920; this change addresses a separate error-path crash reported in #1142. +Fix crash/hang when optional Claude Code SDK is missing; guard AbortError checks, add SDK presence checks, and bump optional @anthropic-ai/claude-code to ^1.0.88.Note: markdownlint MD041 is expected noise for changeset files; safe to ignore.
apps/extension/package.json (2)
14-15: Activation events change looks fine.Collapsing to single-line arrays does not alter behavior. No action needed.
142-143: Enum formatting-only changes are safe.Single-line enum arrays are equivalent. No functional impact.
Also applies to: 203-204
src/ai-providers/custom-sdk/claude-code/language-model.js (1)
235-239: Robust AbortError guards LGTM.Guarding
instanceofwith(AbortError && ...)avoids ReferenceErrors when the SDK isn’t loaded. Good defensive change.Also applies to: 491-495
scripts/modules/task-manager/parse-prd/parse-prd-config.js (2)
80-85: Provider check helper is concise and correct.Simple gating over main vs research provider aligns with CUSTOM_PROVIDERS. No issues.
71-75: The above script will dump the entirety of theparsePRDfunction (lines 210–270). This will let us verify:
- That the only branch-check for streaming versus non-streaming is
if (config.useStreaming).- What the fallback/non-streaming path does immediately after the
catchblock.- That there are no other gating conditions (e.g., inspecting
options.*or other flags).Once we see the output, we can confirm if downstream routing honors
config.useStreamingexclusively or if further adjustments are needed.tests/unit/scripts/modules/task-manager/parse-prd.test.js (2)
840-920: Skipped fallback test: convert to explicit TODO with actionable plan.Skipping is fine short-term, but please annotate the reason and intended rewrite (switch from parseStream to streamObjectService semantics) to avoid permanent drift.
Add a comment like:
- test.skip('should fallback to non-streaming when streaming fails with specific errors (streaming disabled)', async () => { + // TODO(tech-debt): Rework fallback test for streamObjectService shape and unskip. + test.skip('should fallback to non-streaming when streaming fails with specific errors (streaming disabled)', async () => {
954-978: Research path assertion LGTM.Verifies non-streaming with
role: 'research'under streaming-disabled mode. Matches task-manager guidelines.
| "Education", | ||
| "Other" | ||
| ], | ||
| "categories": ["AI", "Visualization", "Education", "Other"], |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
🛠️ Refactor suggestion
Use workspace-local version for monorepo dependency.
Per our monorepo practice, depend on the local workspace package rather than a pinned version to avoid publish-time skew and ensure dev builds pick up HEAD.
Apply this diff:
- "task-master-ai": "0.25.0"
+ "task-master-ai": "*"Follow-up: If you prefer explicit workspace protocol, we can switch to "workspace:*" across the repo in a separate PR.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In apps/extension/package.json around line 12, the package currently references
a pinned external version instead of the workspace-local package; update the
dependency entry in the dependencies/devDependencies to use the workspace
protocol (e.g., "workspace:*") so the monorepo uses the local package at HEAD
during development and avoids publish-time skew.
| "apps/*", | ||
| "." | ||
| ], | ||
| "workspaces": ["apps/*", "."], |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Add the required test scripts per repository guidelines.
Our repo standards call for test, test:watch, test:coverage, test:unit, test:integration, test:e2e, and test:ci in package.json. You already have most of these; add the missing ones as simple aliases to existing commands to keep CI happy.
Apply this diff:
"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: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",
"inspector": "npx @modelcontextprotocol/inspector node mcp-server/server.js",
"mcp-server": "node mcp-server/server.js",
"format-check": "biome format .",
- "format": "biome format . --write"
+ "format": "biome format . --write",
+ "test:unit": "npm run test",
+ "test:integration": "npm run test:e2e",
+ "test:ci": "npm run test -- --ci"
},📝 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.
| "workspaces": ["apps/*", "."], | |
| "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: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", | |
| "inspector": "npx @modelcontextprotocol/inspector node mcp-server/server.js", | |
| "mcp-server": "node mcp-server/server.js", | |
| "format-check": "biome format .", | |
| "format": "biome format . --write", | |
| "test:unit": "npm run test", | |
| "test:integration": "npm run test:e2e", | |
| "test:ci": "npm run test -- --ci" | |
| }, |
🤖 Prompt for AI Agents
In package.json around line 12, add the missing test script aliases required by
repo guidelines: add "test", "test:watch", "test:coverage", "test:unit",
"test:integration", "test:e2e", and "test:ci" in the scripts section as simple
aliases to existing test commands — for example set "test" to run the CI test
alias, "test:watch" to run the test command with --watch, "test:coverage" to run
the test command with --coverage, "test:ci" to run tests in CI mode (e.g.
--runInBand), and make "test:unit", "test:integration", and "test:e2e" point to
the CI test command with appropriate --testPathPattern or tag filters for
unit/integration/e2e; ensure these are just npm script aliases (npm run ...) so
CI recognizes them.
| // Feature flag: Temporarily disable streaming, use generateObject instead | ||
| // TODO: Re-enable streaming once issues are resolved | ||
| const ENABLE_STREAMING = false; | ||
|
|
||
| this.useStreaming = | ||
| typeof this.reportProgress === 'function' || this.outputFormat === 'text'; | ||
| ENABLE_STREAMING && | ||
| (typeof this.reportProgress === 'function' || | ||
| this.outputFormat === 'text'); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Streaming hard-disabled as a feature flag: make it configurable and observable.
The gate is correct for temporarily pausing streaming, but a hard-coded false forces code edits and commits to flip it. Prefer an env/config-driven flag and add a brief debug log when streaming is disabled to aid diagnosis.
Apply this diff to make the flag configurable with a safe default and keep the existing behavior:
@@
- // Feature flag: Temporarily disable streaming, use generateObject instead
- // TODO: Re-enable streaming once issues are resolved
- const ENABLE_STREAMING = false;
+ // Feature flag: Temporarily disable streaming; default off.
+ // TODO: Re-enable once issues are resolved.
+ const ENABLE_STREAMING =
+ process.env.ENABLE_STREAMING === '1' ||
+ process.env.ENABLE_STREAMING === 'true';
@@
- this.useStreaming =
- ENABLE_STREAMING &&
- (typeof this.reportProgress === 'function' || this.outputFormat === 'text');
+ this.useStreaming =
+ ENABLE_STREAMING &&
+ (typeof this.reportProgress === 'function' || this.outputFormat === 'text');
+ if (!this.useStreaming && process?.env?.DEBUG?.includes('parse-prd')) {
+ // lightweight breadcrumb in debug builds
+ log('debug', '[parse-prd] Streaming disabled via feature flag; using generateObject path.');
+ }📝 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.
| // Feature flag: Temporarily disable streaming, use generateObject instead | |
| // TODO: Re-enable streaming once issues are resolved | |
| const ENABLE_STREAMING = false; | |
| this.useStreaming = | |
| typeof this.reportProgress === 'function' || this.outputFormat === 'text'; | |
| ENABLE_STREAMING && | |
| (typeof this.reportProgress === 'function' || | |
| this.outputFormat === 'text'); | |
| } | |
| // Feature flag: Temporarily disable streaming; default off. | |
| // TODO: Re-enable once issues are resolved. | |
| const ENABLE_STREAMING = | |
| process.env.ENABLE_STREAMING === '1' || | |
| process.env.ENABLE_STREAMING === 'true'; | |
| this.useStreaming = | |
| ENABLE_STREAMING && | |
| (typeof this.reportProgress === 'function' || | |
| this.outputFormat === 'text'); | |
| if (!this.useStreaming && process?.env?.DEBUG?.includes('parse-prd')) { | |
| // lightweight breadcrumb in debug builds | |
| log('debug', '[parse-prd] Streaming disabled via feature flag; using generateObject path.'); | |
| } | |
| } |
🤖 Prompt for AI Agents
In scripts/modules/task-manager/parse-prd/parse-prd-config.js around lines 67 to
75, replace the hard-coded ENABLE_STREAMING = false with a config/env-driven
boolean (e.g., read process.env.ENABLE_STREAMING or a config object, parse it
safely to boolean and default to false) so toggling doesn't require code
changes; set this.useStreaming using that value as before, and add a brief
debug/info log when streaming is disabled (using the module's logger or
console.debug) to make the state observable for troubleshooting.
| if (!query) { | ||
| throw new Error( | ||
| "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider." | ||
| ); | ||
| } |
There was a problem hiding this comment.
🧹 Nitpick (assertive)
Good runtime guard, but DRY it and fail earlier in loader.
Duplicate guards for a missing SDK are added in both generate and stream paths. Prefer hardening loadClaudeCodeModule() to validate required exports and throwing there, so call-sites don’t need to re-check.
Apply this diff to make the loader authoritative and remove the redundant checks:
@@
-async function loadClaudeCodeModule() {
- if (!query || !AbortError) {
- try {
- const mod = await import('@anthropic-ai/claude-code');
- query = mod.query;
- AbortError = mod.AbortError;
- } catch (err) {
- throw new Error(
- "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider."
- );
- }
- }
-}
+async function loadClaudeCodeModule() {
+ if (query && AbortError) return;
+ try {
+ const mod = await import('@anthropic-ai/claude-code');
+ if (!mod?.query || !mod?.AbortError) {
+ throw new Error(
+ "Claude Code SDK is installed but missing required exports ('query', 'AbortError'). Please upgrade '@anthropic-ai/claude-code' to a compatible version."
+ );
+ }
+ query = mod.query;
+ AbortError = mod.AbortError;
+ } catch (err) {
+ throw new Error(
+ "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider."
+ );
+ }
+}
@@
- if (!query) {
- throw new Error(
- "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider."
- );
- }
+ // SDK availability validated by loadClaudeCodeModule()
@@
- if (!query) {
- throw new Error(
- "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider."
- );
- }
+ // SDK availability validated by loadClaudeCodeModule()Also applies to: 343-347
| const stream = new ReadableStream({ | ||
| start: async (controller) => { | ||
| try { | ||
| if (!query) { | ||
| throw new Error( | ||
| "Claude Code SDK is not installed. Please install '@anthropic-ai/claude-code' to use the claude-code provider." | ||
| ); | ||
| } | ||
| const response = query({ |
There was a problem hiding this comment.
💡 Verification agent
🧩 Analysis chain
Ensure ReadableStream availability across runtimes.
ReadableStream is used directly; in some Node runtimes it’s behind node:stream/web or may require a polyfill. Verify global availability or import from 'node:stream/web'.
Run to confirm and locate any existing polyfill/import:
🏁 Script executed:
#!/bin/bash
# Check all references to ReadableStream and imports for stream/web
rg -nP '\bReadableStream\b|node:stream/web|stream/web' -C2 --no-ignore-vcsLength of output: 1646
Add explicit ReadableStream import to support Node.js runtimes
The code on line 340 of src/ai-providers/custom-sdk/claude-code/language-model.js uses new ReadableStream(...) without guaranteeing it’s globally available in all Node versions. To ensure compatibility, import ReadableStream from the built-in Node module or provide a browser/global fallback.
• File needing change:
• src/ai-providers/custom-sdk/claude-code/language-model.js
• Action:
- At the top of the file, add:
+ // Ensure ReadableStream is available in Node.js + import { ReadableStream } from 'node:stream/web';
- (Optional) If targeting both browser and Node, you can guard the import:
let ReadableStreamCtor = globalThis.ReadableStream; try { // Node.js ≥ v18 ReadableStreamCtor ||= require('node:stream/web').ReadableStream; } catch {}
— This guarantees the ReadableStream constructor is available regardless of runtime.
🤖 Prompt for AI Agents
In src/ai-providers/custom-sdk/claude-code/language-model.js around lines 340 to
348, the code constructs a ReadableStream directly which may not exist in all
Node runtimes; to fix, add a portable ReadableStream reference at the top of the
file: attempt to use globalThis.ReadableStream and fallback to requiring
'node:stream/web'.ReadableStream (wrapped in try/catch), or otherwise export a
ReadableStreamCtor variable that the stream construction uses; ensure the rest
of the file replaces direct new ReadableStream(...) with new
ReadableStreamCtor(...) so the constructor is available in both Node and browser
environments.
What type of PR is this?
Description
Related Issues
How to Test This
# Example commands or stepsExpected result:
Contributor Checklist
npm run changesetnpm testnpm run format-check(ornpm run formatto fix)Changelog Entry
For Maintainers
Summary by CodeRabbit