npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@xtatistix/rag-wiki

v0.1.34

Published

Narrow-domain, guideline-in-the-loop RAG system built on top of a compiled wiki

Downloads

4,387

Readme

@xtatistix/rag-wiki

Yapılandırılmış bir wiki üzerinden çalışan, kaynak gösterebilen, kapsam dışı soruları reddedebilen hafif bir RAG sistemi.

Ham belge chunk'ları yerine markdown sayfalardan oluşan derlenmiş bir wiki tutar. Sorular bu wikiye dayanarak yanıtlanır. Sistem emin olmadığında söyler — tahmin yürütmez.

Node.js ve tarayıcı ortamlarında çalışır.


Kurulum

npm install @xtatistix/rag-wiki

OpenAI API anahtarı gerektirir.


Nasıl Çalışır

Üç katman:

  • Wiki{projectId}/wiki/ altındaki markdown sayfalar. ingest() ile eklenir veya elle yazılır.
  • Indexindex.md. Tüm wiki sayfalarının tek satırlık özetlerini içeren katalog. ingest() her çağrıda otomatik günceller.
  • Guideline{projectId}/guideline.md. LLM'e neyi yanıtlayıp neyi reddedeceğini söyleyen kural dosyası. İsteğe bağlıdır.

ask() çağrısında:

  1. index.md okunur, soruyla ilgili sayfalar seçilir
  2. Seçilen sayfaların içeriği yüklenir
  3. Guideline varsa eklenir
  4. Hepsi LLM'e gönderilir
  5. LLM ya yanıtlar (kaynak göstererek) ya da reddeder
  6. Sonuç {projectId}/log.md'ye kaydedilir

Hızlı Başlangıç — Node.js

import { createRagWiki } from "@xtatistix/rag-wiki";

const wiki = createRagWiki({
  projectId: "destek",
  openaiApiKey: "sk-...", // ya da OPENAI_API_KEY env değişkeni
});

// Sayfa ekle
await wiki.ingest("İade Politikası", "## Genel Bakış\nTüm ürünler 30 gün içinde iade edilebilir...");

// Soru sor
const result = await wiki.ask("Ürünümü nasıl iade ederim?");

if (result.answered) {
  console.log(result.answer);
  console.log("Kaynaklar:", result.sources?.map((s) => s.summary));
} else {
  console.log(result.escalationMessage);
}

Hızlı Başlangıç — Tarayıcı (PresignedAdapter)

S3 gibi bir depolama servisini presigned URL'lerle kullanmak için:

import { createRagWiki, PresignedAdapter } from "@xtatistix/rag-wiki/dist/browser";

const wiki = createRagWiki({
  openaiApiKey: "sk-...",
  baseURL: "https://api.openai.com/v1",
  fallback: {
    apiKey: "AIza...",
    baseURL: "https://generativelanguage.googleapis.com/v1beta/openai",
    model: "gemini-3.1-flash-lite-preview",
  },
  model: "gpt-4o",
  adapter: new PresignedAdapter({
    getReadUrl: (path) =>
      fetch(`/api/presigned/read?path=${path}`).then((r) => r.json()).then((r) => r.url),
    getWriteUrl: (path) =>
      fetch("/api/presigned/write", {
        method: "POST",
        body: JSON.stringify({ path }),
      }).then((r) => r.json()).then((r) => r.url),
  }),
});

await wiki.ingest("Rapor Başlığı", raporIcerigi, { projectId: "proje-42" });
const result = await wiki.ask("Bu raporu yorumlar mısın?", { projectId: "proje-42" });

API

createRagWiki(config)

const wiki = createRagWiki({
  projectId: "proje-id",     // varsayılan proje — her çağrıda override edilebilir
  openaiApiKey: "sk-...",    // tarayıcıda zorunlu, Node'da env'den okunabilir
  baseURL: "https://api.openai.com/v1", // varsayılan
  model: "gpt-4o",           // varsayılan: "gpt-4o-mini"
  fallback: {
    apiKey: "AIza...",
    baseURL: "https://generativelanguage.googleapis.com/v1beta/openai",
    model: "gemini-3.1-flash-lite-preview",
  },
  rawPath: "./data",         // Node only, varsayılan: "./raw"
  adapter: customAdapter,    // LocalAdapter, BrowserAdapter, PresignedAdapter veya custom
});

wiki.ingest(title, content, options?)

Wiki'ye sayfa ekler, index.md'yi günceller. Aynı başlıkla tekrar çağrılırsa sayfa güncellenir.

await wiki.ingest("İade Politikası", "30 gün iade garantisi...");

// Farklı proje için
await wiki.ingest("Kargo Bilgisi", "...", { projectId: "lojistik" });
  • title dosya adına dönüştürülür: "İade Politikası"iade-politikas.md
  • İçerik # başlığıyla başlamıyorsa otomatik eklenir

wiki.ask(question, options?)

const result = await wiki.ask("Nasıl iade yaparım?");
const result = await wiki.ask("Sözleşme maddeleri?", { projectId: "hukuk" });

QueryResult

interface QueryResult {
  answered: boolean;
  answer?: string;
  sources?: { path: string; summary: string }[];
  escalationReason?: "out_of_scope" | "insufficient_sources" | "guideline_violation" | "no_index";
  escalationMessage?: string;
}

Adaptörler

| Adaptör | Ortam | Okuma | Yazma | |---|---|---|---| | LocalAdapter | Node.js | Dosya sistemi | Dosya sistemi | | BrowserAdapter | Tarayıcı | fetch() (public/) | localStorage | | PresignedAdapter | Tarayıcı | Presigned URL (S3 vb.) | Presigned URL (S3 vb.) | | Custom | Her ikisi | Senin backend'in | Senin backend'in |

Custom Adaptör

import { RagWikiAdapter } from "@xtatistix/rag-wiki";

const myAdapter: RagWikiAdapter = {
  async read(path: string): Promise<string | null> { ... },
  async write(path: string, content: string): Promise<void> { ... },
  async list(prefix: string): Promise<string[]> { ... },
};

Çoklu Proje

Her projectId tamamen izoledir — kendi wiki'si, kılavuzu ve logu vardır.

const wiki = createRagWiki({ adapter }); // varsayılan projectId yok

await wiki.ask("İade politikası?", { projectId: "destek" });
await wiki.ask("Sözleşme maddeleri?", { projectId: "hukuk" });

Guideline Dosyası

Sistemi disiplinli bir domain asistanına dönüştürür. {projectId}/guideline.md oluştur:

# Kılavuz — destek

## Kapsam
Bu wiki yalnızca ürün iadesi, kargo ve hesap sorunlarını yanıtlar.
Rakip ürünler veya genel alışveriş tavsiyeleri kapsam dışıdır.

## Kesinlikle yanıtlama
- Hukuki tavsiye
- Tıbbi tavsiye
- Kişisel müşteri verileri

Guideline dosyası yoksa sistem çalışmaya devam eder, sadece domain kısıtlaması olmaz.


Dizin Yapısı

raw/
├── index.md                        ← ingest() tarafından otomatik yönetilir
└── {projectId}/
    ├── guideline.md                ← isteğe bağlı kural dosyası
    ├── log.md                      ← ask() çağrılarının otomatik logu
    └── wiki/
        ├── iade-politikasi.md
        └── kargo-bilgisi.md

TypeScript Tipleri

import type {
  RagWikiConfig,
  RagWikiAdapter,
  QueryResult,
  WikiPage,
  WikiIndex,
  EscalationReason,
} from "@xtatistix/rag-wiki";