import type { DiagnosticHandler } from "./types.js"; /** * Sample rates per hook name. Tool-related hooks fire many times per turn * (one pair per tool call), so we record only 10% to avoid drowning the * table; the sample_rate column lets dashboards extrapolate counts with * `count(*) * (1.0 / avg(sample_rate))`. Everything else is rare enough * to record in full. */ export declare const HOOK_SAMPLE_RATES: Readonly>; export type CommandOutcome = "ok" | "error" | "cancelled" | "no_match" | "unknown"; export interface CommandEventInput { extensionName: string; commandName: string; /** Whitelisted-token-only classification — see classifyArgsSignature(). Never contains original arg text. */ argsSignature: string; argsLength: number; outcome: CommandOutcome; errorCode?: string | null; durationMs: number; details?: Record | null; startedAt: Date; endedAt: Date; runId?: string | null; sessionId?: string | null; variant?: string | null; } export interface HookEventInput { extensionName: string; hookName: string; durationMs: number; ok: boolean; errorCode?: string | null; /** Sampling probability used to decide whether to emit. Stored on each row so dashboards can extrapolate counts. */ sampleRate: number; recordedAt: Date; runId?: string | null; sessionId?: string | null; variant?: string | null; } export interface LlmCallEventInput { extensionName: string; /** Short scope label, e.g. "command:/recap --smart" or "hook:before_agent_start". */ callerContext: string; /** True for slash-command paths; false for hook auto-fires. SQL dashboards group on this to find idle-thinking-class bugs. */ isUserInitiated: boolean; modelId?: string | null; tokensIn?: number | null; tokensOut?: number | null; costTotal?: number | null; durationMs: number; ok: boolean; errorCode?: string | null; startedAt: Date; endedAt: Date; runId?: string | null; sessionId?: string | null; variant?: string | null; commandEventId?: number | null; } export interface ExtensionTelemetrySink { writeCommandEvent(input: CommandEventInput): void; writeLlmCallEvent(input: LlmCallEventInput): void; writeHookEvent(input: HookEventInput): void; close(): Promise; } export interface CreateExtensionTelemetrySinkOptions { workspaceRoot: string; onDiagnostic?: DiagnosticHandler; batchIntervalMs?: number; } /** * Build a telemetry sink. Returns a noop sink — silently dropping every event — * when insforge credentials are missing or disabled. Callers can therefore wire * the sink unconditionally; users without credentials pay zero cost. */ export declare function createExtensionTelemetrySink(options: CreateExtensionTelemetrySinkOptions): ExtensionTelemetrySink; /** * Classify arg text into a small bounded set of signatures so dashboards can * group invocations without ingesting user-supplied text. Privacy posture: * * - "no-args" — empty or whitespace-only args * - "--" — args start with a `--flag` token; we record the flag name only * (enum-like, low cardinality, no PII) * - "with-args" — any other non-empty args; original text is never recorded * * Anything else interesting (length, etc.) lives on its own typed column so we * never need free-form arg storage. */ export declare function classifyArgsSignature(args: string): string;