Big News: Socket raises $60M Series C at a $1B valuation to secure software supply chains for AI-driven development.Announcement
Sign In

@tokenometer/core

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tokenometer/core - npm Package Compare versions

Comparing version
0.0.5
to
0.1.0
+15
dist/config.d.ts
declare const ALLOWED_FORMATS: readonly ["json", "yaml", "xml", "markdown", "text"];
export type ConfigFormat = (typeof ALLOWED_FORMATS)[number];
export interface TokenometerConfig {
models?: string[];
formats?: ConfigFormat[];
budgets?: {
total?: number;
'per-file'?: number;
};
paths?: string[];
}
export declare const parseConfig: (yamlText: string) => TokenometerConfig;
export declare const loadConfig: (cwd?: string) => Promise<TokenometerConfig | null>;
export {};
//# sourceMappingURL=config.d.ts.map
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,QAAA,MAAM,eAAe,sDAAuD,CAAC;AAE7E,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClD,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB;AAsED,eAAO,MAAM,WAAW,GAAI,UAAU,MAAM,KAAG,iBAmB9C,CAAC;AAMF,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAiC/E,CAAC"}
import { parse as yamlParse } from 'yaml';
import { KNOWN_MODELS } from './rates.js';
const ALLOWED_FORMATS = ['json', 'yaml', 'xml', 'markdown', 'text'];
const CONFIG_FILENAMES = ['.tokenometer.yml', '.tokenometer.yaml'];
const isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
const ensureStringArray = (value, field) => {
if (!Array.isArray(value)) {
throw new Error(`tokenometer config: "${field}" must be an array of strings.`);
}
return value.map((item, idx) => {
if (typeof item !== 'string') {
throw new Error(`tokenometer config: "${field}[${idx}]" must be a string, got ${typeof item}.`);
}
return item;
});
};
const validateModels = (value) => {
const ids = ensureStringArray(value, 'models');
for (const id of ids) {
if (!KNOWN_MODELS.includes(id)) {
throw new Error(`tokenometer config: unknown model "${id}". Known: ${KNOWN_MODELS.join(', ')}.`);
}
}
return ids;
};
const validateFormats = (value) => {
const raw = ensureStringArray(value, 'formats');
for (const fmt of raw) {
if (!ALLOWED_FORMATS.includes(fmt)) {
throw new Error(`tokenometer config: unknown format "${fmt}". Known: ${ALLOWED_FORMATS.join(', ')}.`);
}
}
return raw;
};
const validateBudgets = (value) => {
if (!isPlainObject(value)) {
throw new Error('tokenometer config: "budgets" must be an object.');
}
const out = {};
for (const key of Object.keys(value)) {
if (key !== 'total' && key !== 'per-file') {
throw new Error(`tokenometer config: unknown budget key "${key}". Allowed: total, per-file.`);
}
const raw = value[key];
if (typeof raw !== 'number' || !Number.isFinite(raw) || raw < 0) {
throw new Error(`tokenometer config: "budgets.${key}" must be a non-negative number, got ${JSON.stringify(raw)}.`);
}
if (key === 'total')
out.total = raw;
else
out['per-file'] = raw;
}
return out;
};
const validatePaths = (value) => ensureStringArray(value, 'paths');
const ALLOWED_KEYS = new Set(['models', 'formats', 'budgets', 'paths']);
export const parseConfig = (yamlText) => {
const parsed = yamlText.trim() ? yamlParse(yamlText) : {};
if (parsed === null || parsed === undefined)
return {};
if (!isPlainObject(parsed)) {
throw new Error('tokenometer config: top-level must be a mapping.');
}
for (const key of Object.keys(parsed)) {
if (!ALLOWED_KEYS.has(key)) {
throw new Error(`tokenometer config: unknown top-level key "${key}". Allowed: ${[...ALLOWED_KEYS].join(', ')}.`);
}
}
const out = {};
if ('models' in parsed)
out.models = validateModels(parsed.models);
if ('formats' in parsed)
out.formats = validateFormats(parsed.formats);
if ('budgets' in parsed)
out.budgets = validateBudgets(parsed.budgets);
if ('paths' in parsed)
out.paths = validatePaths(parsed.paths);
return out;
};
// loadConfig touches the filesystem. Imports are deferred via dynamic import so
// browser bundlers (Vite for the web playground) don't statically trace
// `node:fs` and friends — externalized stubs would fail to expose named members
// like `join`, breaking the build. Node still resolves them normally at runtime.
export const loadConfig = async (cwd) => {
const { existsSync } = await import('node:fs');
const { readFile } = await import('node:fs/promises');
const { dirname, join, parse: parsePath } = await import('node:path');
const findConfigFile = (startDir) => {
let dir = startDir;
while (true) {
for (const name of CONFIG_FILENAMES) {
const candidate = join(dir, name);
if (existsSync(candidate))
return candidate;
}
const isGitRoot = existsSync(join(dir, '.git'));
const parent = dirname(dir);
if (isGitRoot)
return null;
if (parent === dir || parent === parsePath(dir).root) {
if (parent !== dir) {
for (const name of CONFIG_FILENAMES) {
const candidate = join(parent, name);
if (existsSync(candidate))
return candidate;
}
}
return null;
}
dir = parent;
}
};
const start = cwd ?? process.cwd();
const file = findConfigFile(start);
if (!file)
return null;
const text = await readFile(file, 'utf8');
return parseConfig(text);
};
//# sourceMappingURL=config.js.map
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
import type { TokenizeResult } from './types.js';
/**
* Per-file aggregate of matrix results, suitable for SARIF emission.
* `path` is the source-relative URI that will land in the SARIF location.
*/
export interface TokenometerFileResult {
path: string;
results: readonly TokenizeResult[];
}
/**
* Top-level result envelope passed to SARIF / future formatters.
* Modeled as a discriminated wrapper so additional fields (e.g. budget verdicts,
* empirical metadata) can be added without breaking existing callers.
*/
export interface TokenometerResult {
files: readonly TokenometerFileResult[];
}
export interface ToSarifOptions {
toolVersion?: string;
}
interface SarifLocation {
physicalLocation: {
artifactLocation: {
uri: string;
};
};
}
interface SarifResultEntry {
ruleId: string;
level: 'note';
message: {
text: string;
};
locations: SarifLocation[];
}
interface SarifTool {
driver: {
name: string;
version: string;
informationUri: string;
rules: {
id: string;
name: string;
shortDescription: {
text: string;
};
}[];
};
}
interface SarifRun {
tool: SarifTool;
results: SarifResultEntry[];
}
interface SarifLog {
$schema: string;
version: string;
runs: SarifRun[];
}
export declare const toSarif: (result: TokenometerResult, opts?: ToSarifOptions) => SarifLog;
export {};
//# sourceMappingURL=format-sarif.d.ts.map
{"version":3,"file":"format-sarif.d.ts","sourceRoot":"","sources":["../src/format-sarif.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,SAAS,cAAc,EAAE,CAAC;CACpC;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,SAAS,qBAAqB,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAeD,UAAU,aAAa;IACrB,gBAAgB,EAAE;QAAE,gBAAgB,EAAE;YAAE,GAAG,EAAE,MAAM,CAAA;SAAE,CAAA;KAAE,CAAC;CACzD;AAED,UAAU,gBAAgB;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1B,SAAS,EAAE,aAAa,EAAE,CAAC;CAC5B;AAED,UAAU,SAAS;IACjB,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,KAAK,EAAE;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAC;YAAC,gBAAgB,EAAE;gBAAE,IAAI,EAAE,MAAM,CAAA;aAAE,CAAA;SAAE,EAAE,CAAC;KAC3E,CAAC;CACH;AAED,UAAU,QAAQ;IAChB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,gBAAgB,EAAE,CAAC;CAC7B;AAED,UAAU,QAAQ;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,EAAE,CAAC;CAClB;AAED,eAAO,MAAM,OAAO,GAAI,QAAQ,iBAAiB,EAAE,OAAO,cAAc,KAAG,QAwC1E,CAAC"}
const formatCost = (usd) => {
if (usd >= 0.01)
return `$${usd.toFixed(4)}`;
if (usd >= 0.000001)
return `$${usd.toFixed(6)}`;
return `$${usd.toExponential(2)}`;
};
const SARIF_SCHEMA = 'https://raw.githubusercontent.com/oasis-tcs/sarif-spec/main/Schemata/sarif-schema-2.1.0.json';
const SARIF_VERSION = '2.1.0';
const TOOL_NAME = 'Tokenometer';
const TOOL_INFO_URI = 'https://github.com/faraa2m/tokenometer';
const RULE_ID = 'prompt-cost';
export const toSarif = (result, opts) => {
const toolVersion = opts?.toolVersion ?? '0.0.0';
const results = [];
for (const file of result.files) {
for (const cell of file.results) {
results.push({
ruleId: RULE_ID,
level: 'note',
message: {
text: `${cell.model} / ${cell.format}: ${cell.inputTokens.toLocaleString()} tokens · ${formatCost(cell.inputCost)}`,
},
locations: [{ physicalLocation: { artifactLocation: { uri: file.path } } }],
});
}
}
return {
$schema: SARIF_SCHEMA,
version: SARIF_VERSION,
runs: [
{
tool: {
driver: {
name: TOOL_NAME,
version: toolVersion,
informationUri: TOOL_INFO_URI,
rules: [
{
id: RULE_ID,
name: 'prompt-cost',
shortDescription: {
text: 'Estimated input-token cost for this prompt file.',
},
},
],
},
},
results,
},
],
};
};
//# sourceMappingURL=format-sarif.js.map
{"version":3,"file":"format-sarif.js","sourceRoot":"","sources":["../src/format-sarif.ts"],"names":[],"mappings":"AAwBA,MAAM,UAAU,GAAG,CAAC,GAAW,EAAU,EAAE;IACzC,IAAI,GAAG,IAAI,IAAI;QAAE,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IAC7C,IAAI,GAAG,IAAI,QAAQ;QAAE,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,OAAO,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC;AACpC,CAAC,CAAC;AAEF,MAAM,YAAY,GAChB,8FAA8F,CAAC;AACjG,MAAM,aAAa,GAAG,OAAO,CAAC;AAC9B,MAAM,SAAS,GAAG,aAAa,CAAC;AAChC,MAAM,aAAa,GAAG,wCAAwC,CAAC;AAC/D,MAAM,OAAO,GAAG,aAAa,CAAC;AAiC9B,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,MAAyB,EAAE,IAAqB,EAAY,EAAE;IACpF,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,OAAO,CAAC;IACjD,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAChC,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC;gBACX,MAAM,EAAE,OAAO;gBACf,KAAK,EAAE,MAAM;gBACb,OAAO,EAAE;oBACP,IAAI,EAAE,GAAG,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,WAAW,CAAC,cAAc,EAAE,aAAa,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;iBACpH;gBACD,SAAS,EAAE,CAAC,EAAE,gBAAgB,EAAE,EAAE,gBAAgB,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC;aAC5E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO;QACL,OAAO,EAAE,YAAY;QACrB,OAAO,EAAE,aAAa;QACtB,IAAI,EAAE;YACJ;gBACE,IAAI,EAAE;oBACJ,MAAM,EAAE;wBACN,IAAI,EAAE,SAAS;wBACf,OAAO,EAAE,WAAW;wBACpB,cAAc,EAAE,aAAa;wBAC7B,KAAK,EAAE;4BACL;gCACE,EAAE,EAAE,OAAO;gCACX,IAAI,EAAE,aAAa;gCACnB,gBAAgB,EAAE;oCAChB,IAAI,EAAE,kDAAkD;iCACzD;6BACF;yBACF;qBACF;iBACF;gBACD,OAAO;aACR;SACF;KACF,CAAC;AACJ,CAAC,CAAC"}
import type { EmpiricalEnv } from './empirical.js';
import type { LatencyResult, LatencyStats, LatencyTrial, Provider } from './types.js';
export type { LatencyResult, LatencyStats, LatencyTrial };
export interface MeasureLatencyOptions {
modelId: string;
prompt: string;
trials: number;
maxTokens?: number;
env: EmpiricalEnv;
}
/**
* Linear-interpolation percentile. `p` is 0-100. With p95 over n=3 trials this
* just returns max(values), which is what we want for the "tail" reading.
*/
declare const nthPercentile: (values: readonly number[], p: number) => number;
/**
* Test seam: callers (tests) can substitute a provider's trial runner. The
* production `measureLatency` always uses the real implementations above.
*/
export interface LatencyDeps {
fetchImpl?: typeof fetch;
trialRunner?: (provider: Provider, modelId: string, prompt: string, maxTokens: number, env: EmpiricalEnv) => Promise<LatencyTrial>;
}
/**
* Run `trials` real streaming generations and return percentile-summarized
* latency data. Each trial is retried once on failure; if both attempts
* fail, the original provider error is rethrown.
*/
export declare const measureLatency: (options: MeasureLatencyOptions, deps?: LatencyDeps) => Promise<LatencyResult>;
export { nthPercentile };
//# sourceMappingURL=latency.d.ts.map
{"version":3,"file":"latency.d.ts","sourceRoot":"","sources":["../src/latency.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtF,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC;AAE1D,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,YAAY,CAAC;CACnB;AAsBD;;;GAGG;AACH,QAAA,MAAM,aAAa,GAAI,QAAQ,SAAS,MAAM,EAAE,EAAE,GAAG,MAAM,KAAG,MAW7D,CAAC;AAqUF;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,WAAW,CAAC,EAAE,CACZ,QAAQ,EAAE,QAAQ,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,YAAY,KACd,OAAO,CAAC,YAAY,CAAC,CAAC;CAC5B;AA+CD;;;;GAIG;AACH,eAAO,MAAM,cAAc,GACzB,SAAS,qBAAqB,EAC9B,OAAM,WAAgB,KACrB,OAAO,CAAC,aAAa,CAyBvB,CAAC;AAEF,OAAO,EAAE,aAAa,EAAE,CAAC"}
// Real-generation latency measurement.
//
// Unlike `tokenizeEmpirical` (which calls the free `countTokens` endpoints),
// this dispatches a real metered streaming generation per provider and
// measures wall-clock TTFT (time to first token) + total stream duration +
// tokens/sec from the actual output. Reported as p50/p95/mean over `trials`
// runs so callers see a stable distribution rather than a single noisy run.
//
// Cost note: every trial is a metered chat completion. The CLI bumps the
// default `--max-spend` ceiling when `--latency` is on; see args.ts.
import Anthropic from '@anthropic-ai/sdk';
import { GoogleGenerativeAI } from '@google/generative-ai';
import { getModel } from './rates.js';
const DEFAULT_MAX_TOKENS = 200;
const ENV_VAR_NAME = {
anthropicApiKey: 'ANTHROPIC_API_KEY',
cohereApiKey: 'COHERE_API_KEY',
googleApiKey: 'GOOGLE_API_KEY',
mistralApiKey: 'MISTRAL_API_KEY',
openaiApiKey: 'OPENAI_API_KEY',
};
const requireKey = (env, key, provider) => {
const value = env[key];
if (!value) {
const envName = key === 'googleApiKey' ? `${ENV_VAR_NAME[key]} (or GEMINI_API_KEY)` : ENV_VAR_NAME[key];
throw new Error(`${provider} latency mode requires ${envName}`);
}
return value;
};
/**
* Linear-interpolation percentile. `p` is 0-100. With p95 over n=3 trials this
* just returns max(values), which is what we want for the "tail" reading.
*/
const nthPercentile = (values, p) => {
if (values.length === 0)
return 0;
const sorted = [...values].sort((a, b) => a - b);
if (sorted.length === 1)
return sorted[0];
const rank = (p / 100) * (sorted.length - 1);
const lower = Math.floor(rank);
const upper = Math.ceil(rank);
const lowerValue = sorted[lower];
if (lower === upper)
return lowerValue;
const upperValue = sorted[upper];
return lowerValue + (upperValue - lowerValue) * (rank - lower);
};
const mean = (values) => {
if (values.length === 0)
return 0;
let sum = 0;
for (const v of values)
sum += v;
return sum / values.length;
};
const summarize = (trials) => {
const ttft = trials.map((t) => t.ttftMs);
const total = trials.map((t) => t.totalMs);
const tps = trials.map((t) => t.tokensPerSec);
return {
trials: [...trials],
p50: {
ttftMs: nthPercentile(ttft, 50),
totalMs: nthPercentile(total, 50),
tokensPerSec: nthPercentile(tps, 50),
},
p95: {
ttftMs: nthPercentile(ttft, 95),
totalMs: nthPercentile(total, 95),
tokensPerSec: nthPercentile(tps, 95),
},
mean: {
ttftMs: mean(ttft),
totalMs: mean(total),
tokensPerSec: mean(tps),
},
};
};
const computeTokensPerSec = (outputTokens, ttftMs, totalMs) => {
// Avoid divide-by-zero on instant streams (mocked tests, very fast paths).
const generationMs = Math.max(totalMs - ttftMs, 1);
return (outputTokens / generationMs) * 1000;
};
// ---------------------------------------------------------------------------
// Per-provider trial runners. Each returns one LatencyTrial.
// ---------------------------------------------------------------------------
const trialAnthropic = async (modelId, prompt, maxTokens, apiKey) => {
const client = new Anthropic({ apiKey, dangerouslyAllowBrowser: true });
const start = Date.now();
let ttftMs = 0;
let outputTokens = 0;
const stream = client.messages.stream({
max_tokens: maxTokens,
messages: [{ content: prompt, role: 'user' }],
model: modelId,
});
for await (const event of stream) {
const e = event;
if (ttftMs === 0 &&
e.type === 'content_block_delta' &&
e.delta?.type === 'text_delta' &&
typeof e.delta?.text === 'string' &&
e.delta.text.length > 0) {
ttftMs = Date.now() - start;
}
if (e.type === 'message_delta' && typeof e.usage?.output_tokens === 'number') {
outputTokens = e.usage.output_tokens;
}
if (e.type === 'message_start' && typeof e.message?.usage?.output_tokens === 'number') {
// initial usage is typically 0 — message_delta carries the running count
}
}
const totalMs = Date.now() - start;
return {
ttftMs: ttftMs || totalMs,
totalMs,
outputTokens,
tokensPerSec: computeTokensPerSec(outputTokens, ttftMs || totalMs, totalMs),
};
};
const trialGoogle = async (modelId, prompt, maxTokens, apiKey) => {
const genAI = new GoogleGenerativeAI(apiKey);
const model = genAI.getGenerativeModel({
model: modelId,
generationConfig: { maxOutputTokens: maxTokens },
});
const start = Date.now();
let ttftMs = 0;
let outputTokens = 0;
const result = await model.generateContentStream(prompt);
for await (const chunk of result.stream) {
if (ttftMs === 0) {
const text = chunk.text?.();
if (text && text.length > 0)
ttftMs = Date.now() - start;
}
const usage = chunk.usageMetadata;
if (usage && typeof usage.candidatesTokenCount === 'number') {
outputTokens = usage.candidatesTokenCount;
}
}
const totalMs = Date.now() - start;
return {
ttftMs: ttftMs || totalMs,
totalMs,
outputTokens,
tokensPerSec: computeTokensPerSec(outputTokens, ttftMs || totalMs, totalMs),
};
};
/**
* Generic SSE iterator. Yields one parsed JSON object per `data: …` line and
* stops on `data: [DONE]`. Used for OpenAI + Mistral (Cohere has its own
* NDJSON-style stream, see below).
*/
async function* iterSse(body) {
const reader = body.getReader();
const decoder = new TextDecoder('utf-8');
let buf = '';
while (true) {
const { done, value } = await reader.read();
if (done)
break;
buf += decoder.decode(value, { stream: true });
// Split on double-newline (SSE event boundary).
while (true) {
const idx = buf.indexOf('\n\n');
if (idx === -1)
break;
const eventBlock = buf.slice(0, idx);
buf = buf.slice(idx + 2);
for (const line of eventBlock.split('\n')) {
if (!line.startsWith('data:'))
continue;
const payload = line.slice(5).trim();
if (payload === '[DONE]' || payload.length === 0)
return;
try {
yield JSON.parse(payload);
}
catch {
// skip malformed line
}
}
}
}
}
const trialOpenAi = async (modelId, prompt, maxTokens, apiKey, fetchImpl = fetch) => {
const start = Date.now();
const response = await fetchImpl('https://api.openai.com/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: modelId,
messages: [{ role: 'user', content: prompt }],
max_tokens: maxTokens,
stream: true,
stream_options: { include_usage: true },
}),
});
if (!response.ok || !response.body) {
const body = await response.text().catch(() => '');
throw new Error(`OpenAI /v1/chat/completions returned ${response.status} ${response.statusText}${body ? `: ${body}` : ''}`);
}
let ttftMs = 0;
let outputTokens = 0;
for await (const ev of iterSse(response.body)) {
const choices = ev.choices;
if (ttftMs === 0 && choices && choices[0]?.delta?.content)
ttftMs = Date.now() - start;
const usage = ev.usage;
if (usage && typeof usage.completion_tokens === 'number')
outputTokens = usage.completion_tokens;
}
const totalMs = Date.now() - start;
return {
ttftMs: ttftMs || totalMs,
totalMs,
outputTokens,
tokensPerSec: computeTokensPerSec(outputTokens, ttftMs || totalMs, totalMs),
};
};
const trialMistral = async (modelId, prompt, maxTokens, apiKey, fetchImpl = fetch) => {
const start = Date.now();
const response = await fetchImpl('https://api.mistral.ai/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
Accept: 'text/event-stream',
},
body: JSON.stringify({
model: modelId,
messages: [{ role: 'user', content: prompt }],
max_tokens: maxTokens,
stream: true,
}),
});
if (!response.ok || !response.body) {
const body = await response.text().catch(() => '');
throw new Error(`Mistral /v1/chat/completions returned ${response.status} ${response.statusText}${body ? `: ${body}` : ''}`);
}
let ttftMs = 0;
let outputTokens = 0;
for await (const ev of iterSse(response.body)) {
const choices = ev.choices;
if (ttftMs === 0 && choices && choices[0]?.delta?.content)
ttftMs = Date.now() - start;
const usage = ev.usage;
if (usage && typeof usage.completion_tokens === 'number')
outputTokens = usage.completion_tokens;
}
const totalMs = Date.now() - start;
return {
ttftMs: ttftMs || totalMs,
totalMs,
outputTokens,
tokensPerSec: computeTokensPerSec(outputTokens, ttftMs || totalMs, totalMs),
};
};
const trialCohere = async (modelId, prompt, maxTokens, apiKey, fetchImpl = fetch) => {
// Cohere /v1/chat streams NDJSON (one JSON object per line), not SSE.
// See https://docs.cohere.com/reference/chat for event types
// (stream-start, text-generation, stream-end).
const start = Date.now();
const response = await fetchImpl('https://api.cohere.com/v1/chat', {
method: 'POST',
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: modelId,
message: prompt,
max_tokens: maxTokens,
stream: true,
}),
});
if (!response.ok || !response.body) {
const body = await response.text().catch(() => '');
throw new Error(`Cohere /v1/chat returned ${response.status} ${response.statusText}${body ? `: ${body}` : ''}`);
}
const reader = response.body.getReader();
const decoder = new TextDecoder('utf-8');
let buf = '';
let ttftMs = 0;
let outputTokens = 0;
while (true) {
const { done, value } = await reader.read();
if (done)
break;
buf += decoder.decode(value, { stream: true });
while (true) {
const nl = buf.indexOf('\n');
if (nl === -1)
break;
const line = buf.slice(0, nl).trim();
buf = buf.slice(nl + 1);
if (!line)
continue;
let ev;
try {
ev = JSON.parse(line);
}
catch {
continue;
}
if (ttftMs === 0 && ev.event_type === 'text-generation')
ttftMs = Date.now() - start;
if (ev.event_type === 'stream-end') {
const resp = ev.response;
const out = resp?.meta?.tokens?.output_tokens;
if (typeof out === 'number')
outputTokens = out;
}
}
}
const totalMs = Date.now() - start;
return {
ttftMs: ttftMs || totalMs,
totalMs,
outputTokens,
tokensPerSec: computeTokensPerSec(outputTokens, ttftMs || totalMs, totalMs),
};
};
const defaultTrialRunner = async (provider, modelId, prompt, maxTokens, env, fetchImpl = fetch) => {
switch (provider) {
case 'anthropic':
return trialAnthropic(modelId, prompt, maxTokens, requireKey(env, 'anthropicApiKey', provider));
case 'google':
return trialGoogle(modelId, prompt, maxTokens, requireKey(env, 'googleApiKey', provider));
case 'openai':
return trialOpenAi(modelId, prompt, maxTokens, requireKey(env, 'openaiApiKey', provider), fetchImpl);
case 'mistral':
return trialMistral(modelId, prompt, maxTokens, requireKey(env, 'mistralApiKey', provider), fetchImpl);
case 'cohere':
return trialCohere(modelId, prompt, maxTokens, requireKey(env, 'cohereApiKey', provider), fetchImpl);
}
};
/**
* Run `trials` real streaming generations and return percentile-summarized
* latency data. Each trial is retried once on failure; if both attempts
* fail, the original provider error is rethrown.
*/
export const measureLatency = async (options, deps = {}) => {
const provider = getModel(options.modelId).provider;
const maxTokens = options.maxTokens ?? DEFAULT_MAX_TOKENS;
const fetchImpl = deps.fetchImpl ?? fetch;
const runner = deps.trialRunner ??
((p, m, prompt, max, env) => defaultTrialRunner(p, m, prompt, max, env, fetchImpl));
const trials = [];
for (let i = 0; i < options.trials; i++) {
let lastErr;
let success = null;
for (let attempt = 0; attempt < 2; attempt++) {
try {
success = await runner(provider, options.modelId, options.prompt, maxTokens, options.env);
break;
}
catch (err) {
lastErr = err;
}
}
if (!success) {
throw lastErr instanceof Error ? lastErr : new Error(String(lastErr));
}
trials.push(success);
}
return summarize(trials);
};
export { nthPercentile };
//# sourceMappingURL=latency.js.map
{"version":3,"file":"latency.js","sourceRoot":"","sources":["../src/latency.ts"],"names":[],"mappings":"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"}
export interface CohereCountResult {
approximate: true;
tokens: number;
tokenizer: 'heuristic';
}
export declare const cohereCount: (text: string) => CohereCountResult;
/**
* Hits Cohere's `POST /v1/tokenize` endpoint. The response shape we care
* about is `{ tokens: number[] }`; only `tokens.length` is used.
*
* Endpoint reference: https://docs.cohere.com/reference/tokenize
*
* Returns the exact token count. Pulled out of `empirical.ts` so the
* dependency surface (one fetch call, no SDK) stays here next to the
* offline path it complements.
*/
export declare const cohereTokenizeApi: (text: string, modelId: string, apiKey: string, fetchImpl?: typeof fetch) => Promise<number>;
//# sourceMappingURL=tokenize-cohere.d.ts.map
{"version":3,"file":"tokenize-cohere.d.ts","sourceRoot":"","sources":["../src/tokenize-cohere.ts"],"names":[],"mappings":"AAwBA,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,WAAW,CAAC;CACxB;AAED,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,iBAIzC,CAAC;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAC5B,MAAM,MAAM,EACZ,SAAS,MAAM,EACf,QAAQ,MAAM,EACd,YAAW,OAAO,KAAa,KAC9B,OAAO,CAAC,MAAM,CAoBhB,CAAC"}
// Cohere tokenizer dispatch.
//
// Cohere ships their tokenizers as `tokenizer.json` files on HuggingFace
// (e.g. `Cohere/command-r-plus`). The `cohere-ai` SDK is a thin REST client
// — it does NOT bundle an offline tokenizer, only a `client.tokenize()`
// method that hits Cohere's API. Confirmed against `cohere-ai@8.0.0` at the
// time of writing (May 2026). So:
//
// * Offline mode: chars/4 heuristic, `approximate: true`. Same accuracy
// tier as the Google heuristic in tokenize.ts.
//
// * Empirical mode: POST https://api.cohere.com/v1/tokenize. The endpoint
// is free and very low latency. Wired in `empirical.ts`.
//
// We deliberately do NOT depend on `cohere-ai` for the empirical path — it
// is a 4.9 MB SDK and we only need one POST. Native `fetch` keeps the
// install footprint identical to the offline-only build.
//
// Future upgrade: once `@huggingface/tokenizers` is stable (Path D in the
// research memo), lazy-load `tokenizer.json` per Cohere model from HF Hub
// for exact offline counts.
const COHERE_HEURISTIC_CHARS_PER_TOKEN = 4;
export const cohereCount = (text) => ({
approximate: true,
tokens: Math.ceil(text.length / COHERE_HEURISTIC_CHARS_PER_TOKEN),
tokenizer: 'heuristic',
});
/**
* Hits Cohere's `POST /v1/tokenize` endpoint. The response shape we care
* about is `{ tokens: number[] }`; only `tokens.length` is used.
*
* Endpoint reference: https://docs.cohere.com/reference/tokenize
*
* Returns the exact token count. Pulled out of `empirical.ts` so the
* dependency surface (one fetch call, no SDK) stays here next to the
* offline path it complements.
*/
export const cohereTokenizeApi = async (text, modelId, apiKey, fetchImpl = fetch) => {
const response = await fetchImpl('https://api.cohere.com/v1/tokenize', {
body: JSON.stringify({ model: modelId, text }),
headers: {
Authorization: `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
method: 'POST',
});
if (!response.ok) {
const body = await response.text().catch(() => '');
throw new Error(`Cohere /v1/tokenize returned ${response.status} ${response.statusText}${body ? `: ${body}` : ''}`);
}
const data = (await response.json());
if (!Array.isArray(data.tokens)) {
throw new Error('Cohere /v1/tokenize returned an unexpected shape (no tokens array).');
}
return data.tokens.length;
};
//# sourceMappingURL=tokenize-cohere.js.map
{"version":3,"file":"tokenize-cohere.js","sourceRoot":"","sources":["../src/tokenize-cohere.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,EAAE;AACF,yEAAyE;AACzE,4EAA4E;AAC5E,wEAAwE;AACxE,4EAA4E;AAC5E,kCAAkC;AAClC,EAAE;AACF,0EAA0E;AAC1E,mDAAmD;AACnD,EAAE;AACF,4EAA4E;AAC5E,6DAA6D;AAC7D,EAAE;AACF,2EAA2E;AAC3E,sEAAsE;AACtE,yDAAyD;AACzD,EAAE;AACF,0EAA0E;AAC1E,0EAA0E;AAC1E,4BAA4B;AAE5B,MAAM,gCAAgC,GAAG,CAAC,CAAC;AAQ3C,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAqB,EAAE,CAAC,CAAC;IAC/D,WAAW,EAAE,IAAI;IACjB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,gCAAgC,CAAC;IACjE,SAAS,EAAE,WAAW;CACvB,CAAC,CAAC;AAEH;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EACpC,IAAY,EACZ,OAAe,EACf,MAAc,EACd,YAA0B,KAAK,EACd,EAAE;IACnB,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,oCAAoC,EAAE;QACrE,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QAC9C,OAAO,EAAE;YACP,aAAa,EAAE,UAAU,MAAM,EAAE;YACjC,cAAc,EAAE,kBAAkB;SACnC;QACD,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QACnD,MAAM,IAAI,KAAK,CACb,gCAAgC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACnG,CAAC;IACJ,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAA0B,CAAC;IAC9D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,qEAAqE,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;AAC5B,CAAC,CAAC"}
export declare const isTekken: (modelId: string) => boolean;
export interface MistralCountResult {
approximate: true;
tokens: number;
tokenizer: 'heuristic' | 'mistral_v1_v3';
}
/**
* Count tokens for a Mistral model. Always `approximate: true` (see file
* header). For SentencePiece models, returns the `mistral-tokenizer-js`
* count (BOS token included, matching the library's default). For Tekken
* models (and any unknown ID — defensive), returns a `chars/4` heuristic.
*/
export declare const mistralCount: (text: string, modelId: string) => MistralCountResult;
//# sourceMappingURL=tokenize-mistral.d.ts.map
{"version":3,"file":"tokenize-mistral.d.ts","sourceRoot":"","sources":["../src/tokenize-mistral.ts"],"names":[],"mappings":"AAsDA,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,OAAqC,CAAC;AAOjF,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,IAAI,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,WAAW,GAAG,eAAe,CAAC;CAC1C;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,kBAU5D,CAAC"}
// Mistral tokenizer dispatch.
//
// Mistral has shipped two tokenizer families:
//
// 1. SentencePiece (V1/V2/V3) — the "classic" Mistral family. Covered by
// `mistral-tokenizer-js` (mistralTokenizer.encode → number[]). Models:
// Mistral 7B (v0.1/v0.2/v0.3), Mixtral 8x7B / 8x22B,
// Mistral Large 2407, Mistral Small 2402, Codestral 22B.
//
// 2. Tekken — a tiktoken-style 128k BPE introduced with Mistral NeMo
// (Jul 2024). Used by NeMo, Pixtral, Mistral Small 2409+, Devstral,
// Mistral Medium 2505+, Magistral, Ministral. NOT covered by
// `mistral-tokenizer-js`. Applying SentencePiece to Tekken models would
// give systematically wrong counts (different vocab, ~32k vs ~128k), so
// we fall back to the same `chars/4` heuristic used for Google.
//
// Both paths set `approximate: true` because:
// - Mistral does not publish an offline reference tokenizer for newer
// models, and even the SentencePiece path is "compatible with most"
// per the upstream README — no formal validation guarantee.
// - Mistral has no public free /v1/tokenize endpoint as of May 2026, so
// there's no empirical anchor available either.
//
// Future upgrade path (Path D in the research memo): once
// `@huggingface/tokenizers` reaches v1.0, lazy-load `tokenizer.json` per
// model for exact counts behind an opt-in flag.
import mistralTokenizer from 'mistral-tokenizer-js';
/**
* Mistral model IDs that use the Tekken tokenizer (post-NeMo families).
*
* Cross-reference list curated from the integration memo. Update as Mistral
* releases new model IDs; default-on-unknown is heuristic too, so this set
* is allowlist-style for SentencePiece, not the other way around.
*/
const TEKKEN_MODELS = new Set([
'mistral-nemo',
'pixtral-12b',
'pixtral-large-latest',
'mistral-small-latest',
'devstral-small-2505',
'devstral-small-2507',
'devstral-medium-2507',
'mistral-medium-2505',
'mistral-medium-2508',
'mistral-medium-latest',
'magistral-small',
'magistral-medium-latest',
'ministral-3b-latest',
'ministral-8b-latest',
]);
export const isTekken = (modelId) => TEKKEN_MODELS.has(modelId);
const MISTRAL_HEURISTIC_CHARS_PER_TOKEN = 4;
const heuristicCount = (text) => Math.ceil(text.length / MISTRAL_HEURISTIC_CHARS_PER_TOKEN);
/**
* Count tokens for a Mistral model. Always `approximate: true` (see file
* header). For SentencePiece models, returns the `mistral-tokenizer-js`
* count (BOS token included, matching the library's default). For Tekken
* models (and any unknown ID — defensive), returns a `chars/4` heuristic.
*/
export const mistralCount = (text, modelId) => {
if (isTekken(modelId)) {
return { approximate: true, tokens: heuristicCount(text), tokenizer: 'heuristic' };
}
// SentencePiece path. `encode()` returns number[] including the BOS token
// by default — this matches what Mistral's chat completions endpoint
// would actually charge for, so we do not strip it.
const ids = mistralTokenizer.encode(text);
const tokenizer = 'mistral_v1_v3';
return { approximate: true, tokens: ids.length, tokenizer };
};
//# sourceMappingURL=tokenize-mistral.js.map
{"version":3,"file":"tokenize-mistral.js","sourceRoot":"","sources":["../src/tokenize-mistral.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,EAAE;AACF,8CAA8C;AAC9C,EAAE;AACF,2EAA2E;AAC3E,4EAA4E;AAC5E,0DAA0D;AAC1D,8DAA8D;AAC9D,EAAE;AACF,uEAAuE;AACvE,yEAAyE;AACzE,kEAAkE;AAClE,6EAA6E;AAC7E,6EAA6E;AAC7E,qEAAqE;AACrE,EAAE;AACF,8CAA8C;AAC9C,wEAAwE;AACxE,wEAAwE;AACxE,gEAAgE;AAChE,0EAA0E;AAC1E,oDAAoD;AACpD,EAAE;AACF,0DAA0D;AAC1D,yEAAyE;AACzE,gDAAgD;AAEhD,OAAO,gBAAgB,MAAM,sBAAsB,CAAC;AAGpD;;;;;;GAMG;AACH,MAAM,aAAa,GAAwB,IAAI,GAAG,CAAC;IACjD,cAAc;IACd,aAAa;IACb,sBAAsB;IACtB,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,sBAAsB;IACtB,qBAAqB;IACrB,qBAAqB;IACrB,uBAAuB;IACvB,iBAAiB;IACjB,yBAAyB;IACzB,qBAAqB;IACrB,qBAAqB;CACtB,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAW,EAAE,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AAEjF,MAAM,iCAAiC,GAAG,CAAC,CAAC;AAE5C,MAAM,cAAc,GAAG,CAAC,IAAY,EAAU,EAAE,CAC9C,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,iCAAiC,CAAC,CAAC;AAQ7D;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,IAAY,EAAE,OAAe,EAAsB,EAAE;IAChF,IAAI,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtB,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,CAAC,IAAI,CAAC,EAAE,SAAS,EAAE,WAAW,EAAE,CAAC;IACrF,CAAC;IACD,0EAA0E;IAC1E,qEAAqE;IACrE,oDAAoD;IACpD,MAAM,GAAG,GAAG,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAkB,eAAe,CAAC;IACjD,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC;AAC9D,CAAC,CAAC"}
export interface AnthropicVisionInput {
width: number;
height: number;
/** Anthropic's estimator does not branch on detail; accepted for API parity. */
detail?: 'low' | 'high' | 'auto';
}
/**
* Anthropic vision token estimator.
*
* Approximation per Anthropic guidance: tokens ≈ ceil((width * height) / 750),
* capped at 1600 tokens per image.
*/
export declare const visionTokens: ({ width, height }: AnthropicVisionInput) => number;
//# sourceMappingURL=vision-anthropic.d.ts.map
{"version":3,"file":"vision-anthropic.d.ts","sourceRoot":"","sources":["../src/vision-anthropic.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,gFAAgF;IAChF,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;CAClC;AAID;;;;;GAKG;AACH,eAAO,MAAM,YAAY,GAAI,mBAAmB,oBAAoB,KAAG,MAQtE,CAAC"}
const MAX_TOKENS = 1600;
/**
* Anthropic vision token estimator.
*
* Approximation per Anthropic guidance: tokens ≈ ceil((width * height) / 750),
* capped at 1600 tokens per image.
*/
export const visionTokens = ({ width, height }) => {
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
throw new Error(`anthropicVisionTokens: width and height must be positive finite numbers, got ${width}x${height}.`);
}
const raw = Math.ceil((width * height) / 750);
return Math.min(raw, MAX_TOKENS);
};
//# sourceMappingURL=vision-anthropic.js.map
{"version":3,"file":"vision-anthropic.js","sourceRoot":"","sources":["../src/vision-anthropic.ts"],"names":[],"mappings":"AAOA,MAAM,UAAU,GAAG,IAAI,CAAC;AAExB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAwB,EAAU,EAAE;IAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,gFAAgF,KAAK,IAAI,MAAM,GAAG,CACnG,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;IAC9C,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;AACnC,CAAC,CAAC"}
export interface GoogleVisionInput {
width: number;
height: number;
/** Google's estimator does not branch on detail; accepted for API parity. */
detail?: 'low' | 'high' | 'auto';
}
/**
* Google (Gemini) vision token estimator.
*
* Per Google guidance:
* - Images ≤ 384×384 cost a flat 258 tokens.
* - Larger images: 258 * ceil(width/768) * ceil(height/768), with a floor of 1 tile per axis.
*/
export declare const visionTokens: ({ width, height }: GoogleVisionInput) => number;
//# sourceMappingURL=vision-google.d.ts.map
{"version":3,"file":"vision-google.d.ts","sourceRoot":"","sources":["../src/vision-google.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6EAA6E;IAC7E,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;CAClC;AAMD;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GAAI,mBAAmB,iBAAiB,KAAG,MAUnE,CAAC"}
const SMALL_THRESHOLD = 384;
const SMALL_TOKENS = 258;
const TILE_SIZE = 768;
/**
* Google (Gemini) vision token estimator.
*
* Per Google guidance:
* - Images ≤ 384×384 cost a flat 258 tokens.
* - Larger images: 258 * ceil(width/768) * ceil(height/768), with a floor of 1 tile per axis.
*/
export const visionTokens = ({ width, height }) => {
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
throw new Error(`googleVisionTokens: width and height must be positive finite numbers, got ${width}x${height}.`);
}
if (width <= SMALL_THRESHOLD && height <= SMALL_THRESHOLD)
return SMALL_TOKENS;
const tilesX = Math.max(1, Math.ceil(width / TILE_SIZE));
const tilesY = Math.max(1, Math.ceil(height / TILE_SIZE));
return SMALL_TOKENS * tilesX * tilesY;
};
//# sourceMappingURL=vision-google.js.map
{"version":3,"file":"vision-google.js","sourceRoot":"","sources":["../src/vision-google.ts"],"names":[],"mappings":"AAOA,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,MAAM,YAAY,GAAG,GAAG,CAAC;AACzB,MAAM,SAAS,GAAG,GAAG,CAAC;AAEtB;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAqB,EAAU,EAAE;IAC3E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,6EAA6E,KAAK,IAAI,MAAM,GAAG,CAChG,CAAC;IACJ,CAAC;IACD,IAAI,KAAK,IAAI,eAAe,IAAI,MAAM,IAAI,eAAe;QAAE,OAAO,YAAY,CAAC;IAC/E,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;IAC1D,OAAO,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AACxC,CAAC,CAAC"}
export interface OpenAIVisionInput {
width: number;
height: number;
/** OpenAI vision detail; defaults to 'high' if omitted. 'auto' resolves to 'high'. */
detail?: 'low' | 'high' | 'auto';
}
/**
* OpenAI vision token estimator.
*
* - 'low' detail: flat 85 tokens.
* - 'high'/'auto' detail (default): resize so the longest side is at most 2048,
* then so the shortest side is at most 768; tile the result by 512×512;
* total = 85 + 170 * tiles.
*/
export declare const visionTokens: ({ width, height, detail }: OpenAIVisionInput) => number;
//# sourceMappingURL=vision-openai.d.ts.map
{"version":3,"file":"vision-openai.d.ts","sourceRoot":"","sources":["../src/vision-openai.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,sFAAsF;IACtF,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;CAClC;AASD;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,GAAI,2BAAoC,iBAAiB,KAAG,MA+BpF,CAAC"}
const LOW_DETAIL_TOKENS = 85;
const HIGH_DETAIL_BASE = 85;
const HIGH_DETAIL_PER_TILE = 170;
const LONGEST_CAP = 2048;
const SHORTEST_CAP = 768;
const TILE_SIZE = 512;
/**
* OpenAI vision token estimator.
*
* - 'low' detail: flat 85 tokens.
* - 'high'/'auto' detail (default): resize so the longest side is at most 2048,
* then so the shortest side is at most 768; tile the result by 512×512;
* total = 85 + 170 * tiles.
*/
export const visionTokens = ({ width, height, detail = 'high' }) => {
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) {
throw new Error(`openaiVisionTokens: width and height must be positive finite numbers, got ${width}x${height}.`);
}
if (detail === 'low')
return LOW_DETAIL_TOKENS;
let w = width;
let h = height;
// Step 1: cap the longest side at 2048, preserving aspect ratio.
const longest = Math.max(w, h);
if (longest > LONGEST_CAP) {
const scale = LONGEST_CAP / longest;
w = w * scale;
h = h * scale;
}
// Step 2: scale so the shortest side is at most 768, preserving aspect ratio.
const shortest = Math.min(w, h);
if (shortest > SHORTEST_CAP) {
const scale = SHORTEST_CAP / shortest;
w = w * scale;
h = h * scale;
}
const tilesX = Math.ceil(w / TILE_SIZE);
const tilesY = Math.ceil(h / TILE_SIZE);
const tiles = tilesX * tilesY;
return HIGH_DETAIL_BASE + HIGH_DETAIL_PER_TILE * tiles;
};
//# sourceMappingURL=vision-openai.js.map
{"version":3,"file":"vision-openai.js","sourceRoot":"","sources":["../src/vision-openai.ts"],"names":[],"mappings":"AAOA,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAC7B,MAAM,gBAAgB,GAAG,EAAE,CAAC;AAC5B,MAAM,oBAAoB,GAAG,GAAG,CAAC;AACjC,MAAM,WAAW,GAAG,IAAI,CAAC;AACzB,MAAM,YAAY,GAAG,GAAG,CAAC;AACzB,MAAM,SAAS,GAAG,GAAG,CAAC;AAEtB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,EAAqB,EAAU,EAAE;IAC5F,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;QACrF,MAAM,IAAI,KAAK,CACb,6EAA6E,KAAK,IAAI,MAAM,GAAG,CAChG,CAAC;IACJ,CAAC;IACD,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,iBAAiB,CAAC;IAE/C,IAAI,CAAC,GAAG,KAAK,CAAC;IACd,IAAI,CAAC,GAAG,MAAM,CAAC;IAEf,iEAAiE;IACjE,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/B,IAAI,OAAO,GAAG,WAAW,EAAE,CAAC;QAC1B,MAAM,KAAK,GAAG,WAAW,GAAG,OAAO,CAAC;QACpC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACd,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,8EAA8E;IAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAChC,IAAI,QAAQ,GAAG,YAAY,EAAE,CAAC;QAC5B,MAAM,KAAK,GAAG,YAAY,GAAG,QAAQ,CAAC;QACtC,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACd,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IAChB,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;IAC9B,OAAO,gBAAgB,GAAG,oBAAoB,GAAG,KAAK,CAAC;AACzD,CAAC,CAAC"}
+4
-1

@@ -5,7 +5,10 @@ import type { Format, TokenizeResult } from './types.js';

exact: true;
source: 'anthropic-count' | 'gemini-count' | 'tiktoken-o200k';
source: 'anthropic-count' | 'cohere-tokenize' | 'gemini-count' | 'tiktoken-o200k';
}
export interface EmpiricalEnv {
anthropicApiKey?: string;
cohereApiKey?: string;
googleApiKey?: string;
mistralApiKey?: string;
openaiApiKey?: string;
}

@@ -12,0 +15,0 @@ export interface TokenizeEmpiricalOptions {

+1
-1

@@ -1,1 +0,1 @@

{"version":3,"file":"empirical.d.ts","sourceRoot":"","sources":["../src/empirical.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,MAAM,EAAY,cAAc,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,iBAAiB,GAAG,cAAc,GAAG,gBAAgB,CAAC;CAC/D;AAED,MAAM,WAAW,YAAY;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAsDD,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iBAAiB,GAC5B,SAAS,wBAAwB,KAChC,OAAO,CAAC,cAAc,CAyBxB,CAAC;AAEF,MAAM,WAAW,8BAA8B;IAC7C,GAAG,EAAE,YAAY,CAAC;IAClB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,uBAAuB,GAClC,SAAS,8BAA8B,KACtC,OAAO,CAAC,cAAc,EAAE,CAe1B,CAAC"}
{"version":3,"file":"empirical.d.ts","sourceRoot":"","sources":["../src/empirical.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAY,cAAc,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;IACZ,MAAM,EAAE,iBAAiB,GAAG,iBAAiB,GAAG,cAAc,GAAG,gBAAgB,CAAC;CACnF;AAED,MAAM,WAAW,YAAY;IAC3B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IAGtB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAwED,MAAM,WAAW,wBAAwB;IACvC,GAAG,EAAE,YAAY,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,iBAAiB,GAC5B,SAAS,wBAAwB,KAChC,OAAO,CAAC,cAAc,CAuCxB,CAAC;AAEF,MAAM,WAAW,8BAA8B;IAC7C,GAAG,EAAE,YAAY,CAAC;IAClB,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,uBAAuB,GAClC,SAAS,8BAA8B,KACtC,OAAO,CAAC,cAAc,EAAE,CAe1B,CAAC"}

@@ -6,6 +6,15 @@ import Anthropic from '@anthropic-ai/sdk';

import { getModel, getRate } from './rates.js';
import { cohereTokenizeApi } from './tokenize-cohere.js';
const ENV_VAR_NAME = {
anthropicApiKey: 'ANTHROPIC_API_KEY',
cohereApiKey: 'COHERE_API_KEY',
googleApiKey: 'GOOGLE_API_KEY',
mistralApiKey: 'MISTRAL_API_KEY',
openaiApiKey: 'OPENAI_API_KEY',
};
const requireKey = (env, key, provider) => {
const value = env[key];
if (!value) {
throw new Error(`${provider} empirical mode requires ${key === 'anthropicApiKey' ? 'ANTHROPIC_API_KEY' : 'GOOGLE_API_KEY'} (or GEMINI_API_KEY)`);
const envName = key === 'googleApiKey' ? `${ENV_VAR_NAME[key]} (or GEMINI_API_KEY)` : ENV_VAR_NAME[key];
throw new Error(`${provider} empirical mode requires ${envName}`);
}

@@ -44,2 +53,7 @@ return value;

});
const countCohere = async (text, modelId, env) => {
const apiKey = requireKey(env, 'cohereApiKey', 'cohere');
const count = await cohereTokenizeApi(text, modelId, apiKey);
return { count, exact: true, source: 'cohere-tokenize' };
};
export const tokenizeEmpirical = async (options) => {

@@ -60,2 +74,14 @@ const model = getModel(options.modelId);

break;
case 'cohere':
result = await countCohere(converted, model.id, options.env);
break;
case 'mistral':
// Mistral does not expose a public free token-count endpoint as of
// May 2026 (see .planning/research/mistral-integration.md). Refuse
// empirical mode rather than silently falling back to the offline
// path — that would violate the `--empirical` contract (count is
// exact). Users who want exact counts can call a metered chat
// completion and read back `usage.prompt_tokens` themselves.
throw new Error('Mistral does not expose a public token-count API; offline mode only. ' +
'For exact counts, send a chat completion to Mistral and read `usage.prompt_tokens`.');
}

@@ -62,0 +88,0 @@ return {

@@ -1,1 +0,1 @@

{"version":3,"file":"empirical.js","sourceRoot":"","sources":["../src/empirical.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"empirical.js","sourceRoot":"","sources":["../src/empirical.ts"],"names":[],"mappings":"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"}

@@ -0,8 +1,20 @@

export { loadConfig, parseConfig } from './config.js';
export type { ConfigFormat, TokenometerConfig } from './config.js';
export { allFormats, isFormat, toFormat } from './convert.js';
export { tokenizeEmpirical, tokenizeMatrixEmpirical } from './empirical.js';
export type { EmpiricalCountResult, EmpiricalEnv } from './empirical.js';
export { toSarif } from './format-sarif.js';
export type { TokenometerFileResult, TokenometerResult, ToSarifOptions } from './format-sarif.js';
export { measureLatency, nthPercentile } from './latency.js';
export type { LatencyDeps, MeasureLatencyOptions } from './latency.js';
export { KNOWN_MODELS, MODELS, RATES, RATES_VERSION, getModel, getRate } from './rates.js';
export { countTokens, tokenize, tokenizeMatrix } from './tokenize.js';
export type { CountResult } from './tokenize.js';
export type { EmpiricalResult, Format, ModelDescriptor, Provider, RateEntry, TokenizeResult, TokenizerKind, } from './types.js';
export type { EmpiricalResult, Format, LatencyResult, LatencyStats, LatencyTrial, ModelDescriptor, Provider, RateEntry, TokenizeResult, TokenizerKind, } from './types.js';
export { visionTokens as anthropicVisionTokens } from './vision-anthropic.js';
export type { AnthropicVisionInput } from './vision-anthropic.js';
export { visionTokens as googleVisionTokens } from './vision-google.js';
export type { GoogleVisionInput } from './vision-google.js';
export { visionTokens as openaiVisionTokens } from './vision-openai.js';
export type { OpenAIVisionInput } from './vision-openai.js';
//# sourceMappingURL=index.d.ts.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EACV,eAAe,EACf,MAAM,EACN,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC"}
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AACtD,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,YAAY,EAAE,oBAAoB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,YAAY,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAClG,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,cAAc,CAAC;AACvE,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACtE,YAAY,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AACjD,YAAY,EACV,eAAe,EACf,MAAM,EACN,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC9E,YAAY,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}

@@ -0,5 +1,11 @@

export { loadConfig, parseConfig } from './config.js';
export { allFormats, isFormat, toFormat } from './convert.js';
export { tokenizeEmpirical, tokenizeMatrixEmpirical } from './empirical.js';
export { toSarif } from './format-sarif.js';
export { measureLatency, nthPercentile } from './latency.js';
export { KNOWN_MODELS, MODELS, RATES, RATES_VERSION, getModel, getRate } from './rates.js';
export { countTokens, tokenize, tokenizeMatrix } from './tokenize.js';
export { visionTokens as anthropicVisionTokens } from './vision-anthropic.js';
export { visionTokens as googleVisionTokens } from './vision-google.js';
export { visionTokens as openaiVisionTokens } from './vision-openai.js';
//# sourceMappingURL=index.js.map

@@ -1,1 +0,1 @@

{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAEtD,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AAE5E,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7D,OAAO,EAAE,YAAY,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC3F,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AActE,OAAO,EAAE,YAAY,IAAI,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9E,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAExE,OAAO,EAAE,YAAY,IAAI,kBAAkB,EAAE,MAAM,oBAAoB,CAAC"}
import type { ModelDescriptor, RateEntry } from './types.js';
export declare const RATES_VERSION = "2026-05-08";
export declare const RATES_VERSION = "2026-05-09";
export declare const RATES: Record<string, RateEntry>;

@@ -4,0 +4,0 @@ export declare const MODELS: Record<string, ModelDescriptor>;

@@ -1,1 +0,1 @@

{"version":3,"file":"rates.d.ts","sourceRoot":"","sources":["../src/rates.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,eAAe,EAAY,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvE,eAAO,MAAM,aAAa,eAAe,CAAC;AAmH1C,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAE3C,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAElD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAAiC,CAAC;AAE5E,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,SAMzC,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,eAM1C,CAAC"}
{"version":3,"file":"rates.d.ts","sourceRoot":"","sources":["../src/rates.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAY,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvE,eAAO,MAAM,aAAa,eAAe,CAAC;AA+I1C,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAE3C,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAElD,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,SAAS,MAAM,EAAiC,CAAC;AAE5E,eAAO,MAAM,OAAO,GAAI,SAAS,MAAM,KAAG,SAMzC,CAAC;AAEF,eAAO,MAAM,QAAQ,GAAI,SAAS,MAAM,KAAG,eAM1C,CAAC"}
import anthropicProvider from '@tokenlens/models/anthropic';
import googleProvider from '@tokenlens/models/google';
import mistralProvider from '@tokenlens/models/mistral';
import openaiProvider from '@tokenlens/models/openai';
import { getContext, getTokenCosts } from 'tokenlens';
export const RATES_VERSION = '2026-05-08';
export const RATES_VERSION = '2026-05-09';
// `@tokenlens/models` does not yet ship a Cohere catalog (verified against
// node_modules/@tokenlens/models/dist/providers/ at v1.3.0). When upstream
// adds it, drop the Cohere LOCAL_OVERRIDES entry and add the import here.
const CATALOG = {
anthropic: anthropicProvider,
google: googleProvider,
mistral: mistralProvider,
openai: openaiProvider,
};
const PROVIDERS = ['anthropic', 'google', 'openai'];
const PROVIDERS = ['anthropic', 'google', 'mistral', 'openai'];
// Bleeding-edge models tokenlens hasn't picked up from upstream yet.
// Remove an entry once `scripts/check-overrides.mjs` reports it landed.
//
// Cohere entries are also here because `@tokenlens/models` does not yet
// ship a Cohere catalog at all (v1.3.0). Pricing pulled from the published
// Cohere pricing page (cohere.com/pricing) at RATES_VERSION date.
const LOCAL_OVERRIDES = {

@@ -45,2 +54,22 @@ 'claude-haiku-4-5': {

},
'command-r': {
rate: { inputPer1k: 0.00015, outputPer1k: 0.0006 },
descriptor: {
contextWindow: 128_000,
id: 'command-r',
maxOutputTokens: 4096,
pricingSource: 'local',
provider: 'cohere',
},
},
'command-r-plus': {
rate: { inputPer1k: 0.0025, outputPer1k: 0.01 },
descriptor: {
contextWindow: 128_000,
id: 'command-r-plus',
maxOutputTokens: 4096,
pricingSource: 'local',
provider: 'cohere',
},
},
};

@@ -47,0 +76,0 @@ // Raw models.dev catalog data has no explicit status field; infer "preview" from

@@ -1,1 +0,1 @@

{"version":3,"file":"rates.js","sourceRoot":"","sources":["../src/rates.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"rates.js","sourceRoot":"","sources":["../src/rates.ts"],"names":[],"mappings":"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"}

@@ -7,3 +7,3 @@ import type { Format, Provider, TokenizeResult, TokenizerKind } from './types.js';

}
export declare const countTokens: (text: string, provider: Provider) => CountResult;
export declare const countTokens: (text: string, provider: Provider, modelId?: string) => CountResult;
export interface TokenizeOptions {

@@ -10,0 +10,0 @@ format: Format;

@@ -1,1 +0,1 @@

{"version":3,"file":"tokenize.d.ts","sourceRoot":"","sources":["../src/tokenize.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAWlF,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,UAAU,QAAQ,KAAG,WAa9D,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,QAAQ,GAAI,SAAS,eAAe,KAAG,cAenD,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,cAAc,GAAI,SAAS,qBAAqB,KAAG,cAAc,EAQ7E,CAAC"}
{"version":3,"file":"tokenize.d.ts","sourceRoot":"","sources":["../src/tokenize.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAalF,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,OAAO,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,EAAE,UAAU,QAAQ,EAAE,UAAU,MAAM,KAAG,WA0BhF,CAAC;AAEF,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,QAAQ,GAAI,SAAS,eAAe,KAAG,cAenD,CAAC;AAEF,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,eAAO,MAAM,cAAc,GAAI,SAAS,qBAAqB,KAAG,cAAc,EAQ7E,CAAC"}

@@ -5,9 +5,13 @@ import { encode as encodeCl100k } from 'gpt-tokenizer/encoding/cl100k_base';

import { getModel, getRate } from './rates.js';
import { cohereCount } from './tokenize-cohere.js';
import { mistralCount } from './tokenize-mistral.js';
const HEURISTIC_CHARS_PER_TOKEN = {
anthropic: 3.5,
cohere: 4,
google: 4,
mistral: 4,
openai: 4,
};
const heuristicCount = (text, provider) => Math.ceil(text.length / HEURISTIC_CHARS_PER_TOKEN[provider]);
export const countTokens = (text, provider) => {
export const countTokens = (text, provider, modelId) => {
switch (provider) {

@@ -24,2 +28,15 @@ case 'openai':

};
case 'mistral': {
// SentencePiece for v1/v2/v3 families; chars/4 heuristic for Tekken
// (NeMo, Pixtral, Devstral, Magistral, Ministral, Mistral Medium 2505+).
// See tokenize-mistral.ts for the full split.
const r = mistralCount(text, modelId ?? '');
return { approximate: r.approximate, count: r.tokens, tokenizer: r.tokenizer };
}
case 'cohere': {
// Cohere SDK is REST-only; no offline tokenizer ships in JS today.
// Empirical mode hits POST /v1/tokenize for exact counts.
const r = cohereCount(text);
return { approximate: r.approximate, count: r.tokens, tokenizer: r.tokenizer };
}
}

@@ -31,3 +48,3 @@ };

const converted = toFormat(options.prompt, options.format);
const counted = countTokens(converted, model.provider);
const counted = countTokens(converted, model.provider, model.id);
const inputCost = (counted.count / 1000) * rate.inputPer1k;

@@ -34,0 +51,0 @@ return {

@@ -1,1 +0,1 @@

{"version":3,"file":"tokenize.js","sourceRoot":"","sources":["../src/tokenize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAC5E,OAAO,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAG/C,MAAM,yBAAyB,GAA6B;IAC1D,SAAS,EAAE,GAAG;IACd,MAAM,EAAE,CAAC;IACT,MAAM,EAAE,CAAC;CACV,CAAC;AAEF,MAAM,cAAc,GAAG,CAAC,IAAY,EAAE,QAAkB,EAAU,EAAE,CAClE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,yBAAyB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAQ/D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,IAAY,EAAE,QAAkB,EAAe,EAAE;IAC3E,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,QAAQ;YACX,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;QAC1F,KAAK,WAAW;YACd,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;QAC3F,KAAK,QAAQ;YACX,OAAO;gBACL,WAAW,EAAE,IAAI;gBACjB,KAAK,EAAE,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC;gBACrC,SAAS,EAAE,WAAW;aACvB,CAAC;IACN,CAAC;AACH,CAAC,CAAC;AAQF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAwB,EAAkB,EAAE;IACnE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,SAAS,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,WAAW,CAAC,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IACvD,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC;IAC3D,OAAO;QACL,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,SAAS;QACT,WAAW,EAAE,OAAO,CAAC,KAAK;QAC1B,KAAK,EAAE,KAAK,CAAC,EAAE;QACf,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;KAC7B,CAAC;AACJ,CAAC,CAAC;AAQF,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAA8B,EAAoB,EAAE;IACjF,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,KAAK,MAAM,OAAO,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACvC,KAAK,MAAM,MAAM,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;QACtE,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC,CAAC"}
{"version":3,"file":"tokenize.js","sourceRoot":"","sources":["../src/tokenize.ts"],"names":[],"mappings":"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"}

@@ -1,2 +0,2 @@

export type Provider = 'anthropic' | 'openai' | 'google';
export type Provider = 'anthropic' | 'cohere' | 'google' | 'mistral' | 'openai';
export type Format = 'json' | 'markdown' | 'text' | 'xml' | 'yaml';

@@ -15,2 +15,19 @@ export interface ModelDescriptor {

}
export interface LatencyTrial {
ttftMs: number;
totalMs: number;
outputTokens: number;
tokensPerSec: number;
}
export interface LatencyStats {
ttftMs: number;
totalMs: number;
tokensPerSec: number;
}
export interface LatencyResult {
trials: LatencyTrial[];
p50: LatencyStats;
p95: LatencyStats;
mean: LatencyStats;
}
export interface TokenizeResult {

@@ -24,4 +41,5 @@ approximate: boolean;

tokenizer: TokenizerKind;
latency?: LatencyResult;
}
export type TokenizerKind = 'cl100k_base' | 'heuristic' | 'o200k_base';
export type TokenizerKind = 'cl100k_base' | 'heuristic' | 'mistral_v1_v3' | 'o200k_base';
export interface EmpiricalResult extends TokenizeResult {

@@ -28,0 +46,0 @@ cachedInputTokens: number;

@@ -1,1 +0,1 @@

{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;CACvC;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,aAAa,CAAC;CAC1B;AAED,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,WAAW,GAAG,YAAY,CAAC;AAEvE,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;CAC5B"}
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEhF,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,QAAQ,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,GAAG,WAAW,CAAC;CACvC;AAED,MAAM,WAAW,SAAS;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAKD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,YAAY,EAAE,CAAC;IACvB,GAAG,EAAE,YAAY,CAAC;IAClB,GAAG,EAAE,YAAY,CAAC;IAClB,IAAI,EAAE,YAAY,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,aAAa,CAAC;IAIzB,OAAO,CAAC,EAAE,aAAa,CAAC;CACzB;AAED,MAAM,MAAM,aAAa,GAAG,aAAa,GAAG,WAAW,GAAG,eAAe,GAAG,YAAY,CAAC;AAEzF,MAAM,WAAW,eAAgB,SAAQ,cAAc;IACrD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kBAAkB,EAAE,MAAM,CAAC;CAC5B"}
{
"name": "@tokenometer/core",
"version": "0.0.5",
"description": "Empirical token-cost benchmarking for LLM prompts — core library (tokenizers, format converters, rate matrix, empirical countTokens dispatch).",
"version": "0.1.0",
"description": "Tokenometer core library — multi-provider LLM token cost, latency, and vision-token estimation with empirical countTokens fallback (Anthropic, OpenAI, Google, Mistral, Cohere).",
"license": "MIT",

@@ -19,13 +19,43 @@ "author": "Faraazuddin Mohammed <mohdfaraaz1@gmail.com>",

"anthropic",
"ci-cd",
"cl100k",
"claude",
"cl100k",
"claude-code",
"claude-code-skill",
"code-scanning",
"codestral",
"cohere",
"command-r",
"cost",
"cost-calculator",
"cursor",
"gemini",
"github-action",
"gpt",
"gpt-4o",
"latency",
"llm",
"llm-cost",
"mistral",
"mistral-7b",
"mistral-large",
"mixtral",
"model-comparison",
"multimodal",
"o200k",
"openai",
"pixtral",
"prompt",
"prompt-cost",
"prompt-cost-regression",
"prompt-engineering",
"prompt-regression",
"sarif",
"tiktoken",
"token",
"tokenizer"
"token-budget",
"tokenizer",
"ttft",
"vision-tokens",
"vscode"
],

@@ -41,6 +71,3 @@ "type": "module",

},
"files": [
"dist",
"README.md"
],
"files": ["dist", "README.md"],
"publishConfig": {

@@ -61,4 +88,5 @@ "access": "public",

"gpt-tokenizer": "^3.4.0",
"mistral-tokenizer-js": "^1.0.0",
"tokenlens": "^1.3.1",
"yaml": "^2.6.1"
"yaml": "^2.8.4"
},

@@ -65,0 +93,0 @@ "devDependencies": {

+103
-4
# @tokenometer/core
> Core library powering [tokenometer](https://www.npmjs.com/package/tokenometer): tokenizer dispatch, format converters, versioned cost rate matrix, and an empirical-mode `countTokens` adapter for Anthropic, OpenAI, and Google.
[![npm @tokenometer/core](https://img.shields.io/npm/v/@tokenometer/core.svg?label=@tokenometer/core)](https://www.npmjs.com/package/@tokenometer/core)
[![License: MIT](https://img.shields.io/github/license/faraa2m/tokenometer.svg)](https://github.com/faraa2m/tokenometer/blob/main/LICENSE)
> Core library powering [tokenometer](https://www.npmjs.com/package/tokenometer): tokenizer dispatch, format converters, versioned cost rate matrix, vision-token estimators, latency measurement, SARIF emitter, config loader, and an empirical-mode `countTokens` adapter for Anthropic, OpenAI, Google, Mistral, and Cohere.
See the [root README](https://github.com/faraa2m/tokenometer#readme) for findings, methodology, and the full project overview.
[**Live playground**](https://tokenometer.vercel.app) · [Source](https://github.com/faraa2m/tokenometer) · MIT
If you just want a CLI, `npm install -g tokenometer`. This package is for programmatic use.
If you just want a CLI, `npm install -g tokenometer`. This package is for programmatic use — it's the engine the CLI, the GitHub Action, the VS Code / Cursor extension, and the playground all share, so counts and pricing stay identical across every surface.

@@ -13,11 +18,28 @@ ## API

import {
// Core tokenization
tokenize,
tokenizeMatrix,
countTokens,
// Empirical (real provider countTokens / tokenize endpoints)
tokenizeEmpirical,
tokenizeMatrixEmpirical,
countTokens,
// Latency benchmarking
measureLatency,
nthPercentile,
// Format conversion
toFormat,
isFormat,
allFormats,
// Config (.tokenometer.yml)
loadConfig,
parseConfig,
// SARIF + JSON emitter
toSarif,
// Vision-token estimators
anthropicVisionTokens,
openaiVisionTokens,
googleVisionTokens,
// Pricing / model registry
KNOWN_MODELS,
MODELS,
RATES,

@@ -28,2 +50,34 @@ RATES_VERSION,

} from '@tokenometer/core';
import type {
// Token results
CountResult,
TokenizeResult,
EmpiricalResult,
EmpiricalCountResult,
EmpiricalEnv,
// Latency
LatencyResult,
LatencyTrial,
LatencyStats,
LatencyDeps,
MeasureLatencyOptions,
// Aggregates / formatters
TokenometerResult,
TokenometerFileResult,
ToSarifOptions,
// Config
TokenometerConfig,
ConfigFormat,
// Vision input shapes
AnthropicVisionInput,
OpenAIVisionInput,
GoogleVisionInput,
// Registry
ModelDescriptor,
Provider,
RateEntry,
Format,
TokenizerKind,
} from '@tokenometer/core';
```

@@ -62,8 +116,53 @@

### Latency benchmarking
```ts
const stats = await measureLatency({
modelId: 'claude-opus-4-7',
prompt: 'Write a haiku about CI.',
trials: 3,
env: { anthropicApiKey: process.env.ANTHROPIC_API_KEY! },
});
// LatencyResult: { trials: LatencyTrial[], stats: { ttftMs, totalMs, tokensPerSec } }
// Each stat is { p50, p95, mean }.
```
Supported providers: Anthropic (`messages.stream`), OpenAI (`/v1/chat/completions` SSE), Google (`generateContentStream`), Cohere (`/v1/chat` NDJSON), Mistral (`/v1/chat/completions` SSE). Each call is capped at `max_tokens=200`; trials retry once on transient failures.
### Vision tokens
```ts
const tokens = anthropicVisionTokens({ width: 1280, height: 720 });
// 1228 (capped at 1600 for very large images)
```
The `openaiVisionTokens` and `googleVisionTokens` exports are formula-equivalent to the OpenAI high-detail tile cost and Gemini's 258-per-768²-tile cost respectively.
### SARIF + JSON output
```ts
const sarif = toSarif({ files: [{ path: 'prompt.md', results: [...] }] });
// SARIF 2.1.0 — drop into GitHub Code Scanning or any SARIF viewer.
```
### Rate table
`RATES` is a `Record<modelId, { inputPer1k, outputPer1k, cachedInputPer1k? }>`. `RATES_VERSION` ships as a date string so consumers can pin or audit.
`RATES` is a `Record<modelId, { inputPer1k, outputPer1k, cachedInputPer1k? }>`. `RATES_VERSION` ships as a date string so consumers can pin or audit. `KNOWN_MODELS` is the union (currently 63 across 5 providers).
## Providers
| Provider | Models | Offline tokenizer | Exactness | Empirical (`tokenizeEmpirical`) |
|-----------|--------|-------------------|-----------|----------------------------------|
| OpenAI | `gpt-4o`, `gpt-4o-mini`, `gpt-4-turbo`, `gpt-3.5-turbo`, `o1` family | `gpt-tokenizer` `o200k_base` | exact | same `o200k_base` (matches production) |
| Anthropic | `claude-opus-4-7`, `claude-sonnet-4-6`, `claude-haiku-4-5`, Claude 3.x family | `gpt-tokenizer` `cl100k_base` | approximate | `messages.countTokens` (free, exact) |
| Google | `gemini-2.5-pro`, `gemini-2.5-flash`, `gemini-1.5-pro`, `gemini-1.5-flash` | `chars / 4` heuristic | approximate | `model.countTokens` (free, exact) |
| Mistral (19 models) | `open-mistral-7b`, `open-mixtral-8x22b`, `mistral-large-latest`, `codestral-latest`, `mistral-nemo`, `pixtral-large-latest`, `mistral-medium-2505`, `magistral-small`, `ministral-3b-latest`, `devstral-small-2505` | `mistral-tokenizer-js` (V1/V2/V3 SentencePiece); `chars/4` for Tekken family (NeMo, Pixtral, Mistral Small 2409+, Devstral, Mistral Medium 2505+, Magistral, Ministral) | exact for SentencePiece · approximate for Tekken | unsupported (no public token-count endpoint) |
| Cohere | `command-r`, `command-r-plus` | `chars / 4` heuristic | approximate | `POST /v1/tokenize` (free, exact, requires `COHERE_API_KEY`) |
Pricing comes from `@tokenlens/models` plus a small `LOCAL_OVERRIDES` map for bleeding-edge models the registry hasn't picked up yet. Cohere lives entirely in `LOCAL_OVERRIDES` because `@tokenlens/models` does not yet ship a Cohere catalog at v1.3.0; pull from `cohere.com/pricing` whenever `RATES_VERSION` bumps.
Internally the dispatch helpers `mistralCount`, `cohereCount`, `cohereTokenizeApi`, and `isTekken` (in `tokenize-mistral.ts` / `tokenize-cohere.ts`) are not part of the public API — they're called from `tokenize` / `tokenizeEmpirical`. If you need them, import the files directly; they may move.
## License
MIT