PUBLIC MODULE · lib/context.js
Agent.Context
lib/context.js — Context: the shared conversation data model.
PUBLIC MODULE (owner of lib/context/). At the bottom of the dependency chain, it imports no other public module; Env, IO, Agent, CLI, and TUI depend on it, never the reverse. Private helpers live in lib/context/; consumers use this façade's named exports or the Context class (instances are stateful contexts; statics are the data model).
class Context class
The conversation context: an ordered message list (a private array — read it through length/at/messages()/iteration, change it through the methods below), optionally NAMED (id/name) and LOGGED to a session file in dir (save). Crash safety is the owner's: an Agent flushes its context from a process-finish hook.
Defined in lib/context/store.js
append(message, options) method
Append a message, MERGING with the last one when possible (consecutive same-type messages / same-sub-type blocks fold — Context.appendMessage); {merge: false} keeps a boundary.
messageobject
Returns object|undefined — the stored message, or `undefined` when an empty message is skipped
at(i) method
The message at index i (negative counts from the end).
inumber
Returns object|undefined
blockAt(i, j) method
Block j of message i (RangeError when either index is out of range).
inumberjnumber
Returns object
close() method
Flush and close; subsequent mutations fail. Flush errors propagate and leave the context open.
Returns Promise<void> — Resolves once durable; on failure reopens for retry.
constructor(options = {…}) constructor
Create a context, optionally named and logged (the file is created on the first flush of a started conversation).
[options]Object[options.id]string|false- session id (default: random UUID); false, "0", "false", "anon" normalize to an anonymous context with no id or logging
[options.dir]string- the sessions folder (env.settings.sessions); required to log
[options.messages]Array- initial messages, deep-copied into this context; no objects are shared with another context
[options.origin]string- the folder the session RUNS in (default: process.cwd()) — recorded in the file's metadata line; resume's scans list only sessions of the current folder
[options.uuid]string- carry an existing sessionUUID forward (Context.resume() only — a fresh session always gets a new one)
[options.name]string- carry an existing stored NAME forward (Context.resume() only — see the module doc)
[options.settings]object- the session-owned agent settings snapshot (Agent-managed; see the settings setter)
[options.save]boolean- whether the context is logged to disk (default: whenever a `dir` is given); false or an anonymous id keeps it in memory
Throws — {TypeError} Invalid options container or unknown own top-level key (including symbols) before reading metadata or creating a folder; stored settings remain unrestricted.
contextUsage property
Read: get contextUsage()
Provider-reported context consumption and model window (tokens). A stable immutable snapshot until the next accepted report or invalidation; identity changes even when a report repeats the same numbers. Values survive replacing IO and are not persisted.
Returns {used: number|undefined, total: number|undefined} — The current Context's report.
Effects — None.
Write: set contextUsage({ used, total } = {…})
Merge a provider report into this conversation. Nonnegative finite used and positive finite total values are floored; invalid values do not replace previous data.
Returns void — No result.
Effects — Updates in-memory Context usage; reports survive changing transport IO.
contextUsageInvalidate({ window = false } = {…}) method
Invalidate exact input consumption after structural changes (e.g. compaction). On a different model identity, also discard the old model's window; an IO replacement for the same model does not require invalidation.
Returns void — No result.
Effects — Clears in-memory `used`, and optionally `total`; does not affect quota or persisted messages.
created property
Read: get created()
Creation timestamp in ISO form.
Returns string — Creation timestamp in ISO form.
static deleteAll({ dir } = {…}) method
Delete EVERY session file in the folder (the /sessions-delete-all! contract — the user confirmed; foreign files stay untouched).
[options]Object[options.dir]string
Returns {deleted: number}
static deleteById({ id, dir } = {…}) method
Permanently delete a STORED session by id: every session file whose metadata carries that id (a leftover duplicate goes with it). A store still holding it open would re-persist it — close it first.
optionsObjectoptions.idstring[options.dir]string
Returns {deleted: number}
dir property
Read: get dir()
Session logging directory.
Returns string|undefined — Session logging directory.
dirty property
Read: get dirty()
Where the context changed since its entries were last accepted: false when nothing did, else the index of the first changed entry (an edit, insertion, removal or reorder there; may be 0). Every append accepts the current entries again, except a changed message that still carries replay data (provider fields on text, thinking or tool-call blocks, such as a thinking signature): that one stays dirty until the replay data is removed, so a provider sees an edit of history it already answered even when new messages followed. Removing trailing entries is not a change.
Returns false|number
edit(i, message) method
Replace message i (rebuilt from recognized fields; stale provider identifiers dropped).
inumbermessageobject
Returns object — the stored message
editBlock(i, j, block) method
Replace block j of message i (the message is rebuilt).
inumberjnumberblockobject
Returns object — the stored block
errorPop() method
Retract a trailing FAILED RESPONSE before the context is submitted again: an assistant message carrying error that is still the last message was not responded to — the user continued as it stands — so it goes and the request is re-attempted. Anything added after it (a user reply) keeps it: then it is part of the conversation.
Returns object|undefined — the removed message
file property
Read: get file()
Backing session file, when a logging directory exists.
Returns string|undefined — Backing session file, when a logging directory exists.
static fileOf({ id, dir } = {…}) method
The session file holding id in dir (a metadata-line scan), or undefined.
Returns string|undefined
flush() method
Synchronously make the CURRENT context durable (choosing remove, none, append or full rewrite). Idempotent; a no-op when nothing changed since the last flush. Filesystem errors propagate.
Returns void
flushAsync() method
Async counterpart for a live loop (Agent's request/tool turns); the synchronous flush() remains the crash/exit contract. "remove"/"append" plans are tiny and interleave-free, so they commit synchronously; only a "full" rewrite yields, snapshotting one version so a mutation while I/O is pending remains dirty for the following flush rather than being lost. I/O errors reject the returned promise.
Returns Promise<void>
id property
Read: get id()
Canonical identifier; undefined for anonymous memory-only contexts. Use rename() to name one.
Returns string|undefined — Canonical identifier; undefined for anonymous memory-only contexts. Use rename() to name one.
static latest({ dir, cwd } = {…}) method
The id of the most recently modified session in the folder (of the cwd origin when given), or undefined when the folder has none.
[options]Object[options.dir]string[options.cwd]string- only sessions of THIS origin folder
Returns string|undefined
length property
Read: get length()
the message count
Returns number — the message count
static list({ dir, cwd, limit = 50 } = {…}) method
Every session in the folder, LATEST FIRST (one entry per id), each with a small preview: the first meaningful line of the first user message (see meaningfulLine; whitespace-folded, capped) and agent, the stored agent name when it is not a default agent-N one. With cwd, only sessions whose metadata records THAT origin folder list (the resume contract: a project sees its own sessions; foreign metadata-less files are skipped by the FIRST-LINE scan, never parsed in full). Previews are read only for the newest limit files (stats are cheap; parsing is not). Unreadable files list without a preview, never an error.
[options]Object[options.dir]string[options.cwd]string- only sessions of THIS origin folder
[options.limit]number- max sessions returned (default 50)
Returns Array<{id: string, file: string, mtime: number, messages: number, preview: string, agent?: string}>
static listAsync({ dir, cwd, limit = 50 } = {…}) method
Nonblocking counterpart of list(). It deliberately has its own async folder identity rather than calling sameFolder(), whose realpathSync would stall the interactive loop.
Returns Promise<Array<{id: string, file: string, mtime: number, messages: number, preview: string, agent?: string}>>
messages() method
A new array of LIVE message objects. Mutating a message changes this context only, without marking it dirty; use edit/update for persistence bookkeeping. Construction deep-copies seeds, so forks never share message objects.
Returns object[] — A new array of LIVE message objects. Mutating a message changes this context only, without marking it dirty; use edit/update for persistence bookkeeping. Construction deep-copies seeds, so forks never share message objects.
name field
Stored or automatically derived session label; remains writable.
Returns string|undefined — Stored or automatically derived session label; remains writable.
origin property
Read: get origin()
Origin project folder recorded in metadata.
Returns string — Origin project folder recorded in metadata.
static originOf({ id, dir } = {…}) method
The ORIGIN FOLDER recorded in a session file's metadata line (the cwd the session ran in), or undefined (no such session). A session resumes only in an Env of this folder; an explicit --resume <id> makes it the process cwd before the Env is built.
optionsObjectoptions.idstring[options.dir]string
Returns string|undefined
planUsage property
Read: get planUsage()
Last complete provider quota/metadata deep snapshot. Replaces reports; never persisted.
Write: set planUsage(report = {…})
Replace a provider report with an independent bounded canonical snapshot. Canonical quota fields outrank count/percentage and snake-case aliases; windowSeconds is a duration, never a reset. Known Anthropic unified header details become window/account state; unconsumed details remain available.
[report={}]object- Complete plan report; neither mutated nor retained.
Returns void — No result. Idempotent; no failures for JSON data.
Effects — Replaces in-memory quotas/metadata only; never persisted or added to Agent lifetime totals.
pop() method
the removed last message
Returns object|undefined — the removed last message
prepend(messages) method
Insert messages at the FRONT — e.g. an Agent's seeded system prompt, always the first message(s) of a fresh context.
messagesobject[]
remove(indexes) method
Remove the messages at indexes.
indexesnumber[]
Returns object[] — the removed messages
rename(newId) method
Rename the session: BOTH the stable id and the file's NAME segment become newId (the same session — the date/uuid8 prefix carries over unchanged) and the old file is gone. Refuses to clobber an EXISTING other session (a directory scan by id, the file name no longer being a direct function of it).
newIdstring
Returns {id: string, file: string}
static renameById({ id, name, dir } = {…}) method
Rename a STORED session by id (the sidebar/menu path for a session no store holds open — a live one renames through its store): loads it, renames it (see rename()) and closes it again.
optionsObjectoptions.idstringoptions.namestring- the new id/name
[options.dir]string
Returns {id: string, file: string}
Throws — {Error} when no such session exists or the name is taken
static resume({ id, dir, save = true } = {…}) method
Load a session file into a fresh store holding its live context. The file is found by a directory scan matching id against each file's metadata line (the file name is a presentation detail, not a direct function of id — see the module doc). Non-message records in the file are quietly ignored (tolerant reader — see loadMessages).
optionsObjectoptions.idstring[options.dir]string[options.save=true]boolean- whether the resumed context keeps logging
Returns Context — the loaded context
rollback(i) method
Remove every message at index >= i (RangeError unless i is an existing index).
inumber
Returns object[] — the removed messages
save property
Read: get save()
whether this context is logged to disk
Returns boolean — whether this context is logged to disk
Write: set save(value)
Enable or disable persistence without replacing the live context. Enabling saving gives an anonymous context a fresh id and makes the complete current context eligible for the next flush.
valueboolean
Returns void — Read save after assignment for the logging state.
settings property
Read: get settings()
the owner's settings snapshot riding the session file (undefined: none recorded — resume keeps the caller's configuration)
Returns object|undefined — the owner's settings snapshot riding the
session file (undefined: none recorded — resume keeps the caller's
configuration)
Write: set settings(value)
Record the owner's SETTINGS snapshot (an Agent's (safe, thinking, endpoint/model, name, … — Agent writes it; the store only persists it; a default agent-N name never rides the file). Only JSON-typed values ride the file; undefined entries are dropped. Marks the store dirty (the next flush is a FULL rewrite: the metadata line changes).
valueobject
summary property
Read: get summary()
one line for status/command output: <id> — <file> while logging, <id> — not logged (memory only) otherwise
Returns string — one line for status/command output:
`<id> — <file>` while logging, `<id> — not logged (memory only)` otherwise
toJSON() method
JSON form: the message array.
update(fn) method
A batch in-place change (a repair pass): fn receives the live message array and returns true when it changed anything — the context then logs a full rewrite. Stored messages are replaced, never mutated.
fn(messages: object[]) => boolean
Returns boolean — whether anything changed
uuid property
Read: get uuid()
Persistent session UUID.
Returns string — Persistent session UUID.
ContentType = Object.freeze({…}) constant
Content block discriminators.
Defined in lib/context/types.js
EventType = Object.freeze({…}) constant
The full normalized event vocabulary.
Defined in lib/context/events.js
FALLBACK_CONTEXT_WINDOWS = Object.freeze({…}) constant
Curated context windows for the CURRENT OpenAI tier, from the models docs (developers.openai.com/api/docs/models, reviewed 2026-09-28 — the gpt-6 family lists 1.05M; o-series 200K). OpenAI's API-key surface publishes NO window anywhere (/models, /models/{id}, and the response envelope are all bare — probed with ai-tmp/probe-openai-models.js), so the status gauge reads this table while a lazy registry lookup (lib/env/model-windows.js) fills the endpoint's model cache. Any provider-published or looked-up value outranks it. Review when a new tier ships.
Defined in lib/context/usage.js
MIME_BY_EXTENSION = Object.freeze({…}) constant
Context-owned media-type map and byte detection for content blocks.
Defined in lib/context/mime.js
MessageType = Object.freeze({…}) constant
Numeric message types. 0 is reserved.
Defined in lib/context/types.js
TOKENS_PER_WORD = 4 / 3 constant
tokens ≈ words × 4/3 (token-per-word likelihood ratio)
Defined in lib/context/usage.js
assemblyCallbacks(assembler) function
Build the camelCase callback set used by Context to feed response events to an assembler. Includes callbacks for start, text/thinking block events, tool-call events, done, and error.
assemblerReturnType<typeof createAssembler>- Assembler receiving the events; no default is provided.
Returns Object<string, function(object): void> — Callbacks keyed by names
such as `onStart`, `onTextDelta`, `onDone`, and `onError`.
Effects — Creates a new callback object; each callback delegates to assembler.consume and therefore mutates that assembler.
Throws — Throws if assembler is missing or does not provide consume, or if event processing throws when a callback is invoked.
Defined in lib/context/assemble.js
createAssembler() function
Create an assembler that folds normalized response events into one assistant message. Events mutate the in-progress message; valid message snapshots on start, done, or error replace it. Unknown event types are ignored, and malformed tool-call JSON is retained as raw text. The returned message remains partial until completion and is exposed by reference.
Returns {consume: (event: object) => void, message: () => object} — The
event consumer and accessor for the current message.
Throws — Creating the assembler does not intentionally throw. Its returned `consume` method can propagate errors from malformed events or message mutations; JSON parse errors for tool arguments are suppressed.
Defined in lib/context/assemble.js
normalizeCallbacks(callbacks = {…}, binding = {…}) function
Build the full callback set for a binding.
[callbacks={}]Object- consumer-supplied callbacks, keyed by camelCase callback name. A function is used as-is; explicit `false` or `null` selects a no-op; an omitted or `undefined` callback gets the binding default.
[binding={}]Object- binding-appropriate default handlers.
[binding.onData](event:object)=>void- receives every event whose callback was omitted (stdout replacement)
[binding.onLog](line:string)=>void- receives error reports (stderr replacement)
[binding.onTerminal](event:object)=>void|false|null- completes the binding; called for `done` and `error` even when the consumer supplied its own terminal callback. `false` or `null` disables this additional call.
Returns Object — Complete callback set keyed by camelCase names.
Throws — {Error} If an invoked binding handler throws; its error propagates to the caller.
Defined in lib/context/events.js
binaryContent(path, buffer) function
Build a canonical base64 binary Context block without exposing the source path.
pathstring- Non-empty local path; only its basename is retained.
bufferUint8Array- Binary data to encode.
Returns {type: "binary", mimetype: string, filename: string, content: string} — A block containing the basename, detected media type, and base64 data.
Throws — {TypeError} If path is not a non-empty string or buffer is not a Uint8Array.
Defined in lib/context/mime.js
contentIndexer() function
Create a per-request content-block indexer for a provider translator. of reuses an index for a previously seen wire-item key, while next always reserves a fresh index; indexes are dense and follow first appearance.
Returns {of: (key: *) => number, next: () => number} — Indexing operations.
Defined in lib/context/assemble.js
textContent(text) function
Wrap a value's string representation in a text content block.
text*- Value converted with `String()`.
Returns TextContent — A block with `type: ContentType.Text` and the converted text.
Throws — {*} Propagates a thrown value encountered during string conversion.
Defined in lib/context/types.js
callbackName(eventName) function
Map an event name to its camelCase callback name. "text_delta" -> "onTextDelta"; "tool_call_start" -> "onToolCallStart".
eventNamestring- normalized event name to convert.
Returns string — The corresponding camelCase callback name.
Throws — {TypeError} If `eventName` does not support `split` (for example, it is not a string).
Defined in lib/context/events.js
dispatch(set, event) function
Dispatch one event through a normalized callback set. Validates the event before invoking its matching callback; callback errors propagate to the caller.
setObject- callback set returned by `normalizeCallbacks`.
eventobject- normalized response event to dispatch.
Returns void
Throws — {TypeError} If `event` is invalid or the callback cannot be invoked; errors thrown by the callback also propagate unchanged.
Defined in lib/context/events.js
isResponseEvent(event) function
Is this a well-formed normalized response event (a known type; indexed events carry a non-negative integer contentIndex)?
event*- value to check.
Returns boolean — `true` for an object with a known event type and, for indexed events, a non-negative integer `contentIndex`; otherwise `false`.
Defined in lib/context/events.js
validateResponseEvent(event) function
Validate a normalized response event (used by IO to check connector output). Returns the same object; throws on violation.
event*- value to validate.
Returns object — The same event object when it is valid.
Throws — {TypeError} If the value is not a well-formed normalized response event.
Defined in lib/context/events.js
fallbackContextWindow(model) function
The curated fallback window for one model id, or null: an exact key, then the longest table prefix the id starts with ("gpt-6-sol" -> "gpt-6", "o3-2025-04-16" -> "o3").
model*- bare model id; non-string or empty values are rejected
Returns number|null — matching fallback token window, or `null` when none
Defined in lib/context/usage.js
appendMessage(context, message, { merge = true } = {…}) function
Append a message to a caller-owned context, MERGING when possible: the message's own adjacent same-sub-type blocks fold first; when the context's last message is mergeable with it (same type, no linkage), their content concatenates (and re-folds) instead of appending a new message. Consecutive same-type text messages — queued user input, repeated /system, a cancel-partial assistant followed by the next turn's — become ONE message, so the context (and every replay of it) shows one merged block per sub-type, not a chain of fragments. Mutates the array in place.
contextArray<object>- Caller-owned context array, mutated in place.
messageobject- Message or metadata record to append.
Returns object|undefined — The stored message (the previous message when merged, otherwise the appended value), or `undefined` when an empty message is skipped.
Throws — {TypeError} If context/message validation fails.
Throws — {TypeError} If folding or merge comparisons fail during processing.
Defined in lib/context/merge.js
assistantMessage(content = []) function
Create an assistant message using the supplied content blocks.
[content=[]Content[]- ] - Ordered content blocks; defaults to an empty array.
Returns Message — An assistant message whose content is the supplied array; no validation or copying is performed.
Defined in lib/context/types.js
errorText(msg) function
Get the presentation text of a normalized assistant failure; tool-result boolean errors are distinct and produce an empty string.
msg*- Value whose error field is inspected.
Returns string — The error string, `error.message`, or an empty string.
Defined in lib/context/validate.js
fileMessage(path, buffer) function
Wrap one local file's bytes in the canonical user-message content structure.
pathstring- Non-empty local file path passed to {@link binaryContent}.
bufferUint8Array- File bytes passed to {@link binaryContent}.
Returns {type: 2, content: Array<{type: "binary", mimetype: string, filename: string, content: string}>} — A user message containing a single binary content block.
Throws — {TypeError} If either argument fails {@link binaryContent}'s validation.
Defined in lib/context/mime.js
hasContent(msg) function
Has this message any CONTENT a provider can consume? A block with no payload — a text/thinking block whose text is empty, a block reduced to its discriminator alone — is not content; an empty content array is not content either. Chat-completions dialects serialize an empty assistant message as content: null and providers 400 the whole request over it (corrupted sessions), so emptiness is a hard contract, not a style point.
msg*- Value whose `content` blocks are inspected.
Returns boolean — True if at least one block carries provider-consumable content.
Defined in lib/context/validate.js
hasError(msg) function
Does this message report a FAILED RESPONSE? A provider or transport failure is normalized as the response message carrying error — a text string or {message, retry} for timed rate limits — beside whatever content arrived before it (possibly none: the error is then its whole payload). A tool result's boolean error: true is not one: that is the tool's own (answered) failure.
msg*- Value whose normalized response error is inspected.
Returns boolean — True for a nonempty error string or nonempty `error.message`.
Defined in lib/context/validate.js
isRecord(msg) function
Test whether a value is a metadata record: a non-array object with a string type (not a numeric message type). Records may share context and session files with messages; they are not messages and are skipped by message validators. Other components pass them through unmerged or filter them from provider-bound contexts as appropriate.
msg*- Value to test.
Returns boolean — True when `msg` carries a string `type`.
Defined in lib/context/validate.js
rebuildMessage(msg) function
Rebuild a message from recognized schema fields only — the stale provider/cache identifier cleanup. See the module header for the field policy.
msgobject- Message to validate and rebuild.
Returns object — A new message containing recognized fields only.
Throws — {TypeError} If the message is invalid.
Defined in lib/context/edit.js
systemMessage(text) function
Create a system message containing one text block made from the given value.
text*- Value converted to a string for the text block.
Returns Message — A system message with one text content block.
Throws — {*} Propagates a thrown value encountered during string conversion.
Defined in lib/context/types.js
userMessage(text, metadata = undefined) function
Create a user message from plain text or an existing ordered block array. Non-array input is converted to a text block; array input is used as-is. If supplied, metadata is spread over the message and can override its fields.
textstring|Content[]|*- Plain-text value to convert, or an array of content blocks to preserve.
[metadata=undefined]*- Optional value whose enumerable own properties are spread last onto the message.
Returns Message — The resulting user message.
Throws — {*} Propagates a thrown value from text conversion or metadata getters/spread.
Defined in lib/context/types.js
isMessage(msg) function
Test whether a value has the core message shape: a non-array object with a numeric type and an array content.
msg*- Value to test.
Returns boolean — True when `msg` has the core message shape.
Defined in lib/context/validate.js
validateMessage(msg, at = "message") function
Validate a message's CORE SHAPE, throwing on a violation. Returns the SAME object reference — metadata is never copied, stripped, or reordered. Emptiness is deliberately NOT part of the shape: appendMessage WARNS and drops an empty incoming message, and IO DROPS empty messages from every provider-bound context (no dialect can carry one), while a merge that consumed an incoming message's whole payload into the previous message may legitimately leave it empty inside the live array.
msg*- Value to validate.
[at="message"]string- Address hint for error messages (e.g. "context[2]").
Returns object — The same `msg` reference, unchanged.
Throws — {TypeError} If `msg` is not a non-array object with a numeric `type` and array `content`; the error includes the address hint.
Defined in lib/context/validate.js
parseContext(input) function
Parse buffered CLI input into a context array using the shared grammar. First, the entire input is parsed as JSON; if that is an array, it is returned unchanged. Otherwise, each nonblank line is parsed independently: message objects and valid messages in arrays are included, while other values become user text messages containing the original line.
inputstring- Complete stdin text after EOF; there is no default.
Returns Array<object> — The resulting context array. This is synchronous
and returns no Promise.
Throws — {TypeError} If input is not a string and line processing attempts to call `split` on it.
Effects — Pure parser: does not read stdin or otherwise perform I/O. JSON parse errors are caught and treated as non-JSON input.
Defined in lib/context/parse.js
isContext(ctx) function
Test whether a value is a context array containing only core-shaped messages and/or metadata records.
ctx*- Value to test.
Returns boolean — True when `ctx` is such an array; an empty array passes.
Defined in lib/context/validate.js
validateContext(ctx) function
Validate a context array, allowing metadata records and validating every other entry as a message. Returns the same array reference without mutation.
ctx*- Value to validate as a context.
Returns Array — The same `ctx` array, unchanged.
Throws — {TypeError} If `ctx` is not an array or any non-record entry fails message validation; entry errors identify their context index.
Defined in lib/context/validate.js
detectMime({ path, buffer } = {…}) function
Determine a media type from a filename extension, then recognized leading bytes.
Returns string — The matching media type, or `application/octet-stream` when
neither input identifies a supported type.
Throws — {TypeError} If options is `null` and therefore cannot be destructured.
Defined in lib/context/mime.js
mimetypeOf(block) function
Return a content block's media type, preferring its non-empty mimetype field and then its non-empty mime field.
blockObject|null|undefined- Block to inspect; nullish values are allowed.
Returns string|undefined — The selected media type, or `undefined` when neither field is a non-empty string.
Throws — {*} Propagates a thrown value from a getter for `mimetype` or `mime`; accessors may be read more than once.
Defined in lib/context/types.js
estimateTokens(text) function
Estimate a token count for text, rounding the heuristic up to a whole token. Non-string inputs produce zero.
text*- value to estimate when it is a string
Returns number — estimated whole-token count
Defined in lib/context/usage.js
estimateContextTokens(context = []) function
Estimated token count of a whole context (the input side of a request — also the live "window consumption" readout when no provider-reported count exists yet). Counts words per block: the historical one-giant-string + word-array version allocated several full copies of the context per call, per frame. Reuses per-block scans only while the current text/argument string values are unchanged; live in-place field and content-array edits are observed on the next call.
[context=[]Array- ] - context messages; each message's supported content-block text and arguments are counted
Returns number — estimated input tokens, rounded up to a whole token
Throws — {TypeError} if `context` is not iterable
Defined in lib/context/usage.js
usageAdd(total, reported) function
Add one request report to lifetime usage. Sum only schema counters; recompute totalTokens; replace (and clear absent) metadata/details with the latest report.
totalobject- Previous totals; neither mutated nor retained.
reported*- Request usage, normalized or wire-shaped; never retained.
Returns object — New independent totals. Non-idempotent: call once per billed attempt.
Effects — None. Invalid reports are ignored; no failures for JSON input.
Defined in lib/context/usage-data.js
usageDetails(value) function
Copy bounded JSON-safe usage/plan extensions, omitting invalid values, cycles, attribution and prototype keys. Limits: 256 nodes, depth 6, 16 array entries, 1024 characters/string, 128/key and 16K total text. Truncation adds no counters.
value*- Untrusted details; neither mutated nor retained.
Returns * — Independent bounded JSON value, or undefined for unsupported input.
Effects — None. Idempotent; no failures for JSON data. Work is bounded by these limits.
Defined in lib/context/usage-data.js
estimateUsage(context = [], message) function
Estimate usage from the request context and the assembled response.
[context=[]Array- ] - request messages used for input estimation
[message=undefined]object- assembled assistant message used for output estimation; its content text/arguments are concatenated before estimating
Returns {inputTokens:number, outputTokens:number, source:"estimate"} — estimated usage
Throws — {TypeError} if `context` is not iterable
Defined in lib/context/usage.js
finalizeUsage(reported, context, message) function
Normalize provider-reported usage, or fall back to estimation. Provider token counts win only as a complete pair: partial/invalid counts use estimation (no mixed token sources), retaining normalized counters, finite reported cost and bounded extensions. Input is neither mutated nor retained. Repeated calls with the same report/context/message are idempotent; no side effects.
reported*- connector-extracted usage; accepted only when both inputTokens and outputTokens (or known aliases) are nonnegative finite numbers. Known aliases are consumed; unknown fields become bounded latest-report details
[context=undefined]Array- request context for fallback input estimation; when omitted, the estimator's empty-array default applies
[message=undefined]object- assembled message for fallback output estimation
Returns {inputTokens:number, outputTokens:number, totalTokens:number, source:string, cost?:number, [key: string]: *} — independent canonical snapshot with reported or estimated token counts
Throws — {TypeError} if fallback estimation is needed and `context` is not iterable
Defined in lib/context/usage.js
usageHeaders(headers, { exclude = [] } = {…}) function
Capture bounded unrepresented rate-limit header extensions, excluding unrelated headers.
headersHeaders|object- Response headers exposing forEach; neither retained nor mutated; absent input returns an empty map.
[options={}]object- Header filtering options.
[options.exclude=[]string[]- ] Header names already represented as quotas, case-insensitive.
Returns Object<string, string> — Independent bounded header map. Idempotent, no side effects.
Throws — {TypeError} If exclude is not an array of strings; correct options before retrying.
Defined in lib/context/usage.js
usageNormalize(reported) function
Normalize a request's usage without estimating tokens. Canonical fields outrank aliases; cache/reasoning detail fields outrank legacy root fields, reasoning outranks thinking. All token counts include cached/reasoning subsets, not extras. Unknown extensions become bounded latest-report details; consumed aliases disappear.
reported*- Provider data; neither mutated nor retained. Invalid fields are omitted.
Returns object — Independent snapshot with nonnegative counters, finite reported cost,
derived totalTokens, optional serviceTier/inferenceGeo and bounded details. Idempotent.
Effects — None. No failures for JSON input; detail processing is bounded.
Defined in lib/context/usage-data.js
wordCount(text) function
Count runs of non-whitespace characters without allocating a split array. Non-string and empty inputs produce zero.
text*- value to count when it is a string
Returns number — number of whitespace-separated words
Defined in lib/context/usage.js