import { f as IrPath, g as IrResidue, e as IrKindState, C as CanonicalBlockIR } from './ir-types-DtGFylUM.cjs'; import { a as KindSchema } from './kind-schema.types-ByGiQxlQ.cjs'; /** * KindStreamParser — the streaming, schema-validating, __kind-discriminated * JSON parser at the heart of content-ir. * * Frame-stack pushdown parser over JsonStreamTokenizer tokens. Every value is * path-addressed; every object resolves a kind against the schema registry; * schema-shaped `block_snapshot` events fire on field arrival so renderers * get live partials; unknown/invalid structures degrade to `raw_object` * instead of failing the stream. * * The pushdown discipline (commit → descend → never re-ask → backtrack): * - SPECULATIVE DESCENT: when a parent field schema predicts a child's kind * ({type:"object", kind} or {type:"array", itemKinds:[K]} with one member), * the child commits to that kind THE INSTANT `{` opens and renders a * placeholder snapshot. `__kind` arrival confirms (no-op), re-tags (allowed * sibling kind), or backtracks to raw (contradiction). An object under a * predicting parent doesn't even need `__kind` — prediction alone types it. * - PENDING SCHEMA: an identified kind whose schema isn't loaded holds the * node open (`pending_schema` event, fields keep accumulating), fires the * resolver's cold fetch, and upgrades in place via `notifySchemaArrived` — * even after the node (or the whole region) has closed. * - POP-UP-ONE-LEVEL: node-scoped problems (duplicate key, schema violation, * disallowed itemKind) mark THAT node raw and keep parsing the parent. * Only grammar/tokenizer errors are region-fatal — and the host degrades * the region to a plain code block, never the stream. */ /** Kept as the historical name for the parser's event paths. */ type JsonPath = IrPath; /** * Schema source abstraction. A plain Record works for static sets; the * registry supplies a resolver whose `request` fires a cold fetch and later * calls `parser.notifySchemaArrived`. */ interface SchemaResolver { get(kind: string): KindSchema | undefined; /** Fire-and-forget cold fetch. Absent = static source, unknown kinds go raw. */ request?(kind: string): void; /** * Optional per-resolver override for legacy root-key recognition. Most hosts * leave this unset and register the lookup once via * `setJsonRootKeyLookup` — see that function for why. */ kindForJsonRootKey?(key: string): string | null; } declare function setJsonRootKeyLookup(lookup: ((key: string) => string | null) | null): void; /** * Why a node degraded off the `resolved` path. * * `"unverified"` is reserved for ONE situation: no schema was registered for * an identified kind, so no check ever ran. Every other degrade — a schema * violation, an array-item kind mismatch, a duplicate key, a bad field * placement, a contradicted speculation — is `"invalid"`: something checked * the node and it failed. */ type RawObjectCause = "unverified" | "invalid"; type KindStreamEvent = { type: "kind_identified"; kind: string; path: JsonPath; /** True when committed from the parent schema before __kind arrived. */ speculative?: boolean; at: number; } | { type: "pending_kind"; path: JsonPath; at: number; } | { type: "kind_wait_end"; path: JsonPath; outcome: "identified" | "raw_fallback"; kind?: string; reason?: string; at: number; } | { type: "pending_schema"; kind: string; path: JsonPath; at: number; } | { type: "field"; kind: string; path: JsonPath; key: string; value: unknown; at: number; } | { type: "object_start"; path: JsonPath; at: number; } | { type: "object_complete"; kind: string; path: JsonPath; value: Record; at: number; } | { type: "raw_object"; path: JsonPath; value: unknown; reason: string; /** * The kind that WAS identified for this node before it degraded — set * for schema-availability degrades AND (since 2026-08-29) structural * ones, so a payload that said what it is stays acknowledged as an * instance of that kind. Absent only when nothing ever identified it * (an object with no `__kind` at all). */ kind?: string; /** * WHY this node is not `resolved` — the discriminator the render route * reads. See `IrKindState` for why collapsing these two is an outage. * * - `"unverified"`: no schema was available, so nothing was checked. * The value is intact and may be perfectly valid. * - `"invalid"` (default): a check RAN and the node failed it, or the * node is structurally broken (duplicate key, bad placement). */ cause?: RawObjectCause; at: number; } | { type: "optional_field_missing"; kind: string; path: JsonPath; field: string; at: number; } | { type: "extra_field"; kind: string; path: JsonPath; field: string; at: number; } | { type: "block_snapshot"; kind: string; path: JsonPath; value: Record; residue: IrResidue | null; complete: boolean; at: number; } | { type: "array_start"; path: JsonPath; field: string; at: number; } | { type: "complete"; kind: string; value: unknown; at: number; } | { type: "error"; reason: string; at: number; }; type KindStreamParserOptions = { onEvent: (event: KindStreamEvent) => void; schemas: Record | SchemaResolver; /** * Known-context root prediction (e.g. "this agent's output schema is * flashcard_set"). The root commits speculatively at `{` open — the Option-1 * provenance path for agents whose schemas don't carry __kind yet. */ expectedRootKind?: string; }; declare class KindStreamParser { private readonly resolver; private readonly stack; private readonly objectKinds; private readonly inlineSchemas; private readonly recordSchemas; private readonly rawObjectPaths; /** * Subtrees whose value domain is "any JSON" by schema (`json` / `json[]` * fields, `record` with `values:"json"` members). OPAQUE by contract: no * kind identification, no pending_kind, no raw_object degradation — unknown * structure here is the declared shape, not a failure. Propagates to every * descendant compound. */ private readonly opaquePaths; private readonly deferredFields; private readonly awaitingKindPaths; /** Paths whose kind came from parent-schema prediction, unconfirmed so far. */ private readonly speculativeKinds; /** * Kind named by the root object's FIRST key through the `json_root_key` * surface registry — a candidate, adopted only at root finalize. */ private rootSurfaceKind; /** kind → paths (by key) waiting for the resolver's cold fetch. */ private readonly pendingSchemaPaths; /** Pending-schema paths whose object already closed. */ private readonly closedPendingPaths; /** Schemas delivered via notifySchemaArrived (overlay over the resolver). */ private readonly arrivedSchemas; private tokenizer; private root; private rootKind; private rootDone; private failed; private readonly options; constructor(options: KindStreamParserOptions); push(chunk: string): void; end(): void; private resolvePendingSchemasAsRaw; /** True once the root value has closed — the region is fully consumed. */ get isComplete(): boolean; get hasFailed(): boolean; /** * Upgrade-in-place: the registry's cold fetch answered. Pending nodes for * this kind validate and complete (closed nodes retroactively); a null * schema (fetch miss) drops them to raw. Safe to call after end(). */ notifySchemaArrived(kind: string, schema: KindSchema | null): void; private handleToken; private handleString; private handlePunctuation; private beginCompound; /** * THE JSON-ROOT-KEY SURFACE — `content_ir.kind_surface` rows of type * `json_root_key`, live at last (they were inert phantom rows until * 2026-08-20). * * A legacy payload such as `{"quiz_title": ...}` carries no `__kind`, but * the ONE surface registry knows exactly which kind that root key names — * the same lookup the SERVER performs before adapting the payload * (`aidream .../processing/blocks/envelope.py`). Consulting it HERE, in the * shared parser core, is what makes one place decide it: both hosts — the * one-shot `normalizeJsonRegion` (DB reload / reconcile) and the live * `openParseSession` (streaming) — build their parser through * `createKindStreamParser`, so neither passes an option and neither can * drift from the other. * * Recorded at the first root key; ADOPTED only when the root object closes * (`completeTypedObject`). That is the surface registry's complete-only * convergence law, and every json_root_key row is `streaming:false` — these * legacy shapes are recognized by their whole payload, so speculating * mid-stream would flash a kind component over an object that may never * satisfy the schema. An explicit `expectedRootKind` (an agent's declared * output schema) is stronger context and always wins; an actual `__kind` * still wins over both. */ private noteRootSurfaceKind; /** * Prediction from the parent schema: object field → declared kind; array * item → sole itemKind; root → expectedRootKind. Only when the schema is * actually resolvable (a prediction we can't validate against is not a * commitment worth making). */ private resolveSpeculativeKind; /** * A schema usable for OBJECT speculation/snapshots — root-form kinds * (non-object data-only shapes) are never a valid object commitment. */ private lookupObjectSchema; private beginScalar; private placeValue; private acceptObjectKey; private acceptColon; private acceptComma; private closeCompound; /** * True when a value placed at `path` sits directly under a json-any * placement: a `json`/`json[]` FIELD, or a member of a `record` whose * values are `"json"`. (Deeper descendants inherit via `opaquePaths`.) */ private isJsonAnyPlacement; private onValueFinalized; /** __kind arrived for an object — confirm speculation, identify, or backtrack. */ private onKindDiscriminatorArrived; /** A contradicted speculation may re-tag only where the new kind is legal. */ private speculativeRetagAllowed; private addPendingSchemaPath; private completeTypedObject; /** Validate + complete an object whose value carries __kind. */ private finalizeTypedObject; /** Validate + complete an object typed purely by parent prediction. */ private finalizeSpeculatedObject; private validateArrayItemKind; private completeRoot; /** Mark a node raw (node-scoped failure) without killing the stream. */ private markNodeRaw; /** * Degrade ONE node off the resolved path. * * `cause` defaults to `"invalid"` deliberately: every call site that omits * it is a real failure (validation, duplicate key, placement, contradicted * speculation). ONLY the "no schema registered" sites pass `"unverified"`, * and they are the reason the parameter exists — see `IrKindState`. */ private emitRawObject; private clearKindWait; private emitFieldIfReady; private flushDeferredFields; private getLiveObjectValue; private emitBlockSnapshotForObject; /** * On `complete` snapshots (and post-close schema upgrades) the frame has * already been popped — the finalized value lives in the root tree. */ private getFinalizedObjectValue; private validateFieldPlacement; private emitSchemaNotices; private validateObjectAgainstSchema; private validateFinalFieldValue; private validateValueAgainstField; private validateScalarField; private validateRecordScalar; private validateRecordObject; private validateObjectAgainstFields; private registerObjectContext; private resolveParentFieldSchema; private getObjectKindForPath; private getDirectObjectKind; private isAllowedSchemaField; private parentFieldName; private fieldKeyFromPath; private isKindFieldPath; private pathKey; private lookupSchema; private fail; private emit; private currentFrame; } declare function createKindStreamParser(options: KindStreamParserOptions): KindStreamParser; /** * IrTree — the immutable, structurally-shared view of a parsed region. * * Consumes KindStreamEvents and maintains one node per kind-resolved path. * Node values are STABILIZED: compound children that are themselves kind * nodes are substituted by their current tree value, so an update to * cards[7] produces new identities for root → cards → cards[7] ONLY; * cards[0..6] keep referential identity and memoized components bail out. * * Parser frame values are NEVER exposed — everything handed out is rebuilt * copy-on-write, so it is safe to freeze (Redux dev-mode immutability) and * safe to hold across renders. * * Both the live ParseSession and the one-shot normalizer build their * CanonicalBlockIR from this tree — one assembly path, structurally * identical output for stream and static input. */ interface IrTreeNode { kind: string; kindState: IrKindState; path: IrPath; pathKey: string; /** Stabilized immutable snapshot value (schema fields + __kind only). */ value: Record; residue: IrResidue | null; complete: boolean; /** Bumps on every update to this node (incl. child propagation). */ version: number; } declare class IrTree { private readonly nodes; private readonly rawPaths; private readonly dirty; /** * KIND PRESERVATION (streaming db/cloud kinds): pathKey → identified kind * for nodes whose kind is KNOWN (kind_identified / pending_schema) but that * have no snapshot node yet because the schema is still cold-fetching. * Without this, the envelope reports `kind: ""` for the whole pending * window and the render seam can only show raw JSON. */ private readonly identifiedKinds; /** pathKeys currently waiting on a schema cold fetch. */ private readonly pendingSchemaPaths; /** * Early top-level scalar fields (title, loading_message, …) captured for * identified-but-schema-pending nodes — the loading-component fuel. Scalars * only (no live parser references can escape through here). Superseded the * moment a real snapshot node exists. */ private readonly earlyFields; /** * pathKey → identified kind preserved through a raw fallback (parser stamped * `kind` on the raw_object event) — schema-availability degrades and, since * 2026-08-29, structural ones too. Only a node nothing ever identified (no * `__kind` at all) is absent here. */ private readonly rawKinds; /** * pathKey → WHY the node degraded. `"unverified"` means no schema was * available and nothing was ever checked; `"invalid"` means a check ran and * failed. THE RENDER ROUTE BRANCHES ON THIS — see `IrKindState`. Absent = * `"invalid"`, so a parser that predates the `cause` field (or any consumer * hand-building events) keeps the strict, safe reading. */ private readonly rawCauses; private regionStatus; private errorReason; private rootRawValue; /** Notices for degrades that tried to erase already-published data. */ private readonly rescueNotices; private completedKind; get status(): "streaming" | "complete" | "error"; applyEvent(event: KindStreamEvent): void; getNode(pathKey: string): IrTreeNode | null; listNodes(): IrTreeNode[]; isRawPath(pathKey: string): boolean; /** Dirty pathKeys since the last drain — the flush/notify unit. */ drainDirty(): string[]; hasDirty(): boolean; private upsertNode; /** * Substitute kind-node children with their current tree values so sibling * identities are stable; deep-copy everything else so no live parser * reference ever escapes. */ private stabilizeValue; /** * COW spine rebuild: replace the child's slot in each ancestor kind-node's * value, shallow-copying only the containers along the way. Siblings keep * identity; every ancestor gets a new value identity + version bump. */ private propagateToAncestors; private findNearestAncestorNode; private cloneAlong; private markRaw; /** * A rescue means a degrade tried to erase data a user could already see — * an upstream defect. It rides the envelope as a notice so it surfaces in the * Error Inspector instead of being silently absorbed (`core/` is a pure * kernel: no console, no capture — the notice IS the alarm). */ private recordRescue; /** * Assemble the canonical envelope. ONE code path for stream + one-shot. * Callers supply the fingerprint (one-shot hashes the source; live sessions * keep an incremental hasher so no per-flush re-hash happens). */ buildEnvelope(fingerprint: string): CanonicalBlockIR; } export { IrTree as I, KindStreamParser as b, createKindStreamParser as d, setJsonRootKeyLookup as s }; export type { JsonPath as J, KindStreamEvent as K, RawObjectCause as R, SchemaResolver as S, IrTreeNode as a, KindStreamParserOptions as c };