tokensniff 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +809 -0
- package/bin/tokensniff-status.js +8 -0
- package/bin/tokensniff.js +8 -0
- package/dist/cli/run.d.ts +64 -0
- package/dist/cli/run.d.ts.map +1 -0
- package/dist/cli.js +2206 -0
- package/dist/cli.js.map +1 -0
- package/dist/collector/config.d.ts +43 -0
- package/dist/collector/config.d.ts.map +1 -0
- package/dist/collector/index.d.ts +14 -0
- package/dist/collector/index.d.ts.map +1 -0
- package/dist/collector/parse.d.ts +42 -0
- package/dist/collector/parse.d.ts.map +1 -0
- package/dist/collector/store.d.ts +76 -0
- package/dist/collector/store.d.ts.map +1 -0
- package/dist/dashboard/heatmap.d.ts +34 -0
- package/dist/dashboard/heatmap.d.ts.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2474 -0
- package/dist/index.js.map +1 -0
- package/dist/pricing.js +145 -0
- package/dist/pricing.js.map +1 -0
- package/dist/proxy.js +1744 -0
- package/dist/proxy.js.map +1 -0
- package/dist/renderer/format.d.ts +33 -0
- package/dist/renderer/format.d.ts.map +1 -0
- package/dist/renderer/index.d.ts +42 -0
- package/dist/renderer/index.d.ts.map +1 -0
- package/dist/schema.js +90 -0
- package/dist/schema.js.map +1 -0
- package/dist/shared/pricing.d.ts +60 -0
- package/dist/shared/pricing.d.ts.map +1 -0
- package/dist/shared/schema.d.ts +122 -0
- package/dist/shared/schema.d.ts.map +1 -0
- package/dist/status.js +521 -0
- package/dist/status.js.map +1 -0
- package/package.json +105 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/collector/config.ts","../src/shared/schema.ts","../src/shared/pricing.ts","../src/renderer/format.ts","../src/renderer/index.ts"],"names":["path","fs"],"mappings":"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","file":"status.js","sourcesContent":["/**\n * tokensniff — Configuration Loader & Resolver (v1 Production)\n *\n * Implements strict hierarchical configuration resolution:\n * process.env > ~/.tokensniff/config.json > embedded defaults.\n *\n * Hardened with defensive path normalization, numeric bounds verification,\n * safe stringified boolean parsing, and corruption fault-tolerance.\n */\n\nimport fs from 'node:fs';\nimport os from 'node:os';\nimport path from 'node:path';\n\nexport interface TokenSniffConfig {\n readonly listenPort: number;\n readonly listenHost: string;\n readonly upstreamHost: string;\n readonly upstreamPort: number;\n readonly upstreamTimeoutMs: number;\n readonly maxBodyBytes: number;\n readonly statusDirs: readonly string[];\n readonly maxSessions: number;\n readonly deadSessionMs: number;\n readonly staleAfterS: number;\n readonly labelMaxIn: number;\n readonly labelMaxOut: number;\n readonly warnPct: number;\n readonly critPct: number;\n readonly color: boolean;\n readonly upstreamCommand: string;\n readonly upstreamStopCommand: string;\n readonly harnessCommand: string;\n}\n\n/**\n * Validates TCP/IP port numbers against standard IANA boundaries [1, 65535].\n */\nfunction toValidPort(value: unknown, fallback: number): number {\n const parsed = Number(value);\n return Number.isInteger(parsed) && parsed >= 1 && parsed <= 65535 ? parsed : fallback;\n}\n\n/**\n * Validates and clamps integer bounds defensively.\n */\nfunction toBoundedInt(\n value: unknown,\n fallback: number,\n min = 0,\n max = Number.MAX_SAFE_INTEGER,\n): number {\n const parsed = Number(value);\n if (!Number.isFinite(parsed)) return fallback;\n const intVal = Math.floor(parsed);\n return Math.max(min, Math.min(max, intVal));\n}\n\n/**\n * Validates non-empty string fields with fallback protection against whitespace-only values.\n */\nfunction toNonEmptyString(value: unknown, fallback: string): string {\n if (typeof value !== 'string') return fallback;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : fallback;\n}\n\n/**\n * Accurately parses boolean flags, safely handling stringified representations (\"false\", \"0\").\n */\nfunction toSafeBoolean(value: unknown, fallback: boolean): boolean {\n if (typeof value === 'boolean') return value;\n if (typeof value === 'string') {\n const lower = value.trim().toLowerCase();\n if (lower === 'true' || lower === '1') return true;\n if (lower === 'false' || lower === '0') return false;\n }\n return fallback;\n}\n\n/**\n * Normalizes directory paths, resolving cross-platform slashes and relative references to absolute paths.\n */\nfunction normalizeDirectory(targetPath: string): string {\n const resolved = path.resolve(targetPath.trim());\n return path.normalize(resolved);\n}\n\n/**\n * Dynamically resolves the canonical user home directory (~/.tokensniff) across OSes.\n */\nexport function getGlobalDir(): string {\n const home = process.env.USERPROFILE || os.homedir();\n return path.join(home, '.tokensniff');\n}\n\n/**\n * Resolves the configuration file location ~/.tokensniff/config.json.\n */\nexport function getGlobalConfigPath(): string {\n return path.join(getGlobalDir(), 'config.json');\n}\n\n/**\n * Loads configuration with strict precedence:\n * Environment Variables > File Configuration > Embedded Defaults.\n */\nexport function loadConfig(env: NodeJS.ProcessEnv = process.env): TokenSniffConfig {\n const targetConfigFile = env.TOKENSNIFF_CONFIG || getGlobalConfigPath();\n let fileConfig: Record<string, unknown> = {};\n\n // Safe JSON extraction with non-crashing syntax defense\n if (fs.existsSync(targetConfigFile)) {\n try {\n const raw = fs.readFileSync(targetConfigFile, 'utf8');\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n fileConfig = parsed as Record<string, unknown>;\n }\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n console.error(`[tokensniff] ignoring corrupt config at ${targetConfigFile}: ${msg}`);\n }\n }\n\n const resolve = <T>(envKey: string, configKey: string, defaultValue: T): unknown => {\n return env[envKey] ?? fileConfig[configKey] ?? defaultValue;\n };\n\n const rootDir = getGlobalDir();\n const defaultStatusDir = path.join(rootDir, 'status');\n\n const rawStatusDirs = resolve('TOKENSNIFF_STATUS_DIRS', 'statusDirs', [defaultStatusDir]);\n\n // Handle both array and comma-separated string declarations of status directories\n const parsedDirs: string[] = Array.isArray(rawStatusDirs)\n ? rawStatusDirs.map(String)\n : String(rawStatusDirs).split(',');\n\n const normalizedStatusDirs = parsedDirs\n .map((d) => d.trim())\n .filter((d) => d.length > 0)\n .map(normalizeDirectory);\n\n const statusDirs =\n normalizedStatusDirs.length > 0 ? normalizedStatusDirs : [normalizeDirectory(defaultStatusDir)];\n\n // NO_COLOR standard (https://no-color.org/): any non-empty value disables ANSI formatting\n const isNoColorSet = typeof env.NO_COLOR === 'string' && env.NO_COLOR.length > 0;\n const colorDefault = !isNoColorSet;\n\n return {\n listenPort: toValidPort(resolve('TOKENSNIFF_PORT', 'listenPort', 4000), 4000),\n listenHost: toNonEmptyString(\n resolve('TOKENSNIFF_HOST', 'listenHost', '127.0.0.1'),\n '127.0.0.1',\n ),\n upstreamHost: toNonEmptyString(\n resolve('TOKENSNIFF_UPSTREAM_HOST', 'upstreamHost', 'localhost'),\n 'localhost',\n ),\n upstreamPort: toValidPort(resolve('TOKENSNIFF_UPSTREAM_PORT', 'upstreamPort', 8085), 8085),\n upstreamTimeoutMs: toBoundedInt(\n resolve('TOKENSNIFF_UPSTREAM_TIMEOUT_MS', 'upstreamTimeoutMs', 300_000),\n 300_000,\n 1000,\n 3_600_000,\n ),\n maxBodyBytes: toBoundedInt(\n resolve('TOKENSNIFF_MAX_BODY_BYTES', 'maxBodyBytes', 10 * 1024 * 1024),\n 10_485_760,\n 1024,\n 100 * 1024 * 1024,\n ),\n statusDirs,\n maxSessions: toBoundedInt(resolve('TOKENSNIFF_MAX_SESSIONS', 'maxSessions', 50), 50, 1, 1000),\n deadSessionMs: toBoundedInt(\n resolve('TOKENSNIFF_DEAD_SESSION_MS', 'deadSessionMs', 72 * 3600 * 1000),\n 259_200_000,\n 3600 * 1000,\n ),\n staleAfterS: toBoundedInt(\n resolve('TOKENSNIFF_STALE_AFTER_S', 'staleAfterS', 120),\n 120,\n 5,\n 86400,\n ),\n labelMaxIn: toBoundedInt(resolve('TOKENSNIFF_LABEL_MAX_IN', 'labelMaxIn', 2000), 2000, 100),\n labelMaxOut: toBoundedInt(resolve('TOKENSNIFF_LABEL_MAX_OUT', 'labelMaxOut', 60), 60, 1),\n warnPct: toBoundedInt(resolve('TOKENSNIFF_WARN_PCT', 'warnPct', 60), 60, 1, 99),\n critPct: toBoundedInt(resolve('TOKENSNIFF_CRIT_PCT', 'critPct', 80), 80, 2, 100),\n color: colorDefault && toSafeBoolean(resolve('TOKENSNIFF_COLOR', 'color', true), true),\n upstreamCommand: toNonEmptyString(\n resolve(\n 'TOKENSNIFF_UPSTREAM_CMD',\n 'upstreamCommand',\n 'npx antigravity-claude-proxy@latest start',\n ),\n 'npx antigravity-claude-proxy@latest start',\n ),\n upstreamStopCommand: String(\n resolve('TOKENSNIFF_UPSTREAM_STOP_CMD', 'upstreamStopCommand', ''),\n ).trim(),\n harnessCommand: toNonEmptyString(\n resolve('TOKENSNIFF_HARNESS_CMD', 'harnessCommand', 'claude'),\n 'claude',\n ),\n };\n}\n","/**\n * tokensniff — Canonical Domain Telemetry Schema (v1 Production)\n *\n * Single source of truth for telemetry interfaces, runtime validation guards,\n * safe default factories, and agent state text parsing.\n */\n\nexport const SCHEMA_VERSION = 1 as const;\n\n/**\n * Summary representation of an aggregated tool call across a single turn.\n */\nexport interface ToolSummaryItem {\n readonly name: string;\n readonly count: number;\n readonly arg_tk: number;\n}\n\n/**\n * Granular record of an individual tool call during an execution turn.\n */\nexport interface ToolCallItem {\n readonly name: string;\n readonly argTk: number;\n}\n\n/**\n * Classification of the primary driver of a model turn.\n */\nexport type TurnKind = 'text' | 'tool' | 'thinking' | 'label' | 'error' | 'unknown';\n\n/**\n * Snapshot of provider upstream rate limits and token bucket quotas.\n */\nexport interface QuotaSnapshot {\n readonly remainingPct: number | null;\n readonly remainingFraction: number | null;\n readonly resetTime: string | null;\n readonly tier: string | null;\n readonly isRateLimited: boolean;\n}\n\n/**\n * Raw telemetry extracted directly from a single network interaction.\n */\nexport interface TurnMetrics {\n readonly model: string;\n readonly kind: TurnKind;\n readonly input: number;\n readonly output: number;\n readonly cacheRead: number;\n readonly cacheCreate: number;\n readonly tools: readonly ToolCallItem[];\n readonly toolsSummary: readonly ToolSummaryItem[];\n readonly thinking: boolean;\n readonly thinkingTokens: number;\n readonly stopReason: string;\n readonly label: string;\n}\n\n/**\n * Fully hydrated telemetry state persisted to ~/.tokensniff/status/<session_id>.json.\n * Consumed directly by terminal statusline renderers and CLI dashboards.\n */\nexport interface TokenSniffLatest {\n readonly v: typeof SCHEMA_VERSION;\n readonly session_id: string;\n readonly turn_index: number;\n readonly ts: number;\n readonly model: string;\n readonly is_bg: boolean;\n readonly ctx: number;\n readonly window: number;\n readonly pct: number;\n readonly cache_read: number;\n readonly cache_create: number;\n readonly delta_in: number;\n readonly in_tokens: number;\n readonly out_tokens: number;\n readonly thinking: boolean;\n readonly thinking_tokens: number;\n readonly tool: string | null;\n readonly tool_tk: number;\n readonly tools_summary: readonly ToolSummaryItem[];\n readonly stop_reason: string;\n readonly is_label: boolean;\n readonly label: string;\n readonly ttft_ms: number;\n readonly tps: number;\n readonly dur_s: number;\n readonly cost_turn: number;\n readonly cost_session: number;\n readonly cost_today: number;\n readonly error: number | null;\n readonly status: number;\n readonly quota_pct: number | null;\n readonly quota_reset: string | null;\n readonly tier: string | null;\n}\n\n/**\n * Compact append-only historical turn record for analytics and sparklines.\n */\nexport interface HistoryEntry {\n readonly d: string;\n readonly ts: number;\n readonly s: string;\n readonly t: number;\n readonly m: string;\n readonly tk: number;\n readonly c: number;\n readonly cr: number;\n readonly th: number;\n}\n\n/**\n * Defensive number sanitizer ensuring NaN and Infinity never corrupt telemetry output.\n */\nfunction toFiniteNumber(value: unknown, fallback = 0): number {\n const num = Number(value);\n return Number.isFinite(num) ? num : fallback;\n}\n\n/**\n * Runtime Type Guard to safely validate deserialized disk telemetry without unsafe casts.\n */\nexport function isTokenSniffLatest(value: unknown): value is TokenSniffLatest {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n\n const candidate = value as Record<string, unknown>;\n\n return (\n candidate.v === SCHEMA_VERSION &&\n typeof candidate.session_id === 'string' &&\n typeof candidate.turn_index === 'number' &&\n typeof candidate.ts === 'number' &&\n typeof candidate.model === 'string' &&\n typeof candidate.ctx === 'number' &&\n typeof candidate.window === 'number' &&\n typeof candidate.pct === 'number'\n );\n}\n\n/**\n * Factory creating fully hydrated TokenSniffLatest records with strictly sanitized defaults.\n */\nexport function buildLatest(\n partial: Partial<TokenSniffLatest> & { readonly session_id: string },\n): TokenSniffLatest {\n return {\n v: SCHEMA_VERSION,\n session_id: partial.session_id,\n turn_index: Math.max(1, Math.floor(toFiniteNumber(partial.turn_index, 1))),\n ts: toFiniteNumber(partial.ts, Date.now()),\n model:\n typeof partial.model === 'string' && partial.model.length > 0 ? partial.model : 'unknown',\n is_bg: Boolean(partial.is_bg),\n ctx: Math.max(0, toFiniteNumber(partial.ctx, 0)),\n window: Math.max(1, toFiniteNumber(partial.window, 1_000_000)),\n pct: Math.max(0, Math.min(100, toFiniteNumber(partial.pct, 0))),\n cache_read: Math.max(0, toFiniteNumber(partial.cache_read, 0)),\n cache_create: Math.max(0, toFiniteNumber(partial.cache_create, 0)),\n delta_in: toFiniteNumber(partial.delta_in, 0),\n in_tokens: Math.max(0, toFiniteNumber(partial.in_tokens, 0)),\n out_tokens: Math.max(0, toFiniteNumber(partial.out_tokens, 0)),\n thinking: Boolean(partial.thinking),\n thinking_tokens: Math.max(0, toFiniteNumber(partial.thinking_tokens, 0)),\n tool: typeof partial.tool === 'string' && partial.tool.length > 0 ? partial.tool : null,\n tool_tk: Math.max(0, toFiniteNumber(partial.tool_tk, 0)),\n tools_summary: Array.isArray(partial.tools_summary) ? partial.tools_summary : [],\n stop_reason: typeof partial.stop_reason === 'string' ? partial.stop_reason : '',\n is_label: Boolean(partial.is_label),\n label: typeof partial.label === 'string' ? partial.label : '',\n ttft_ms: Math.max(0, toFiniteNumber(partial.ttft_ms, 0)),\n tps: Math.max(0, toFiniteNumber(partial.tps, 0)),\n dur_s: Math.max(0, toFiniteNumber(partial.dur_s, 0)),\n cost_turn: Math.max(0, toFiniteNumber(partial.cost_turn, 0)),\n cost_session: Math.max(0, toFiniteNumber(partial.cost_session, 0)),\n cost_today: Math.max(0, toFiniteNumber(partial.cost_today, 0)),\n error:\n typeof partial.error === 'number' && Number.isFinite(partial.error) ? partial.error : null,\n status: Math.max(0, toFiniteNumber(partial.status, 0)),\n quota_pct:\n typeof partial.quota_pct === 'number' && Number.isFinite(partial.quota_pct)\n ? Math.max(0, Math.min(100, partial.quota_pct))\n : null,\n quota_reset: typeof partial.quota_reset === 'string' ? partial.quota_reset : null,\n tier: typeof partial.tier === 'string' ? partial.tier : null,\n };\n}\n\n/**\n * Extracts a concise, human-readable 1-line label from AI agent task descriptions.\n * Handles compound state/detail JSON structures, stringified JSON, and fallback text.\n */\nexport function extractCleanLabel(text: unknown): string {\n if (typeof text !== 'string' || text.length === 0) {\n return '';\n }\n\n const trimmed = text.trim();\n\n if (trimmed.startsWith('{')) {\n if (trimmed.endsWith('}')) {\n try {\n const parsed: unknown = JSON.parse(trimmed);\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n const record = parsed as Record<string, unknown>;\n\n // High priority: compound state + detail (e.g. \"Running tests: auth.test.ts\")\n if (record.state && record.detail) {\n return `${String(record.state).trim()}: ${String(record.detail).trim()}`;\n }\n\n // Secondary priority: specific action titles or summaries\n const candidate =\n record.title ??\n record.summary ??\n record.label ??\n record.message ??\n record.detail ??\n record.state;\n\n if (typeof candidate === 'string' && candidate.trim().length > 0) {\n return candidate.trim();\n }\n }\n } catch {\n // Fall through to regex extraction for malformed JSON\n }\n }\n\n // Regex fallback for truncated or malformed JSON streams\n const stateMatch = trimmed.match(/\"state\"\\s*:\\s*\"([^\"\\\\]*)(?:\"|$)/);\n const detailMatch = trimmed.match(/\"detail\"\\s*:\\s*\"([^\"\\\\]*)(?:\"|$)/);\n\n if (stateMatch?.[1] && detailMatch?.[1]) {\n return `${stateMatch[1].trim()}: ${detailMatch[1].trim()}`;\n }\n\n const singleMatch = trimmed.match(\n /\"(?:title|summary|label|message|detail|state)\"\\s*:\\s*\"([^\"\\\\]*)(?:\"|$)/,\n );\n if (singleMatch?.[1]) {\n return singleMatch[1].trim();\n }\n }\n\n // Strip wrapping quotation marks and extra whitespace\n return trimmed.replace(/^[\"']+|[\"']+$/g, '').trim();\n}\n","/**\n * tokensniff — Dynamic Universal Pricing & Context Capacity Engine (v1 Production)\n *\n * Provider-agnostic rate resolver mapping 1:1 to OpenRouter's live catalog schema.\n * Dynamically resolves token rates (prompt, completion, cache-read, cache-write)\n * and maximum context length (context_length) without vendor hardcoding or dummy fallbacks.\n */\n\nexport interface ModelRates {\n readonly in: number; // Cost per prompt token in USD\n readonly out: number; // Cost per completion token in USD\n readonly cached: number; // Cost per cache-read token in USD\n readonly cacheWrite: number; // Cost per cache-write token in USD\n readonly window: number; // Maximum context length in tokens\n}\n\nexport interface ModelPricingOverrides {\n readonly [model: string]: Partial<ModelRates>;\n}\n\ninterface OpenRouterPricingPayload {\n readonly prompt?: string;\n readonly completion?: string;\n readonly input_cache_read?: string;\n readonly input_cache_write?: string;\n}\n\ninterface OpenRouterModelItem {\n readonly id?: string;\n readonly context_length?: number;\n readonly pricing?: OpenRouterPricingPayload;\n}\n\n/**\n * In-memory index mapping model identifiers and clean slugs to ModelRates.\n * Guarantees O(1) latency on all subsequent turns after initial resolution.\n */\nconst rateCache = new Map<string, ModelRates>();\n\n/**\n * Concurrency guard preventing multiple redundant requests to OpenRouter.\n */\nlet catalogPromise: Promise<boolean> | null = null;\n\n/**\n * Normalizes vendor model names into canonical matching slugs.\n * Provider-agnostic: does not hardcode vendor names.\n *\n * Normalization rules:\n * 1. Strips provider namespaces (e.g. \"anthropic/...\", \"google/...\", \"~anthropic/...\")\n * 2. Strips variant flags (e.g. \":free\", \":batch\")\n * 3. Strips runtime proxy & mode suffixes (e.g. \"-tiered\", \"-thinking\", \"-preview\", \"-low\", \"-high\", \"-latest\")\n * 4. Strips calendar release dates (e.g. \"-20241022\", \"-2024-08-06\", \"-2407\")\n * 5. Standardizes numeric version separators (e.g. \"3-5\" -> \"3.5\", \"4-6\" -> \"4.6\")\n *\n * Examples:\n * - \"google/gemini-3.8-flash-tiered\" -> \"gemini-3.8-flash\"\n * - \"anthropic/claude-3-5-sonnet-20241022\" -> \"claude-3.5-sonnet\"\n * - \"claude-opus-4-6-thinking\" -> \"claude-opus-4.6\"\n * - \"meta-llama/llama-3.3-70b-instruct:free\" -> \"llama-3.3-70b-instruct\"\n */\nexport function normalizeModelName(raw: unknown): string {\n if (typeof raw !== 'string' || raw.trim().length === 0) {\n return 'unknown';\n }\n\n const trimmed = raw.trim().toLowerCase();\n\n // Strip provider namespace (anything before the first slash, including leading '~' aliases)\n const withoutNamespace = trimmed.replace(/^~?[a-zA-Z0-9_-]+\\//, '');\n\n // Strip variant flags (:free, :batch), proxy/mode tags, dates, and convert digit-dash-digit to dots\n return withoutNamespace\n .replace(/:[a-zA-Z0-9_-]+$/, '')\n .replace(/-(?:tiered|thinking|preview|low|high|latest)$/, '')\n .replace(/-(?:\\d{4}-\\d{2}-\\d{2}|\\d{8}|\\d{4})$/, '')\n .replace(/\\b(\\d+)-(\\d+)\\b/g, '$1.$2');\n}\n\n/**\n * Parses numeric rate strings from OpenRouter safely, guaranteeing non-negative finite numbers.\n */\nfunction toSafeRate(value: string | undefined, fallback = 0): number {\n if (!value) return fallback;\n const parsed = Number.parseFloat(value);\n return Number.isFinite(parsed) && parsed >= 0 ? parsed : fallback;\n}\n\n/**\n * Fetches and indexes OpenRouter's live models catalog.\n * Uses native Node 24 AbortSignal.timeout to enforce a strict network boundary.\n */\nexport async function syncOpenRouterCatalog(): Promise<boolean> {\n if (catalogPromise) {\n return catalogPromise;\n }\n\n catalogPromise = (async (): Promise<boolean> => {\n try {\n const response = await fetch('https://openrouter.ai/api/v1/models', {\n signal: AbortSignal.timeout(5000),\n headers: { Accept: 'application/json' },\n });\n\n if (!response.ok) {\n return false;\n }\n\n const json = (await response.json()) as {\n readonly data?: readonly OpenRouterModelItem[];\n };\n\n if (!Array.isArray(json?.data)) {\n return false;\n }\n\n for (const item of json.data) {\n if (!item?.id || !item.pricing) continue;\n\n const promptRate = toSafeRate(item.pricing.prompt);\n const completionRate = toSafeRate(item.pricing.completion);\n const cacheReadRate = toSafeRate(\n item.pricing.input_cache_read,\n promptRate > 0 ? promptRate * 0.1 : 0,\n );\n const cacheWriteRate = toSafeRate(item.pricing.input_cache_write, promptRate);\n\n // Dynamically extract real maximum context length from OpenRouter\n const rawWindow = item.context_length;\n const contextWindow =\n typeof rawWindow === 'number' && Number.isFinite(rawWindow) && rawWindow > 0\n ? rawWindow\n : 128_000;\n\n const resolvedRates: ModelRates = {\n in: promptRate,\n out: completionRate,\n cached: cacheReadRate,\n cacheWrite: cacheWriteRate,\n window: contextWindow,\n };\n\n const fullId = item.id.toLowerCase();\n const bareSlug = item.id.includes('/')\n ? (item.id.split('/')[1]?.toLowerCase() ?? fullId)\n : fullId;\n const cleanSlug = normalizeModelName(item.id);\n\n // Multi-key indexing for instant O(1) matching\n rateCache.set(fullId, resolvedRates);\n rateCache.set(bareSlug, resolvedRates);\n rateCache.set(cleanSlug, resolvedRates);\n }\n\n return true;\n } catch {\n return false;\n } finally {\n catalogPromise = null;\n }\n })();\n\n return catalogPromise;\n}\n\n/**\n * Resolves rates and maximum context length dynamically for the active turn model.\n * Seamlessly handles mid-session model switches and user custom overrides.\n */\nexport async function resolveModelRates(\n model: string,\n overrides: ModelPricingOverrides = {},\n): Promise<ModelRates> {\n const clean = normalizeModelName(model);\n const rawKey = model.trim().toLowerCase();\n\n // 1. User config overrides always take highest priority\n const matchedOverride = overrides[rawKey] ?? overrides[clean];\n if (matchedOverride) {\n const existing = rateCache.get(clean) ?? rateCache.get(rawKey);\n const resolvedOverride: ModelRates = {\n in: matchedOverride.in ?? existing?.in ?? 0,\n out: matchedOverride.out ?? existing?.out ?? 0,\n cached: matchedOverride.cached ?? existing?.cached ?? 0,\n cacheWrite: matchedOverride.in ?? existing?.cacheWrite ?? 0,\n window: matchedOverride.window ?? existing?.window ?? 128_000,\n };\n rateCache.set(clean, resolvedOverride);\n rateCache.set(rawKey, resolvedOverride);\n return resolvedOverride;\n }\n\n // 2. Fast-path: Instant in-memory cache hit\n const cached = rateCache.get(clean) ?? rateCache.get(rawKey);\n if (cached) {\n return cached;\n }\n\n // 3. Cache-miss: Fetch OpenRouter catalog on-demand\n await syncOpenRouterCatalog();\n\n const postSync = rateCache.get(clean) ?? rateCache.get(rawKey);\n if (postSync) {\n return postSync;\n }\n\n // 4. Longest-match fallback across indexed models (prioritizes specific variants over shorter base slugs)\n const candidateKeys = Array.from(rateCache.keys()).sort((a, b) => b.length - a.length);\n for (const key of candidateKeys) {\n if (key.length > 3 && (clean.includes(key) || key.includes(clean))) {\n const rates = rateCache.get(key);\n if (rates) {\n rateCache.set(clean, rates);\n return rates;\n }\n }\n }\n\n // 5. Zero-rate boundary if completely unknown to OpenRouter\n const defaultBoundary: ModelRates = {\n in: 0,\n out: 0,\n cached: 0,\n cacheWrite: 0,\n window: 128_000,\n };\n rateCache.set(clean, defaultBoundary);\n return defaultBoundary;\n}\n\n/**\n * Synchronous cache lookup for instantaneous read during statusline rendering.\n */\nexport function ratesFor(model: string): ModelRates {\n const clean = normalizeModelName(model);\n const rawKey = model.trim().toLowerCase();\n\n const hit = rateCache.get(clean) ?? rateCache.get(rawKey);\n if (hit) {\n return hit;\n }\n\n // Kick off background sync for future turns if not yet cached\n void syncOpenRouterCatalog();\n\n return {\n in: 0,\n out: 0,\n cached: 0,\n cacheWrite: 0,\n window: 128_000,\n };\n}\n\n/**\n * Calculates exact monetary cost in USD for a turn interaction.\n * Supports prompt, completion, cache-read, and cache-write token accounting.\n */\nexport function costFor(\n rates: ModelRates,\n usage: {\n readonly input?: number;\n readonly output?: number;\n readonly cacheRead?: number;\n readonly cacheCreate?: number;\n },\n): number {\n const inputTokens = Math.max(0, usage.input ?? 0);\n const outputTokens = Math.max(0, usage.output ?? 0);\n const cacheReadTokens = Math.max(0, usage.cacheRead ?? 0);\n const cacheCreateTokens = Math.max(0, usage.cacheCreate ?? 0);\n\n const cacheWriteRate = rates.cacheWrite > 0 ? rates.cacheWrite : rates.in;\n\n const total =\n inputTokens * rates.in +\n outputTokens * rates.out +\n cacheReadTokens * rates.cached +\n cacheCreateTokens * cacheWriteRate;\n\n if (!Number.isFinite(total) || total < 0) {\n return 0;\n }\n\n // 8-decimal deterministic rounding prevents IEEE 754 floating-point drift across turns\n return Math.round(total * 100_000_000) / 100_000_000;\n}\n","/**\n * tokensniff — Dynamic Responsive Statusline Formatter (v1 Production)\n *\n * Sequence: Turn -> Model -> [bg] -> Context [Cache %] -> Tool/Input/Output -> TTFT/Speed -> Cost.\n * Zero emojis. Explicit \"tok\" token units.\n * Responsive layout: dynamically adapts to terminal width (process.stdout.columns)\n * ensuring the line NEVER wraps and the cost is NEVER cut off.\n */\n\nimport { normalizeModelName, ratesFor } from '../shared/pricing.js';\nimport { extractCleanLabel, type TokenSniffLatest } from '../shared/schema.js';\n\nexport interface FormatOptions {\n readonly warnPct?: number;\n readonly critPct?: number;\n readonly color?: boolean;\n readonly staleAfterS?: number;\n readonly now?: number;\n readonly modelFallback?: string;\n readonly columns?: number;\n}\n\nconst ANSI_RED = '\\x1b[31m';\nconst ANSI_YELLOW = '\\x1b[33m';\nconst ANSI_GREEN = '\\x1b[32m';\nconst ANSI_RESET = '\\x1b[0m';\n\n/**\n * Strips ANSI color sequences to calculate the true visible character width on screen.\n */\nfunction stripAnsi(text: string): string {\n return text.replace(/\\x1b\\[[0-9;]*m/g, '');\n}\n\n/**\n * Formats raw token counts into clean, human-readable numbers without redundant trailing zeros.\n * E.g.: 1500 -> \"1.5k\", 1000000 -> \"1M\", 450 -> \"450\".\n */\nexport function formatTokenCount(value: number | null | undefined): string {\n if (value == null || !Number.isFinite(value)) return '0';\n const absolute = Math.abs(value);\n if (absolute >= 1e6) {\n const formatted = (value / 1e6).toFixed(1);\n return formatted.endsWith('.0') ? `${(value / 1e6).toFixed(0)}M` : `${formatted}M`;\n }\n if (absolute >= 1e3) {\n const formatted = (value / 1e3).toFixed(1);\n return formatted.endsWith('.0') ? `${(value / 1e3).toFixed(0)}k` : `${formatted}k`;\n }\n return String(value);\n}\n\n/**\n * Strips line breaks, tabs, and carriage returns to ensure single-line terminal rendering.\n */\nfunction sanitizeText(text: unknown, maxLength: number): string {\n return String(text || '')\n .replace(/[\\r\\n\\t]+/g, ' ')\n .trim()\n .slice(0, maxLength);\n}\n\n/**\n * Formats tool execution summary with explicit \"tok\" unit.\n */\nexport function formatToolSegment(snapshot: Partial<TokenSniffLatest>, isCompact = false): string {\n const summary =\n Array.isArray(snapshot.tools_summary) && snapshot.tools_summary.length > 0\n ? snapshot.tools_summary\n : snapshot.tool\n ? [{ name: snapshot.tool, count: 1, arg_tk: snapshot.tool_tk || 0 }]\n : [];\n\n if (summary.length === 0) {\n return snapshot.tool ? `tool: ${sanitizeText(snapshot.tool, 20)}` : '';\n }\n\n let toolNamePart = '';\n let totalArgTk = 0;\n\n for (const item of summary) {\n totalArgTk += item.arg_tk || 0;\n }\n\n if (summary.length === 1) {\n const item = summary[0];\n if (item) {\n const countSuffix = item.count > 1 ? ` x${item.count}` : '';\n toolNamePart = `${sanitizeText(item.name, 16)}${countSuffix}`;\n }\n } else if (summary.length === 2) {\n const first = summary[0];\n const second = summary[1];\n toolNamePart = `${sanitizeText(first?.name, 10)}+${sanitizeText(second?.name, 10)}`;\n } else {\n const first = summary[0];\n const second = summary[1];\n toolNamePart = `${sanitizeText(first?.name, 8)}+${sanitizeText(second?.name, 8)} +${summary.length - 2}more`;\n }\n\n if (isCompact) {\n return `tool: ${toolNamePart}`;\n }\n\n const argSnippet = totalArgTk > 0 ? ` (${totalArgTk} tok)` : '';\n return `tool: ${toolNamePart}${argSnippet}`;\n}\n\n/**\n * Formats telemetry snapshot into a single-line status bar that dynamically adapts\n * to terminal columns, preventing line wrapping and preventing cost truncation.\n */\nexport function formatStatus(\n snapshot: Partial<TokenSniffLatest> | null,\n options: FormatOptions = {},\n): string {\n const opts = {\n warnPct: 60,\n critPct: 80,\n color: true,\n staleAfterS: 120,\n now: Date.now(),\n modelFallback: 'tokensniff',\n columns:\n options.columns ??\n (process.env.COLUMNS ? Number.parseInt(process.env.COLUMNS, 10) : undefined) ??\n process.stdout?.columns ??\n 120,\n ...options,\n };\n\n if (!snapshot?.ts) {\n return `[${opts.modelFallback}] waiting for first turn...`;\n }\n\n const maxCols = Math.max(50, opts.columns);\n\n // 1. Identity Segment: Turn + Model + Background Flag\n const turnIndex = snapshot.turn_index ?? 1;\n const turnPrefix = `turn ${turnIndex}`;\n const rawModel = snapshot.model || opts.modelFallback;\n const normalized = normalizeModelName(rawModel);\n const cleanModel =\n normalized === 'unknown'\n ? opts.modelFallback\n : normalized.replace(/^(?:gemini|claude|gpt|deepseek)-/, '');\n const bgBadge = snapshot.is_bg ? ' [bg]' : '';\n const identitySegment = `${turnPrefix} [${cleanModel}]${bgBadge}`;\n\n // 2. Context Window & Cache Percentage\n const ctxTokens = snapshot.ctx || 0;\n const fallbackWindow = ratesFor(snapshot.model ?? '').window;\n const ctxWindow = snapshot.window && snapshot.window > 0 ? snapshot.window : fallbackWindow;\n const windowStr = formatTokenCount(ctxWindow);\n const percentage =\n typeof snapshot.pct === 'number' ? snapshot.pct : (ctxTokens / ctxWindow) * 100;\n const pctStr = `${percentage.toFixed(1)}%`;\n\n const cacheTokens = snapshot.cache_read ?? 0;\n const cacheHitPct =\n ctxTokens > 0 ? Math.min(100, (cacheTokens / ctxTokens) * 100).toFixed(1) : '0.0';\n\n const formatContext = (isCompact = false): string => {\n let cacheText = '';\n if (cacheTokens > 0) {\n cacheText = isCompact\n ? ` [cache: ${cacheHitPct}%]`\n : ` [cache: ${formatTokenCount(cacheTokens)} (${cacheHitPct}%)]`;\n }\n const raw = `ctx: ${formatTokenCount(ctxTokens)}/${windowStr} (${pctStr})${cacheText}`;\n if (!opts.color) return raw;\n\n const colorCode =\n percentage >= opts.critPct ? ANSI_RED : percentage >= opts.warnPct ? ANSI_YELLOW : ANSI_GREEN;\n return `${colorCode}${raw}${ANSI_RESET}`;\n };\n\n // 3. Error Case (429 Rate Limit / 502 Outages)\n if (snapshot.error && (snapshot.error === 429 || snapshot.error >= 500)) {\n const turnCostStr = `$${Number(snapshot.cost_turn || 0).toFixed(4)}`;\n const sessCostStr = `$${Number(snapshot.cost_session || 0).toFixed(3)}`;\n const costSegment = `cost: turn ${turnCostStr}, sess ${sessCostStr}`;\n return `${identitySegment} | ${formatContext(true)} | error: rate limit ${snapshot.error} (retrying...) | ${costSegment}`;\n }\n\n // 4. Activity: Tool / Label / Input / Output / Thinking\n const toolSegment =\n snapshot.tool || (Array.isArray(snapshot.tools_summary) && snapshot.tools_summary.length > 0)\n ? formatToolSegment(snapshot, false)\n : '';\n\n const labelSegment =\n snapshot.is_label && snapshot.label\n ? `label: \"${sanitizeText(extractCleanLabel(snapshot.label), 35)}\"`\n : '';\n\n const formatTokens = (): string => {\n const delta = snapshot.delta_in ?? 0;\n let inText = '';\n if (delta > 0) {\n inText = `input: +${formatTokenCount(delta)} tok`;\n } else if (delta < 0) {\n inText = `input: freed ${formatTokenCount(Math.abs(delta))} tok`;\n } else {\n inText = `input: ${formatTokenCount(snapshot.in_tokens || 0)} tok`;\n }\n\n const outText = `output: ${formatTokenCount(snapshot.out_tokens || 0)} tok`;\n\n let thinkText = '';\n if (snapshot.thinking_tokens && snapshot.thinking_tokens > 0) {\n thinkText = `, think: ${formatTokenCount(snapshot.thinking_tokens)} tok`;\n }\n\n return `${inText}, ${outText}${thinkText}`;\n };\n\n // 5. Performance (TTFT and Velocity)\n const formatPerformance = (): string => {\n const ttft = snapshot.ttft_ms ?? 0;\n const ttftStr = ttft >= 1000 ? `${(ttft / 1000).toFixed(1)}s` : `${ttft}ms`;\n let tpsVal = snapshot.tps && snapshot.tps > 0 ? snapshot.tps : 0;\n if (\n !tpsVal &&\n snapshot.out_tokens &&\n snapshot.out_tokens > 0 &&\n snapshot.dur_s &&\n snapshot.dur_s > 0\n ) {\n tpsVal = Math.max(1, Math.round(snapshot.out_tokens / snapshot.dur_s));\n }\n const tpsStr = tpsVal > 0 ? `${tpsVal} tok/s` : '0 tok/s';\n return `ttft: ${ttftStr}, ${tpsStr}`;\n };\n\n // 6. Cost (Always at the very end)\n const isStale = opts.now - (snapshot.ts || 0) > opts.staleAfterS * 1000 ? ' [idle]' : '';\n const turnCost = Number(snapshot.cost_turn || 0).toFixed(4);\n const sessCost = Number(snapshot.cost_session || 0).toFixed(3);\n const todayCost = Number(snapshot.cost_today || 0).toFixed(3);\n\n const fullCost = `cost: turn $${turnCost}, sess $${sessCost}, today $${todayCost}${isStale}`;\n\n // Single-line layout: used when screen is wide enough (>= 180 columns)\n const singleParts = [identitySegment, formatContext(false)];\n if (labelSegment) {\n singleParts.push(labelSegment);\n } else {\n if (toolSegment) singleParts.push(toolSegment);\n singleParts.push(formatTokens());\n }\n singleParts.push(formatPerformance());\n singleParts.push(fullCost);\n const singleLine = singleParts.join(' | ');\n\n if (stripAnsi(singleLine).length <= maxCols) {\n return singleLine.replace(/[\\r\\n\\t]+/g, ' ').trim();\n }\n\n // 2-line clean stack: divides metrics evenly across 2 rows so nothing is ever truncated\n // Line 1: Identity + Context & Cache + Tool / Label (if any)\n const line1Parts = [identitySegment, formatContext(false)];\n if (labelSegment) {\n line1Parts.push(labelSegment);\n } else if (toolSegment) {\n line1Parts.push(toolSegment);\n }\n const line1 = line1Parts.join(' | ');\n\n // Line 2: Tokens (if not label) + Performance + Financials\n const line2Parts: string[] = [];\n if (!labelSegment) {\n line2Parts.push(formatTokens());\n }\n line2Parts.push(formatPerformance());\n line2Parts.push(fullCost);\n const line2 = line2Parts.join(' | ');\n\n return `${line1.replace(/[\\r\\n\\t]+/g, ' ').trim()}\\n${line2.replace(/[\\r\\n\\t]+/g, ' ').trim()}`;\n}\n","/**\n * tokensniff — Statusline CLI Renderer Entrypoint (v1 Production)\n *\n * Executed by Claude Code statusLine hook. Consumes piped stdin JSON from Claude,\n * locates the session-specific latest-<session_id>.json snapshot, and outputs\n * the scannable single-line status bar to stdout.\n *\n * GUARANTEE: Never throws or exits non-zero, preserving terminal UI integrity.\n */\n\nimport fs from 'node:fs';\nimport path from 'node:path';\nimport { loadConfig } from '../collector/config.js';\nimport { isTokenSniffLatest, type TokenSniffLatest } from '../shared/schema.js';\nimport { formatStatus } from './format.js';\n\nexport interface StdinPayload {\n readonly session_id?: string;\n readonly sessionId?: string;\n readonly model?: string | { readonly id?: string; readonly display_name?: string };\n}\n\nexport interface StatusRunnerOptions {\n readonly statusDirs?: readonly string[];\n readonly staleAfterS?: number;\n readonly color?: boolean;\n}\n\n/**\n * Consumes Claude Code JSON piped via stdin with a strict non-blocking timeout guard.\n * Unrefs the timer so the process never hangs if stdin stays open indefinitely.\n */\nexport function readStdin(timeoutMs = 300): Promise<StdinPayload> {\n return new Promise((resolve) => {\n let raw = '';\n let done = false;\n\n const finish = (value: StdinPayload): void => {\n if (done) return;\n done = true;\n clearTimeout(timer);\n try {\n process.stdin.destroy();\n } catch {\n /* ignore destruction errors */\n }\n resolve(value);\n };\n\n const timer = setTimeout(() => finish({}), timeoutMs);\n if (timer.unref) timer.unref();\n\n // If invoked interactively in a TTY without piped input, exit immediately\n if (process.stdin.isTTY) {\n return finish({});\n }\n\n process.stdin.setEncoding('utf8');\n process.stdin.on('data', (chunk: string) => {\n raw += chunk;\n });\n\n process.stdin.on('end', () => {\n try {\n const parsed: unknown = JSON.parse(raw || '{}');\n if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {\n finish(parsed as StdinPayload);\n } else {\n finish({});\n }\n } catch {\n finish({});\n }\n });\n\n process.stdin.resume();\n });\n}\n\n/**\n * Resolves the latest telemetry snapshot across global status directories.\n * Prioritizes session-specific state, falling back to universal latest.json.\n */\nexport function pickLatest(\n statusDirs: readonly string[],\n sessionId?: string,\n): TokenSniffLatest | null {\n const safeSessionId = sessionId?.trim().replace(/[^a-zA-Z0-9_-]/g, '');\n const fileCandidates = safeSessionId\n ? [`latest-${safeSessionId}.json`, 'latest.json']\n : ['latest.json'];\n\n for (const dir of statusDirs) {\n for (const name of fileCandidates) {\n const fullPath = path.join(dir, name);\n try {\n if (fs.existsSync(fullPath)) {\n const parsed: unknown = JSON.parse(fs.readFileSync(fullPath, 'utf8'));\n if (isTokenSniffLatest(parsed)) {\n return parsed;\n }\n if (typeof parsed === 'object' && parsed !== null) {\n return parsed as TokenSniffLatest;\n }\n }\n } catch {\n /* continue searching next directory */\n }\n }\n }\n return null;\n}\n\n/**\n * Extracts the model name string from Claude Code's stdin payload.\n */\nexport function extractModel(input: StdinPayload): string | undefined {\n if (!input?.model) return undefined;\n if (typeof input.model === 'object') {\n return input.model.id || input.model.display_name;\n }\n return String(input.model);\n}\n\n/**\n * Main execution hook for tokensniff-status.\n */\nexport async function main(opts: StatusRunnerOptions = {}): Promise<void> {\n const cfg = loadConfig();\n const statusDirs = opts.statusDirs ?? cfg.statusDirs;\n\n try {\n const input = await readStdin();\n const sessionId = input.session_id || input.sessionId;\n const latest = pickLatest(statusDirs, sessionId);\n\n // If raw JSON output is requested\n if (process.env.TOKENSNIFF_JSON === '1') {\n console.log(JSON.stringify(latest || { waiting: true }));\n return;\n }\n\n // Output formatted single-line status bar\n console.log(\n formatStatus(latest, {\n staleAfterS: opts.staleAfterS ?? cfg.staleAfterS,\n color: opts.color ?? cfg.color,\n warnPct: cfg.warnPct,\n critPct: cfg.critPct,\n modelFallback: extractModel(input) || 'tokensniff',\n }),\n );\n } catch (error) {\n const msg = error instanceof Error ? error.message : String(error);\n try {\n console.log(`[tokensniff] status unavailable (${msg})`);\n } catch {\n /* fail completely silent to preserve prompt UI */\n }\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tokensniff",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Claude Code telemetry proxy and live terminal status line HUD. Real-time token tracking, API costs, TTFT, and calendar heatmap dashboard. Zero dependencies.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./schema": {
|
|
16
|
+
"types": "./dist/shared/schema.d.ts",
|
|
17
|
+
"import": "./dist/schema.js"
|
|
18
|
+
},
|
|
19
|
+
"./pricing": {
|
|
20
|
+
"types": "./dist/shared/pricing.d.ts",
|
|
21
|
+
"import": "./dist/pricing.js"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
24
|
+
},
|
|
25
|
+
"typesVersions": {
|
|
26
|
+
"*": {
|
|
27
|
+
"schema": [
|
|
28
|
+
"./dist/shared/schema.d.ts"
|
|
29
|
+
],
|
|
30
|
+
"pricing": [
|
|
31
|
+
"./dist/shared/pricing.d.ts"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"bin": {
|
|
36
|
+
"tokensniff": "./bin/tokensniff.js",
|
|
37
|
+
"tokensniff-status": "./bin/tokensniff-status.js"
|
|
38
|
+
},
|
|
39
|
+
"files": [
|
|
40
|
+
"dist",
|
|
41
|
+
"bin",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE"
|
|
44
|
+
],
|
|
45
|
+
"sideEffects": false,
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"engines": {
|
|
50
|
+
"node": ">=22.0.0"
|
|
51
|
+
},
|
|
52
|
+
"packageManager": "pnpm@11.25.0",
|
|
53
|
+
"scripts": {
|
|
54
|
+
"build": "tsup && tsc --emitDeclarationOnly",
|
|
55
|
+
"dev": "tsup --watch",
|
|
56
|
+
"typecheck": "tsc --noEmit",
|
|
57
|
+
"lint": "biome check .",
|
|
58
|
+
"lint:fix": "biome check --write .",
|
|
59
|
+
"test": "tsx --test test/*.test.ts",
|
|
60
|
+
"check:package": "publint && attw --pack . --ignore-rules cjs-resolves-to-esm",
|
|
61
|
+
"prepack": "pnpm build",
|
|
62
|
+
"prepublishOnly": "pnpm typecheck && pnpm test"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@arethetypeswrong/cli": "^0.18.5",
|
|
66
|
+
"@biomejs/biome": "^2.5.12",
|
|
67
|
+
"@types/node": "^26.5.0",
|
|
68
|
+
"publint": "^0.3.24",
|
|
69
|
+
"tsup": "^8.5.1",
|
|
70
|
+
"tsx": "^4.23.13",
|
|
71
|
+
"typescript": "^7.0.2"
|
|
72
|
+
},
|
|
73
|
+
"keywords": [
|
|
74
|
+
"claude-code",
|
|
75
|
+
"claude code",
|
|
76
|
+
"claude-code-statusline",
|
|
77
|
+
"claude-code-hud",
|
|
78
|
+
"claude",
|
|
79
|
+
"anthropic",
|
|
80
|
+
"token-tracker",
|
|
81
|
+
"cost-tracker",
|
|
82
|
+
"telemetry",
|
|
83
|
+
"statusline",
|
|
84
|
+
"status-bar",
|
|
85
|
+
"hud",
|
|
86
|
+
"reverse-proxy",
|
|
87
|
+
"heatmap-dashboard",
|
|
88
|
+
"zero-dependency",
|
|
89
|
+
"TTFT",
|
|
90
|
+
"TPS",
|
|
91
|
+
"Turns",
|
|
92
|
+
"Input Tokens",
|
|
93
|
+
"Output Tokens",
|
|
94
|
+
"Cache %",
|
|
95
|
+
"Tool Calls",
|
|
96
|
+
"Context window",
|
|
97
|
+
"Gemini",
|
|
98
|
+
"Antigravity",
|
|
99
|
+
"proxy"
|
|
100
|
+
],
|
|
101
|
+
"repository": {
|
|
102
|
+
"type": "git",
|
|
103
|
+
"url": "git+https://github.com/neeraj0304/tokensniff.git"
|
|
104
|
+
}
|
|
105
|
+
}
|