@tokenometer/core
Advanced tools
| 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"} |
+120
| 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"} |
+375
| // 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"} |
@@ -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 +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"} |
+27
-1
@@ -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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"} |
+13
-1
@@ -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"} |
+6
-0
@@ -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"} |
+1
-1
| 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"} |
+31
-2
| 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"} |
+19
-2
@@ -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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"} |
+20
-2
@@ -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"} |
+37
-9
| { | ||
| "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. | ||
| [](https://www.npmjs.com/package/@tokenometer/core) | ||
| [](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 |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
120102
200.21%58
123.08%1483
230.29%166
147.76%7
16.67%1
Infinity%9
Infinity%+ Added
+ Added
Updated