/** * Opt-in local telemetry. * * Principles (non-negotiable): * 1. Opt-in only — default is off. A fresh install collects nothing. * 2. Local only — this module writes to ~/.blockrun/telemetry.jsonl. * No network transmission, ever. A future opt-in "upload" feature * would be a separate module with its own consent gate. * 3. No content — never log prompts, tool inputs, tool outputs, file * paths, or wallet addresses. Count-level aggregates only. * 4. Inspectable — the log is plain JSONL, one record per session. * `franklin telemetry view` prints it. Users see exactly what was * recorded before ever considering sharing it. * 5. Revocable — `franklin telemetry disable` stops future writes * and leaves historical data intact. `franklin telemetry reset` * (future) would wipe the log. * * Data model is a sanitized projection of SessionMeta. Nothing original * is stored here that isn't already derivable from the session meta * files — telemetry is just a stable, aggregation-friendly view of * information the user already has. */ import { type SessionMeta } from '../session/storage.js'; interface ConsentRecord { enabled: boolean; enabledAt?: number; disabledAt?: number; } /** Sanitized projection of a session used for telemetry. No content. */ export interface TelemetryRecord { /** Stable per-install random UUID. Not tied to wallet or email. */ installId: string; /** Franklin version at the time this session ran. */ version: string; /** Session timestamp (ISO string). */ ts: string; /** Number of user turns. */ turns: number; /** Number of message entries (user + assistant + tool_result). */ messages: number; /** Input / output tokens for the whole session. */ inputTokens: number; outputTokens: number; /** Cost in USDC. */ costUsd: number; /** Savings vs Opus-tier baseline in USDC. */ savedVsOpusUsd: number; /** Last-active model id for the session. */ model: string; /** Chain the session settled on (base / solana). */ chain?: string; /** Session driver — "cli" for normal use, or the channel tag for Telegram/etc. */ driver: string; /** Per-tool invocation counts (names only, no content). */ toolCallCounts?: Record; } /** Enabled-state check. Default: false. */ export declare function isTelemetryEnabled(): boolean; export declare function setTelemetryEnabled(enabled: boolean): void; export declare function readConsent(): ConsentRecord; /** Stable per-install random UUID. Generated lazily on first write. */ export declare function getOrCreateInstallId(): string; /** * Sanitize a SessionMeta into a telemetry record. No content is added here * that isn't already present in the meta — the sanitization rule is that * every field must be count-level or identifier-level, never user content. */ export declare function sessionMetaToRecord(meta: SessionMeta, installId: string, chain?: string): TelemetryRecord; /** Append one record to the telemetry log. Silent no-op if disabled. */ export declare function recordSession(meta: SessionMeta, chain?: string): void; /** * Locate the session that just finished by ID or by "newest in the sessions * directory whose workDir matches", then record it. Used by start.ts at * exit since interactiveSession() doesn't currently thread the session id * back to the caller. */ export declare function recordLatestSessionIfEnabled(workingDir: string, chain?: string): void; /** Read every record in the log. Returns [] if the file is missing. */ export declare function readAllRecords(): TelemetryRecord[]; /** File paths — surfaced so the CLI can show users where data lives. */ export declare const telemetryPaths: { consent: string; log: string; installId: string; }; export {};