@ai-matrx/content-ir 0.22.6 → 0.23.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 CHANGED
@@ -1,5 +1,26 @@
1
1
  # Changelog
2
2
 
3
+
4
+ ## 0.23.0 — the one markdown-source home
5
+
6
+ - `/source` gains the delimiter guard (`guardMarkdownDelimiters`, `guardMathDelimiters`,
7
+ `guardRunawayLinks`, `reportDelimiterViolations` + types) and the thinking-tag helpers
8
+ (`stripThinking`, `hasThinkingTags`, `stripThinkingStreaming`), moved from `@ai-matrx/kit`. The
9
+ guard's math rules are now THE rules of `source/math-pairs` (kit carried a private copy);
10
+ `opensFlowBlock` is exported there.
11
+ - New subpath `/json-extract` (moved from `@ai-matrx/kit/json-extract`): JSON in model text,
12
+ fenced or bare, complete or streaming. New dependencies: `json5`, `jsonrepair`.
13
+ - `/text-case` is gone: the implementation lives in `@ai-matrx/kit/text-case`, which this
14
+ package now depends on.
15
+
16
+ Consumer action: `@ai-matrx/content-ir/text-case` → `@ai-matrx/kit/text-case`.
17
+
18
+ ## 0.22.7
19
+
20
+ - `kindSchemaFromJsonSchema` / `convertAiSchemaToBlockFields`: a `$ref` to a `$def` that does NOT declare its kind (`__kind` const/enum) is a plain nested structure and now converts IN PLACE — `inline_object` for a field, a nullable `inline_object` for `anyOf: [$ref, null]`. It used to become `{type:"object", kind:"<ClassName>"}`, so the parser demanded `__kind === "<ClassName>"` of every pydantic sub-structure (they carry none) and the whole instance resolved `raw` the moment a kind's database schema reached the registry — the generic key/value fallback instead of the kind's component (Applet builder floating window, 2026-10-07). Live corpus: 397 optional-`__kind` defs across 134 active kinds, plus 89 defs with no `__kind`. A def that declares its kind is still a kind reference; array-item `$ref`s are unchanged.
21
+
22
+ **Consumer action:** `pnpm up @ai-matrx/content-ir@latest`. Nothing else — the kind registry's cold fetch derives through this converter.
23
+
3
24
  ## 0.22.6
4
25
 
5
26
  - `startsLikeTableRow` / `isGrowingDelimiterRow` (the streaming forms of the table rule) now live in `source/gfm-table.ts` beside the rest of THE GFM table rule; the public exports are unchanged (AP-2: `check-table-readers` green with an empty baseline).
package/dist/convert.cjs CHANGED
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var textCase = require('@ai-matrx/kit/text-case');
4
+
3
5
  // core/kind-schema.types.ts
4
6
  var KIND_KEY = "__kind";
5
7
  function scalarArrayItemType(type) {
@@ -7,297 +9,8 @@ function scalarArrayItemType(type) {
7
9
  if (type === "boolean[]") return "boolean";
8
10
  return "string";
9
11
  }
10
-
11
- // text-case.ts
12
- var DEFAULT_WORD_REPLACEMENTS = {
13
- // Acronyms & initialisms
14
- "api": "API",
15
- "apis": "APIs",
16
- "ui": "UI",
17
- "ux": "UX",
18
- "id": "ID",
19
- "ids": "IDs",
20
- "qr": "QR",
21
- "ssr": "SSR",
22
- "csr": "CSR",
23
- "ssg": "SSG",
24
- "isr": "ISR",
25
- "spa": "SPA",
26
- "pwa": "PWA",
27
- "sdk": "SDK",
28
- "sdks": "SDKs",
29
- "cli": "CLI",
30
- "tty": "TTY",
31
- "repl": "REPL",
32
- "ci": "CI",
33
- "cd": "CD",
34
- "cpu": "CPU",
35
- "cpus": "CPUs",
36
- "gpu": "GPU",
37
- "gpus": "GPUs",
38
- "ram": "RAM",
39
- "rom": "ROM",
40
- "ssd": "SSD",
41
- "ssds": "SSDs",
42
- "hdd": "HDD",
43
- "hdds": "HDDs",
44
- "kpi": "KPI",
45
- "kpis": "KPIs",
46
- "sla": "SLA",
47
- "slas": "SLAs",
48
- "slo": "SLO",
49
- "slos": "SLOs",
50
- "sli": "SLI",
51
- "slis": "SLIs",
52
- "dom": "DOM",
53
- // Web, formats, protocols
54
- "url": "URL",
55
- "urls": "URLs",
56
- "uri": "URI",
57
- "uris": "URIs",
58
- "http": "HTTP",
59
- "https": "HTTPS",
60
- "html": "HTML",
61
- "css": "CSS",
62
- "json": "JSON",
63
- "yaml": "YAML",
64
- "yml": "YML",
65
- "toml": "TOML",
66
- "csv": "CSV",
67
- "pdf": "PDF",
68
- "tsv": "TSV",
69
- "jpg": "JPG",
70
- "jpeg": "JPEG",
71
- "png": "PNG",
72
- "gif": "GIF",
73
- "webp": "WebP",
74
- "heic": "HEIC",
75
- "heif": "HEIF",
76
- "bmp": "BMP",
77
- "tiff": "TIFF",
78
- "ico": "ICO",
79
- "xml": "XML",
80
- "sql": "SQL",
81
- "db": "DB",
82
- "dbs": "DBs",
83
- "nosql": "NoSQL",
84
- "graphql": "GraphQL",
85
- "grpc": "gRPC",
86
- "rest": "REST",
87
- "restful": "RESTful",
88
- "websocket": "WebSocket",
89
- "websockets": "WebSockets",
90
- "webrtc": "WebRTC",
91
- // Networking
92
- "ip": "IP",
93
- "ipv4": "IPv4",
94
- "ipv6": "IPv6",
95
- "dns": "DNS",
96
- "dhcp": "DHCP",
97
- "nat": "NAT",
98
- "tcp": "TCP",
99
- "udp": "UDP",
100
- "icmp": "ICMP",
101
- "ttl": "TTL",
102
- "lan": "LAN",
103
- "wan": "WAN",
104
- "vlan": "VLAN",
105
- "cdn": "CDN",
106
- "ftp": "FTP",
107
- "ssh": "SSH",
108
- "tls": "TLS",
109
- "ssl": "SSL",
110
- // Security & crypto
111
- "jwt": "JWT",
112
- "jws": "JWS",
113
- "jwe": "JWE",
114
- "hmac": "HMAC",
115
- "rsa": "RSA",
116
- "ecdsa": "ECDSA",
117
- "aes": "AES",
118
- "pbkdf2": "PBKDF2",
119
- "argon2": "Argon2",
120
- "scrypt": "scrypt",
121
- "totp": "TOTP",
122
- "hotp": "HOTP",
123
- "mfa": "MFA",
124
- "2fa": "2FA",
125
- "csrf": "CSRF",
126
- "xss": "XSS",
127
- "ssrf": "SSRF",
128
- "rce": "RCE",
129
- "dos": "DoS",
130
- "ddos": "DDoS",
131
- "mitm": "MITM",
132
- "csp": "CSP",
133
- "cors": "CORS",
134
- "pii": "PII",
135
- "phi": "PHI",
136
- "gdpr": "GDPR",
137
- "ccpa": "CCPA",
138
- "hipaa": "HIPAA",
139
- "rfc": "RFC",
140
- // Platforms, langs, tools (single-token)
141
- "javascript": "JavaScript",
142
- "typescript": "TypeScript",
143
- "jsx": "JSX",
144
- "tsx": "TSX",
145
- "node": "Node",
146
- // (used when tokenized alone)
147
- "deno": "Deno",
148
- "bun": "Bun",
149
- "react": "React",
150
- "nextjs": "Next.js",
151
- // if your tokenizer drops dots, keep this
152
- "nodejs": "Node.js",
153
- "postgresql": "PostgreSQL",
154
- "postgres": "Postgres",
155
- "mysql": "MySQL",
156
- "sqlite": "SQLite",
157
- "redis": "Redis",
158
- "supabase": "Supabase",
159
- "docker": "Docker",
160
- "kubernetes": "Kubernetes",
161
- "k8s": "Kubernetes",
162
- "helm": "Helm",
163
- "npm": "npm",
164
- "pnpm": "pnpm",
165
- "yarn": "Yarn",
166
- "eslint": "ESLint",
167
- "prettier": "Prettier",
168
- "vite": "Vite",
169
- "webpack": "Webpack",
170
- "babel": "Babel",
171
- // OS & vendors
172
- "macos": "macOS",
173
- "ios": "iOS",
174
- "ipados": "iPadOS",
175
- "watchos": "watchOS",
176
- "tvos": "tvOS",
177
- "windows": "Windows",
178
- "linux": "Linux",
179
- "ubuntu": "Ubuntu",
180
- "github": "GitHub",
181
- "gitlab": "GitLab",
182
- "bitbucket": "Bitbucket",
183
- // Data & analytics
184
- "etl": "ETL",
185
- "elt": "ELT",
186
- "olap": "OLAP",
187
- "oltp": "OLTP",
188
- "bi": "BI",
189
- // Time & locales
190
- "utc": "UTC",
191
- "gmt": "GMT",
192
- "pst": "PST",
193
- "pdt": "PDT",
194
- "pt": "PT",
195
- // Common “small words” to keep lowercase (unless first/last word)
196
- "or": "or",
197
- "and": "and",
198
- "the": "the",
199
- "of": "of",
200
- "in": "in",
201
- "to": "to",
202
- "with": "with",
203
- "as": "as",
204
- "by": "by",
205
- "for": "for",
206
- "on": "on",
207
- "at": "at",
208
- "up": "up",
209
- "a": "a",
210
- "an": "an",
211
- "is": "is",
212
- "are": "are",
213
- "was": "was",
214
- "were": "were",
215
- "be": "be",
216
- "but": "but",
217
- "nor": "nor",
218
- "so": "so",
219
- "yet": "yet",
220
- "per": "per",
221
- "via": "via",
222
- // Latin abbreviations (tokenized as words in some pipelines)
223
- "eg": "e.g.",
224
- "ie": "i.e.",
225
- "etc": "etc.",
226
- "aka": "aka",
227
- "vs": "vs.",
228
- "v": "v.",
229
- // Client abbreviations
230
- "CIC": "CIC",
231
- "AGR": "AGR",
232
- "AGER": "AGER",
233
- "DD": "DD",
234
- "TS": "TS",
235
- "TM": "TM",
236
- "arman": "Arman"
237
- };
238
- var DEFAULT_OPTIONS = {
239
- textCase: "title",
240
- wordReplacements: DEFAULT_WORD_REPLACEMENTS,
241
- trim: true
242
- };
243
- function formatText(text, options = {}) {
244
- const opts = { ...DEFAULT_OPTIONS, ...options };
245
- if (!text) return "";
246
- let normalized = text.replace(/_/g, " ").replace(/-/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").replace(/\s+/g, " ");
247
- if (opts.trim) {
248
- normalized = normalized.trim();
249
- }
250
- let caseTransformed = normalized;
251
- switch (opts.textCase) {
252
- case "title":
253
- caseTransformed = normalized.replace(
254
- /\w\S*/g,
255
- (word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
256
- );
257
- break;
258
- case "sentence":
259
- if (normalized.length > 0) {
260
- caseTransformed = normalized.charAt(0).toUpperCase() + normalized.slice(1).toLowerCase();
261
- }
262
- break;
263
- case "lower":
264
- caseTransformed = normalized.toLowerCase();
265
- break;
266
- case "upper":
267
- caseTransformed = normalized.toUpperCase();
268
- break;
269
- }
270
- let result = caseTransformed;
271
- if (opts.wordReplacements) {
272
- Object.entries(opts.wordReplacements).forEach(([key, value]) => {
273
- const regex = new RegExp(`\\b${key}\\b`, "gi");
274
- result = result.replace(regex, value);
275
- });
276
- }
277
- return result;
278
- }
279
- var IDENTIFIER_ACRONYMS = [
280
- "ID",
281
- "URL",
282
- "PDF",
283
- "HTML",
284
- "JSON",
285
- "API",
286
- "AI",
287
- "UI",
288
- "CSV",
289
- "SMS",
290
- "SEO",
291
- "LLM",
292
- "MCP",
293
- "UUID",
294
- "ISO"
295
- ];
296
- new Set(IDENTIFIER_ACRONYMS.map((a) => a.toLowerCase()));
297
-
298
- // core/schema-structure.ts
299
12
  function formatBlockLabel(key) {
300
- return formatText(key, { textCase: "title" });
13
+ return textCase.formatText(key, { textCase: "title" });
301
14
  }
302
15
 
303
16
  // convert/openai-schema-converter.ts
@@ -517,7 +230,7 @@ function buildAgentSchemaWithRenderBlockSupport(input, rootKindSlug, arrayBindin
517
230
  }
518
231
  function resolveRef(ref, ctx) {
519
232
  if (ref === "#" || ref === "#/") {
520
- return { slug: ctx.schemaName, node: ctx.rootSchema };
233
+ return { slug: ctx.schemaName, node: ctx.rootSchema, declaresKind: true };
521
234
  }
522
235
  const match = /^#\/(?:\$defs|definitions)\/(.+)$/.exec(ref);
523
236
  if (!match) return null;
@@ -527,7 +240,11 @@ function resolveRef(ref, ctx) {
527
240
  const node = ctx.defs[name];
528
241
  if (!isRecord(node)) return null;
529
242
  const declared = isRecord(node.properties) ? readBlockKindFromProperties(node.properties) : null;
530
- return { slug: declared ?? name, node };
243
+ return { slug: declared ?? name, node, declaresKind: declared !== null };
244
+ }
245
+ function inlineRefNode(refNode, resolved) {
246
+ const { $ref: _ref, ...beside } = refNode;
247
+ return { ...resolved.node, ...beside };
531
248
  }
532
249
  function refToObjectField(resolved, path, ctx) {
533
250
  if (ctx.refsInProgress.has(resolved.slug)) return;
@@ -597,6 +314,29 @@ function convertPropertyCore(fieldName, node, required, path, ctx) {
597
314
  });
598
315
  return null;
599
316
  }
317
+ if (!resolved.declaresKind) {
318
+ const guard = `$def:${node.$ref}`;
319
+ if (ctx.refsInProgress.has(guard)) {
320
+ ctx.problems.push({
321
+ severity: "info",
322
+ path,
323
+ message: `Self-referencing structure "${node.$ref}" \u2014 carried as any JSON value (json).`
324
+ });
325
+ return { ...requiredNullableFlags(required), type: "json" };
326
+ }
327
+ ctx.refsInProgress.add(guard);
328
+ try {
329
+ return convertPropertyCore(
330
+ fieldName,
331
+ inlineRefNode(node, resolved),
332
+ required,
333
+ path,
334
+ ctx
335
+ );
336
+ } finally {
337
+ ctx.refsInProgress.delete(guard);
338
+ }
339
+ }
600
340
  refToObjectField(resolved, path, ctx);
601
341
  return {
602
342
  ...requiredNullableFlags(required),
@@ -628,6 +368,10 @@ function convertPropertyCore(fieldName, node, required, path, ctx) {
628
368
  unsupported = true;
629
369
  continue;
630
370
  }
371
+ if (!resolvedVariant.declaresKind) {
372
+ anonymousObjects.push(inlineRefNode(variant, resolvedVariant));
373
+ continue;
374
+ }
631
375
  refToObjectField(resolvedVariant, path, ctx);
632
376
  memberKinds.push(resolvedVariant.slug);
633
377
  continue;