// Main entry point — orchestrates fetch → cache → merge → filter
import { CATEGORY_TTL, } from '../../types/index.js';
import { findCachedEntry, readCache, setCacheEntry } from './knowledge-cache.js';
import { buildSearchQueries, normalizeContext } from './context-resolver.js';
import { fetchKnowledge } from './web-researcher.js';
import { loadStaticFallback, mergeKnowledge } from './knowledge-merger.js';
import { filterByContext } from './stack-filter.js';
/**
 * Query the Dynamic Knowledge Engine.
 * Pipeline: cache check → web fetch → merge with static → filter → cache result
 *
 * Graceful degradation:
 * 1. Try cache (fastest)
 * 2. Try web search (freshest)
 * 3. Fall back to static JSON (always available)
 */
export async function queryKnowledge(category, context) {
    const normalizedCtx = normalizeContext(context);
    const ttl = CATEGORY_TTL[category];
    // Step 1: Check cache
    try {
        const store = await readCache();
        const cached = findCachedEntry(store, category, normalizedCtx);
        if (cached) {
            return {
                items: filterByContext(cached.items, context),
                source: 'cache',
                fetchedAt: cached.fetchedAt,
                ttl,
                category,
            };
        }
    }
    catch {
        // Cache read failed — continue to web
    }
    // Step 2: Try web search
    let webItems = [];
    try {
        const queries = buildSearchQueries(category, context);
        webItems = await fetchKnowledge(queries, category);
    }
    catch {
        // Web search failed — will use static
    }
    // Step 3: Load static fallback
    const staticItems = await loadStaticFallback(category);
    // Step 4: Merge web + static
    const merged = mergeKnowledge(webItems, staticItems);
    // Step 5: Filter by context
    const filtered = filterByContext(merged, context);
    // Step 6: Cache the merged result (fire-and-forget)
    if (merged.length > 0) {
        void setCacheEntry(category, normalizedCtx, merged).catch((err) => {
            console.error('[planu] query-knowledge setCacheEntry failed:', err);
        });
    }
    // Determine source
    const source = webItems.length > 0 ? 'web' : 'static';
    return {
        items: filtered,
        source,
        fetchedAt: new Date().toISOString(),
        ttl,
        category,
    };
}
/**
 * Query multiple categories at once.
 * Runs queries in parallel for performance.
 */
export async function queryMultipleCategories(categories, context) {
    return Promise.all(categories.map((cat) => queryKnowledge(cat, context)));
}
//# sourceMappingURL=query-knowledge.js.map