Compare commits

...

3 Commits

Author SHA1 Message Date
github-actions[bot]
4cae2991d4 Version Packages (#1154)
* Version Packages

* chore: fix changelog

---------

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
2025-08-23 00:44:25 +02:00
Ralph Khreish
0d7ff627c9 Merge pull request #1152 from eyaltoledano/next 2025-08-23 00:34:40 +02:00
Ralph Khreish
db720a954d Fix: disable streaming for parse prd (#1151)
* fix: temporarily disable streaming
2025-08-22 18:33:02 +02:00
8 changed files with 51 additions and 39 deletions

View File

@@ -1,8 +0,0 @@
---
"task-master-ai": patch
---
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.

View File

@@ -1,5 +1,15 @@
# task-master-ai # task-master-ai
## 0.25.1
### Patch Changes
- [#1152](https://github.com/eyaltoledano/claude-task-master/pull/1152) [`8933557`](https://github.com/eyaltoledano/claude-task-master/commit/89335578ffffc65504b2055c0c85aa7521e5e79b) Thanks [@ben-vargas](https://github.com/ben-vargas)! - 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.
- [#1151](https://github.com/eyaltoledano/claude-task-master/pull/1151) [`db720a9`](https://github.com/eyaltoledano/claude-task-master/commit/db720a954d390bb44838cd021b8813dde8f3d8de) Thanks [@Crunchyman-ralph](https://github.com/Crunchyman-ralph)! - Temporarily disable streaming for improved model compatibility - will be re-enabled in upcoming release
## 0.25.0 ## 0.25.0
### Minor Changes ### Minor Changes

View File

@@ -1,5 +1,12 @@
# Change Log # Change Log
## 0.24.1
### Patch Changes
- Updated dependencies [[`8933557`](https://github.com/eyaltoledano/claude-task-master/commit/89335578ffffc65504b2055c0c85aa7521e5e79b), [`db720a9`](https://github.com/eyaltoledano/claude-task-master/commit/db720a954d390bb44838cd021b8813dde8f3d8de)]:
- task-master-ai@0.25.1
## 0.24.0 ## 0.24.0
### Minor Changes ### Minor Changes

View File

@@ -3,7 +3,7 @@
"private": true, "private": true,
"displayName": "TaskMaster", "displayName": "TaskMaster",
"description": "A visual Kanban board interface for TaskMaster projects in VS Code", "description": "A visual Kanban board interface for TaskMaster projects in VS Code",
"version": "0.24.0", "version": "0.24.1",
"publisher": "Hamster", "publisher": "Hamster",
"icon": "assets/icon.png", "icon": "assets/icon.png",
"engines": { "engines": {
@@ -256,7 +256,7 @@
"check-types": "tsc --noEmit" "check-types": "tsc --noEmit"
}, },
"dependencies": { "dependencies": {
"task-master-ai": "0.25.0" "task-master-ai": "0.25.1"
}, },
"devDependencies": { "devDependencies": {
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",

8
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "task-master-ai", "name": "task-master-ai",
"version": "0.25.0", "version": "0.25.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "task-master-ai", "name": "task-master-ai",
"version": "0.25.0", "version": "0.25.1",
"license": "MIT WITH Commons-Clause", "license": "MIT WITH Commons-Clause",
"workspaces": [ "workspaces": [
"apps/*", "apps/*",
@@ -93,9 +93,9 @@
} }
}, },
"apps/extension": { "apps/extension": {
"version": "0.24.0", "version": "0.24.1",
"dependencies": { "dependencies": {
"task-master-ai": "0.25.0" "task-master-ai": "0.25.1"
}, },
"devDependencies": { "devDependencies": {
"@dnd-kit/core": "^6.3.1", "@dnd-kit/core": "^6.3.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "task-master-ai", "name": "task-master-ai",
"version": "0.25.0", "version": "0.25.1",
"description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.", "description": "A task management system for ambitious AI-driven development that doesn't overwhelm and confuse Cursor.",
"main": "index.js", "main": "index.js",
"type": "module", "type": "module",

View File

@@ -63,8 +63,15 @@ export class PrdParseConfig {
this.targetTag = this.tag || getCurrentTag(this.projectRoot) || 'master'; this.targetTag = this.tag || getCurrentTag(this.projectRoot) || 'master';
this.isMCP = !!this.mcpLog; this.isMCP = !!this.mcpLog;
this.outputFormat = this.isMCP && !this.reportProgress ? 'json' : 'text'; this.outputFormat = this.isMCP && !this.reportProgress ? 'json' : 'text';
// Feature flag: Temporarily disable streaming, use generateObject instead
// TODO: Re-enable streaming once issues are resolved
const ENABLE_STREAMING = false;
this.useStreaming = this.useStreaming =
typeof this.reportProgress === 'function' || this.outputFormat === 'text'; ENABLE_STREAMING &&
(typeof this.reportProgress === 'function' ||
this.outputFormat === 'text');
} }
/** /**

View File

@@ -795,7 +795,7 @@ describe('parsePRD', () => {
}); });
describe('Streaming vs Non-Streaming Modes', () => { describe('Streaming vs Non-Streaming Modes', () => {
test('should use streaming when reportProgress function is provided', async () => { test('should use non-streaming when reportProgress function is provided (streaming disabled)', async () => {
// Setup mocks to simulate normal conditions (no existing output file) // Setup mocks to simulate normal conditions (no existing output file)
fs.default.existsSync.mockImplementation((path) => { fs.default.existsSync.mockImplementation((path) => {
if (path === 'tasks/tasks.json') return false; // Output file doesn't exist if (path === 'tasks/tasks.json') return false; // Output file doesn't exist
@@ -815,23 +815,20 @@ describe('parsePRD', () => {
}; };
JSONParser.mockReturnValue(mockParser); JSONParser.mockReturnValue(mockParser);
// Call the function with reportProgress to trigger streaming path // Call the function with reportProgress - with streaming disabled, should use non-streaming
const result = await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 3, { const result = await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 3, {
reportProgress: mockReportProgress reportProgress: mockReportProgress
}); });
// Verify streamObjectService was called (streaming path) // With streaming disabled, should use generateObjectService instead
expect(streamObjectService).toHaveBeenCalled(); expect(generateObjectService).toHaveBeenCalled();
// Verify generateObjectService was NOT called (non-streaming path) // Verify streamObjectService was NOT called (streaming is disabled)
expect(generateObjectService).not.toHaveBeenCalled(); expect(streamObjectService).not.toHaveBeenCalled();
// Verify progress reporting was called // Verify progress reporting was still called
expect(mockReportProgress).toHaveBeenCalled(); expect(mockReportProgress).toHaveBeenCalled();
// We no longer use parseStream with streamObject
// expect(parseStream).toHaveBeenCalled();
// Verify result structure // Verify result structure
expect(result).toEqual({ expect(result).toEqual({
success: true, success: true,
@@ -840,7 +837,7 @@ describe('parsePRD', () => {
}); });
}); });
test('should fallback to non-streaming when streaming fails with specific errors', async () => { test.skip('should fallback to non-streaming when streaming fails with specific errors (streaming disabled)', async () => {
// Setup mocks to simulate normal conditions (no existing output file) // Setup mocks to simulate normal conditions (no existing output file)
fs.default.existsSync.mockImplementation((path) => { fs.default.existsSync.mockImplementation((path) => {
if (path === 'tasks/tasks.json') return false; // Output file doesn't exist if (path === 'tasks/tasks.json') return false; // Output file doesn't exist
@@ -954,7 +951,7 @@ describe('parsePRD', () => {
}); });
}); });
test('should handle research flag with streaming', async () => { test('should handle research flag with non-streaming (streaming disabled)', async () => {
// Setup mocks to simulate normal conditions // Setup mocks to simulate normal conditions
fs.default.existsSync.mockImplementation((path) => { fs.default.existsSync.mockImplementation((path) => {
if (path === 'tasks/tasks.json') return false; // Output file doesn't exist if (path === 'tasks/tasks.json') return false; // Output file doesn't exist
@@ -965,19 +962,19 @@ describe('parsePRD', () => {
// Mock progress reporting function // Mock progress reporting function
const mockReportProgress = jest.fn(() => Promise.resolve()); const mockReportProgress = jest.fn(() => Promise.resolve());
// Call with streaming + research // Call with reportProgress + research - with streaming disabled, should use non-streaming
await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 3, { await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 3, {
reportProgress: mockReportProgress, reportProgress: mockReportProgress,
research: true research: true
}); });
// Verify streaming path was used with research role // With streaming disabled, should use generateObjectService with research role
expect(streamObjectService).toHaveBeenCalledWith( expect(generateObjectService).toHaveBeenCalledWith(
expect.objectContaining({ expect.objectContaining({
role: 'research' role: 'research'
}) })
); );
expect(generateObjectService).not.toHaveBeenCalled(); expect(streamObjectService).not.toHaveBeenCalled();
}); });
test('should handle research flag with non-streaming', async () => { test('should handle research flag with non-streaming', async () => {
@@ -1009,7 +1006,7 @@ describe('parsePRD', () => {
expect(streamObjectService).not.toHaveBeenCalled(); expect(streamObjectService).not.toHaveBeenCalled();
}); });
test('should use streaming for CLI text mode even without reportProgress', async () => { test('should use non-streaming for CLI text mode (streaming disabled)', async () => {
// Setup mocks to simulate normal conditions // Setup mocks to simulate normal conditions
fs.default.existsSync.mockImplementation((path) => { fs.default.existsSync.mockImplementation((path) => {
if (path === 'tasks/tasks.json') return false; // Output file doesn't exist if (path === 'tasks/tasks.json') return false; // Output file doesn't exist
@@ -1020,13 +1017,12 @@ describe('parsePRD', () => {
// Call without mcpLog and without reportProgress (CLI text mode) // Call without mcpLog and without reportProgress (CLI text mode)
const result = await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 3); const result = await parsePRD('path/to/prd.txt', 'tasks/tasks.json', 3);
// Verify streaming path was used (no mcpLog means CLI text mode, which should use streaming) // With streaming disabled, should use generateObjectService even in CLI text mode
expect(streamObjectService).toHaveBeenCalled(); expect(generateObjectService).toHaveBeenCalled();
expect(generateObjectService).not.toHaveBeenCalled(); expect(streamObjectService).not.toHaveBeenCalled();
// Verify progress tracker components were called for CLI mode // Progress tracker components may still be called for CLI mode display
expect(createParsePrdTracker).toHaveBeenCalled(); // but the actual parsing uses non-streaming
expect(displayParsePrdStart).toHaveBeenCalled();
expect(result).toEqual({ expect(result).toEqual({
success: true, success: true,