@ai-matrx/content-ir 0.19.20 → 0.19.25

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/dist/index.cjs CHANGED
@@ -1274,7 +1274,7 @@ var KindStreamParser = class {
1274
1274
  }
1275
1275
  if (!declaredKind2 && committedKind && this.speculativeKinds.has(pathKey)) {
1276
1276
  this.speculativeKinds.delete(pathKey);
1277
- this.finalizeSpeculatedObject(path, objectValue, committedKind, at);
1277
+ this.finalizeSpeculatedObject(path, objectValue, committedKind, at, true);
1278
1278
  return;
1279
1279
  }
1280
1280
  if (path.length === 0 && !declaredKind2 && !committedKind && this.rootSurfaceKind) {
@@ -1352,7 +1352,7 @@ var KindStreamParser = class {
1352
1352
  });
1353
1353
  }
1354
1354
  /** Validate + complete an object typed purely by parent prediction. */
1355
- finalizeSpeculatedObject(path, objectValue, kind, at) {
1355
+ finalizeSpeculatedObject(path, objectValue, kind, at, requireSharedField = false) {
1356
1356
  const schema = this.lookupSchema(kind);
1357
1357
  if (!schema) {
1358
1358
  this.emitRawObject(
@@ -1365,6 +1365,15 @@ var KindStreamParser = class {
1365
1365
  );
1366
1366
  return;
1367
1367
  }
1368
+ if (requireSharedField && !Object.keys(objectValue).some((key) => key in schema.fields)) {
1369
+ this.emitRawObject(
1370
+ path,
1371
+ objectValue,
1372
+ `Object carries none of "${kind}"'s fields.`,
1373
+ at
1374
+ );
1375
+ return;
1376
+ }
1368
1377
  const outcome = this.validateObjectAgainstSchema(
1369
1378
  { ...objectValue, [KIND_KEY]: kind },
1370
1379
  schema
@@ -1625,16 +1634,7 @@ var KindStreamParser = class {
1625
1634
  ...emptyOutcome
1626
1635
  };
1627
1636
  }
1628
- for (const [fieldName, fieldSchema] of Object.entries(schema.fields)) {
1629
- if (fieldSchema.required) {
1630
- if (!(fieldName in objectValue)) {
1631
- return {
1632
- error: `Kind "${schema.kind}" is missing required field "${fieldName}".`,
1633
- ...emptyOutcome
1634
- };
1635
- }
1636
- continue;
1637
- }
1637
+ for (const fieldName of Object.keys(schema.fields)) {
1638
1638
  if (!(fieldName in objectValue)) {
1639
1639
  optionalMissing.push(fieldName);
1640
1640
  }
@@ -1841,17 +1841,7 @@ var KindStreamParser = class {
1841
1841
  validateObjectAgainstFields(objectValue, fields) {
1842
1842
  const optionalMissing = [];
1843
1843
  const extraFields = [];
1844
- const emptyOutcome = { optionalMissing, extraFields };
1845
- for (const [fieldName, fieldSchema] of Object.entries(fields)) {
1846
- if (fieldSchema.required) {
1847
- if (!(fieldName in objectValue)) {
1848
- return {
1849
- error: `Inline object is missing required field "${fieldName}".`,
1850
- ...emptyOutcome
1851
- };
1852
- }
1853
- continue;
1854
- }
1844
+ for (const fieldName of Object.keys(fields)) {
1855
1845
  if (!(fieldName in objectValue)) {
1856
1846
  optionalMissing.push(fieldName);
1857
1847
  }
@@ -3198,13 +3188,13 @@ function makeKindJsonSchemaProperty(kindSlug, strict) {
3198
3188
  return { ...base2, enum: [kindSlug] };
3199
3189
  }
3200
3190
  function injectKindIntoObjectSchema(objectSchema, kindSlug, strict) {
3201
- const clone = deepClone(objectSchema);
3202
- const properties = isRecord4(clone.properties) ? { ...clone.properties } : {};
3191
+ const clone2 = deepClone(objectSchema);
3192
+ const properties = isRecord4(clone2.properties) ? { ...clone2.properties } : {};
3203
3193
  properties[KIND_KEY] = makeKindJsonSchemaProperty(kindSlug, strict);
3204
- const required = Array.isArray(clone.required) ? clone.required.filter((k) => typeof k === "string") : [];
3194
+ const required = Array.isArray(clone2.required) ? clone2.required.filter((k) => typeof k === "string") : [];
3205
3195
  const nextRequired = required.includes(KIND_KEY) ? required : [KIND_KEY, ...required];
3206
3196
  return {
3207
- ...clone,
3197
+ ...clone2,
3208
3198
  properties,
3209
3199
  required: nextRequired,
3210
3200
  ...strict ? { additionalProperties: false } : {}
@@ -4401,8 +4391,132 @@ function kindSchemaToJsonSchema(kind, resolve, options = {}) {
4401
4391
  return { name: kind, schema: { ...rootNode, $defs: defs }, strict, unresolved };
4402
4392
  }
4403
4393
 
4394
+ // convert/control-keys.ts
4395
+ var CONTROL_KEYS = ["_replaces", "_new", "_record_id", "_records"];
4396
+ var RECORD_DISPOSITION = "record";
4397
+ var KIND_KEY2 = "__kind";
4398
+ var DOCUMENT_KEYS = /* @__PURE__ */ new Set(["$schema", "$id", "$defs", "definitions", "title", "description"]);
4399
+ var CONTROL = new Set(CONTROL_KEYS);
4400
+ function controlKeysApplyTo(disposition) {
4401
+ return disposition === RECORD_DISPOSITION;
4402
+ }
4403
+ function clone(value) {
4404
+ return value === void 0 ? value : JSON.parse(JSON.stringify(value));
4405
+ }
4406
+ function isObjectSchema(schema) {
4407
+ if (!schema || typeof schema !== "object" || Array.isArray(schema)) return false;
4408
+ const s = schema;
4409
+ return s.type === "object" && !!s.properties && typeof s.properties === "object" && !Array.isArray(s.properties);
4410
+ }
4411
+ function requiredOf(schema) {
4412
+ return Array.isArray(schema.required) ? schema.required : [];
4413
+ }
4414
+ function recordObject(schema) {
4415
+ const item = {};
4416
+ for (const [k, v] of Object.entries(schema)) {
4417
+ if (!DOCUMENT_KEYS.has(k)) item[k] = clone(v);
4418
+ }
4419
+ const props = {};
4420
+ for (const [k, v] of Object.entries(item.properties)) {
4421
+ if (k !== KIND_KEY2 && !CONTROL.has(k)) props[k] = v;
4422
+ }
4423
+ item.properties = props;
4424
+ const required = requiredOf(item).filter((k) => k !== KIND_KEY2 && !CONTROL.has(k));
4425
+ if (required.length > 0) item.required = required;
4426
+ else delete item.required;
4427
+ return item;
4428
+ }
4429
+ function stored(schema) {
4430
+ const out = clone(schema);
4431
+ const item = recordObject(schema);
4432
+ const props = out.properties;
4433
+ props._replaces = { type: ["string", "null"], format: "uuid" };
4434
+ props._new = { type: ["boolean", "null"] };
4435
+ props._record_id = { type: ["string", "null"], format: "uuid" };
4436
+ props._records = { type: ["array", "null"], items: item };
4437
+ const rootRequired = requiredOf(out).filter((k) => !CONTROL.has(k));
4438
+ const lifted = rootRequired.filter((k) => k !== KIND_KEY2);
4439
+ if (lifted.length > 0) {
4440
+ const kept = rootRequired.filter((k) => k === KIND_KEY2);
4441
+ if (kept.length > 0) out.required = kept;
4442
+ else delete out.required;
4443
+ const branch = {
4444
+ if: {
4445
+ anyOf: [
4446
+ { required: ["_record_id"], properties: { _record_id: { type: "string" } } },
4447
+ { required: ["_records"], properties: { _records: { type: "array" } } }
4448
+ ]
4449
+ },
4450
+ else: { required: lifted }
4451
+ };
4452
+ out.allOf = Array.isArray(out.allOf) ? [...out.allOf, branch] : [branch];
4453
+ }
4454
+ return out;
4455
+ }
4456
+ function authored(schema, many, allowEdit) {
4457
+ const signals = {
4458
+ _replaces: { type: "string", format: "uuid" },
4459
+ _new: { type: "boolean" }
4460
+ };
4461
+ if (allowEdit) signals._record_id = { type: "string", format: "uuid" };
4462
+ if (!many) {
4463
+ const out2 = clone(schema);
4464
+ Object.assign(out2.properties, clone(signals));
4465
+ const required = requiredOf(out2).filter((k) => !CONTROL.has(k));
4466
+ if (required.length > 0 || "required" in out2) out2.required = required;
4467
+ return out2;
4468
+ }
4469
+ const out = {};
4470
+ for (const [k, v] of Object.entries(schema)) {
4471
+ if (DOCUMENT_KEYS.has(k)) out[k] = clone(v);
4472
+ }
4473
+ out.type = "object";
4474
+ const kindProp = schema.properties[KIND_KEY2];
4475
+ const properties = {};
4476
+ if (kindProp !== void 0) properties[KIND_KEY2] = clone(kindProp);
4477
+ properties._records = { type: "array", items: recordObject(schema) };
4478
+ Object.assign(properties, clone(signals));
4479
+ out.properties = properties;
4480
+ out.required = [KIND_KEY2, "_records"].filter((k) => k in properties);
4481
+ out.additionalProperties = false;
4482
+ return out;
4483
+ }
4484
+ function withControlKeys(schema, options) {
4485
+ const { mode, many = false, allowEdit = false } = options;
4486
+ if (mode !== "stored" && mode !== "authored") {
4487
+ throw new Error(`withControlKeys: mode must be "stored" or "authored", got ${String(mode)}`);
4488
+ }
4489
+ if (!isObjectSchema(schema)) return schema;
4490
+ return mode === "stored" ? stored(schema) : authored(schema, many, allowEdit);
4491
+ }
4492
+ var CONTROL_KEY_FIELDS = Object.freeze({
4493
+ _replaces: { type: "string", nullable: true },
4494
+ _new: { type: "boolean", nullable: true },
4495
+ _record_id: { type: "string", nullable: true },
4496
+ // A batch's items are records of this kind WITHOUT `__kind`; the render layer reads them
4497
+ // as opaque JSON (never stricter than the store, which validates each item).
4498
+ _records: { type: "json[]", nullable: true }
4499
+ });
4500
+ function withControlKeyFields(schema) {
4501
+ if (schema.root) return schema;
4502
+ const fields = { ...schema.fields };
4503
+ for (const key of CONTROL_KEYS) {
4504
+ if (!(key in fields)) fields[key] = { ...CONTROL_KEY_FIELDS[key] };
4505
+ }
4506
+ return { ...schema, fields };
4507
+ }
4508
+ function stripControlKeys(value) {
4509
+ const values = {};
4510
+ const signals = {};
4511
+ for (const [k, v] of Object.entries(value)) {
4512
+ if (CONTROL.has(k)) signals[k] = v;
4513
+ else values[k] = v;
4514
+ }
4515
+ return { values, signals };
4516
+ }
4517
+
4404
4518
  // convert/json-schema-to-kind.ts
4405
- function kindSchemaFromJsonSchema(kind, jsonSchema) {
4519
+ function kindSchemaFromJsonSchema(kind, jsonSchema, options = {}) {
4406
4520
  if (jsonSchema === null || jsonSchema === void 0) {
4407
4521
  return { schema: null, children: {}, problems: [] };
4408
4522
  }
@@ -4433,6 +4547,9 @@ function kindSchemaFromJsonSchema(kind, jsonSchema) {
4433
4547
  if (draft.slug === kind) schema = asKindSchema;
4434
4548
  else children[draft.slug] = asKindSchema;
4435
4549
  }
4550
+ if (schema && controlKeysApplyTo(options.disposition)) {
4551
+ schema = withControlKeyFields(schema);
4552
+ }
4436
4553
  return { schema, children, problems: converted.problems };
4437
4554
  }
4438
4555
 
@@ -7943,6 +8060,8 @@ exports.BacktickRuns = BacktickRuns;
7943
8060
  exports.CALLOUT_NAMES = CALLOUT_NAMES;
7944
8061
  exports.CAPABILITY_BY_CLASS = CAPABILITY_BY_CLASS;
7945
8062
  exports.CLASSES = CLASSES;
8063
+ exports.CONTROL_KEYS = CONTROL_KEYS;
8064
+ exports.CONTROL_KEY_FIELDS = CONTROL_KEY_FIELDS;
7946
8065
  exports.DIRECTIVE_VERSION = DIRECTIVE_VERSION;
7947
8066
  exports.DirectiveDecodeError = DirectiveDecodeError;
7948
8067
  exports.FENCE_OPENER_WHITESPACE = FENCE_OPENER_WHITESPACE;
@@ -7962,6 +8081,7 @@ exports.KindStreamParser = KindStreamParser;
7962
8081
  exports.NESTING_FENCE_LANGUAGES = NESTING_FENCE_LANGUAGES;
7963
8082
  exports.NODE_OUTCOME_KIND = NODE_OUTCOME_KIND;
7964
8083
  exports.ParseSession = ParseSession;
8084
+ exports.RECORD_DISPOSITION = RECORD_DISPOSITION;
7965
8085
  exports.RESERVED_PREFIX = RESERVED_PREFIX;
7966
8086
  exports.ROOT_STORAGE_NAME = ROOT_STORAGE_NAME;
7967
8087
  exports.RUN_RESULT_KIND = RUN_RESULT_KIND;
@@ -7989,6 +8109,7 @@ exports.collectReferencedKinds = collectReferencedKinds;
7989
8109
  exports.collectSchemaReferencedKinds = collectSchemaReferencedKinds;
7990
8110
  exports.compareWithExistingKindSchema = compareWithExistingKindSchema;
7991
8111
  exports.continuesTable = continuesTable;
8112
+ exports.controlKeysApplyTo = controlKeysApplyTo;
7992
8113
  exports.convertAiSchemaToBlockFields = convertAiSchemaToBlockFields;
7993
8114
  exports.createFingerprinter = createFingerprinter;
7994
8115
  exports.createKindStreamParser = createKindStreamParser;
@@ -8075,6 +8196,7 @@ exports.opensTable = opensTable;
8075
8196
  exports.pairDisplayMath = pairDisplayMath;
8076
8197
  exports.parseDirectiveSlug = parseDirectiveSlug;
8077
8198
  exports.parseFenceOpener = parseFenceOpener;
8199
+ exports.pendingCodeSpanStart = pendingCodeSpanStart;
8078
8200
  exports.pendingDisplayMathOpener = pendingDisplayMathOpener;
8079
8201
  exports.readEnvelope = readEnvelope;
8080
8202
  exports.readNodeOutcomeValue = readNodeOutcomeValue;
@@ -8107,6 +8229,7 @@ exports.splitsSurrogatePair = splitsSurrogatePair;
8107
8229
  exports.startsHtmlBlock = startsHtmlBlock;
8108
8230
  exports.startsPipelessTable = startsPipelessTable;
8109
8231
  exports.storageToKindSchema = storageToKindSchema;
8232
+ exports.stripControlKeys = stripControlKeys;
8110
8233
  exports.stripKindDeep = stripKindDeep;
8111
8234
  exports.tableContainerIndent = tableContainerIndent;
8112
8235
  exports.tableStartsAt = tableStartsAt;
@@ -8120,6 +8243,8 @@ exports.tryDecodeDirectiveContent = tryDecodeDirectiveContent;
8120
8243
  exports.unescapeCellPipes = unescapeCellPipes;
8121
8244
  exports.validateBlockSchemaSavePlan = validateBlockSchemaSavePlan;
8122
8245
  exports.validateStructuralLeg = validateStructuralLeg;
8246
+ exports.withControlKeyFields = withControlKeyFields;
8247
+ exports.withControlKeys = withControlKeys;
8123
8248
  exports.withRootKind = withRootKind;
8124
8249
  exports.xmlDiscriminator = xmlDiscriminator;
8125
8250
  //# sourceMappingURL=index.cjs.map