PUBLIC MODULE · lib/context.js

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 its static Context namespace.

parseInput(input) function

Parse a buffered input string (such as CLI input after EOF) into a context array.

class Context class

Canonical context module namespace; its API is exposed as static members.

MessageType = Object.freeze({…}) constant

Numeric message types. 0 is reserved.

Defined in lib/context/types.js

ContentType = Object.freeze({…}) constant

Content block discriminators.

Defined in lib/context/types.js

textContent(text) function

Wrap plain text in a text content block. @returns {TextContent}

Defined in lib/context/types.js

userMessage(text, metadata = undefined) function

user message wrapping text or preserving ordered blocks

Returns Message — user message wrapping text or preserving ordered blocks

Defined in lib/context/types.js

systemMessage(text) function

system message wrapping plain text

Returns Message — system message wrapping plain text

Defined in lib/context/types.js

assistantMessage(content = []) function

assistant message from content blocks

Returns Message — assistant message from content blocks

Defined in lib/context/types.js

mimetypeOf(block) function

Return a content block's canonical media type.

Defined in lib/context/types.js

MIME_BY_EXTENSION = Object.freeze({…}) constant

Context-owned media-type map and byte detection for content blocks.

Defined in lib/context/mime.js

detectMime({ path, buffer } = {…}) function

Detect a media type from a filename extension or recognized leading bytes.

Defined in lib/context/mime.js

binaryContent(path, buffer) function

Build a canonical base64 binary Context block without leaking its source path.

Defined in lib/context/mime.js

fileMessage(path, buffer) function

Wrap one local file's bytes as a canonical user message.

Defined in lib/context/mime.js

isMessage(msg) function

Is this a core-shaped message (a numeric type and a content array)?

msg *

Returns boolean — true when msg has the core message shape

Defined in lib/context/validate.js

isRecord(msg) function

Is this a metadata RECORD (a string type, never a numeric message type)? Records are harness/tool-owned data entries that may share the context array and the session file with messages (the note tool's compaction-surviving store backup is the first). A record is NEVER a message: validators skip it, appendMessage passes it through unmerged, IO filters it from every provider-bound context, and the session file's own session-metadata header record is the loader's one exclusion (it maps the file, it is not context content).

msg *

Returns boolean — true when msg carries a string `type`

Defined in lib/context/validate.js

isContext(ctx) function

Is this a context (an array of core-shaped messages and/or records)?

ctx *

Returns boolean — true when ctx is an array of messages/records

Defined in lib/context/validate.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 *

Returns boolean

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 REFUSES (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 *
[at] string
address hint for error messages (e.g. "context[2]")

Returns object — msg, unchanged

Defined in lib/context/validate.js

validateContext(ctx) function

Validate a context array. Returns the same array reference.

ctx *

Returns Array — ctx, unchanged

Defined in lib/context/validate.js

EventType = Object.freeze({…}) constant

The full normalized event vocabulary.

Defined in lib/context/events.js

callbackName(eventName) function

Map an event name to its camelCase callback name. "text_delta" -> "onTextDelta"; "toolcall_start" -> "onToolcallStart".

eventName string

Returns string

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 *

Returns boolean — true for a well-formed normalized response event

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 *

Returns object

Defined in lib/context/events.js

normalizeCallbacks(callbacks = {…}, binding = {…}) function

Build the full callback set for a binding.

[callbacks] Object
consumer-supplied callbacks. A function is used as-is; explicit false/null selects a no-op; undefined gets the binding default.
binding Object
binding-appropriate defaults
[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
completes the binding; fires on done/error even when the consumer supplied its own terminal callback (unless itself false/null)

Returns Object — complete callback set keyed by camelCase names

Defined in lib/context/events.js

dispatch(set, event) function

Dispatch one event through a (normalized) callback set.

set Object
callback set from normalizeCallbacks
event object
a normalized response event

Defined in lib/context/events.js

parseContext(input) function

Parse buffered CLI input into a context array per the shared grammar. Pure function — testable without a process.

input string
complete stdin text (post-EOF)

Returns Array<object> — context array of messages

Defined in lib/context/parse.js

createAssembler() function

Create an assembler that consumes normalized IO response events into one assistant message. The message is partial until done; at any point message() returns what has been assembled so far (this is what cancellation persists).

Returns {consume: (event: object) => void, message: () => object}

Defined in lib/context/assemble.js

assemblyCallbacks(assembler) function

The callback set (camelCase, matching lib/context/events.js) that assembles a response — Context "supplies the callback set".

assembler ReturnType<typeof createAssembler>

Returns Object — callbacks keyed onStart/onTextDelta/.../onDone/onError

Defined in lib/context/assemble.js

foldContent(content) function

Fold ADJACENT same-sub-type text/thinking blocks within one content array (a stream with repeated indexes, or a cross-message merge, can leave runs of them — one logical block should BE one block). Returns a NEW array (blocks themselves are shared unless folded).

content Array

Returns Array — folded content

Defined in lib/context/merge.js

mergeableMessages(a, b) function

Can two CONSECUTIVE messages merge into one? Same numeric type, never a ToolResult (each result's callId/name/error linkage is its own — merging would destroy call→answer addressing), and exactly matching metadata. Metadata is a message boundary when it differs: in particular, a subtype: "chat" message cannot merge with normal user input. System, user and assistant continuations may merge only when their non-message keys match.

a object
b object

Returns boolean

Defined in lib/context/merge.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.

context Array
caller-owned array
message object

Returns object — the stored message (the PREVIOUS one when merged)

Defined in lib/context/merge.js

at(context, i) function

Address a message: context[i], validated (throws on a bad integer index or shape).

context Array
i number

Returns object — context[i], validated

Defined in lib/context/edit.js

blockAt(context, i, j) function

Address a content block: context[i].content[j], validated (RangeError when j is out of range).

context Array
i number
j number

Returns object — context[i].content[j], validated

Defined in lib/context/edit.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.

msg object

Returns object — a NEW message object

Defined in lib/context/edit.js

rebuildBlock(block) function

Rebuild one content block per the module-header field policy.

block *

Returns object — a NEW block object

Defined in lib/context/edit.js

editMessage(context, i, newMessage) function

Replace context[i] with an edited message, rebuilt from recognized fields (stale provider/cache identifiers dropped). Mutates in place.

context Array
caller-owned array
i number
message index
newMessage object
the edited message

Returns object — the stored (rebuilt) message

Defined in lib/context/edit.js

editBlock(context, i, j, newBlock) function

Replace context[i].content[j] with an edited block. The containing message is rebuilt as well (stale message-level identifiers dropped); other blocks are preserved through block rebuild.

context Array
i number
j number
newBlock object

Returns object — the stored (rebuilt) block

Defined in lib/context/edit.js

rollbackTo(context, i) function

Roll back to index i: remove messages at index >= i. Mutates in place. Valid targets are exactly the existing indexes 0..length-1 — passing the count is out of range (never a silent no-op).

context Array
i number

Returns Array — the removed messages

Defined in lib/context/edit.js

pop(context) function

Remove and return the last message. Mutates in place.

context Array

Returns object|undefined — the removed message

Defined in lib/context/edit.js

removeMessages(context, indexes) function

Remove selected message indexes and return them in source order.

Defined in lib/context/edit.js

TOKENS_PER_WORD = 4 / 3 constant

tokens ≈ words × 4/3 (token-per-word likelihood ratio)

Defined in lib/context/usage.js

wordCount(text) function

@returns {number} whitespace-separated words

text string
@returns {number} whitespace-separated words

Defined in lib/context/usage.js

estimateTokens(text) function

@returns {number} estimated token count

text string
@returns {number} estimated 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.

[context] Array

Returns number

Defined in lib/context/usage.js

estimateUsage(context = [], message) function

Estimate usage from the request context and the assembled response.

[context] Array
request messages (input side)
[message] object
assembled assistant message (output side)

Returns {inputTokens:number, outputTokens:number, source:"estimate"}

Defined in lib/context/usage.js

finalizeUsage(reported, context, message) function

Normalize provider-reported usage, or fall back to estimation. Provider numbers win per-field only as a whole: a partial/invalid report is treated as absent (honest fallback, no mixed sources).

reported *
whatever the connector extracted
[context] Array
request context (fallback input side)
[message] object
assembled message (fallback output side)

Returns {inputTokens:number, outputTokens:number, source:string}

Defined in lib/context/usage.js

usageSummary(usage) function

One-line human-readable usage summary (e.g. for a host's diagnostics).

Defined in lib/context/usage.js