UNPKG

@ankimcp/anki-mcp-server

Version:

Model Context Protocol server for Anki - enables AI assistants to interact with your Anki flashcards

92 lines • 3.6 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.deckStats = deckStats; const stats_utils_1 = require("../../../../../utils/stats.utils.js"); const deck_hierarchy_utils_1 = require("../../../../../utils/deck-hierarchy.utils.js"); const card_states_utils_1 = require("../../../../../utils/card-states.utils.js"); async function deckStats(params, client) { const { deck, easeBuckets = [2.0, 2.5, 3.0], intervalBuckets = [7, 21, 90], } = params; const deckNamesAndIds = await client.invoke("deckNamesAndIds", {}); const deckId = deckNamesAndIds?.[deck]; if (deckId == null) { throw new Error(`Deck "${deck}" not found`); } const subtreeDeckNames = Object.keys(deckNamesAndIds).filter((name) => name === deck || (0, deck_hierarchy_utils_1.isDescendantOf)(name, deck)); const deckStatsResponse = await client.invoke("getDeckStats", { decks: subtreeDeckNames, }); const rootDeckStats = deckStatsResponse?.[String(deckId)]; if (!rootDeckStats) { throw new Error(`Deck "${deck}" not found in statistics response`); } const newCount = rootDeckStats.new_count || 0; const learning = rootDeckStats.learn_count || 0; const review = rootDeckStats.review_count || 0; let total = 0; for (const descendantName of subtreeDeckNames) { const descId = deckNamesAndIds[descendantName]; const descStats = descId != null ? deckStatsResponse?.[String(descId)] : undefined; total += descStats?.total_in_deck ?? 0; } const other = Math.max(0, total - newCount - learning - review); const counts = { total, new: newCount, learning, review, other, }; const deckScope = (0, card_states_utils_1.deckScopeQuery)(deck); const cardIds = await client.invoke("findCards", { query: deckScope, }); if (cardIds != null && !Array.isArray(cardIds)) { throw new Error("Invalid findCards response: expected array"); } if (!cardIds || cardIds.length === 0) { return { success: true, deck, counts, states: (0, card_states_utils_1.emptyCardStateCounts)(), ease: (0, stats_utils_1.computeDistribution)([], { boundaries: easeBuckets }), intervals: (0, stats_utils_1.computeDistribution)([], { boundaries: intervalBuckets, unitSuffix: "d", }), }; } const states = await (0, card_states_utils_1.fetchCardStateCounts)(client, deckScope); const easeFactorsRaw = await client.invoke("getEaseFactors", { cards: cardIds, }); if (!Array.isArray(easeFactorsRaw)) { throw new Error("Invalid getEaseFactors response: expected array"); } const easeValues = easeFactorsRaw .map((e) => e / 1000) .filter((e) => e > 0); const intervalsRaw = await client.invoke("getIntervals", { cards: cardIds, }); if (!Array.isArray(intervalsRaw)) { throw new Error("Invalid getIntervals response: expected array"); } const intervalValues = intervalsRaw.filter((i) => i > 0); const ease = (0, stats_utils_1.computeDistribution)(easeValues, { boundaries: easeBuckets, }); const intervals = (0, stats_utils_1.computeDistribution)(intervalValues, { boundaries: intervalBuckets, unitSuffix: "d", }); return { success: true, deck, counts, states, ease, intervals, }; } //# sourceMappingURL=deckStats.action.js.map