/** * ChatGuard: per-conversation PII filter for wiring into a chat app. * * const guard = await createGuard(); * const safe = await guard.protect(userInput); * const reply = await llm(safe.text); * guard.reveal(reply); // non-streaming * stream.pipeThrough(guard.revealTransform()); // streaming * * The entity table lives only on the client; the real values never leave the * device. Each guard keeps placeholder identity stable across every turn of a * conversation. * * user message * → heuristics (sync, structured PII) * → NER (optional, async, contextual PII) * → merge + default-deny policy (keep {city, state, zip}) * → session table: replace with stable placeholders * assistant reply * → rehydrate placeholders → render to user */ import { type NerOptions } from "./ner/classifier"; import { type PlaceholderAliases, type ScrubResult } from "./session"; import { type PiiLabel, type Span } from "./types"; /** An async contextual detector. Matches both the in-process and worker forms. */ export type NerDetector = (text: string) => Promise; /** * Default placeholder aliases. Empty: names are split into GIVEN_NAME/SURNAME * and a household may share a surname, so each keeps its own typed token * (`[GIVEN_NAME_1]`, `[SURNAME_1]`) rather than collapsing to a single `NAME`. */ export declare const DEFAULT_ALIASES: PlaceholderAliases; export interface GuardOptions { /** Placeholder aliases. Defaults to `{}` — typed tokens like `[GIVEN_NAME_1]`. */ readonly aliases?: PlaceholderAliases; /** Labels to preserve; defaults to `{CITY, STATE, ZIP_CODE}`. */ readonly keepLabels?: readonly PiiLabel[]; /** * When `true`, skip the structured-PII premask before the model. Required for * a model trained without prefilter (no-prefilter ablation) whose classes * include SSN / CREDIT_CARD / IP_ADDRESS. Heuristic spans for those types * still run as a safety net. */ readonly noPrefilter?: boolean; /** Pre-built NER detector. When set, `model` is ignored. */ readonly ner?: NerDetector; /** When `true`, skip the classifier and run heuristics only. */ readonly heuristicsOnly?: boolean; /** * Hugging Face model id or local directory path (q4 ONNX). Defaults to * {@link RAMPART_MODEL_ID}. */ readonly model?: string; /** Worker script URL. When set, NER runs off the main thread. */ readonly worker?: string | URL; /** Backend. `"wasm"`/`"webgpu"` in browsers; `"cpu"` for Node. */ readonly device?: NerOptions["device"]; /** Spans below this score are discarded. */ readonly minScore?: number; } type ChatGuardConfig = Pick; export declare class ChatGuard { private readonly table; private readonly ner?; private readonly noPrefilter; constructor(config?: ChatGuardConfig); private detect; /** * Run this on the user's text *before* handing it to the AI SDK. Returns the * placeholdered text to send plus the placeholders introduced this turn. */ protect(text: string): Promise; /** Restore real values in a complete (non-streaming) assistant reply. */ reveal(reply: string): string; /** * A Web Streams transform that reveals placeholders in a streamed reply, * correctly handling placeholders split across chunks. Pipe an AI SDK * `textStream` through it before rendering. */ revealTransform(): TransformStream; /** * Defense in depth: scrub the model's *output* before logging/persisting it, * since a model can emit PII the user never typed. Returns placeholdered text. */ protectReply(reply: string): Promise; } /** * Build a conversation guard. Loads the Rampart classifier (q4 ONNX) by default. * Pass `model` for a different Hugging Face id or local path, `heuristicsOnly: * true` to skip NER, or `ner` to inject a custom detector. */ export declare function createGuard(options?: GuardOptions): Promise; export {}; //# sourceMappingURL=guard.d.ts.map