Fixes streamingInterval issue. Updates system prompt for tasks json.
This commit is contained in:
79
templates/dev.js
Normal file → Executable file
79
templates/dev.js
Normal file → Executable file
@@ -45,6 +45,7 @@ import path from 'path';
|
||||
import dotenv from 'dotenv';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { dirname } from 'path';
|
||||
import readline from 'readline';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = dirname(__filename);
|
||||
@@ -98,6 +99,16 @@ const anthropic = new Anthropic({
|
||||
apiKey: process.env.ANTHROPIC_API_KEY,
|
||||
});
|
||||
|
||||
function readJSON(filepath) {
|
||||
if (!fs.existsSync(filepath)) return null;
|
||||
const content = fs.readFileSync(filepath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
function writeJSON(filepath, data) {
|
||||
fs.writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
// Add a simple loading indicator function
|
||||
function startLoadingIndicator(message) {
|
||||
const frames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
||||
@@ -118,16 +129,6 @@ function stopLoadingIndicator(interval) {
|
||||
readline.clearLine(process.stdout, 0);
|
||||
}
|
||||
|
||||
function readJSON(filepath) {
|
||||
if (!fs.existsSync(filepath)) return null;
|
||||
const content = fs.readFileSync(filepath, 'utf8');
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
function writeJSON(filepath, data) {
|
||||
fs.writeFileSync(filepath, JSON.stringify(data, null, 2), 'utf8');
|
||||
}
|
||||
|
||||
async function callClaude(prdContent, prdPath, numTasks, retryCount = 0) {
|
||||
const MAX_RETRIES = 3;
|
||||
const INITIAL_BACKOFF_MS = 1000;
|
||||
@@ -197,62 +198,14 @@ async function callClaude(prdContent, prdPath, numTasks, retryCount = 0) {
|
||||
}
|
||||
}
|
||||
|
||||
// Determine if we should use streaming based on PRD size
|
||||
// For PRDs larger than 20,000 characters (roughly 5,000 tokens), use streaming
|
||||
const useStreaming = prdContent.length > 20000;
|
||||
// Always use streaming to avoid "Streaming is strongly recommended" error
|
||||
log('info', `Using streaming API for PRD processing...`);
|
||||
return await handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens, systemPrompt, loadingIndicator);
|
||||
|
||||
if (useStreaming) {
|
||||
log('info', `Large PRD detected (${prdContent.length} characters). Using streaming API...`);
|
||||
return await handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens, systemPrompt, loadingIndicator);
|
||||
} else {
|
||||
log('info', "Sending request to Claude API...");
|
||||
|
||||
const response = await anthropic.messages.create({
|
||||
max_tokens: maxTokens,
|
||||
model: CONFIG.model,
|
||||
temperature: CONFIG.temperature,
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: prdContent
|
||||
}
|
||||
],
|
||||
system: systemPrompt
|
||||
});
|
||||
|
||||
// Stop loading indicator
|
||||
stopLoadingIndicator(loadingIndicator);
|
||||
log('info', "Received response from Claude API!");
|
||||
|
||||
// Extract the text content from the response
|
||||
const textContent = response.content[0].text;
|
||||
return processClaudeResponse(textContent, numTasks, retryCount, prdContent, prdPath);
|
||||
}
|
||||
} catch (error) {
|
||||
// Stop loading indicator
|
||||
stopLoadingIndicator(loadingIndicator);
|
||||
|
||||
// Check if this is the streaming recommendation error
|
||||
if (error.message && error.message.includes("Streaming is strongly recommended")) {
|
||||
log('info', "Claude recommends streaming for this large PRD. Switching to streaming mode...");
|
||||
try {
|
||||
// Calculate appropriate max tokens based on PRD size
|
||||
let maxTokens = CONFIG.maxTokens;
|
||||
const estimatedPrdTokens = Math.ceil(prdContent.length / 4);
|
||||
const suggestedMaxTokens = Math.min(32000, estimatedPrdTokens * 2);
|
||||
if (suggestedMaxTokens > maxTokens) {
|
||||
maxTokens = suggestedMaxTokens;
|
||||
}
|
||||
|
||||
// Restart the loading indicator
|
||||
const newLoadingIndicator = startLoadingIndicator(loadingMessage);
|
||||
return await handleStreamingRequest(prdContent, prdPath, numTasks, maxTokens, systemPrompt, newLoadingIndicator);
|
||||
} catch (streamingError) {
|
||||
log('error', "Error with streaming API call:", streamingError);
|
||||
throw streamingError;
|
||||
}
|
||||
}
|
||||
|
||||
log('error', "Error calling Claude API:", error);
|
||||
|
||||
// Implement exponential backoff for retries
|
||||
@@ -465,7 +418,7 @@ async function parsePRD(prdPath, tasksPath, numTasks) {
|
||||
writeJSON(tasksPath, data);
|
||||
log('info', `Parsed PRD from '${prdPath}' -> wrote ${tasks.length} tasks to '${tasksPath}'.`);
|
||||
} catch (error) {
|
||||
log('error', `Failed to generate tasks from PRD: ${error.message}`);
|
||||
log('error', "Failed to generate tasks:", error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
@@ -499,7 +452,7 @@ function generateTaskFiles(tasksPath, outputDir) {
|
||||
log('info', `Reading tasks from ${tasksPath}...`);
|
||||
const data = readJSON(tasksPath);
|
||||
if (!data || !data.tasks) {
|
||||
log('error', "No valid tasks to generate. Please run parse-prd first.");
|
||||
log('error', "No valid tasks to generate files for.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user