UNPKG

@juspay/neurolink

Version:

The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002

53 lines (52 loc) • 3.34 kB
/** * Reads token usage out of Qwen Code's own session transcripts. * * Layout, confirmed on a real machine: `~/.qwen/projects/<sanitized-cwd>/chats/ * <sessionId>.jsonl`, where the sanitized cwd is the absolute working-directory * path with every `/` replaced by `-` — the same convention Claude Code uses * for its own `~/.claude/projects` layout, which is unsurprising since Qwen * Code's chat-recording model traces back to the same lineage as Gemini CLI's. * `~/.qwen/projects/<slug>/` also holds a sibling `memory/` directory with a * `MEMORY.md` file and no JSONL, so the walk below is scoped to `chats/` * specifically rather than the whole project directory. * * The bundled CLI (`@qwen-code/qwen-code`, installed copy inspected directly) * references `parentSessionId` the same way Gemini CLI's engine does for * subagent transcripts, so this reader recurses under each project's `chats/` * directory at any depth rather than globbing one level — the same lesson * `claudeCodeReader.ts` already paid for. * * Each line is a flat record with `type`, `uuid`, and (for `type: "assistant"`) * a `model` and `usageMetadata` object shaped like Google's GenAI * `usageMetadata`: `promptTokenCount`, `candidatesTokenCount`, * `thoughtsTokenCount`, `totalTokenCount`, `cachedContentTokenCount`. On a real * machine, `totalTokenCount` equalled `promptTokenCount + candidatesTokenCount * + thoughtsTokenCount` exactly across all 21 real assistant records sampled — * so `thoughtsTokenCount` is additive into output, not a separate bucket. * * `cachedContentTokenCount` is a SUBSET of `promptTokenCount`, not disjoint — * confirmed by reading the installed CLI's own converters rather than * inferring from samples, because every real sample on this machine had zero * cache tokens. `buildAnthropicUsageMetadata` in * `chunks/anthropicContentGenerator-*.js` and the OpenAI-compatible converter * in `chunks/chunk-*.js` both derive `cachedContentTokenCount` from the * upstream response's own cache-read field and leave `promptTokenCount` as the * upstream's full prompt count — the cached portion is never added on top. So * `inputTokens` here is `prompt - cached`, matching the convention this * subsystem's `LocalUsageTotals` type expects (`inputTokens` + * `cacheReadTokens` must sum to the true prompt size without double-counting), * the same subtraction `codexReader.ts` does for the same reason. * * Cost is deliberately `unavailable`. Two independent reasons, either one * sufficient on its own: (1) no provider identifier is logged alongside the * model name, and Qwen Code is pluggable to arbitrary OpenAI- or * Anthropic-compatible backends — on the machine this was written against, the * model names logged were `claude-sonnet-4-5` and `claude-haiku-4-5`, i.e. this * particular install was routed through a custom/litellm endpoint rather than * Alibaba's own Qwen models, so even the model name does not reliably identify * a vendor to price against; (2) Qwen Code's own hosted models are commonly * used via a subscription/OAuth flow rather than metered API keys, the same * situation that keeps Codex's confidence `unavailable`. */ import type { LocalUsageReader } from "../types/index.js"; export declare function createQwenCodeReader(): Promise<LocalUsageReader>;