@ai-matrx/rich-content 0.0.0 → 0.2.3
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.
- package/CHANGELOG.md +80 -0
- package/LICENSE +1 -1
- package/README.md +58 -3
- package/dist/display/blocks/csv/CsvBlock.d.ts +10 -0
- package/dist/display/blocks/csv/CsvBlock.js +245 -0
- package/dist/display/blocks/table/parseMarkdownTable.d.ts +20 -0
- package/dist/display/blocks/table/parseMarkdownTable.js +35 -0
- package/dist/display/chat-markdown/citations/remarkMatrxCite.d.ts +33 -0
- package/dist/display/chat-markdown/citations/remarkMatrxCite.js +71 -0
- package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.d.ts +29 -0
- package/dist/display/chat-markdown/matrx-variables/remarkMatrxVariable.js +71 -0
- package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.d.ts +55 -0
- package/dist/display/chat-markdown/page-break/remarkMatrxPageBreak.js +108 -0
- package/dist/display/chat-markdown/rehypeSafeRawHtml.d.ts +59 -0
- package/dist/display/chat-markdown/rehypeSafeRawHtml.js +140 -0
- package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.d.ts +14 -0
- package/dist/display/markdown-classification/processors/bock-processors/parse-markdown-table.js +171 -0
- package/dist/display/markdown-classification/processors/types.d.ts +120 -0
- package/dist/display/markdown-classification/processors/types.js +10 -0
- package/dist/display/markdown-classification/processors/utils/client-blocks.d.ts +169 -0
- package/dist/display/markdown-classification/processors/utils/client-blocks.js +0 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-core.d.ts +223 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-core.js +1791 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-v2.d.ts +15 -0
- package/dist/display/markdown-classification/processors/utils/content-splitter-v2.js +19 -0
- package/dist/display/markdown-classification/processors/utils/expand-text-blocks.d.ts +9 -0
- package/dist/display/markdown-classification/processors/utils/expand-text-blocks.js +36 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-lines.d.ts +5 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-lines.js +40 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.d.ts +16 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vector-inputs.js +385 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.d.ts +43 -0
- package/dist/display/markdown-classification/processors/utils/gfm-table-vectors.js +33 -0
- package/dist/display/markdown-classification/processors/utils/table-data-parser.d.ts +9 -0
- package/dist/display/markdown-classification/processors/utils/table-data-parser.js +30 -0
- package/dist/display/markdown-classification/processors/utils/thinking-parser.d.ts +7 -0
- package/dist/display/markdown-classification/processors/utils/thinking-parser.js +70 -0
- package/dist/display/render-block.d.ts +23 -0
- package/dist/display/render-block.js +0 -0
- package/dist/display/themes.d.ts +1023 -0
- package/dist/display/themes.js +1105 -0
- package/dist/display/types.d.ts +32 -0
- package/dist/display/types.js +0 -0
- package/dist/host/ContentIrHostBoundary.d.ts +8 -0
- package/dist/host/ContentIrHostBoundary.js +15 -0
- package/dist/host/ErrorActions.d.ts +4 -0
- package/dist/host/ErrorActions.js +11 -0
- package/dist/host/NestedContent.d.ts +3 -0
- package/dist/host/NestedContent.js +12 -0
- package/dist/host/ResourcePeek.d.ts +6 -0
- package/dist/host/ResourcePeek.js +14 -0
- package/dist/host/component-registry.d.ts +2 -0
- package/dist/host/component-registry.js +25 -0
- package/dist/host/diagnostics.d.ts +2 -0
- package/dist/host/diagnostics.js +15 -0
- package/dist/host/index.d.ts +3 -0
- package/dist/host/index.js +18 -0
- package/dist/host/kind-incident.d.ts +3 -0
- package/dist/host/kind-incident.js +12 -0
- package/dist/host/kind-registry.d.ts +2 -0
- package/dist/host/kind-registry.js +35 -0
- package/dist/host/people.d.ts +3 -0
- package/dist/host/people.js +12 -0
- package/dist/host/registry.d.ts +27 -0
- package/dist/host/registry.js +55 -0
- package/dist/host/splitter-envelopes.d.ts +2 -0
- package/dist/host/splitter-envelopes.js +7 -0
- package/dist/host/tables.d.ts +6 -0
- package/dist/host/tables.js +8 -0
- package/dist/host/toast.d.ts +2 -0
- package/dist/host/toast.js +57 -0
- package/dist/host/types.d.ts +157 -0
- package/dist/host/types.js +0 -0
- package/dist/host/wikilinks.d.ts +15 -0
- package/dist/host/wikilinks.js +23 -0
- package/dist/kinds/host/route-env.d.ts +33 -0
- package/dist/kinds/host/route-env.js +16 -0
- package/dist/kinds/react/KindEscapedNotice.d.ts +14 -0
- package/dist/kinds/react/KindEscapedNotice.js +72 -0
- package/dist/kinds/react/ProvisionalKindBoundary.d.ts +19 -0
- package/dist/kinds/react/ProvisionalKindBoundary.js +17 -0
- package/dist/kinds/react/ensure-kind-renderable.d.ts +14 -0
- package/dist/kinds/react/ensure-kind-renderable.js +45 -0
- package/dist/kinds/react/kind-problems.d.ts +62 -0
- package/dist/kinds/react/kind-problems.js +134 -0
- package/dist/kinds/react/kind-route.d.ts +23 -0
- package/dist/kinds/react/kind-route.js +24 -0
- package/dist/kinds/react/loading/infer-loading-slug.d.ts +58 -0
- package/dist/kinds/react/loading/infer-loading-slug.js +100 -0
- package/dist/kinds/react/loading/kind-loading-components.d.ts +48 -0
- package/dist/kinds/react/loading/kind-loading-components.js +447 -0
- package/dist/kinds/react/loading/kind-loading-registry.d.ts +21 -0
- package/dist/kinds/react/loading/kind-loading-registry.js +62 -0
- package/dist/kinds/react/loading/kind-loading-slugs.d.ts +18 -0
- package/dist/kinds/react/loading/kind-loading-slugs.js +34 -0
- package/dist/kinds/react/loading/kind-loading.types.d.ts +79 -0
- package/dist/kinds/react/loading/kind-loading.types.js +31 -0
- package/dist/kinds/react/loading/resolve-loading-slug.d.ts +29 -0
- package/dist/kinds/react/loading/resolve-loading-slug.js +51 -0
- package/dist/kinds/react/partial-kind-route.d.ts +32 -0
- package/dist/kinds/react/partial-kind-route.js +27 -0
- package/dist/kinds/react/registry-versioned.d.ts +54 -0
- package/dist/kinds/react/registry-versioned.js +18 -0
- package/dist/kinds/react/route-at-version.d.ts +38 -0
- package/dist/kinds/react/route-at-version.js +78 -0
- package/dist/kinds/react/slot/KindSlot.d.ts +87 -0
- package/dist/kinds/react/slot/KindSlot.js +65 -0
- package/dist/kinds/react/use-registry-repaint.d.ts +6 -0
- package/dist/kinds/react/use-registry-repaint.js +36 -0
- package/dist/kinds/react/useIrNode.d.ts +9 -0
- package/dist/kinds/react/useIrNode.js +46 -0
- package/dist/kinds/react/useLiveJsonRegion.d.ts +15 -0
- package/dist/kinds/react/useLiveJsonRegion.js +84 -0
- package/dist/kinds/redux/render-block-envelope.d.ts +14 -0
- package/dist/kinds/redux/render-block-envelope.js +26 -0
- package/dist/kinds/registry/kind-correctors.d.ts +63 -0
- package/dist/kinds/registry/kind-correctors.js +94 -0
- package/dist/kinds/registry/legacy-quiz-envelope.d.ts +1 -0
- package/dist/kinds/registry/legacy-quiz-envelope.js +1 -0
- package/dist/kinds/registry/region-envelope-memo.d.ts +45 -0
- package/dist/kinds/registry/region-envelope-memo.js +94 -0
- package/dist/kinds/registry/registry-debug.d.ts +38 -0
- package/dist/kinds/registry/registry-debug.js +39 -0
- package/dist/markdown-core/MarkdownCore.d.ts +6 -0
- package/dist/markdown-core/MarkdownCore.js +32 -0
- package/dist/markdown-core/MarkdownCoreImpl.d.ts +3 -0
- package/dist/markdown-core/MarkdownCoreImpl.js +27 -0
- package/dist/markdown-core/MarkdownCoreServer.d.ts +4 -0
- package/dist/markdown-core/MarkdownCoreServer.js +26 -0
- package/dist/markdown-core/heading-anchors-context.d.ts +2 -0
- package/dist/markdown-core/heading-anchors-context.js +11 -0
- package/dist/markdown-core/heading-anchors-props.d.ts +2 -0
- package/dist/markdown-core/heading-anchors-props.js +6 -0
- package/dist/markdown-core/markdown-core-html.d.ts +3 -0
- package/dist/markdown-core/markdown-core-html.js +33 -0
- package/dist/markdown-core/markdown-core-presets.d.ts +22 -0
- package/dist/markdown-core/markdown-core-presets.js +118 -0
- package/dist/markdown-core/markdown-core-types.d.ts +43 -0
- package/dist/markdown-core/markdown-core-types.js +0 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-flow.d.ts +15 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-flow.js +143 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-text.d.ts +24 -0
- package/dist/markdown-core/math/vendor/micromark-math-math-text.js +127 -0
- package/dist/markdown-core/math/vendor/micromark-math-syntax.d.ts +30 -0
- package/dist/markdown-core/math/vendor/micromark-math-syntax.js +15 -0
- package/dist/markdown-core/math/vendor/rehype-katex.d.ts +15 -0
- package/dist/markdown-core/math/vendor/rehype-katex.js +83 -0
- package/dist/markdown-core/math/vendor/remark-math.d.ts +9 -0
- package/dist/markdown-core/math/vendor/remark-math.js +20 -0
- package/dist/markdown-core/math-normalizer.d.ts +57 -0
- package/dist/markdown-core/math-normalizer.js +315 -0
- package/dist/markdown-core/plain-title.d.ts +2 -0
- package/dist/markdown-core/plain-title.js +1 -0
- package/dist/markdown-core/stream-heal.d.ts +2 -0
- package/dist/markdown-core/stream-heal.js +184 -0
- package/dist/markdown-core/streaming-context.d.ts +2 -0
- package/dist/markdown-core/streaming-context.js +11 -0
- package/dist/markdown-core/syntax/callout-types.d.ts +9 -0
- package/dist/markdown-core/syntax/callout-types.js +101 -0
- package/dist/markdown-core/syntax/containers.d.ts +17 -0
- package/dist/markdown-core/syntax/containers.js +353 -0
- package/dist/markdown-core/syntax/document-numbering.d.ts +52 -0
- package/dist/markdown-core/syntax/document-numbering.js +184 -0
- package/dist/markdown-core/syntax/elements/CalloutIcon.d.ts +3 -0
- package/dist/markdown-core/syntax/elements/CalloutIcon.js +41 -0
- package/dist/markdown-core/syntax/elements/CrossRef.d.ts +12 -0
- package/dist/markdown-core/syntax/elements/CrossRef.js +57 -0
- package/dist/markdown-core/syntax/elements/CsvFence.d.ts +4 -0
- package/dist/markdown-core/syntax/elements/CsvFence.js +18 -0
- package/dist/markdown-core/syntax/elements/DetailsElements.d.ts +12 -0
- package/dist/markdown-core/syntax/elements/DetailsElements.js +38 -0
- package/dist/markdown-core/syntax/elements/DocumentNumbering.d.ts +20 -0
- package/dist/markdown-core/syntax/elements/DocumentNumbering.js +37 -0
- package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.d.ts +4 -0
- package/dist/markdown-core/syntax/elements/DocumentPropertiesPanel.js +46 -0
- package/dist/markdown-core/syntax/elements/InDocAnchor.d.ts +11 -0
- package/dist/markdown-core/syntax/elements/InDocAnchor.js +87 -0
- package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.d.ts +24 -0
- package/dist/markdown-core/syntax/elements/MarkdownSourceEdit.js +28 -0
- package/dist/markdown-core/syntax/elements/MatrxTabs.d.ts +10 -0
- package/dist/markdown-core/syntax/elements/MatrxTabs.js +59 -0
- package/dist/markdown-core/syntax/elements/MentionChip.d.ts +7 -0
- package/dist/markdown-core/syntax/elements/MentionChip.js +69 -0
- package/dist/markdown-core/syntax/elements/NestedBody.d.ts +3 -0
- package/dist/markdown-core/syntax/elements/NestedBody.js +13 -0
- package/dist/markdown-core/syntax/elements/TableOfContents.d.ts +5 -0
- package/dist/markdown-core/syntax/elements/TableOfContents.js +44 -0
- package/dist/markdown-core/syntax/elements/TaskCheckbox.d.ts +7 -0
- package/dist/markdown-core/syntax/elements/TaskCheckbox.js +63 -0
- package/dist/markdown-core/syntax/elements/WikiEmbed.d.ts +7 -0
- package/dist/markdown-core/syntax/elements/WikiEmbed.js +68 -0
- package/dist/markdown-core/syntax/elements/WikiLink.d.ts +10 -0
- package/dist/markdown-core/syntax/elements/WikiLink.js +114 -0
- package/dist/markdown-core/syntax/elements/core-syntax-elements.d.ts +22 -0
- package/dist/markdown-core/syntax/elements/core-syntax-elements.js +70 -0
- package/dist/markdown-core/syntax/elements/find-in-document.d.ts +3 -0
- package/dist/markdown-core/syntax/elements/find-in-document.js +20 -0
- package/dist/markdown-core/syntax/elements/wiki-target.d.ts +5 -0
- package/dist/markdown-core/syntax/elements/wiki-target.js +8 -0
- package/dist/markdown-core/syntax/frontmatter.d.ts +26 -0
- package/dist/markdown-core/syntax/frontmatter.js +72 -0
- package/dist/markdown-core/syntax/gfm-cell-pipes.d.ts +11 -0
- package/dist/markdown-core/syntax/gfm-cell-pipes.js +4 -0
- package/dist/markdown-core/syntax/inline-syntax.d.ts +26 -0
- package/dist/markdown-core/syntax/inline-syntax.js +163 -0
- package/dist/markdown-core/syntax/linear-scan.d.ts +46 -0
- package/dist/markdown-core/syntax/linear-scan.js +129 -0
- package/dist/markdown-core/syntax/mdast-helpers.d.ts +48 -0
- package/dist/markdown-core/syntax/mdast-helpers.js +48 -0
- package/dist/markdown-core/syntax/mentions.d.ts +2 -0
- package/dist/markdown-core/syntax/mentions.js +42 -0
- package/dist/markdown-core/syntax/names.d.ts +6 -0
- package/dist/markdown-core/syntax/names.js +18 -0
- package/dist/markdown-core/syntax/prepare-syntax-source.d.ts +1 -0
- package/dist/markdown-core/syntax/prepare-syntax-source.js +78 -0
- package/dist/markdown-core/syntax/rehype-matrx-syntax.d.ts +9 -0
- package/dist/markdown-core/syntax/rehype-matrx-syntax.js +180 -0
- package/dist/markdown-core/syntax/remark-inline-only.d.ts +23 -0
- package/dist/markdown-core/syntax/remark-inline-only.js +25 -0
- package/dist/markdown-core/syntax/remark-matrx-syntax.d.ts +7 -0
- package/dist/markdown-core/syntax/remark-matrx-syntax.js +351 -0
- package/dist/markdown-core/syntax/remark-table-code-pipes.d.ts +7 -0
- package/dist/markdown-core/syntax/remark-table-code-pipes.js +23 -0
- package/dist/markdown-core/syntax/stream-heal-syntax.d.ts +2 -0
- package/dist/markdown-core/syntax/stream-heal-syntax.js +108 -0
- package/dist/markdown-core/syntax/task-source.d.ts +10 -0
- package/dist/markdown-core/syntax/task-source.js +34 -0
- package/dist/markdown-core/syntax/useDocumentProperties.d.ts +3 -0
- package/dist/markdown-core/syntax/useDocumentProperties.js +8 -0
- package/dist/math-vendor-LICENSE-NOTICE.md +18 -0
- package/dist/styles.css +0 -0
- package/dist/utils/addressWithoutNavigating.d.ts +68 -0
- package/dist/utils/addressWithoutNavigating.js +60 -0
- package/dist/utils/client-lazy.d.ts +13 -0
- package/dist/utils/client-lazy.js +24 -0
- package/dist/utils/decision-options.d.ts +21 -0
- package/dist/utils/decision-options.js +32 -0
- package/dist/utils/gfm-lexer.d.ts +5 -0
- package/dist/utils/gfm-lexer.js +10 -0
- package/dist/utils/json.d.ts +63 -0
- package/dist/utils/json.js +22 -0
- package/dist/utils/plain-title.d.ts +25 -0
- package/dist/utils/plain-title.js +51 -0
- package/dist/utils/table-source.d.ts +62 -0
- package/dist/utils/table-source.js +191 -0
- package/dist/utils/youtube.d.ts +52 -0
- package/dist/utils/youtube.js +137 -0
- package/package.json +132 -5
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* THE MATRIX BINDING of `@ai-matrx/content-ir-react`'s route environment.
|
|
3
|
+
*
|
|
4
|
+
* The render DECISIONS live in the package; the registries, the resolution
|
|
5
|
+
* platform, and the error sink are ours. This module is the one place those
|
|
6
|
+
* two halves meet, and it is deliberately React-free so reducers, stream
|
|
7
|
+
* accumulators, and tests can import it.
|
|
8
|
+
*/
|
|
9
|
+
import type { KindRouteEnv } from "@ai-matrx/content-ir-react";
|
|
10
|
+
/**
|
|
11
|
+
* `web` is not a placeholder: `content_ir.kind_component.platform` already
|
|
12
|
+
* models react-native and friends, and a host that lies here renders the wrong
|
|
13
|
+
* component everywhere. This app is the web one.
|
|
14
|
+
*/
|
|
15
|
+
export declare const MATRX_CONTENT_IR_PLATFORM: "web";
|
|
16
|
+
export declare const matrxKindRouteEnv: KindRouteEnv;
|
|
17
|
+
/**
|
|
18
|
+
* Block types THIS app owns and the route must never re-type.
|
|
19
|
+
*
|
|
20
|
+
* An `artifact` block has an identity, a version, and a Canvas to open in, and
|
|
21
|
+
* since 2026-08-18 it carries `metadata.__ir` so SELECTORS can read the
|
|
22
|
+
* envelope (`selectKindEnvelope` — the live flashcard preview and every other
|
|
23
|
+
* wrapped-payload surface). That envelope is DATA there, not a route: routing
|
|
24
|
+
* it to the bare kind component would strip the artifact chrome and lose the
|
|
25
|
+
* door to the Canvas.
|
|
26
|
+
*
|
|
27
|
+
* A `matrx` block is a Kind Directive — its reserved-namespace slug is BY
|
|
28
|
+
* DESIGN never a kind_definition row, so any resolution the route could find
|
|
29
|
+
* for it would be wrong, and re-typing it away from MatrxEnvelopeBlock
|
|
30
|
+
* re-opens the raw-JSON break the Kind Directives merge closed (adversarial
|
|
31
|
+
* finding A-8: today the block survives only because the lookup misses).
|
|
32
|
+
*/
|
|
33
|
+
export declare const MATRX_OWNED_BLOCK_TYPES: readonly ["artifact", "matrx"];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { captureError } from "../../host/diagnostics.js";
|
|
2
|
+
import { kindRegistry } from "../../host/kind-registry.js";
|
|
3
|
+
import { componentRegistry } from "../../host/component-registry.js";
|
|
4
|
+
const MATRX_CONTENT_IR_PLATFORM = "web";
|
|
5
|
+
const matrxKindRouteEnv = {
|
|
6
|
+
kinds: kindRegistry,
|
|
7
|
+
components: componentRegistry,
|
|
8
|
+
reportError: (report) => captureError(report),
|
|
9
|
+
platform: MATRX_CONTENT_IR_PLATFORM
|
|
10
|
+
};
|
|
11
|
+
const MATRX_OWNED_BLOCK_TYPES = ["artifact", "matrx"];
|
|
12
|
+
export {
|
|
13
|
+
MATRX_CONTENT_IR_PLATFORM,
|
|
14
|
+
MATRX_OWNED_BLOCK_TYPES,
|
|
15
|
+
matrxKindRouteEnv
|
|
16
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { FoundKindMarker } from "./kind-problems.js";
|
|
3
|
+
export declare function KindEscapedNotice({ markers, rendered, }: {
|
|
4
|
+
markers: FoundKindMarker[];
|
|
5
|
+
/**
|
|
6
|
+
* The host already drew the value as its kind (the JSON block's settled
|
|
7
|
+
* kind route, Arman 2026-09-30). A REGISTERED slug is still reported — it
|
|
8
|
+
* escaped the promotion path — but the line saying it is "not rendering as
|
|
9
|
+
* its component" would now be false, so nothing is shown. An UNREGISTERED
|
|
10
|
+
* slug keeps its line.
|
|
11
|
+
*/
|
|
12
|
+
rendered?: boolean;
|
|
13
|
+
}): React.JSX.Element | null;
|
|
14
|
+
export default KindEscapedNotice;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { humanizeIdentifier } from "@ai-matrx/kit/text-case";
|
|
4
|
+
import { useEffect } from "react";
|
|
5
|
+
import { TriangleAlert } from "lucide-react";
|
|
6
|
+
import { isTableKind } from "@ai-matrx/records";
|
|
7
|
+
import { kindRegistry } from "../../host/kind-registry.js";
|
|
8
|
+
import { useEnsureKindRenderable } from "./ensure-kind-renderable.js";
|
|
9
|
+
import { useContentIrKindVersion } from "./use-registry-repaint.js";
|
|
10
|
+
import { readAtVersionForKey } from "./registry-versioned.js";
|
|
11
|
+
import { reportKindComponentIncident } from "../../host/kind-incident.js";
|
|
12
|
+
import { captureError } from "../../host/diagnostics.js";
|
|
13
|
+
const screamed = /* @__PURE__ */ new Set();
|
|
14
|
+
const registeredCache = /* @__PURE__ */ new Map();
|
|
15
|
+
function KindEscapedNotice({
|
|
16
|
+
markers,
|
|
17
|
+
rendered = false
|
|
18
|
+
}) {
|
|
19
|
+
const first = markers[0] ?? null;
|
|
20
|
+
const slug = first?.slug ?? null;
|
|
21
|
+
useEnsureKindRenderable(slug);
|
|
22
|
+
const kindVersion = useContentIrKindVersion(slug);
|
|
23
|
+
const registered = readAtVersionForKey(
|
|
24
|
+
registeredCache,
|
|
25
|
+
slug ?? "",
|
|
26
|
+
kindVersion,
|
|
27
|
+
() => Boolean(slug && kindRegistry.isRenderableKind(slug))
|
|
28
|
+
);
|
|
29
|
+
const tableKind = isTableKind(slug);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (!slug || !registered || tableKind) return;
|
|
32
|
+
const firstPath = first?.path;
|
|
33
|
+
const key = `${slug}:${firstPath === void 0 ? "" : firstPath}`;
|
|
34
|
+
if (screamed.has(key)) return;
|
|
35
|
+
screamed.add(key);
|
|
36
|
+
captureError({
|
|
37
|
+
source: "content-ir",
|
|
38
|
+
relation: slug,
|
|
39
|
+
message: `Registered kind "${slug}" rendered as a raw JSON code block \u2014 it escaped the promotion path (path: ${first?.path || "root"}).`,
|
|
40
|
+
hint: "The accumulator/splitter should have promoted this region (or embedded-kind recovery should have caught it). Find which arrival path delivered it.",
|
|
41
|
+
recoverable: true
|
|
42
|
+
});
|
|
43
|
+
reportKindComponentIncident({
|
|
44
|
+
kind: slug,
|
|
45
|
+
errorType: "kind_escaped_render",
|
|
46
|
+
message: `Registered kind "${slug}" rendered as a raw JSON code block (escaped the promotion path at ${first?.path || "root"}).`
|
|
47
|
+
});
|
|
48
|
+
}, [slug, registered, tableKind, first?.path]);
|
|
49
|
+
if (!first) return null;
|
|
50
|
+
if (rendered && registered) return null;
|
|
51
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-1 flex items-start gap-1.5 text-xs text-amber-700 dark:text-amber-400", children: [
|
|
52
|
+
/* @__PURE__ */ jsx(TriangleAlert, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
|
|
53
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
54
|
+
registered ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
55
|
+
"This JSON contains a ",
|
|
56
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: humanizeIdentifier(first.slug) }),
|
|
57
|
+
" ",
|
|
58
|
+
"Shape instance that is not rendering as its component \u2014 this is a pipeline defect and has been reported."
|
|
59
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
60
|
+
"This JSON declares a Shape (",
|
|
61
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium", children: humanizeIdentifier(first.slug) }),
|
|
62
|
+
") that isn't registered on this platform \u2014 check the name, or create the Shape to render it properly."
|
|
63
|
+
] }),
|
|
64
|
+
markers.length > 1 ? ` (+${markers.length - 1} more)` : null
|
|
65
|
+
] })
|
|
66
|
+
] });
|
|
67
|
+
}
|
|
68
|
+
var KindEscapedNotice_default = KindEscapedNotice;
|
|
69
|
+
export {
|
|
70
|
+
KindEscapedNotice,
|
|
71
|
+
KindEscapedNotice_default as default
|
|
72
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Matrix binding of the provisional-render safety net and the "still
|
|
3
|
+
* arriving" affordance (streaming partial kinds).
|
|
4
|
+
*
|
|
5
|
+
* Both live in `@ai-matrx/content-ir-react`: the boundary catches a component
|
|
6
|
+
* that throws on a provisional value, SCREAMS to the Error Inspector, drops the
|
|
7
|
+
* kind back to withhold for the session, and falls back to that kind's loading
|
|
8
|
+
* skeleton; the frame rides a `ShimmerText` chip on the block's top edge with
|
|
9
|
+
* no layout cost. Read the semantics there.
|
|
10
|
+
*/
|
|
11
|
+
import type { ReactNode } from "react";
|
|
12
|
+
export declare function ProvisionalKindBoundary(props: {
|
|
13
|
+
kind: string;
|
|
14
|
+
fallback: ReactNode;
|
|
15
|
+
children: ReactNode;
|
|
16
|
+
}): import("react").JSX.Element;
|
|
17
|
+
export declare function ProvisionalKindFrame({ children }: {
|
|
18
|
+
children: ReactNode;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import {
|
|
4
|
+
ProvisionalKindBoundary as SharedProvisionalKindBoundary,
|
|
5
|
+
ProvisionalKindFrame as SharedProvisionalKindFrame
|
|
6
|
+
} from "@ai-matrx/content-ir-react";
|
|
7
|
+
import { ContentIrHostBoundary } from "../../host/ContentIrHostBoundary.js";
|
|
8
|
+
function ProvisionalKindBoundary(props) {
|
|
9
|
+
return /* @__PURE__ */ jsx(ContentIrHostBoundary, { children: /* @__PURE__ */ jsx(SharedProvisionalKindBoundary, { ...props }) });
|
|
10
|
+
}
|
|
11
|
+
function ProvisionalKindFrame({ children }) {
|
|
12
|
+
return /* @__PURE__ */ jsx(ContentIrHostBoundary, { children: /* @__PURE__ */ jsx(SharedProvisionalKindFrame, { children }) });
|
|
13
|
+
}
|
|
14
|
+
export {
|
|
15
|
+
ProvisionalKindBoundary,
|
|
16
|
+
ProvisionalKindFrame
|
|
17
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fire-and-forget: make sure this kind's schema and web output component are
|
|
3
|
+
* fetched (or known-missing). Safe to call redundantly — every layer dedupes.
|
|
4
|
+
*
|
|
5
|
+
* DD-215: the demand is UNCONDITIONAL for the component. See the comment in
|
|
6
|
+
* the body — a resolution that exists is not the same as a resolution that is
|
|
7
|
+
* settled, and the difference is which component a reader sees.
|
|
8
|
+
*/
|
|
9
|
+
export declare function ensureKindRenderable(kind: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Hook form for render paths: request on mount and whenever the kind
|
|
12
|
+
* changes. Pass null for blocks with no envelope kind (nothing to fetch).
|
|
13
|
+
*/
|
|
14
|
+
export declare function useEnsureKindRenderable(kind: string | null): void;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { kindRegistry } from "../../host/kind-registry.js";
|
|
4
|
+
import { componentRegistry } from "../../host/component-registry.js";
|
|
5
|
+
import { MATRX_CONTENT_IR_PLATFORM } from "../host/route-env.js";
|
|
6
|
+
function ensureKindRenderable(kind) {
|
|
7
|
+
if (!kindRegistry.getSchema(kind)) {
|
|
8
|
+
kindRegistry.requestSchema(kind);
|
|
9
|
+
}
|
|
10
|
+
componentRegistry.requestComponent(kind, MATRX_CONTENT_IR_PLATFORM, "output");
|
|
11
|
+
announceWrongComponent(kind);
|
|
12
|
+
}
|
|
13
|
+
function announceWrongComponent(kind) {
|
|
14
|
+
const resolution = componentRegistry.resolve(
|
|
15
|
+
kind,
|
|
16
|
+
MATRX_CONTENT_IR_PLATFORM,
|
|
17
|
+
"output"
|
|
18
|
+
);
|
|
19
|
+
const sourcelessDbRow = resolution?.resolvedBy === "db" && resolution.source === "db" && resolution.isActive && !resolution.hasComponentSource;
|
|
20
|
+
if (!sourcelessDbRow && !componentRegistry.wasRefused(kind)) return;
|
|
21
|
+
void (async () => {
|
|
22
|
+
try {
|
|
23
|
+
const { reportKindComponentIncident } = await import("../../host/kind-incident.js");
|
|
24
|
+
reportKindComponentIncident({
|
|
25
|
+
kind,
|
|
26
|
+
errorType: "component_read_refused",
|
|
27
|
+
platform: MATRX_CONTENT_IR_PLATFORM,
|
|
28
|
+
role: "output",
|
|
29
|
+
componentKey: resolution?.componentKey ?? null,
|
|
30
|
+
componentUpdatedAt: resolution?.updatedAt ?? null,
|
|
31
|
+
message: sourcelessDbRow ? `"${kind}" is bound to the active component "${resolution?.componentKey}" (source='db'), but the resolver holds no body for it, so the route refused it and the reader was shown the platform's bundled component instead. Nothing will fetch the body again on its own.` : `The reader was shown the platform's bundled component for "${kind}" because this organization's component row could not be READ \u2014 the request carried no session and the door refused it.`
|
|
32
|
+
});
|
|
33
|
+
} catch {
|
|
34
|
+
}
|
|
35
|
+
})();
|
|
36
|
+
}
|
|
37
|
+
function useEnsureKindRenderable(kind) {
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (kind) ensureKindRenderable(kind);
|
|
40
|
+
}, [kind]);
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
ensureKindRenderable,
|
|
44
|
+
useEnsureKindRenderable
|
|
45
|
+
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The kind-problems reader — the ONE place the parser's recorded evidence of a
|
|
3
|
+
* broken / degraded / unroutable kind instance is flattened for human display.
|
|
4
|
+
*
|
|
5
|
+
* WHY THIS EXISTS (Arman, 2026-08-29): the parser has always recorded exactly
|
|
6
|
+
* what went wrong with a kind region — `residue.notices` carries `parse_error`,
|
|
7
|
+
* `raw_fallback` (schema violations, duplicate keys, missing `__kind`),
|
|
8
|
+
* `degrade_data_rescued`; `root.status`/`kindState` carry degradation; the
|
|
9
|
+
* route marker carries why no component rendered — and NOTHING in the UI ever
|
|
10
|
+
* read any of it. A shape that failed rendered as an anonymous key/value dump,
|
|
11
|
+
* indistinguishable from data that was never a shape at all. That silence is
|
|
12
|
+
* what made kind rendering feel random. This module turns that evidence into
|
|
13
|
+
* `KindProblem[]`, consumed by the Errors tab in `StructuredValueTabs` — so a
|
|
14
|
+
* broken kind is ACKNOWLEDGED as a kind, with its exact problems, everywhere
|
|
15
|
+
* the fallback renders.
|
|
16
|
+
*
|
|
17
|
+
* Pure over envelope data (`CanonicalBlockIR` is plain JSON from
|
|
18
|
+
* `@ai-matrx/content-ir`). Host diagnostics are host property (content-ir-twin
|
|
19
|
+
* boundary) — this makes no routing decision and renders nothing.
|
|
20
|
+
*/
|
|
21
|
+
import type { CanonicalBlockIR } from "@ai-matrx/content-ir";
|
|
22
|
+
import type { IrRouteMarker } from "./kind-route.js";
|
|
23
|
+
export type KindProblemSeverity = "error" | "warning" | "info";
|
|
24
|
+
export interface KindProblem {
|
|
25
|
+
/** Stable machine code (`parse_error`, `raw_fallback`, `component_inactive`, …). */
|
|
26
|
+
code: string;
|
|
27
|
+
/** Human sentence — shown verbatim in the Errors tab. */
|
|
28
|
+
message: string;
|
|
29
|
+
/** Region-relative path of the node the problem is about ("" = root). */
|
|
30
|
+
path?: string;
|
|
31
|
+
severity: KindProblemSeverity;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Flatten everything the envelope + route marker recorded about why this kind
|
|
35
|
+
* instance is not rendering as its component. Empty array = a clean value that
|
|
36
|
+
* simply has no component yet (the fix-it bar's territory, not an error).
|
|
37
|
+
*/
|
|
38
|
+
export declare function collectKindProblems(envelope: CanonicalBlockIR | null | undefined, marker?: IrRouteMarker | null): KindProblem[];
|
|
39
|
+
/** True when any collected problem is a real error (drives the tab's tint). */
|
|
40
|
+
export declare function hasKindErrors(problems: KindProblem[]): boolean;
|
|
41
|
+
export interface FoundKindMarker {
|
|
42
|
+
slug: string;
|
|
43
|
+
/** Dotted path inside the scanned value ("" = the value itself). */
|
|
44
|
+
path: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Deep-scan a parsed JSON value for `__kind` markers — the tripwire for a kind
|
|
48
|
+
* instance that escaped the promotion path and is being shown as anonymous
|
|
49
|
+
* JSON. Bounded (node + depth caps) so a pathological payload cannot stall a
|
|
50
|
+
* render; caps mean "found some", never an exhaustive census.
|
|
51
|
+
*/
|
|
52
|
+
export declare function findKindMarkers(value: unknown, limit?: number): FoundKindMarker[];
|
|
53
|
+
/**
|
|
54
|
+
* Keep the raw-JSON tripwire about the boundary it can actually prove.
|
|
55
|
+
*
|
|
56
|
+
* A marker is escaped only when the canonical envelope did not already claim
|
|
57
|
+
* that exact path/kind. A schema-invalid kind deliberately remains on the raw
|
|
58
|
+
* JSON fallback, but it was still promoted; reporting it as a promotion crack
|
|
59
|
+
* sends repair patrols to the wrong producer and hides the real validation
|
|
60
|
+
* evidence carried by the envelope.
|
|
61
|
+
*/
|
|
62
|
+
export declare function findEscapedKindMarkers(value: unknown, envelope: CanonicalBlockIR | null | undefined, limit?: number): FoundKindMarker[];
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
const ERROR_NOTICE_CODES = /* @__PURE__ */ new Set(["parse_error", "raw_fallback"]);
|
|
2
|
+
function noticeSeverity(code) {
|
|
3
|
+
if (ERROR_NOTICE_CODES.has(code)) return "error";
|
|
4
|
+
if (code === "partial_unvalidated") return "info";
|
|
5
|
+
return "warning";
|
|
6
|
+
}
|
|
7
|
+
function residueProblems(residue, path) {
|
|
8
|
+
if (!residue) return [];
|
|
9
|
+
const problems = [];
|
|
10
|
+
for (const notice of residue.notices ?? []) {
|
|
11
|
+
problems.push({
|
|
12
|
+
code: notice.code,
|
|
13
|
+
message: notice.message,
|
|
14
|
+
...path ? { path } : {},
|
|
15
|
+
severity: noticeSeverity(notice.code)
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
const extraKeys = residue.extra ? Object.keys(residue.extra) : [];
|
|
19
|
+
if (extraKeys.length > 0) {
|
|
20
|
+
problems.push({
|
|
21
|
+
code: "unknown_keys",
|
|
22
|
+
message: `Keys not in this shape's schema (kept, not lost): ${extraKeys.join(", ")}`,
|
|
23
|
+
...path ? { path } : {},
|
|
24
|
+
severity: "warning"
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return problems;
|
|
28
|
+
}
|
|
29
|
+
function collectKindProblems(envelope, marker) {
|
|
30
|
+
const problems = [];
|
|
31
|
+
if (envelope) {
|
|
32
|
+
const root = envelope.root;
|
|
33
|
+
if (root.status === "error") {
|
|
34
|
+
problems.push({
|
|
35
|
+
code: "region_error",
|
|
36
|
+
message: "This region hit a fatal parse error \u2014 the payload below is what arrived before it broke.",
|
|
37
|
+
severity: "error"
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
if (root.kindState === "raw" && root.kind) {
|
|
41
|
+
problems.push({
|
|
42
|
+
code: "degraded_raw",
|
|
43
|
+
message: `This is a "${root.kind}" shape instance, but it could not be validated against the shape's schema, so it degraded to plain data.`,
|
|
44
|
+
severity: "error"
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
if (root.kindState === "pending_schema") {
|
|
48
|
+
problems.push({
|
|
49
|
+
code: "schema_unavailable",
|
|
50
|
+
message: `The schema for "${root.kind}" had not loaded when this region finished.`,
|
|
51
|
+
severity: "warning"
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (root.kindState === "unverified" && root.kind) {
|
|
55
|
+
problems.push({
|
|
56
|
+
code: "schema_unavailable",
|
|
57
|
+
message: `No field schema is registered for "${root.kind}", so this payload could not be checked. The data is shown as it arrived \u2014 this is a gap in the shape, not in the content.`,
|
|
58
|
+
severity: "warning"
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
problems.push(...residueProblems(root.residue, ""));
|
|
62
|
+
if (envelope.nodeIndex) {
|
|
63
|
+
for (const [pathKey, node] of Object.entries(envelope.nodeIndex)) {
|
|
64
|
+
if (node.kindState === "raw" && node.kind) {
|
|
65
|
+
problems.push({
|
|
66
|
+
code: "nested_degraded_raw",
|
|
67
|
+
message: `Nested "${node.kind}" at ${pathKey} failed validation and degraded to plain data.`,
|
|
68
|
+
path: pathKey,
|
|
69
|
+
severity: "error"
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
problems.push(...residueProblems(node.residue, pathKey));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
if (marker?.reason === "inactive") {
|
|
77
|
+
problems.push({
|
|
78
|
+
code: "component_inactive",
|
|
79
|
+
message: "A component is registered for this shape but is held inactive \u2014 activate it to render this properly.",
|
|
80
|
+
severity: "warning"
|
|
81
|
+
});
|
|
82
|
+
} else if (marker?.reason === "generic-row") {
|
|
83
|
+
problems.push({
|
|
84
|
+
code: "generic_component_row",
|
|
85
|
+
message: "This shape's registered component IS the generic viewer \u2014 a real component still needs to be authored.",
|
|
86
|
+
severity: "warning"
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
return problems;
|
|
90
|
+
}
|
|
91
|
+
function hasKindErrors(problems) {
|
|
92
|
+
return problems.some((p) => p.severity === "error");
|
|
93
|
+
}
|
|
94
|
+
const KIND_KEY = "__kind";
|
|
95
|
+
const SCAN_NODE_CAP = 2e3;
|
|
96
|
+
const SCAN_DEPTH_CAP = 8;
|
|
97
|
+
function findKindMarkers(value, limit = 5) {
|
|
98
|
+
const found = [];
|
|
99
|
+
let visited = 0;
|
|
100
|
+
const walk = (node, path, depth) => {
|
|
101
|
+
if (found.length >= limit) return;
|
|
102
|
+
if (visited++ > SCAN_NODE_CAP || depth > SCAN_DEPTH_CAP) return;
|
|
103
|
+
if (Array.isArray(node)) {
|
|
104
|
+
node.forEach(
|
|
105
|
+
(item, i) => walk(item, path ? `${path}.${i}` : String(i), depth + 1)
|
|
106
|
+
);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (typeof node !== "object" || node === null) return;
|
|
110
|
+
const record = node;
|
|
111
|
+
const slug = record[KIND_KEY];
|
|
112
|
+
if (typeof slug === "string" && slug.trim()) {
|
|
113
|
+
found.push({ slug: slug.trim(), path });
|
|
114
|
+
}
|
|
115
|
+
for (const [key, child] of Object.entries(record)) {
|
|
116
|
+
if (key === KIND_KEY) continue;
|
|
117
|
+
walk(child, path ? `${path}.${key}` : key, depth + 1);
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
walk(value, "", 0);
|
|
121
|
+
return found;
|
|
122
|
+
}
|
|
123
|
+
function findEscapedKindMarkers(value, envelope, limit = 5) {
|
|
124
|
+
return findKindMarkers(value, limit).filter((marker) => {
|
|
125
|
+
const claimedNode = marker.path ? envelope?.nodeIndex?.[marker.path] : envelope?.root;
|
|
126
|
+
return claimedNode?.kind !== marker.slug;
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
export {
|
|
130
|
+
collectKindProblems,
|
|
131
|
+
findEscapedKindMarkers,
|
|
132
|
+
findKindMarkers,
|
|
133
|
+
hasKindErrors
|
|
134
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Matrix binding of THE KIND ROUTE.
|
|
3
|
+
*
|
|
4
|
+
* The route itself — envelope → registered kind → the right component, with the
|
|
5
|
+
* db-override flip, the compiled-bridge path, the resolver path, and the R6
|
|
6
|
+
* generic fallback — lives in `@ai-matrx/content-ir-react`
|
|
7
|
+
* (`route/kind-route.ts`), and since 0.8.0 the per-host partial application
|
|
8
|
+
* does too (`createKindRouteBinding`). Read the semantics there.
|
|
9
|
+
*
|
|
10
|
+
* This module only INJECTS our env + owned block types (host/route-env.ts) and
|
|
11
|
+
* keeps the historical import path stable so ~60 call sites and every doc
|
|
12
|
+
* pointer still read the same.
|
|
13
|
+
*/
|
|
14
|
+
export { DB_KIND_COMPONENT_KEY, GENERIC_STRUCTURED_COMPONENT_KEY, IR_ROUTE_KEY, readIrRouteMarker, type GenericFallbackReason, type IrRoutableBlock, type IrRouteMarker, } from "@ai-matrx/content-ir-react";
|
|
15
|
+
/** Route one block through the Matrix registries. */
|
|
16
|
+
export declare const applyIrKindRoute: <T extends import("@ai-matrx/content-ir-react").IrRoutableBlock>(block: T) => T;
|
|
17
|
+
/**
|
|
18
|
+
* Rehydration route for STRUCTURED persisted artifacts (Track 2B): given a
|
|
19
|
+
* stored zero-loss value object, derive the registered kind's legacy
|
|
20
|
+
* `serverData` with no re-parse. Null for non-objects, unregistered kinds, or
|
|
21
|
+
* kinds without a legacy bridge.
|
|
22
|
+
*/
|
|
23
|
+
export declare const kindServerDataFromStoredValue: (value: unknown) => Record<string, unknown> | null;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createKindRouteBinding } from "@ai-matrx/content-ir-react";
|
|
2
|
+
import {
|
|
3
|
+
MATRX_OWNED_BLOCK_TYPES,
|
|
4
|
+
matrxKindRouteEnv
|
|
5
|
+
} from "../host/route-env.js";
|
|
6
|
+
import {
|
|
7
|
+
DB_KIND_COMPONENT_KEY,
|
|
8
|
+
GENERIC_STRUCTURED_COMPONENT_KEY,
|
|
9
|
+
IR_ROUTE_KEY,
|
|
10
|
+
readIrRouteMarker
|
|
11
|
+
} from "@ai-matrx/content-ir-react";
|
|
12
|
+
const binding = createKindRouteBinding(matrxKindRouteEnv, {
|
|
13
|
+
ownedTypes: MATRX_OWNED_BLOCK_TYPES
|
|
14
|
+
});
|
|
15
|
+
const applyIrKindRoute = binding.applyIrKindRoute;
|
|
16
|
+
const kindServerDataFromStoredValue = binding.kindServerDataFromStoredValue;
|
|
17
|
+
export {
|
|
18
|
+
DB_KIND_COMPONENT_KEY,
|
|
19
|
+
GENERIC_STRUCTURED_COMPONENT_KEY,
|
|
20
|
+
IR_ROUTE_KEY,
|
|
21
|
+
applyIrKindRoute,
|
|
22
|
+
kindServerDataFromStoredValue,
|
|
23
|
+
readIrRouteMarker
|
|
24
|
+
};
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DERIVED loading slugs — the smart floor under the declared one.
|
|
3
|
+
*
|
|
4
|
+
* A kind that never declared `metadata.loading_component` used to fall all
|
|
5
|
+
* the way through to the `generic` skeleton, which tells the reader nothing
|
|
6
|
+
* about what is coming. On 2026-08-25 that was 354 of the 357 renderable
|
|
7
|
+
* ACTIVE kinds: a backlog nobody can close one row at a time.
|
|
8
|
+
*
|
|
9
|
+
* So the fallback stops being dumb. A kind's own SCHEMA already says what
|
|
10
|
+
* shape it is — a long prose body is a document, a list of structured items
|
|
11
|
+
* is a list, image fields are media — and the loader whose silhouette
|
|
12
|
+
* matches the finished component is derivable from exactly that. Every kind
|
|
13
|
+
* therefore gets a shape-appropriate loader with zero authoring, zero DB
|
|
14
|
+
* writes, and zero deploys.
|
|
15
|
+
*
|
|
16
|
+
* PRECEDENCE — declaration always wins:
|
|
17
|
+
* metadata.loading_component → this derivation → `generic`
|
|
18
|
+
* so setting a slug is still the way to override. The order is executed in
|
|
19
|
+
* ONE place, `resolve-loading-slug.ts` — never re-inline it as a `??` chain,
|
|
20
|
+
* because an INVALID declaration has to fall through to this derivation
|
|
21
|
+
* rather than short-circuit to `generic`.
|
|
22
|
+
*
|
|
23
|
+
* The shape doctor agrees with that precedence (2026-08-25): a kind with a
|
|
24
|
+
* DERIVED loader reads `ok` and raises no finding, because a shape-appropriate
|
|
25
|
+
* loader is a real loader however it was chosen. The `no-loading-component`
|
|
26
|
+
* yellow now fires only when derivation finds nothing distinctive either — the
|
|
27
|
+
* kinds that genuinely do stream behind the generic skeleton (428 yellows
|
|
28
|
+
* became 19).
|
|
29
|
+
*
|
|
30
|
+
* The rules read the schema, never the instance value: derivation must be
|
|
31
|
+
* stable for a kind, identical on every render, and available before a
|
|
32
|
+
* single byte of the value has arrived.
|
|
33
|
+
*/
|
|
34
|
+
import type { KindSchema } from "@ai-matrx/content-ir";
|
|
35
|
+
import type { KindLoadingSlug } from "./kind-loading-slugs.js";
|
|
36
|
+
/**
|
|
37
|
+
* The best-matching library slug for this schema, or null when nothing in the
|
|
38
|
+
* shape is distinctive enough to beat the generic skeleton.
|
|
39
|
+
*
|
|
40
|
+
* Ordered most-specific first. The order encodes a judgment made with Arman
|
|
41
|
+
* on 2026-08-24 while looking at real shapes: a kind with BOTH a prose body
|
|
42
|
+
* and structured lists (a newsjacking article: `article_body` + quotes +
|
|
43
|
+
* sources + faqs) reads as a DOCUMENT, because the body is what fills the
|
|
44
|
+
* screen — the lists are supporting material.
|
|
45
|
+
*/
|
|
46
|
+
export declare function inferLoadingSlug(schema: KindSchema | undefined | null): KindLoadingSlug | null;
|
|
47
|
+
/**
|
|
48
|
+
* The SAME derivation over a raw JSON Schema.
|
|
49
|
+
*
|
|
50
|
+
* Most kinds have no parser `KindSchema` at all: Python owns them and stores
|
|
51
|
+
* only `emitted_json_schema` (344 of 392 undeclared renderable kinds on
|
|
52
|
+
* 2026-08-25, measured — `kind_definition.data` is NULL for every one). A
|
|
53
|
+
* derivation that reads only `KindSchema` is therefore blind to the large
|
|
54
|
+
* majority of the backlog it exists to serve, which is why this second door
|
|
55
|
+
* exists rather than a second set of rules: both doors normalize to the same
|
|
56
|
+
* `{name → type}` census and run the identical precedence above.
|
|
57
|
+
*/
|
|
58
|
+
export declare function inferLoadingSlugFromJsonSchema(jsonSchema: unknown): KindLoadingSlug | null;
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
const MEDIA_NAME = /(^|_)(image|images|photo|photos|thumbnail|cover_image|video|videos|audio|media)(_|$)/i;
|
|
2
|
+
const GALLERY_NAME = /(^|_)(gallery|images|photos|screenshots|slides_images)(_|$)/i;
|
|
3
|
+
const BODY_NAME = /(^|_)(body|article_body|content|markdown|text|prose|transcript|summary_long|full_text|report|essay|description_long)(_|$)/i;
|
|
4
|
+
const CODE_NAME = /(^|_)(code|snippet|source|diff|patch|sql|script)(_|$)/i;
|
|
5
|
+
const DOC_ARRAY_NAME = /(^|_)(sections|chapters|paragraphs|pages)(_|$)/i;
|
|
6
|
+
const CHART_NAME = /(^|_)(series|datapoints|data_points|metrics|chart|trend|timeseries)(_|$)/i;
|
|
7
|
+
const TIMELINE_NAME = /(^|_)(timeline|events|milestones|history|phases|periods)(_|$)/i;
|
|
8
|
+
const STEP_NAME = /(^|_)(steps|stages|progress|checklist|tasks)(_|$)/i;
|
|
9
|
+
const STAT_NAME = /(^|_)(stats|statistics|totals|counts|kpis|summary_stats)(_|$)/i;
|
|
10
|
+
function isStructuredArray(field) {
|
|
11
|
+
return field.type === "array" || field.type === "json[]";
|
|
12
|
+
}
|
|
13
|
+
function isProseField(name, field) {
|
|
14
|
+
return field.type === "string" && BODY_NAME.test(name);
|
|
15
|
+
}
|
|
16
|
+
function inferLoadingSlug(schema) {
|
|
17
|
+
if (!schema) return null;
|
|
18
|
+
if (schema.root) {
|
|
19
|
+
if (schema.root.type === "string") return "document";
|
|
20
|
+
if (isStructuredArray(schema.root)) return "list";
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const entries = Object.entries(schema.fields ?? {}).filter(
|
|
24
|
+
([name]) => name !== "__kind"
|
|
25
|
+
);
|
|
26
|
+
if (entries.length === 0) return null;
|
|
27
|
+
let hasProse = false;
|
|
28
|
+
let hasDocArray = false;
|
|
29
|
+
let structuredArrays = 0;
|
|
30
|
+
let hasMedia = false;
|
|
31
|
+
let hasGallery = false;
|
|
32
|
+
let hasCode = false;
|
|
33
|
+
let hasChart = false;
|
|
34
|
+
let hasTimeline = false;
|
|
35
|
+
let hasSteps = false;
|
|
36
|
+
let hasStats = false;
|
|
37
|
+
for (const [name, field] of entries) {
|
|
38
|
+
if (!field || typeof field !== "object") continue;
|
|
39
|
+
if (isProseField(name, field)) hasProse = true;
|
|
40
|
+
if (isStructuredArray(field)) {
|
|
41
|
+
structuredArrays += 1;
|
|
42
|
+
if (DOC_ARRAY_NAME.test(name)) hasDocArray = true;
|
|
43
|
+
if (GALLERY_NAME.test(name)) hasGallery = true;
|
|
44
|
+
if (CHART_NAME.test(name)) hasChart = true;
|
|
45
|
+
if (TIMELINE_NAME.test(name)) hasTimeline = true;
|
|
46
|
+
if (STEP_NAME.test(name)) hasSteps = true;
|
|
47
|
+
if (STAT_NAME.test(name)) hasStats = true;
|
|
48
|
+
}
|
|
49
|
+
if (MEDIA_NAME.test(name) && !isStructuredArray(field)) hasMedia = true;
|
|
50
|
+
if (CODE_NAME.test(name) && field.type === "string") hasCode = true;
|
|
51
|
+
}
|
|
52
|
+
if (hasGallery) return "gallery";
|
|
53
|
+
if (hasMedia) return "media";
|
|
54
|
+
if (hasProse || hasDocArray) return "document";
|
|
55
|
+
if (hasCode) return "code";
|
|
56
|
+
if (hasTimeline) return "timeline";
|
|
57
|
+
if (hasChart) return "chart";
|
|
58
|
+
if (hasSteps) return "progress";
|
|
59
|
+
if (hasStats) return "stat-grid";
|
|
60
|
+
if (structuredArrays > 0) return "list";
|
|
61
|
+
if (entries.length >= 2 && entries.length <= 12) return "card";
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
function inferLoadingSlugFromJsonSchema(jsonSchema) {
|
|
65
|
+
if (!jsonSchema || typeof jsonSchema !== "object" || Array.isArray(jsonSchema)) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const root = jsonSchema;
|
|
69
|
+
const rootType = root.type;
|
|
70
|
+
if (rootType === "string") return "document";
|
|
71
|
+
if (rootType === "array") return "list";
|
|
72
|
+
const properties = root.properties;
|
|
73
|
+
if (!properties || typeof properties !== "object" || Array.isArray(properties)) {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const fields = {};
|
|
77
|
+
for (const [name, raw] of Object.entries(properties)) {
|
|
78
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) continue;
|
|
79
|
+
const prop = raw;
|
|
80
|
+
const type = prop.type;
|
|
81
|
+
if (type === "array") {
|
|
82
|
+
const items = prop.items;
|
|
83
|
+
const itemType = items && typeof items === "object" && !Array.isArray(items) ? items.type : void 0;
|
|
84
|
+
const structured = itemType === "object" || itemType === void 0 || // $ref'd child kind — structured by definition
|
|
85
|
+
items && typeof items === "object" && "$ref" in items;
|
|
86
|
+
fields[name] = { type: structured ? "array" : "string[]" };
|
|
87
|
+
continue;
|
|
88
|
+
}
|
|
89
|
+
if (type === "string") {
|
|
90
|
+
fields[name] = { type: "string" };
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
fields[name] = { type: typeof type === "string" ? type : "json" };
|
|
94
|
+
}
|
|
95
|
+
return inferLoadingSlug({ kind: "", fields });
|
|
96
|
+
}
|
|
97
|
+
export {
|
|
98
|
+
inferLoadingSlug,
|
|
99
|
+
inferLoadingSlugFromJsonSchema
|
|
100
|
+
};
|