@ai-matrx/content-ir 0.5.0 → 0.6.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.
- package/CHANGELOG.md +30 -0
- package/dist/index.cjs +108 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +108 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.0 — 2026-08-29
|
|
4
|
+
|
|
5
|
+
- **`$ref` / `$defs` resolution — a kind's child kinds are no longer invisible
|
|
6
|
+
to JSON Schema → KindSchema.** `convertAiSchemaToBlockFields` resolves `#`,
|
|
7
|
+
`#/$defs/<name>` and `#/definitions/<name>` in field position, in array
|
|
8
|
+
`items`, and inside `anyOf`/`oneOf` (including `items: {anyOf: [$ref, …]}`,
|
|
9
|
+
the multi-kind array). Referenced defs are registered as their own drafts,
|
|
10
|
+
with a cycle brake so a self-referencing kind terminates. An unresolvable
|
|
11
|
+
ref is a loud error, never a guess.
|
|
12
|
+
|
|
13
|
+
WHY: `kindSchemaToJsonSchema` externalizes every child kind as a `$def`, and
|
|
14
|
+
the reverse direction rejected `$ref` outright — so every
|
|
15
|
+
`{type:"object", kind}` and `{type:"array", itemKinds}` field came back
|
|
16
|
+
EMPTY. Measured over the 62 live kinds carrying both a stored field list and
|
|
17
|
+
a schema, 36 lost fields this way (sections, slides, nodes, edges, criteria,
|
|
18
|
+
questions, segments, …).
|
|
19
|
+
|
|
20
|
+
- **A `__kind`-carrying record reads back as a record.** An object whose only
|
|
21
|
+
declared property is `__kind`, with typed `additionalProperties`, is the
|
|
22
|
+
forward converter's emission for `{type:"record", values}` — it was widening
|
|
23
|
+
to an open `inline_object` and losing the value type.
|
|
24
|
+
|
|
25
|
+
- Live-corpus result: schema-derived KindSchemas now match the stored field
|
|
26
|
+
list byte-for-byte for 48 of 62 kinds, with 1 strictly richer. The remaining
|
|
27
|
+
13 are DIVERGENCE BETWEEN THE TWO STORED COPIES, not conversion gaps — 4
|
|
28
|
+
stored lists carry `__kind` as a data field (it is the discriminator, never
|
|
29
|
+
a field), and 9 disagree on enums, bounds, required flags or descriptions
|
|
30
|
+
the schema states and the copy does not. That is the evidence for retiring
|
|
31
|
+
the stored copy.
|
|
32
|
+
|
|
3
33
|
## 0.5.0 — 2026-08-29
|
|
4
34
|
|
|
5
35
|
- **A multi-type union is no longer silently narrowed to its first member.**
|
package/dist/index.cjs
CHANGED
|
@@ -3177,6 +3177,29 @@ function buildAgentSchemaWithRenderBlockSupport(input, rootKindSlug, arrayBindin
|
|
|
3177
3177
|
}
|
|
3178
3178
|
return updatedRoot;
|
|
3179
3179
|
}
|
|
3180
|
+
function resolveRef(ref, ctx) {
|
|
3181
|
+
if (ref === "#" || ref === "#/") {
|
|
3182
|
+
return { slug: ctx.schemaName, node: ctx.rootSchema };
|
|
3183
|
+
}
|
|
3184
|
+
const match = /^#\/(?:\$defs|definitions)\/(.+)$/.exec(ref);
|
|
3185
|
+
if (!match) return null;
|
|
3186
|
+
const name = decodeURIComponent(
|
|
3187
|
+
(match[1] ?? "").replace(/~1/g, "/").replace(/~0/g, "~")
|
|
3188
|
+
);
|
|
3189
|
+
const node = ctx.defs[name];
|
|
3190
|
+
if (!isRecord4(node)) return null;
|
|
3191
|
+
const declared = isRecord4(node.properties) ? readBlockKindFromProperties(node.properties) : null;
|
|
3192
|
+
return { slug: declared ?? name, node };
|
|
3193
|
+
}
|
|
3194
|
+
function refToObjectField(resolved, path, ctx) {
|
|
3195
|
+
if (ctx.refsInProgress.has(resolved.slug)) return;
|
|
3196
|
+
ctx.refsInProgress.add(resolved.slug);
|
|
3197
|
+
try {
|
|
3198
|
+
registerDeclaredKindDraft(resolved.slug, resolved.node, path, ctx);
|
|
3199
|
+
} finally {
|
|
3200
|
+
ctx.refsInProgress.delete(resolved.slug);
|
|
3201
|
+
}
|
|
3202
|
+
}
|
|
3180
3203
|
function isAnyValueSchema(node) {
|
|
3181
3204
|
return node.type === void 0 && node.enum === void 0 && node.const === void 0 && node.properties === void 0 && node.items === void 0 && node.additionalProperties === void 0 && node.anyOf === void 0 && node.oneOf === void 0 && node.allOf === void 0 && node.$ref === void 0;
|
|
3182
3205
|
}
|
|
@@ -3213,12 +3236,21 @@ function convertProperty(fieldName, node, required, path, ctx) {
|
|
|
3213
3236
|
}
|
|
3214
3237
|
function convertPropertyCore(fieldName, node, required, path, ctx) {
|
|
3215
3238
|
if (typeof node.$ref === "string") {
|
|
3216
|
-
ctx
|
|
3217
|
-
|
|
3218
|
-
|
|
3219
|
-
|
|
3220
|
-
|
|
3221
|
-
|
|
3239
|
+
const resolved = resolveRef(node.$ref, ctx);
|
|
3240
|
+
if (!resolved) {
|
|
3241
|
+
ctx.problems.push({
|
|
3242
|
+
severity: "error",
|
|
3243
|
+
path,
|
|
3244
|
+
message: `Unresolvable $ref ("${node.$ref}") \u2014 only "#", "#/$defs/<name>" and "#/definitions/<name>" are supported.`
|
|
3245
|
+
});
|
|
3246
|
+
return null;
|
|
3247
|
+
}
|
|
3248
|
+
refToObjectField(resolved, path, ctx);
|
|
3249
|
+
return {
|
|
3250
|
+
...requiredNullableFlags(required),
|
|
3251
|
+
type: "object",
|
|
3252
|
+
kind: resolved.slug
|
|
3253
|
+
};
|
|
3222
3254
|
}
|
|
3223
3255
|
if (Array.isArray(node.anyOf) || Array.isArray(node.oneOf)) {
|
|
3224
3256
|
const variants = node.anyOf ?? node.oneOf;
|
|
@@ -3234,12 +3266,18 @@ function convertPropertyCore(fieldName, node, required, path, ctx) {
|
|
|
3234
3266
|
continue;
|
|
3235
3267
|
}
|
|
3236
3268
|
if (typeof variant.$ref === "string") {
|
|
3237
|
-
ctx
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3269
|
+
const resolvedVariant = resolveRef(variant.$ref, ctx);
|
|
3270
|
+
if (!resolvedVariant) {
|
|
3271
|
+
ctx.problems.push({
|
|
3272
|
+
severity: "error",
|
|
3273
|
+
path,
|
|
3274
|
+
message: `Unresolvable $ref inside anyOf/oneOf ("${variant.$ref}").`
|
|
3275
|
+
});
|
|
3276
|
+
unsupported = true;
|
|
3277
|
+
continue;
|
|
3278
|
+
}
|
|
3279
|
+
refToObjectField(resolvedVariant, path, ctx);
|
|
3280
|
+
memberKinds.push(resolvedVariant.slug);
|
|
3243
3281
|
continue;
|
|
3244
3282
|
}
|
|
3245
3283
|
const { type: type2, nullable: nullable2 } = resolvePrimaryType(variant);
|
|
@@ -3442,6 +3480,27 @@ function convertPropertyCore(fieldName, node, required, path, ctx) {
|
|
|
3442
3480
|
});
|
|
3443
3481
|
return null;
|
|
3444
3482
|
}
|
|
3483
|
+
if (typeof itemNode.$ref === "string") {
|
|
3484
|
+
const resolvedItem = resolveRef(itemNode.$ref, ctx);
|
|
3485
|
+
if (!resolvedItem) {
|
|
3486
|
+
ctx.problems.push({
|
|
3487
|
+
severity: "error",
|
|
3488
|
+
path: `${path}[]`,
|
|
3489
|
+
message: `Unresolvable $ref in array items ("${itemNode.$ref}").`
|
|
3490
|
+
});
|
|
3491
|
+
return null;
|
|
3492
|
+
}
|
|
3493
|
+
refToObjectField(resolvedItem, `${path}[]`, ctx);
|
|
3494
|
+
ctx.arrayBindings.push({
|
|
3495
|
+
arrayField: fieldName,
|
|
3496
|
+
itemKindSlug: resolvedItem.slug
|
|
3497
|
+
});
|
|
3498
|
+
return {
|
|
3499
|
+
...requiredNullableFlags(required, nullable),
|
|
3500
|
+
type: "array",
|
|
3501
|
+
itemKinds: [resolvedItem.slug]
|
|
3502
|
+
};
|
|
3503
|
+
}
|
|
3445
3504
|
if (isAnyValueSchema(itemNode)) {
|
|
3446
3505
|
return {
|
|
3447
3506
|
...requiredNullableFlags(required, nullable),
|
|
@@ -3476,11 +3535,29 @@ function convertPropertyCore(fieldName, node, required, path, ctx) {
|
|
|
3476
3535
|
}
|
|
3477
3536
|
const itemKinds = [];
|
|
3478
3537
|
for (const variant of itemVariants) {
|
|
3538
|
+
if (isRecord4(variant) && typeof variant.$ref === "string") {
|
|
3539
|
+
const resolvedVariant = resolveRef(variant.$ref, ctx);
|
|
3540
|
+
if (!resolvedVariant) {
|
|
3541
|
+
ctx.problems.push({
|
|
3542
|
+
severity: "error",
|
|
3543
|
+
path: `${path}[]`,
|
|
3544
|
+
message: `Unresolvable $ref in array items anyOf ("${variant.$ref}").`
|
|
3545
|
+
});
|
|
3546
|
+
return null;
|
|
3547
|
+
}
|
|
3548
|
+
itemKinds.push(resolvedVariant.slug);
|
|
3549
|
+
refToObjectField(resolvedVariant, `${path}[]<${resolvedVariant.slug}>`, ctx);
|
|
3550
|
+
ctx.arrayBindings.push({
|
|
3551
|
+
arrayField: fieldName,
|
|
3552
|
+
itemKindSlug: resolvedVariant.slug
|
|
3553
|
+
});
|
|
3554
|
+
continue;
|
|
3555
|
+
}
|
|
3479
3556
|
if (!isRecord4(variant) || !isRecord4(variant.properties)) {
|
|
3480
3557
|
ctx.problems.push({
|
|
3481
3558
|
severity: "error",
|
|
3482
3559
|
path: `${path}[]`,
|
|
3483
|
-
message: "Array items anyOf/oneOf variants must be inline objects declaring __kind."
|
|
3560
|
+
message: "Array items anyOf/oneOf variants must be inline objects declaring __kind, or $refs to defs."
|
|
3484
3561
|
});
|
|
3485
3562
|
return null;
|
|
3486
3563
|
}
|
|
@@ -3614,6 +3691,14 @@ function convertPropertyCore(fieldName, node, required, path, ctx) {
|
|
|
3614
3691
|
kind: referencedKind
|
|
3615
3692
|
};
|
|
3616
3693
|
}
|
|
3694
|
+
if (Object.keys(nestedFields).length === 0 && !apIsOpen && isRecord4(ap) && KIND_KEY in node.properties) {
|
|
3695
|
+
const apType = resolvePrimaryType(ap).type;
|
|
3696
|
+
return {
|
|
3697
|
+
...requiredNullableFlags(required, nullable),
|
|
3698
|
+
type: "record",
|
|
3699
|
+
values: apType === "string" || apType === "number" || apType === "boolean" ? apType : "json"
|
|
3700
|
+
};
|
|
3701
|
+
}
|
|
3617
3702
|
let open = apIsOpen;
|
|
3618
3703
|
if (!apIsOpen && isRecord4(ap)) {
|
|
3619
3704
|
ctx.problems.push({
|
|
@@ -3730,12 +3815,21 @@ function normalizeAiSchemaInput(input) {
|
|
|
3730
3815
|
return { name: null, strict: null, rootSchema: null, parseErrors };
|
|
3731
3816
|
}
|
|
3732
3817
|
function convertAiSchemaToBlockFields(schemaName, rootSchema, strict) {
|
|
3818
|
+
const rawDefs = isRecord4(rootSchema.$defs) ? rootSchema.$defs : isRecord4(rootSchema.definitions) ? rootSchema.definitions : {};
|
|
3819
|
+
const defs = {};
|
|
3820
|
+
for (const [name, node] of Object.entries(rawDefs)) {
|
|
3821
|
+
if (isRecord4(node)) defs[name] = node;
|
|
3822
|
+
}
|
|
3733
3823
|
const ctx = {
|
|
3734
3824
|
schemaName,
|
|
3825
|
+
strict,
|
|
3735
3826
|
problems: [],
|
|
3736
3827
|
droppedMetadata: [],
|
|
3737
3828
|
blockSchemas: [],
|
|
3738
|
-
arrayBindings: []
|
|
3829
|
+
arrayBindings: [],
|
|
3830
|
+
defs,
|
|
3831
|
+
rootSchema,
|
|
3832
|
+
refsInProgress: /* @__PURE__ */ new Set()
|
|
3739
3833
|
};
|
|
3740
3834
|
ctx.droppedMetadata.push(...collectDropped(rootSchema, ""));
|
|
3741
3835
|
const rootAp = rootSchema.additionalProperties;
|