feat: CLI & MCP progress tracking for parse-prd command (#1048)

* initial cutover

* update log to debug

* update tracker to pass units

* update test to match new base tracker format

* add streamTextService mocks

* remove unused imports

* Ensure the CLI waits for async main() completion

* refactor to reduce code duplication

* update comment

* reuse function

* ensure targetTag is defined in streaming mode

* avoid throwing inside process.exit spy

* check for null

* remove reference to generate

* fix formatting

* fix textStream assignment

* ensure no division by 0

* fix jest chalk mocks

* refactor for maintainability

* Improve bar chart calculation logic for consistent visual representation

* use custom streaming error types; fix mocks

* Update streamText extraction in parse-prd.js to match actual service response

* remove check - doesn't belong here

* update mocks

* remove streaming test that wasn't really doing anything

* add comment

* make parsing logic more DRY

* fix formatting

* Fix textStream extraction to match actual service response

* fix mock

* Add a cleanup method to ensure proper resource disposal and prevent memory leaks

* debounce progress updates to reduce UI flicker during rapid updates

* Implement timeout protection for streaming operations (60-second timeout) with automatic fallback to non-streaming mode.

* clear timeout properly

* Add a maximum buffer size limit (1MB) to prevent unbounded memory growth with very large streaming responses.

* fix formatting

* remove duplicate mock

* better docs

* fix formatting

* sanitize the dynamic property name

* Fix incorrect remaining progress calculation

* Use onError callback instead of console.warn

* Remove unused chalk import

* Add missing custom validator in fallback parsing configuration

* add custom validator parameter in fallback parsing

* chore: fix package-lock.json

* chore: large code refactor

* chore: increase timeout from 1 minute to 3 minutes

* fix: refactor and fix streaming

* Merge remote-tracking branch 'origin/next' into joedanz/parse-prd-progress

* fix: cleanup and fix unit tests

* chore: fix unit tests

* chore: fix format

* chore: run format

* chore: fix weird CI unit test error

* chore: fix format

---------

Co-authored-by: Ralph Khreish <35776126+Crunchyman-ralph@users.noreply.github.com>
This commit is contained in:
Joe Danziger
2025-08-12 16:37:07 -04:00
committed by GitHub
parent fc47714340
commit e3ed4d7c14
39 changed files with 6993 additions and 1137 deletions

View File

@@ -79,6 +79,38 @@ jest.unstable_mockModule(
totalCost: 0.012414,
currency: 'USD'
}
}),
streamTextService: jest.fn().mockResolvedValue({
mainResult: async function* () {
yield '{"tasks":[';
yield '{"id":1,"title":"Test Task","priority":"high"}';
yield ']}';
},
telemetryData: {
timestamp: new Date().toISOString(),
userId: '1234567890',
commandName: 'analyze-complexity',
modelUsed: 'claude-3-5-sonnet',
providerName: 'anthropic',
inputTokens: 1000,
outputTokens: 500,
totalTokens: 1500,
totalCost: 0.012414,
currency: 'USD'
}
}),
streamObjectService: jest.fn().mockImplementation(async () => {
return {
get partialObjectStream() {
return (async function* () {
yield { tasks: [] };
yield { tasks: [{ id: 1, title: 'Test Task', priority: 'high' }] };
})();
},
object: Promise.resolve({
tasks: [{ id: 1, title: 'Test Task', priority: 'high' }]
})
};
})
})
);
@@ -189,9 +221,8 @@ const { readJSON, writeJSON, log, CONFIG, findTaskById } = await import(
'../../../../../scripts/modules/utils.js'
);
const { generateObjectService, generateTextService } = await import(
'../../../../../scripts/modules/ai-services-unified.js'
);
const { generateObjectService, generateTextService, streamTextService } =
await import('../../../../../scripts/modules/ai-services-unified.js');
const fs = await import('fs');

View File

@@ -178,6 +178,24 @@ jest.unstable_mockModule(
});
}
}),
streamTextService: jest.fn().mockResolvedValue({
mainResult: async function* () {
yield '{"tasks":[';
yield '{"id":1,"title":"Test Task","priority":"high"}';
yield ']}';
},
telemetryData: {
timestamp: new Date().toISOString(),
commandName: 'analyze-complexity',
modelUsed: 'claude-3-5-sonnet',
providerName: 'anthropic',
inputTokens: 1000,
outputTokens: 500,
totalTokens: 1500,
totalCost: 0.012414,
currency: 'USD'
}
}),
generateObjectService: jest.fn().mockResolvedValue({
mainResult: {
object: {
@@ -402,7 +420,7 @@ const { readJSON, writeJSON, getTagAwareFilePath } = await import(
'../../../../../scripts/modules/utils.js'
);
const { generateTextService } = await import(
const { generateTextService, streamTextService } = await import(
'../../../../../scripts/modules/ai-services-unified.js'
);

File diff suppressed because it is too large Load Diff