Compare commits
3 Commits
ralph/fix/
...
task-maste
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cae2991d4 | ||
|
|
0d7ff627c9 | ||
|
|
db720a954d |
@@ -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.
|
|
||||||
|
|
||||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
8
package-lock.json
generated
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
Reference in New Issue
Block a user