Load Due Cards
Load decks and calculate which cards are due for review today
Source Code
import { readFileSync, writeFileSync, existsSync } from "fs";
const [decksPath, dueCardsPath, deckFilter] = process.argv.slice(2);
try {
// Check if decks file exists
if (!existsSync(decksPath)) {
console.log(
JSON.stringify({
success: true,
totalDue: 0,
decks: [],
message: "No flashcard decks found. Create some flashcards first!",
})
);
writeFileSync(
dueCardsPath,
JSON.stringify({ summary: { totalDue: 0, decks: [] }, cards: [] }, null, 2)
);
process.exit(0);
}
const decksData = JSON.parse(readFileSync(decksPath, "utf-8"));
const today = new Date().toISOString().split("T")[0];
const dueCards = [];
const deckSummaries = [];
for (const [slug, deck] of Object.entries(decksData.decks)) {
// Skip if filtering and this isn't the target deck
if (deckFilter && deckFilter !== slug) continue;
const deckDueCards = deck.cards.filter((card) => {
// Card is due if nextReview is today or earlier
return card.nextReview <= today;
});
if (deckDueCards.length > 0) {
deckSummaries.push({
slug: slug,
name: deck.name,
dueCount: deckDueCards.length,
totalCards: deck.cards.length,
});
// Add cards with deck context
for (const card of deckDueCards) {
dueCards.push({
id: card.id,
deckSlug: slug,
deckName: deck.name,
front: card.front,
back: card.back,
interval: card.interval,
correctCount: card.correctCount,
incorrectCount: card.incorrectCount,
});
}
}
}
// Write due cards to session file
const dueCardsOutput = {
summary: {
totalDue: dueCards.length,
decks: deckSummaries,
generatedAt: new Date().toISOString(),
},
cards: dueCards,
};
writeFileSync(dueCardsPath, JSON.stringify(dueCardsOutput, null, 2));
// Log summary for agent
if (dueCards.length === 0) {
// Find next due card
let nextDue = null;
let nextDueDeck = null;
for (const [slug, deck] of Object.entries(decksData.decks)) {
for (const card of deck.cards) {
if (!nextDue || card.nextReview < nextDue) {
nextDue = card.nextReview;
nextDueDeck = deck.name;
}
}
}
console.log(
JSON.stringify({
success: true,
totalDue: 0,
decks: [],
message: nextDue
? `No cards due for review today. Next card due on ${nextDue} from "${nextDueDeck}".`
: "No cards due for review.",
})
);
} else {
const deckList = deckSummaries
.map((d) => `${d.dueCount} from "${d.name}"`)
.join(", ");
console.log(
JSON.stringify({
success: true,
totalDue: dueCards.length,
decks: deckSummaries,
dueCardsPath: dueCardsPath,
message: `${dueCards.length} cards due for review: ${deckList}`,
})
);
}
} catch (error) {
console.log(
JSON.stringify({
success: false,
error: `Failed to load decks: ${error.message}`,
})
);
process.exit(1);
}