@ai-matrx/content-ir 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +24 -5
  3. package/dist/convert.cjs +1680 -0
  4. package/dist/convert.cjs.map +1 -0
  5. package/dist/convert.d.cts +230 -0
  6. package/dist/convert.d.ts +230 -0
  7. package/dist/convert.js +1666 -0
  8. package/dist/convert.js.map +1 -0
  9. package/dist/core.cjs +2493 -0
  10. package/dist/core.cjs.map +1 -0
  11. package/dist/core.d.cts +370 -0
  12. package/dist/core.d.ts +370 -0
  13. package/dist/core.js +2452 -0
  14. package/dist/core.js.map +1 -0
  15. package/dist/index.cjs +3 -1
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +9 -2030
  18. package/dist/index.d.ts +9 -2030
  19. package/dist/index.js +3 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/ir-tree-DbLVxbf1.d.cts +441 -0
  22. package/dist/ir-tree-Dsc_66ek.d.ts +441 -0
  23. package/dist/ir-types-95bA2cXH.d.cts +119 -0
  24. package/dist/ir-types-95bA2cXH.d.ts +119 -0
  25. package/dist/kind-schema.types-CwncWj9U.d.cts +139 -0
  26. package/dist/kind-schema.types-CwncWj9U.d.ts +139 -0
  27. package/dist/registry.cjs +468 -0
  28. package/dist/registry.cjs.map +1 -0
  29. package/dist/registry.d.cts +357 -0
  30. package/dist/registry.d.ts +357 -0
  31. package/dist/registry.js +456 -0
  32. package/dist/registry.js.map +1 -0
  33. package/dist/session.cjs +2052 -0
  34. package/dist/session.cjs.map +1 -0
  35. package/dist/session.d.cts +75 -0
  36. package/dist/session.d.ts +75 -0
  37. package/dist/session.js +2047 -0
  38. package/dist/session.js.map +1 -0
  39. package/dist/wire.cjs +310 -0
  40. package/dist/wire.cjs.map +1 -0
  41. package/dist/wire.d.cts +326 -0
  42. package/dist/wire.d.ts +326 -0
  43. package/dist/wire.js +291 -0
  44. package/dist/wire.js.map +1 -0
  45. package/package.json +73 -1
@@ -0,0 +1,370 @@
1
+ import { g as IrResidue, d as IrDiscriminator, C as CanonicalBlockIR } from './ir-types-95bA2cXH.cjs';
2
+ export { a as CanonicalContent, b as CanonicalSegment, I as IR_ENVELOPE_KEY, c as IR_VERSION, e as IrKindState, f as IrPath, h as IrStructuredNode, i as irPathIsUnderOrEqual, j as irPathKey, k as irPathLabel, l as irPathsEqual, m as isEmptyResidue } from './ir-types-95bA2cXH.cjs';
3
+ import { S as SchemaResolver } from './ir-tree-DbLVxbf1.cjs';
4
+ export { I as IrTree, a as IrTreeNode, J as JsonPath, K as KindStreamEvent, b as KindStreamParser, c as KindStreamParserOptions, R as RawObjectCause, d as createKindStreamParser, s as setJsonRootKeyLookup } from './ir-tree-DbLVxbf1.cjs';
5
+ import { a as KindSchema, F as FieldSchema } from './kind-schema.types-CwncWj9U.cjs';
6
+ export { A as ArrayItemScalarType, K as KIND_KEY, R as RecordValueType, S as ScalarFieldType, i as isJsonAnyField, b as isScalarArrayType, r as readObjectKind, s as scalarArrayItemType } from './kind-schema.types-CwncWj9U.cjs';
7
+
8
+ /**
9
+ * Character-level incremental JSON tokenizer. Survives chunk boundaries
10
+ * mid-token (strings, escapes, unicode sequences, primitives). Pure — no
11
+ * React, no Redux, no IO.
12
+ *
13
+ * Moved from app/(dev)/demos/json-block-detector/reusable-logic.ts (the demo
14
+ * is now a consumer of this library).
15
+ */
16
+ type Punct = "{" | "}" | "[" | "]" | ":" | ",";
17
+ type JsonToken = {
18
+ type: "punct";
19
+ value: Punct;
20
+ at: number;
21
+ } | {
22
+ type: "string";
23
+ value: string;
24
+ at: number;
25
+ } | {
26
+ type: "number";
27
+ value: number;
28
+ at: number;
29
+ } | {
30
+ type: "boolean";
31
+ value: boolean;
32
+ at: number;
33
+ } | {
34
+ type: "null";
35
+ value: null;
36
+ at: number;
37
+ };
38
+ declare class JsonStreamTokenizer {
39
+ private mode;
40
+ private pos;
41
+ private stringBuffer;
42
+ private primitiveBuffer;
43
+ private unicodeBuffer;
44
+ private tokenStart;
45
+ private readonly onToken;
46
+ constructor(onToken: (token: JsonToken) => void);
47
+ get position(): number;
48
+ push(chunk: string): void;
49
+ end(): void;
50
+ private handleNormalChar;
51
+ private emitPrimitive;
52
+ private isDelimiter;
53
+ }
54
+
55
+ /**
56
+ * Compliant snapshot builder — the guarantee that a renderer always receives
57
+ * a well-formed, schema-shaped object even mid-stream.
58
+ *
59
+ * ZERO DATA LOSS: unknown keys are NOT merged into the snapshot value (they
60
+ * would be indistinguishable from schema fields). They are returned on the
61
+ * residue channel and re-merged only at wire-serialization time via
62
+ * `mergeResidueIntoValue`.
63
+ */
64
+
65
+ /** Placeholder for a required field not yet received during streaming. */
66
+ declare function emptyValueForFieldSchema(field: FieldSchema): unknown;
67
+ interface CompliantKindSnapshot {
68
+ /** Schema fields + __kind only. Required-but-missing fields hold typed placeholders. */
69
+ value: Record<string, unknown>;
70
+ /** Unknown keys + missing optionals. Null when both channels are empty. */
71
+ residue: IrResidue | null;
72
+ }
73
+ declare function buildCompliantKindSnapshot(schema: KindSchema, partial: Record<string, unknown>): CompliantKindSnapshot;
74
+ /**
75
+ * Wire/round-trip form: schema fields + unknown keys back together, exactly
76
+ * as the source carried them. `residue.extra` wins nothing — snapshot value
77
+ * and extras are disjoint by construction.
78
+ */
79
+ declare function mergeResidueIntoValue(value: Record<string, unknown>, residue: IrResidue | null): Record<string, unknown>;
80
+
81
+ /**
82
+ * Idempotent normalizer — the "recognizes its own work" property.
83
+ *
84
+ * THE LAW: anything already carrying a current CanonicalBlockIR envelope is
85
+ * returned BY REFERENCE — zero reprocessing, reference equality holds, React
86
+ * bails out. Only raw text (a detected region's source) is ever parsed, and
87
+ * it is parsed exactly once per fingerprint.
88
+ *
89
+ * `normalizeJsonRegion` is the one-shot mode: the same KindStreamParser that
90
+ * powers live streams, run over a complete region string (DB reloads,
91
+ * reconcile passes), assembled through the same IrTree the live session uses
92
+ * — stream and static output are structurally identical by construction.
93
+ */
94
+
95
+ declare function isCanonicalBlockIR(value: unknown): value is CanonicalBlockIR;
96
+ /**
97
+ * The idempotence fast path: return the existing envelope by reference when
98
+ * it still describes this source text; null means "parse needed".
99
+ */
100
+ declare function reuseEnvelopeIfCurrent(source: string, candidate: unknown): CanonicalBlockIR | null;
101
+ interface NormalizeJsonRegionOptions {
102
+ schemas: Record<string, KindSchema> | SchemaResolver;
103
+ /** Known-context root prediction (agent output schema, fence hint). */
104
+ expectedRootKind?: string;
105
+ /**
106
+ * Pass a previously persisted envelope (message metadata, artifact row);
107
+ * when its fingerprint matches, it is returned as-is and nothing parses.
108
+ */
109
+ existing?: unknown;
110
+ }
111
+ interface CompleteValueEnvelopeOptions {
112
+ /**
113
+ * Wire discriminator recorded on the root node — which syntax established
114
+ * the kind. Defaults to the JSON `__kind` key; XML surfaces converging at
115
+ * region finalize pass `xmlDiscriminator(tag)` so round-trip serializers
116
+ * know the original arrival format.
117
+ */
118
+ discriminator?: IrDiscriminator;
119
+ }
120
+ /**
121
+ * Build a resolved, complete envelope directly from an already-structured
122
+ * value (a persisted artifact's `content.data` object, or a completed XML
123
+ * region's strategy output). This is the zero-reprocessing rehydration path:
124
+ * the value IS the reconstructed region value (schema fields + residue extras
125
+ * merged at persist time), so no tokenizer/parser run is needed — the
126
+ * envelope wraps it verbatim. The fingerprint hashes the canonical value
127
+ * serialization, so any two paths producing the same value produce the SAME
128
+ * envelope (stream ≡ static by construction).
129
+ */
130
+ declare function envelopeFromCompleteValue(value: Record<string, unknown>, kind: string, options?: CompleteValueEnvelopeOptions): CanonicalBlockIR;
131
+ /** One-shot: complete region text in → canonical envelope out. */
132
+ declare function normalizeJsonRegion(source: string, options: NormalizeJsonRegionOptions): CanonicalBlockIR;
133
+
134
+ /**
135
+ * Stable, fast content fingerprint for IR envelopes.
136
+ *
137
+ * Used as the idempotence / cache key: a persisted CanonicalBlockIR is only
138
+ * reused when its fingerprint matches the region source text it claims to
139
+ * represent. Not cryptographic — collision resistance at the "same message,
140
+ * same block" scale is all that's required, and it must be synchronous and
141
+ * dependency-free (runs per region on the hot streaming path).
142
+ *
143
+ * FNV-1a 32-bit, applied twice with different seeds and concatenated, so a
144
+ * single 32-bit collision doesn't alias two regions.
145
+ *
146
+ * `createFingerprinter` is the incremental form for live streams: feeding
147
+ * chunks one at a time yields EXACTLY the same fingerprint as
148
+ * `fingerprintText` over the concatenation — sessions never re-hash the
149
+ * whole source per flush.
150
+ */
151
+ interface Fingerprinter {
152
+ push(chunk: string): void;
153
+ /** Fingerprint of everything pushed so far. */
154
+ current(): string;
155
+ }
156
+ declare function createFingerprinter(): Fingerprinter;
157
+ declare function fingerprintText(source: string): string;
158
+
159
+ /**
160
+ * Discriminator abstraction — how a node's kind is established from the wire.
161
+ *
162
+ * The parser never hardcodes "kind comes from a JSON key". JSON resolves via
163
+ * the `__kind` field (implemented today); XML resolves via tag → registry
164
+ * alias (Phase 6 — contract only). `IrStructuredNode.discriminator` records
165
+ * which resolver produced each node so renderers and round-trip serializers
166
+ * can reconstruct the original wire format per node.
167
+ */
168
+
169
+ declare const JSON_DISCRIMINATOR: IrDiscriminator;
170
+ declare function xmlDiscriminator(tag: string): IrDiscriminator;
171
+ declare function fenceDiscriminator(language: string): IrDiscriminator;
172
+ /** What a resolver can say about an opening compound value. */
173
+ type KindResolution = {
174
+ outcome: "kind";
175
+ kind: string;
176
+ } | {
177
+ outcome: "pending";
178
+ } | {
179
+ outcome: "raw";
180
+ reason: string;
181
+ };
182
+
183
+ /**
184
+ * IrEnvelopeCache — the persisted envelope cache carried on MESSAGE PARTS.
185
+ *
186
+ * Phase 5 (reload without re-parse): at stream end, `assembleMessageParts`
187
+ * stamps every completed JSON region's CanonicalBlockIR onto the committed
188
+ * `CxTextContent.metadata.__ir` as this cache — keyed by fingerprint, because
189
+ * one text part can embed several regions. On reload the splitter's envelope
190
+ * memo consults the seeded cache (`registry/region-envelope-memo.ts`) and
191
+ * reuses the persisted envelope BY REFERENCE via `reuseEnvelopeIfCurrent`
192
+ * (exact fingerprint match of the detected region source) — zero re-parse.
193
+ *
194
+ * Shape discipline: the SAME `__ir` metadata key carries two shapes at two
195
+ * levels, disambiguated by validators that reject each other —
196
+ * - render block metadata → a single CanonicalBlockIR (`isCanonicalBlockIR`)
197
+ * - message part metadata → this cache (`isIrEnvelopeCache`)
198
+ *
199
+ * Pure kernel module: types + validators only. No React/Redux/Supabase.
200
+ */
201
+
202
+ /** Cache version. Bump = migration point for persisted part caches. */
203
+ declare const IR_ENVELOPE_CACHE_VERSION: 1;
204
+ /**
205
+ * The envelope cache persisted on a message part's `metadata.__ir`.
206
+ * `blocks` maps each region-source fingerprint to its complete envelope.
207
+ */
208
+ interface IrEnvelopeCache {
209
+ v: typeof IR_ENVELOPE_CACHE_VERSION;
210
+ blocks: Record<string, CanonicalBlockIR>;
211
+ }
212
+ /**
213
+ * Strict whole-cache validation: every entry must be a complete
214
+ * CanonicalBlockIR keyed by its OWN fingerprint. A cache failing this guard
215
+ * came from a buggy or foreign writer — callers surface that loudly and seed
216
+ * nothing (a half-trusted cache is how poisoned envelopes reach renderers).
217
+ */
218
+ declare function isIrEnvelopeCache(value: unknown): value is IrEnvelopeCache;
219
+ /**
220
+ * Build the persistable cache from a run's collected envelopes. Only
221
+ * complete envelopes are cacheable (a streaming/error envelope can never be
222
+ * reused — its fingerprint doesn't describe a finished region). Duplicate
223
+ * regions (same fingerprint) collapse to one entry. Engine-agnostic by
224
+ * design: an aidream-built `engine: "py-block-detector"` envelope is cached
225
+ * identically to an FE-parsed one. Returns null when nothing qualifies so
226
+ * callers skip the metadata stamp entirely.
227
+ */
228
+ declare function envelopeCacheFromEnvelopes(envelopes: readonly CanonicalBlockIR[]): IrEnvelopeCache | null;
229
+
230
+ /**
231
+ * PURE envelope ingestion — reading `metadata.__ir` off a block's metadata
232
+ * and gating SERVER-BUILT envelopes at the wire boundary. Twin-safe: no
233
+ * React / Redux / Supabase / host diagnostics — side effects (seeding the
234
+ * region-envelope memo, screaming to the Error Inspector) are injected by
235
+ * the host through `InboundEnvelopeHooks`.
236
+ *
237
+ * The frontend host shell is `redux/render-block-envelope.ts` (binds the
238
+ * hooks to `seedEnvelope` + `captureError`); aidream's Workflow Studio binds
239
+ * its own. Contract: /Users/armanisadeghi/code/common-docs/systems/content-ir-system/PYTHON_ENVELOPE_CONTRACT.md.
240
+ */
241
+
242
+ /** Read a CanonicalBlockIR envelope off a block's metadata (or anything). */
243
+ declare function readEnvelope(metadata: Record<string, unknown> | null | undefined): CanonicalBlockIR | null;
244
+ /** Pure classification of inbound metadata carrying (or not) an envelope. */
245
+ type InboundEnvelopeVerdict = {
246
+ /** No `__ir` key — zero-touch pass, same reference back. */
247
+ outcome: "absent";
248
+ metadata: Record<string, unknown> | undefined;
249
+ } | {
250
+ /** Valid CanonicalBlockIR — same reference back (idempotence law). */
251
+ outcome: "valid";
252
+ metadata: Record<string, unknown>;
253
+ envelope: CanonicalBlockIR;
254
+ } | {
255
+ /** Malformed/foreign `__ir` — a COPY with `__ir` stripped. */
256
+ outcome: "malformed";
257
+ metadata: Record<string, unknown>;
258
+ engine: string;
259
+ raw: unknown;
260
+ };
261
+ declare function classifyInboundEnvelopeMetadata(metadata: Record<string, unknown> | null | undefined): InboundEnvelopeVerdict;
262
+ /** Host-injected side effects for the inbound gate. */
263
+ interface InboundEnvelopeHooks {
264
+ /** Called with every VALID envelope so later re-splits reuse it by reference. */
265
+ seedEnvelope?: (envelope: CanonicalBlockIR) => void;
266
+ /** Called LOUDLY for every malformed envelope — a bad envelope is a defect. */
267
+ reportMalformed?: (info: {
268
+ blockId: string;
269
+ engine: string;
270
+ raw: unknown;
271
+ }) => void;
272
+ }
273
+ /**
274
+ * Ingest guard for SERVER-BUILT envelopes riding `metadata.__ir` on a
275
+ * `render_block` event.
276
+ *
277
+ * - No `__ir` key → the SAME metadata reference back (zero-touch pass).
278
+ * - Valid CanonicalBlockIR → the SAME metadata reference back (reuse-by-
279
+ * reference — the idempotence law) AND `hooks.seedEnvelope` fires so any
280
+ * later re-split of the same region source reuses it instead of parsing.
281
+ * - Malformed/foreign `__ir` → a COPY with `__ir` stripped, plus a loud
282
+ * `hooks.reportMalformed`. A bad envelope must never poison kind routing
283
+ * or the persistence cache; dropping it degrades that block to the
284
+ * ordinary content-driven path, nothing more.
285
+ */
286
+ declare function sanitizeInboundEnvelopeMetadata(metadata: Record<string, unknown> | null | undefined, context: {
287
+ blockId: string;
288
+ }, hooks?: InboundEnvelopeHooks): Record<string, unknown> | undefined;
289
+
290
+ /**
291
+ * Pure envelope→value functions (the zero-data-loss wire round-trip).
292
+ *
293
+ * These live in core/ (the pure kernel) because every layer needs them —
294
+ * including kinds/legacy-bridge-utils, whose bridges are built at MODULE
295
+ * SCOPE inside kinds/<slug>.ts files that system-kinds.ts imports. When these
296
+ * functions lived in redux/render-block-envelope.ts, that file's memo/capture
297
+ * imports closed a module cycle (kinds → bridge-utils → render-block-envelope
298
+ * → region-envelope-memo → kind-registry → system-kinds → kinds), which made
299
+ * SYSTEM_KIND_DEFINITIONS entry-point-fragile (undefined defs when a kinds
300
+ * module was the import entry). Keeping them here makes every kinds module
301
+ * cycle-free BY CONSTRUCTION. redux/render-block-envelope re-exports them for
302
+ * its existing consumers.
303
+ */
304
+
305
+ /**
306
+ * Rebuild the region's full data: walk the root value and merge each node's
307
+ * residue extras back in (root residue + nodeIndex residues). This is the
308
+ * zero-data-loss read: nothing the model emitted is missing, whether or not
309
+ * a schema knew about it.
310
+ */
311
+ declare function reconstructRegionValue(envelope: CanonicalBlockIR): Record<string, unknown>;
312
+ /**
313
+ * Deep-remove the `__kind` discriminator.
314
+ *
315
+ * 🚨 NOT A TRANSFORM FOR PLATFORM DATA. `__kind` is part of the data
316
+ * (KINDS_EVERYWHERE_PLAN §4.2) and stripping it from anything stored, passed or
317
+ * rendered was annihilated on 2026-08-23. This helper survives for exactly two
318
+ * shapes of caller, both of which are guarded:
319
+ * - a SYMMETRIC COMPARISON that reduces both sides and returns a boolean;
320
+ * - legacy validation TOLERANCE against a pre-2026-08-23 schema version.
321
+ * Guards: aidream `scripts/check_kind_marker_law.py`,
322
+ * matrx-frontend `pnpm check:kind-marker-law`.
323
+ */
324
+ declare function stripKindDeep(value: unknown): unknown;
325
+
326
+ /**
327
+ * ContentRegion — the handshake between a host detector and this library.
328
+ *
329
+ * Boundary rule (the answer to the single-root problem): the HOST detector
330
+ * (StreamBlockAccumulator on streams, content-splitter-v2 on DB loads) finds
331
+ * where a structured region begins and ends inside prose; the kind parser
332
+ * owns everything INSIDE the region. A fresh parser is created per region, so
333
+ * "one root object" is true within a region by construction, and multiple
334
+ * blocks per message are just multiple regions.
335
+ *
336
+ * Through Phase 6 the host's fence-close / brace-count logic remains the
337
+ * region-end oracle (bit-level parity with today). In Phase 7 the parser's
338
+ * own frame stack becomes the oracle and the mirrored counters are deleted.
339
+ */
340
+ type RegionFormat = "json";
341
+ type RegionSourceKind = "fence" | "bare";
342
+ interface ContentRegionInit {
343
+ regionId: string;
344
+ format: RegionFormat;
345
+ sourceKind: RegionSourceKind;
346
+ }
347
+ /** How a region ended. Truncation is a normal outcome, never stream-fatal. */
348
+ type RegionEndReason = "closed" | "truncated" | "aborted";
349
+
350
+ /**
351
+ * Schema-shape helpers — structural depth and layout hints derived from a
352
+ * KindSchema. Drives the generic renderer's flat / grid / nested layout and
353
+ * human labels for slugs.
354
+ *
355
+ * Moved from app/(dev)/demos/json-block-detector/schema-structure.ts.
356
+ */
357
+
358
+ /** Human label from a slug or field key (snake_case → Title Case + acronym fixes). */
359
+ declare function formatBlockLabel(key: string): string;
360
+ /**
361
+ * Structural nesting depth of a kind schema — drives generic renderer layout.
362
+ * 0 = flat card (scalars only)
363
+ * 1 = grid (one array/object nesting level)
364
+ * 2+ = expandable grid (parent → child → grandchild)
365
+ */
366
+ declare function schemaStructureDepth(schema: KindSchema, allSchemas: Record<string, KindSchema>, visiting?: Set<string>): number;
367
+ type SchemaLayoutMode = "flat" | "grid" | "nested";
368
+ declare function schemaLayoutMode(schema: KindSchema, allSchemas: Record<string, KindSchema>): SchemaLayoutMode;
369
+
370
+ export { CanonicalBlockIR, type CompleteValueEnvelopeOptions, type CompliantKindSnapshot, type ContentRegionInit, FieldSchema, type Fingerprinter, IR_ENVELOPE_CACHE_VERSION, type InboundEnvelopeHooks, type InboundEnvelopeVerdict, IrDiscriminator, type IrEnvelopeCache, IrResidue, JSON_DISCRIMINATOR, JsonStreamTokenizer, type JsonToken, type KindResolution, KindSchema, type NormalizeJsonRegionOptions, type Punct, type RegionEndReason, type RegionFormat, type RegionSourceKind, type SchemaLayoutMode, SchemaResolver, buildCompliantKindSnapshot, classifyInboundEnvelopeMetadata, createFingerprinter, emptyValueForFieldSchema, envelopeCacheFromEnvelopes, envelopeFromCompleteValue, fenceDiscriminator, fingerprintText, formatBlockLabel, isCanonicalBlockIR, isIrEnvelopeCache, mergeResidueIntoValue, normalizeJsonRegion, readEnvelope, reconstructRegionValue, reuseEnvelopeIfCurrent, sanitizeInboundEnvelopeMetadata, schemaLayoutMode, schemaStructureDepth, stripKindDeep, xmlDiscriminator };