@aglyn/plugins-ai 1.0.0-beta.151 → 1.0.0-beta.153
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/package.json +17 -17
- package/src/lib/jobs/ai-job-component-step.d.ts +27 -1
- package/src/lib/jobs/ai-job-component-step.js +68 -3
- package/src/lib/jobs/ai-job-component-step.js.map +1 -1
- package/src/lib/jobs/ai-job-drafts.d.ts +19 -0
- package/src/lib/jobs/ai-job-drafts.js +22 -0
- package/src/lib/jobs/ai-job-drafts.js.map +1 -1
- package/src/lib/jobs/ai-job-form-step.d.ts +22 -1
- package/src/lib/jobs/ai-job-form-step.js +69 -1
- package/src/lib/jobs/ai-job-form-step.js.map +1 -1
- package/src/lib/jobs/ai-job-layout-step.js +6 -1
- package/src/lib/jobs/ai-job-layout-step.js.map +1 -1
- package/src/lib/jobs/ai-job-page-sections.d.ts +19 -6
- package/src/lib/jobs/ai-job-page-sections.js +20 -7
- package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
- package/src/lib/jobs/ai-job-template-step.d.ts +22 -1
- package/src/lib/jobs/ai-job-template-step.js +59 -3
- package/src/lib/jobs/ai-job-template-step.js.map +1 -1
- package/src/lib/jobs/fixtures/ai-page-briefs.d.ts +18 -1
- package/src/lib/jobs/fixtures/ai-page-briefs.js +79 -0
- package/src/lib/jobs/fixtures/ai-page-briefs.js.map +1 -1
- package/src/lib/runtime/ai-doctrine-validators.d.ts +21 -0
- package/src/lib/runtime/ai-doctrine-validators.js +50 -0
- package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
- package/src/lib/runtime/ai-palette.generated.js +2 -2
- package/src/lib/runtime/ai-palette.generated.js.map +1 -1
- package/src/lib/runtime/ai-repeated-items.d.ts +13 -2
- package/src/lib/runtime/ai-repeated-items.js +41 -17
- package/src/lib/runtime/ai-repeated-items.js.map +1 -1
|
@@ -37,6 +37,16 @@ import { type AiDoctrineViolation } from './ai-doctrine-validators';
|
|
|
37
37
|
* `repeat` holds one list of values a copy, and `{{n}}` stands for a copy's
|
|
38
38
|
* n-th value wherever it appears in the item's props or styles.
|
|
39
39
|
*
|
|
40
|
+
* A workspace that DOES keep reusable components writes the same shape around
|
|
41
|
+
* an instance (AGL-3024): one `reusableInstance` inside the repeated item,
|
|
42
|
+
* `{{n}}` through the values it fills, and one list of values a copy. Six
|
|
43
|
+
* cards written out as six instances spend their structure six times and run
|
|
44
|
+
* past the ceiling a pass answers within; written once they spend it once, and
|
|
45
|
+
* the section stays ONE section with one heading, which is what a page's
|
|
46
|
+
* outline and its search ranking are built on. The item still places the
|
|
47
|
+
* component — rule 1 is untouched — and an item that places none is refused
|
|
48
|
+
* here exactly as before.
|
|
49
|
+
*
|
|
40
50
|
* - **Positional, because it is the smallest list a copy can be.** Each value
|
|
41
51
|
* costs its quotes and a comma. A named value repeats its name on every
|
|
42
52
|
* copy, and a list of columns keeps a copy's values apart from each other.
|
|
@@ -54,8 +64,9 @@ import { type AiDoctrineViolation } from './ai-doctrine-validators';
|
|
|
54
64
|
* `repeat` or a placeholder.
|
|
55
65
|
*
|
|
56
66
|
* Refused, each with a sentence a re-ask can act on and the model's own nodes
|
|
57
|
-
* named: `repeat`
|
|
58
|
-
* a component's instances), on the document
|
|
67
|
+
* named: `repeat` on an item that places no instance where the workspace keeps
|
|
68
|
+
* reusable components (rule 1: place a component's instances), on the document
|
|
69
|
+
* wrapper or what it holds
|
|
59
70
|
* directly, or inside another repeated item; a list that is not one list of
|
|
60
71
|
* values a copy; fewer than 2 copies or more than `AI_REPEAT_MAX_COPIES`; a
|
|
61
72
|
* placeholder a copy gives no value for, or one outside every repeated item; a
|
|
@@ -14,7 +14,8 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
14
14
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
15
15
|
* See the License for the specific language governing permissions and
|
|
16
16
|
* limitations under the License.
|
|
17
|
-
*/ import {
|
|
17
|
+
*/ import { REUSABLE_INSTANCE_COMPONENT_ID } from "@aglyn/aglyn/app-utils/reusable-component-keys";
|
|
18
|
+
import { AI_TYPED_LIST_MIN_ITEMS } from "./ai-doctrine-validators.js";
|
|
18
19
|
/**
|
|
19
20
|
* A repeated item written once (AGL-3053).
|
|
20
21
|
*
|
|
@@ -37,6 +38,16 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
37
38
|
* `repeat` holds one list of values a copy, and `{{n}}` stands for a copy's
|
|
38
39
|
* n-th value wherever it appears in the item's props or styles.
|
|
39
40
|
*
|
|
41
|
+
* A workspace that DOES keep reusable components writes the same shape around
|
|
42
|
+
* an instance (AGL-3024): one `reusableInstance` inside the repeated item,
|
|
43
|
+
* `{{n}}` through the values it fills, and one list of values a copy. Six
|
|
44
|
+
* cards written out as six instances spend their structure six times and run
|
|
45
|
+
* past the ceiling a pass answers within; written once they spend it once, and
|
|
46
|
+
* the section stays ONE section with one heading, which is what a page's
|
|
47
|
+
* outline and its search ranking are built on. The item still places the
|
|
48
|
+
* component — rule 1 is untouched — and an item that places none is refused
|
|
49
|
+
* here exactly as before.
|
|
50
|
+
*
|
|
40
51
|
* - **Positional, because it is the smallest list a copy can be.** Each value
|
|
41
52
|
* costs its quotes and a comma. A named value repeats its name on every
|
|
42
53
|
* copy, and a list of columns keeps a copy's values apart from each other.
|
|
@@ -54,8 +65,9 @@ import { _ as _extends } from "@swc/helpers/_/_extends";
|
|
|
54
65
|
* `repeat` or a placeholder.
|
|
55
66
|
*
|
|
56
67
|
* Refused, each with a sentence a re-ask can act on and the model's own nodes
|
|
57
|
-
* named: `repeat`
|
|
58
|
-
* a component's instances), on the document
|
|
68
|
+
* named: `repeat` on an item that places no instance where the workspace keeps
|
|
69
|
+
* reusable components (rule 1: place a component's instances), on the document
|
|
70
|
+
* wrapper or what it holds
|
|
59
71
|
* directly, or inside another repeated item; a list that is not one list of
|
|
60
72
|
* values a copy; fewer than 2 copies or more than `AI_REPEAT_MAX_COPIES`; a
|
|
61
73
|
* placeholder a copy gives no value for, or one outside every repeated item; a
|
|
@@ -175,20 +187,6 @@ function childIds(node) {
|
|
|
175
187
|
}
|
|
176
188
|
}
|
|
177
189
|
const marked = order.filter((id)=>Object.prototype.hasOwnProperty.call(nodeOf(id), AI_REPEAT_KEY));
|
|
178
|
-
if (!options.inline) {
|
|
179
|
-
return marked.length ? {
|
|
180
|
-
ok: false,
|
|
181
|
-
violations: [
|
|
182
|
-
{
|
|
183
|
-
rule: 1,
|
|
184
|
-
code: 'repeat-not-inline',
|
|
185
|
-
message: 'This draws a repeated item to be copied, instead of placing it as instances of a component.',
|
|
186
|
-
detail: `Remove "${AI_REPEAT_KEY}", and place each copy as an instance of a component the site has (componentId "reusableInstance").`,
|
|
187
|
-
nodeIds: marked
|
|
188
|
-
}
|
|
189
|
-
]
|
|
190
|
-
} : unchanged;
|
|
191
|
-
}
|
|
192
190
|
/** A node and everything under it, each node once. */ const subtreeOf = (id)=>{
|
|
193
191
|
const seen = new Set();
|
|
194
192
|
const stack = [
|
|
@@ -204,6 +202,32 @@ function childIds(node) {
|
|
|
204
202
|
}
|
|
205
203
|
return out;
|
|
206
204
|
};
|
|
205
|
+
// Where the workspace keeps reusable components, writing an item once is how
|
|
206
|
+
// an answer places MANY instances inside one ceiling (AGL-3024), not a way
|
|
207
|
+
// around placing them: an item that places an instance is drawn into its
|
|
208
|
+
// copies exactly as a Free one is, and one that places none is still drawing
|
|
209
|
+
// by hand a component the site has, which rule 1 refuses as it always did.
|
|
210
|
+
if (!options.inline) {
|
|
211
|
+
const byHand = marked.filter((id)=>!subtreeOf(id).some((node)=>{
|
|
212
|
+
var _nodeOf;
|
|
213
|
+
return ((_nodeOf = nodeOf(node)) == null ? void 0 : _nodeOf['componentId']) === REUSABLE_INSTANCE_COMPONENT_ID;
|
|
214
|
+
}));
|
|
215
|
+
if (byHand.length) {
|
|
216
|
+
return {
|
|
217
|
+
ok: false,
|
|
218
|
+
violations: [
|
|
219
|
+
{
|
|
220
|
+
rule: 1,
|
|
221
|
+
code: 'repeat-not-inline',
|
|
222
|
+
message: 'This draws a repeated item to be copied, instead of placing it as instances of a component.',
|
|
223
|
+
detail: `Put one instance of a component the site has (componentId "reusableInstance") inside the repeated item, or remove "${AI_REPEAT_KEY}" and place each copy as an instance.`,
|
|
224
|
+
nodeIds: byHand
|
|
225
|
+
}
|
|
226
|
+
]
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
if (!marked.length) return unchanged;
|
|
230
|
+
}
|
|
207
231
|
const ancestorsOf = (id)=>{
|
|
208
232
|
const out = [];
|
|
209
233
|
for(let parent = parentOf.get(id); parent; parent = parentOf.get(parent))out.push(parent);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/runtime/ai-repeated-items.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { AI_TYPED_LIST_MIN_ITEMS, type AiDoctrineViolation } from './ai-doctrine-validators'\n\n/**\n * A repeated item written once (AGL-3053).\n *\n * A workspace that keeps no reusable components can place no instance, so a\n * row of cards is drawn card by card. Written out in a model's answer, every\n * card repeats its whole subtree — the Card, its body, its heading and its\n * text, each node's JSON escaped inside the tool call — and four practice\n * areas with real copy run past a section pass's answer ceiling. So on such a\n * workspace an answer writes the item ONCE and lists what differs between its\n * copies, and this module draws the copies before any check reads the answer:\n *\n * ```json\n * \"card\": { \"componentId\": \"muiCard\", \"nodes\": [\"body\"],\n * \"repeat\": [[\"Estate planning\", \"Wills and trusts…\"],\n * [\"Real estate\", \"Closings and title…\"]] },\n * \"title\": { \"componentId\": \"muiTypography\", \"props\": { \"children\": \"{{1}}\" } },\n * \"text\": { \"componentId\": \"muiTypography\", \"props\": { \"children\": \"{{2}}\" } }\n * ```\n *\n * `repeat` holds one list of values a copy, and `{{n}}` stands for a copy's\n * n-th value wherever it appears in the item's props or styles.\n *\n * - **Positional, because it is the smallest list a copy can be.** Each value\n * costs its quotes and a comma. A named value repeats its name on every\n * copy, and a list of columns keeps a copy's values apart from each other.\n * - **Numbered, because no binding token is a number.** A site variable's\n * `{{name}}` starts with a letter, and a component's `{{prop.name}}`, a\n * template's `{{entry.field}}` and a function's `{{fn:…}}` carry a dot or a\n * colon (`binding-tokens.ts`), so copy that binds one keeps its token, and\n * nothing a placeholder leaves behind can bind.\n *\n * The copies are the item cloned in order, in its place under its parent. The\n * first keeps the ids the model wrote, and copy `n` takes `<id>~<n>` on every\n * node of the subtree, so one answer always draws one tree and every id a copy\n * took leads back to the node the model wrote (`sourceIds`). The drawn tree is\n * what every check reads and what a page stores: nothing downstream sees\n * `repeat` or a placeholder.\n *\n * Refused, each with a sentence a re-ask can act on and the model's own nodes\n * named: `repeat` where the workspace keeps reusable components (rule 1: place\n * a component's instances), on the document wrapper or what it holds\n * directly, or inside another repeated item; a list that is not one list of\n * values a copy; fewer than 2 copies or more than `AI_REPEAT_MAX_COPIES`; a\n * placeholder a copy gives no value for, or one outside every repeated item; a\n * value no placeholder uses; and a copy's id that the answer already gives\n * another node. Pure: no provider and no Firestore.\n */\n\n/** The key a repeated item's node lists its copies' values under. */\nexport const AI_REPEAT_KEY = 'repeat'\n\n/**\n * The most copies one item may list: a list of `AI_TYPED_LIST_MIN_ITEMS` or\n * more typed into a page is data (rule 8), which a plan binds or shortens.\n */\nexport const AI_REPEAT_MAX_COPIES = AI_TYPED_LIST_MIN_ITEMS - 1\n\n/** A copy's `n`-th value, by its 1-based position. */\nconst PLACEHOLDER = /\\{\\{\\s*(\\d+)\\s*\\}\\}/g\n\n/** A string that is one placeholder and nothing else, whose value keeps its own type. */\nconst WHOLE_PLACEHOLDER = /^\\s*\\{\\{\\s*(\\d+)\\s*\\}\\}\\s*$/\n\n/** What a list of copies looks like, in every sentence that asks for one. */\nconst EXAMPLE = '[[\"Title 1\", \"Text 1\"], [\"Title 2\", \"Text 2\"]]'\n\nexport interface AiRepeatedItemsOptions {\n /** The workspace keeps no reusable components: the one place an item is written once. */\n inline: boolean\n /** What the answer is, as a person reads a refusal: `section`, `page`. */\n noun: string\n}\n\nexport type AiRepeatedItemsResult =\n | {\n ok: true\n /** The answer with every repeated item drawn into its copies; the answer itself when none is. */\n tree: unknown\n /** Each id a copy took → the id the model wrote for that node. */\n sourceIds: Record<string, string>\n /** How many items were written once. */\n items: number\n }\n | { ok: false; violations: AiDoctrineViolation[] }\n\ntype RawNode = Record<string, unknown>\ntype Scalar = string | number | boolean\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isScalar(value: unknown): value is Scalar {\n return (\n typeof value === 'string' || typeof value === 'boolean' || (typeof value === 'number' && Number.isFinite(value))\n )\n}\n\nfunction childIds(node: RawNode | undefined): string[] {\n const children = node?.['nodes']\n return Array.isArray(children) ? children.filter((id): id is string => typeof id === 'string') : []\n}\n\n/** Every placeholder position a value uses, however deep in props or styles. */\nfunction positionsIn(value: unknown, into: Set<number>): Set<number> {\n if (typeof value === 'string') {\n for (const match of value.matchAll(PLACEHOLDER)) into.add(Number(match[1]))\n } else if (Array.isArray(value)) {\n for (const inner of value) positionsIn(inner, into)\n } else if (isRecord(value)) {\n for (const inner of Object.values(value)) positionsIn(inner, into)\n }\n return into\n}\n\n/** The positions one node's props and styles use. */\nfunction nodePositions(node: RawNode): Set<number> {\n return positionsIn(node['sx'], positionsIn(node['props'], new Set()))\n}\n\n/** A value with every placeholder filled from one copy's values. */\nfunction fill(value: unknown, values: readonly Scalar[]): unknown {\n if (typeof value === 'string') {\n const whole = WHOLE_PLACEHOLDER.exec(value)\n if (whole) return values[Number(whole[1]) - 1]\n return value.replace(PLACEHOLDER, (_token, position: string) => String(values[Number(position) - 1]))\n }\n if (Array.isArray(value)) return value.map((inner) => fill(inner, values))\n if (isRecord(value)) {\n return Object.fromEntries(Object.entries(value).map(([key, inner]) => [key, fill(inner, values)]))\n }\n return value\n}\n\n/** 1 → first, 2 → second, 12 → 12th. */\nfunction ordinal(position: number): string {\n const word = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh'][position - 1]\n if (word) return word\n const tens = position % 100\n const suffix = tens >= 11 && tens <= 13 ? 'th' : (['th', 'st', 'nd', 'rd'][position % 10] ?? 'th')\n return `${position}${suffix}`\n}\n\n/** `{{1}}`, `{{1}} and {{2}}`, `{{1}}, {{2}} and {{3}}`. */\nfunction placeholders(positions: Iterable<number>): string {\n const list = [...positions].sort((a, b) => a - b).map((position) => `{{${position}}}`)\n return list.length <= 1 ? list.join('') : `${list.slice(0, -1).join(', ')} and ${list[list.length - 1]}`\n}\n\n/**\n * The answer with every repeated item drawn into its copies, or the reasons it\n * cannot be. An answer that is not a node map, or that writes nothing once, is\n * handed back as it came, for the palette validator to read as it always has.\n */\nexport function expandAiRepeatedItems(input: unknown, options: AiRepeatedItemsOptions): AiRepeatedItemsResult {\n const unchanged: AiRepeatedItemsResult = { ok: true, tree: input, sourceIds: {}, items: 0 }\n if (!isRecord(input) || typeof input['rootId'] !== 'string' || !isRecord(input['nodes'])) return unchanged\n const rootId = input['rootId']\n const nodes = input['nodes'] as Record<string, unknown>\n const nodeOf = (id: string): RawNode | undefined => {\n const node = nodes[id]\n return isRecord(node) ? node : undefined\n }\n\n // The walk the palette validator makes: breadth first from the root, each\n // node under the first parent that lists it.\n const parentOf = new Map<string, string | null>([[rootId, null]])\n const order: string[] = []\n const queue = [rootId]\n for (let index = 0; index < queue.length; index += 1) {\n const id = queue[index]\n if (!nodeOf(id)) continue\n order.push(id)\n for (const child of childIds(nodeOf(id))) {\n if (parentOf.has(child)) continue\n parentOf.set(child, id)\n queue.push(child)\n }\n }\n const marked = order.filter((id) => Object.prototype.hasOwnProperty.call(nodeOf(id), AI_REPEAT_KEY))\n\n if (!options.inline) {\n return marked.length\n ? {\n ok: false,\n violations: [\n {\n rule: 1,\n code: 'repeat-not-inline',\n message: 'This draws a repeated item to be copied, instead of placing it as instances of a component.',\n detail: `Remove \"${AI_REPEAT_KEY}\", and place each copy as an instance of a component the site has (componentId \"reusableInstance\").`,\n nodeIds: marked,\n },\n ],\n }\n : unchanged\n }\n\n /** A node and everything under it, each node once. */\n const subtreeOf = (id: string): string[] => {\n const seen = new Set<string>()\n const stack = [id]\n const out: string[] = []\n while (stack.length) {\n const next = stack.pop() as string\n if (seen.has(next) || !nodeOf(next)) continue\n seen.add(next)\n out.push(next)\n stack.push(...childIds(nodeOf(next)).reverse())\n }\n return out\n }\n const ancestorsOf = (id: string): string[] => {\n const out: string[] = []\n for (let parent = parentOf.get(id); parent; parent = parentOf.get(parent)) out.push(parent)\n return out\n }\n\n const violations: AiDoctrineViolation[] = []\n const refuse = (code: string, detail: string, nodeIds: string[]) => {\n violations.push({\n rule: null,\n code,\n message: `The answer could not be used as a ${options.noun}.`,\n detail,\n nodeIds: [...new Set(nodeIds)],\n })\n }\n const inItem = new Set(marked.flatMap(subtreeOf))\n const topLevel = new Set([rootId, ...childIds(nodeOf(rootId))])\n const taken = new Set(Object.keys(nodes))\n const items: Array<{ id: string; parent: string; subtree: string[]; copies: Scalar[][] }> = []\n\n for (const id of marked) {\n const outer = ancestorsOf(id).find((ancestor) => marked.includes(ancestor))\n if (outer) {\n refuse(\n 'repeat-nested',\n `\"${id}\" has \"${AI_REPEAT_KEY}\" inside \"${outer}\", which repeats already: keep \"${AI_REPEAT_KEY}\" on \"${outer}\" alone, and write what repeats inside it out in full.`,\n [id, outer],\n )\n continue\n }\n if (topLevel.has(id)) {\n refuse(\n 'repeat-on-section',\n `\"${id}\" is the document wrapper or what it holds directly, and never repeats: put \"${AI_REPEAT_KEY}\" on the item that repeats inside the ${options.noun}.`,\n [id],\n )\n continue\n }\n const list = nodeOf(id)?.[AI_REPEAT_KEY]\n if (!Array.isArray(list)) {\n refuse(\n 'repeat-shape',\n `\"${AI_REPEAT_KEY}\" on \"${id}\" is not a list of copies: give it one list of values for each copy, such as ${EXAMPLE}.`,\n [id],\n )\n continue\n }\n // A copy of one value may be the value itself.\n const listed = list.map((copy: unknown) => (isScalar(copy) ? [copy] : copy))\n const malformed = listed.findIndex((copy) => !Array.isArray(copy) || !copy.every(isScalar))\n if (malformed !== -1) {\n refuse(\n 'repeat-shape',\n `The ${ordinal(malformed + 1)} copy of \"${id}\" is not a list of text values: give each copy one list, such as ${EXAMPLE}.`,\n [id],\n )\n continue\n }\n const copies = listed as Scalar[][]\n if (copies.length < 2 || copies.length > AI_REPEAT_MAX_COPIES) {\n refuse(\n 'repeat-count',\n `\"${AI_REPEAT_KEY}\" on \"${id}\" lists ${copies.length} ${copies.length === 1 ? 'copy' : 'copies'}: list from 2 to ${AI_REPEAT_MAX_COPIES}, and write an item that appears once without \"${AI_REPEAT_KEY}\".`,\n [id],\n )\n continue\n }\n const subtree = subtreeOf(id)\n const users = new Map<number, string[]>()\n for (const node of subtree) {\n for (const position of nodePositions(nodeOf(node) as RawNode)) {\n users.set(position, [...(users.get(position) ?? []), node])\n }\n }\n const used = [...users.keys()].sort((a, b) => a - b)\n const highest = used.length ? used[used.length - 1] : 0\n if (users.has(0)) {\n refuse(\n 'repeat-placeholder-without-value',\n `\"${(users.get(0) as string[])[0]}\" uses {{0}}, and a copy's values count from {{1}}: write {{1}} for each copy's first value.`,\n [id, ...(users.get(0) as string[])],\n )\n continue\n }\n const gap = used.findIndex((position, index) => position !== index + 1) + 1\n if (gap > 0) {\n refuse(\n 'repeat-value-without-placeholder',\n `\"${id}\" uses ${placeholders(used)} and no {{${gap}}}, so each copy's ${ordinal(gap)} value fills nothing: number the placeholders from {{1}} with no gap.`,\n [id],\n )\n continue\n }\n const short = copies.findIndex((copy) => copy.length < highest)\n if (short !== -1) {\n const unfilled = used.filter((position) => position > copies[short].length)\n refuse(\n 'repeat-placeholder-without-value',\n `The ${ordinal(short + 1)} copy of \"${id}\" gives ${copies[short].length} ${copies[short].length === 1 ? 'value' : 'values'}, and the item uses ${placeholders(used)}: give every copy one value for each placeholder, in order.`,\n [id, ...unfilled.flatMap((position) => users.get(position) ?? [])],\n )\n continue\n }\n const long = copies.findIndex((copy) => copy.length > highest)\n if (long !== -1) {\n refuse(\n 'repeat-value-without-placeholder',\n highest\n ? `The ${ordinal(long + 1)} copy of \"${id}\" gives ${copies[long].length} values, and the item uses only ${placeholders(used)}: give every copy one value for each placeholder, in order.`\n : `\"${id}\" lists values and uses no placeholder for them: write {{1}}, {{2}} and on where its copies differ, each copy's values in that order.`,\n [id],\n )\n continue\n }\n const collision = subtree\n .flatMap((node) => copies.slice(1).map((_values, index) => ({ node, copy: index + 2 })))\n .find(({ node, copy }) => taken.has(`${node}~${copy}`))\n if (collision) {\n const clash = `${collision.node}~${collision.copy}`\n refuse(\n 'repeat-id-collision',\n `The ${ordinal(collision.copy)} copy of \"${collision.node}\" takes the id \"${clash}\", which the answer already gives another node: rename \"${clash}\".`,\n [id, clash],\n )\n continue\n }\n for (const node of subtree) copies.slice(1).forEach((_values, index) => taken.add(`${node}~${index + 2}`))\n items.push({ id, parent: parentOf.get(id) as string, subtree, copies })\n }\n\n // A placeholder in no repeated item has no copy to take a value from.\n for (const id of order) {\n if (inItem.has(id)) continue\n const positions = nodePositions(nodeOf(id) as RawNode)\n if (!positions.size) continue\n refuse(\n 'repeat-placeholder-without-value',\n `\"${id}\" uses ${placeholders(positions)} and sits in no item with \"${AI_REPEAT_KEY}\": write its text out, or put \"${AI_REPEAT_KEY}\" on the item it repeats in.`,\n [id],\n )\n }\n\n if (violations.length) return { ok: false, violations }\n if (!items.length) return unchanged\n\n const drawn: Record<string, unknown> = { ...nodes }\n const sourceIds: Record<string, string> = {}\n for (const item of items) {\n const members = new Set(item.subtree)\n const idIn = (node: string, copy: number) => (copy === 1 || !members.has(node) ? node : `${node}~${copy}`)\n item.copies.forEach((values, index) => {\n const copy = index + 1\n for (const node of item.subtree) {\n const source = nodeOf(node) as RawNode\n const clone: RawNode = { ...source }\n delete clone[AI_REPEAT_KEY]\n if (source['props'] !== undefined) clone['props'] = fill(source['props'], values)\n if (source['sx'] !== undefined) clone['sx'] = fill(source['sx'], values)\n if (Array.isArray(source['nodes'])) {\n clone['nodes'] = source['nodes'].map((child: unknown) => (typeof child === 'string' ? idIn(child, copy) : child))\n }\n if (node !== item.id && typeof source['parentId'] === 'string') clone['parentId'] = idIn(source['parentId'], copy)\n const id = idIn(node, copy)\n drawn[id] = clone\n if (copy > 1) sourceIds[id] = node\n }\n })\n // Every copy in the item's place, in order: the parent as drawn so far,\n // which an item beside this one may already have drawn into.\n const parent = drawn[item.parent] as RawNode\n const siblings = Array.isArray(parent['nodes']) ? [...parent['nodes']] : []\n siblings.splice(siblings.indexOf(item.id), 1, ...item.copies.map((_values, index) => idIn(item.id, index + 1)))\n drawn[item.parent] = { ...parent, nodes: siblings }\n }\n return { ok: true, tree: { ...input, nodes: drawn }, sourceIds, items: items.length }\n}\n"],"names":["AI_TYPED_LIST_MIN_ITEMS","AI_REPEAT_KEY","AI_REPEAT_MAX_COPIES","PLACEHOLDER","WHOLE_PLACEHOLDER","EXAMPLE","isRecord","value","Array","isArray","isScalar","Number","isFinite","childIds","node","children","filter","id","positionsIn","into","match","matchAll","add","inner","Object","values","nodePositions","Set","fill","whole","exec","replace","_token","position","String","map","fromEntries","entries","key","ordinal","word","tens","suffix","placeholders","positions","list","sort","a","b","length","join","slice","expandAiRepeatedItems","input","options","unchanged","ok","tree","sourceIds","items","rootId","nodes","nodeOf","undefined","parentOf","Map","order","queue","index","push","child","has","set","marked","prototype","hasOwnProperty","call","inline","violations","rule","code","message","detail","nodeIds","subtreeOf","seen","stack","out","next","pop","reverse","ancestorsOf","parent","get","refuse","noun","inItem","flatMap","topLevel","taken","keys","outer","find","ancestor","includes","listed","copy","malformed","findIndex","every","copies","subtree","users","used","highest","gap","short","unfilled","long","collision","_values","clash","forEach","size","drawn","item","members","idIn","source","clone","siblings","splice","indexOf"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../../../../libs/plugins/ai/src/lib/runtime/ai-repeated-items.ts"],"sourcesContent":["/**\n * @license\n * Copyright 2026 Aglyn LLC\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { REUSABLE_INSTANCE_COMPONENT_ID } from '@aglyn/aglyn/app-utils/reusable-component-keys'\nimport { AI_TYPED_LIST_MIN_ITEMS, type AiDoctrineViolation } from './ai-doctrine-validators'\n\n/**\n * A repeated item written once (AGL-3053).\n *\n * A workspace that keeps no reusable components can place no instance, so a\n * row of cards is drawn card by card. Written out in a model's answer, every\n * card repeats its whole subtree — the Card, its body, its heading and its\n * text, each node's JSON escaped inside the tool call — and four practice\n * areas with real copy run past a section pass's answer ceiling. So on such a\n * workspace an answer writes the item ONCE and lists what differs between its\n * copies, and this module draws the copies before any check reads the answer:\n *\n * ```json\n * \"card\": { \"componentId\": \"muiCard\", \"nodes\": [\"body\"],\n * \"repeat\": [[\"Estate planning\", \"Wills and trusts…\"],\n * [\"Real estate\", \"Closings and title…\"]] },\n * \"title\": { \"componentId\": \"muiTypography\", \"props\": { \"children\": \"{{1}}\" } },\n * \"text\": { \"componentId\": \"muiTypography\", \"props\": { \"children\": \"{{2}}\" } }\n * ```\n *\n * `repeat` holds one list of values a copy, and `{{n}}` stands for a copy's\n * n-th value wherever it appears in the item's props or styles.\n *\n * A workspace that DOES keep reusable components writes the same shape around\n * an instance (AGL-3024): one `reusableInstance` inside the repeated item,\n * `{{n}}` through the values it fills, and one list of values a copy. Six\n * cards written out as six instances spend their structure six times and run\n * past the ceiling a pass answers within; written once they spend it once, and\n * the section stays ONE section with one heading, which is what a page's\n * outline and its search ranking are built on. The item still places the\n * component — rule 1 is untouched — and an item that places none is refused\n * here exactly as before.\n *\n * - **Positional, because it is the smallest list a copy can be.** Each value\n * costs its quotes and a comma. A named value repeats its name on every\n * copy, and a list of columns keeps a copy's values apart from each other.\n * - **Numbered, because no binding token is a number.** A site variable's\n * `{{name}}` starts with a letter, and a component's `{{prop.name}}`, a\n * template's `{{entry.field}}` and a function's `{{fn:…}}` carry a dot or a\n * colon (`binding-tokens.ts`), so copy that binds one keeps its token, and\n * nothing a placeholder leaves behind can bind.\n *\n * The copies are the item cloned in order, in its place under its parent. The\n * first keeps the ids the model wrote, and copy `n` takes `<id>~<n>` on every\n * node of the subtree, so one answer always draws one tree and every id a copy\n * took leads back to the node the model wrote (`sourceIds`). The drawn tree is\n * what every check reads and what a page stores: nothing downstream sees\n * `repeat` or a placeholder.\n *\n * Refused, each with a sentence a re-ask can act on and the model's own nodes\n * named: `repeat` on an item that places no instance where the workspace keeps\n * reusable components (rule 1: place a component's instances), on the document\n * wrapper or what it holds\n * directly, or inside another repeated item; a list that is not one list of\n * values a copy; fewer than 2 copies or more than `AI_REPEAT_MAX_COPIES`; a\n * placeholder a copy gives no value for, or one outside every repeated item; a\n * value no placeholder uses; and a copy's id that the answer already gives\n * another node. Pure: no provider and no Firestore.\n */\n\n/** The key a repeated item's node lists its copies' values under. */\nexport const AI_REPEAT_KEY = 'repeat'\n\n/**\n * The most copies one item may list: a list of `AI_TYPED_LIST_MIN_ITEMS` or\n * more typed into a page is data (rule 8), which a plan binds or shortens.\n */\nexport const AI_REPEAT_MAX_COPIES = AI_TYPED_LIST_MIN_ITEMS - 1\n\n/** A copy's `n`-th value, by its 1-based position. */\nconst PLACEHOLDER = /\\{\\{\\s*(\\d+)\\s*\\}\\}/g\n\n/** A string that is one placeholder and nothing else, whose value keeps its own type. */\nconst WHOLE_PLACEHOLDER = /^\\s*\\{\\{\\s*(\\d+)\\s*\\}\\}\\s*$/\n\n/** What a list of copies looks like, in every sentence that asks for one. */\nconst EXAMPLE = '[[\"Title 1\", \"Text 1\"], [\"Title 2\", \"Text 2\"]]'\n\nexport interface AiRepeatedItemsOptions {\n /** The workspace keeps no reusable components: the one place an item is written once. */\n inline: boolean\n /** What the answer is, as a person reads a refusal: `section`, `page`. */\n noun: string\n}\n\nexport type AiRepeatedItemsResult =\n | {\n ok: true\n /** The answer with every repeated item drawn into its copies; the answer itself when none is. */\n tree: unknown\n /** Each id a copy took → the id the model wrote for that node. */\n sourceIds: Record<string, string>\n /** How many items were written once. */\n items: number\n }\n | { ok: false; violations: AiDoctrineViolation[] }\n\ntype RawNode = Record<string, unknown>\ntype Scalar = string | number | boolean\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction isScalar(value: unknown): value is Scalar {\n return (\n typeof value === 'string' || typeof value === 'boolean' || (typeof value === 'number' && Number.isFinite(value))\n )\n}\n\nfunction childIds(node: RawNode | undefined): string[] {\n const children = node?.['nodes']\n return Array.isArray(children) ? children.filter((id): id is string => typeof id === 'string') : []\n}\n\n/** Every placeholder position a value uses, however deep in props or styles. */\nfunction positionsIn(value: unknown, into: Set<number>): Set<number> {\n if (typeof value === 'string') {\n for (const match of value.matchAll(PLACEHOLDER)) into.add(Number(match[1]))\n } else if (Array.isArray(value)) {\n for (const inner of value) positionsIn(inner, into)\n } else if (isRecord(value)) {\n for (const inner of Object.values(value)) positionsIn(inner, into)\n }\n return into\n}\n\n/** The positions one node's props and styles use. */\nfunction nodePositions(node: RawNode): Set<number> {\n return positionsIn(node['sx'], positionsIn(node['props'], new Set()))\n}\n\n/** A value with every placeholder filled from one copy's values. */\nfunction fill(value: unknown, values: readonly Scalar[]): unknown {\n if (typeof value === 'string') {\n const whole = WHOLE_PLACEHOLDER.exec(value)\n if (whole) return values[Number(whole[1]) - 1]\n return value.replace(PLACEHOLDER, (_token, position: string) => String(values[Number(position) - 1]))\n }\n if (Array.isArray(value)) return value.map((inner) => fill(inner, values))\n if (isRecord(value)) {\n return Object.fromEntries(Object.entries(value).map(([key, inner]) => [key, fill(inner, values)]))\n }\n return value\n}\n\n/** 1 → first, 2 → second, 12 → 12th. */\nfunction ordinal(position: number): string {\n const word = ['first', 'second', 'third', 'fourth', 'fifth', 'sixth', 'seventh'][position - 1]\n if (word) return word\n const tens = position % 100\n const suffix = tens >= 11 && tens <= 13 ? 'th' : (['th', 'st', 'nd', 'rd'][position % 10] ?? 'th')\n return `${position}${suffix}`\n}\n\n/** `{{1}}`, `{{1}} and {{2}}`, `{{1}}, {{2}} and {{3}}`. */\nfunction placeholders(positions: Iterable<number>): string {\n const list = [...positions].sort((a, b) => a - b).map((position) => `{{${position}}}`)\n return list.length <= 1 ? list.join('') : `${list.slice(0, -1).join(', ')} and ${list[list.length - 1]}`\n}\n\n/**\n * The answer with every repeated item drawn into its copies, or the reasons it\n * cannot be. An answer that is not a node map, or that writes nothing once, is\n * handed back as it came, for the palette validator to read as it always has.\n */\nexport function expandAiRepeatedItems(input: unknown, options: AiRepeatedItemsOptions): AiRepeatedItemsResult {\n const unchanged: AiRepeatedItemsResult = { ok: true, tree: input, sourceIds: {}, items: 0 }\n if (!isRecord(input) || typeof input['rootId'] !== 'string' || !isRecord(input['nodes'])) return unchanged\n const rootId = input['rootId']\n const nodes = input['nodes'] as Record<string, unknown>\n const nodeOf = (id: string): RawNode | undefined => {\n const node = nodes[id]\n return isRecord(node) ? node : undefined\n }\n\n // The walk the palette validator makes: breadth first from the root, each\n // node under the first parent that lists it.\n const parentOf = new Map<string, string | null>([[rootId, null]])\n const order: string[] = []\n const queue = [rootId]\n for (let index = 0; index < queue.length; index += 1) {\n const id = queue[index]\n if (!nodeOf(id)) continue\n order.push(id)\n for (const child of childIds(nodeOf(id))) {\n if (parentOf.has(child)) continue\n parentOf.set(child, id)\n queue.push(child)\n }\n }\n const marked = order.filter((id) => Object.prototype.hasOwnProperty.call(nodeOf(id), AI_REPEAT_KEY))\n\n /** A node and everything under it, each node once. */\n const subtreeOf = (id: string): string[] => {\n const seen = new Set<string>()\n const stack = [id]\n const out: string[] = []\n while (stack.length) {\n const next = stack.pop() as string\n if (seen.has(next) || !nodeOf(next)) continue\n seen.add(next)\n out.push(next)\n stack.push(...childIds(nodeOf(next)).reverse())\n }\n return out\n }\n\n // Where the workspace keeps reusable components, writing an item once is how\n // an answer places MANY instances inside one ceiling (AGL-3024), not a way\n // around placing them: an item that places an instance is drawn into its\n // copies exactly as a Free one is, and one that places none is still drawing\n // by hand a component the site has, which rule 1 refuses as it always did.\n if (!options.inline) {\n const byHand = marked.filter(\n (id) => !subtreeOf(id).some((node) => nodeOf(node)?.['componentId'] === REUSABLE_INSTANCE_COMPONENT_ID),\n )\n if (byHand.length) {\n return {\n ok: false,\n violations: [\n {\n rule: 1,\n code: 'repeat-not-inline',\n message: 'This draws a repeated item to be copied, instead of placing it as instances of a component.',\n detail: `Put one instance of a component the site has (componentId \"reusableInstance\") inside the repeated item, or remove \"${AI_REPEAT_KEY}\" and place each copy as an instance.`,\n nodeIds: byHand,\n },\n ],\n }\n }\n if (!marked.length) return unchanged\n }\n const ancestorsOf = (id: string): string[] => {\n const out: string[] = []\n for (let parent = parentOf.get(id); parent; parent = parentOf.get(parent)) out.push(parent)\n return out\n }\n\n const violations: AiDoctrineViolation[] = []\n const refuse = (code: string, detail: string, nodeIds: string[]) => {\n violations.push({\n rule: null,\n code,\n message: `The answer could not be used as a ${options.noun}.`,\n detail,\n nodeIds: [...new Set(nodeIds)],\n })\n }\n const inItem = new Set(marked.flatMap(subtreeOf))\n const topLevel = new Set([rootId, ...childIds(nodeOf(rootId))])\n const taken = new Set(Object.keys(nodes))\n const items: Array<{ id: string; parent: string; subtree: string[]; copies: Scalar[][] }> = []\n\n for (const id of marked) {\n const outer = ancestorsOf(id).find((ancestor) => marked.includes(ancestor))\n if (outer) {\n refuse(\n 'repeat-nested',\n `\"${id}\" has \"${AI_REPEAT_KEY}\" inside \"${outer}\", which repeats already: keep \"${AI_REPEAT_KEY}\" on \"${outer}\" alone, and write what repeats inside it out in full.`,\n [id, outer],\n )\n continue\n }\n if (topLevel.has(id)) {\n refuse(\n 'repeat-on-section',\n `\"${id}\" is the document wrapper or what it holds directly, and never repeats: put \"${AI_REPEAT_KEY}\" on the item that repeats inside the ${options.noun}.`,\n [id],\n )\n continue\n }\n const list = nodeOf(id)?.[AI_REPEAT_KEY]\n if (!Array.isArray(list)) {\n refuse(\n 'repeat-shape',\n `\"${AI_REPEAT_KEY}\" on \"${id}\" is not a list of copies: give it one list of values for each copy, such as ${EXAMPLE}.`,\n [id],\n )\n continue\n }\n // A copy of one value may be the value itself.\n const listed = list.map((copy: unknown) => (isScalar(copy) ? [copy] : copy))\n const malformed = listed.findIndex((copy) => !Array.isArray(copy) || !copy.every(isScalar))\n if (malformed !== -1) {\n refuse(\n 'repeat-shape',\n `The ${ordinal(malformed + 1)} copy of \"${id}\" is not a list of text values: give each copy one list, such as ${EXAMPLE}.`,\n [id],\n )\n continue\n }\n const copies = listed as Scalar[][]\n if (copies.length < 2 || copies.length > AI_REPEAT_MAX_COPIES) {\n refuse(\n 'repeat-count',\n `\"${AI_REPEAT_KEY}\" on \"${id}\" lists ${copies.length} ${copies.length === 1 ? 'copy' : 'copies'}: list from 2 to ${AI_REPEAT_MAX_COPIES}, and write an item that appears once without \"${AI_REPEAT_KEY}\".`,\n [id],\n )\n continue\n }\n const subtree = subtreeOf(id)\n const users = new Map<number, string[]>()\n for (const node of subtree) {\n for (const position of nodePositions(nodeOf(node) as RawNode)) {\n users.set(position, [...(users.get(position) ?? []), node])\n }\n }\n const used = [...users.keys()].sort((a, b) => a - b)\n const highest = used.length ? used[used.length - 1] : 0\n if (users.has(0)) {\n refuse(\n 'repeat-placeholder-without-value',\n `\"${(users.get(0) as string[])[0]}\" uses {{0}}, and a copy's values count from {{1}}: write {{1}} for each copy's first value.`,\n [id, ...(users.get(0) as string[])],\n )\n continue\n }\n const gap = used.findIndex((position, index) => position !== index + 1) + 1\n if (gap > 0) {\n refuse(\n 'repeat-value-without-placeholder',\n `\"${id}\" uses ${placeholders(used)} and no {{${gap}}}, so each copy's ${ordinal(gap)} value fills nothing: number the placeholders from {{1}} with no gap.`,\n [id],\n )\n continue\n }\n const short = copies.findIndex((copy) => copy.length < highest)\n if (short !== -1) {\n const unfilled = used.filter((position) => position > copies[short].length)\n refuse(\n 'repeat-placeholder-without-value',\n `The ${ordinal(short + 1)} copy of \"${id}\" gives ${copies[short].length} ${copies[short].length === 1 ? 'value' : 'values'}, and the item uses ${placeholders(used)}: give every copy one value for each placeholder, in order.`,\n [id, ...unfilled.flatMap((position) => users.get(position) ?? [])],\n )\n continue\n }\n const long = copies.findIndex((copy) => copy.length > highest)\n if (long !== -1) {\n refuse(\n 'repeat-value-without-placeholder',\n highest\n ? `The ${ordinal(long + 1)} copy of \"${id}\" gives ${copies[long].length} values, and the item uses only ${placeholders(used)}: give every copy one value for each placeholder, in order.`\n : `\"${id}\" lists values and uses no placeholder for them: write {{1}}, {{2}} and on where its copies differ, each copy's values in that order.`,\n [id],\n )\n continue\n }\n const collision = subtree\n .flatMap((node) => copies.slice(1).map((_values, index) => ({ node, copy: index + 2 })))\n .find(({ node, copy }) => taken.has(`${node}~${copy}`))\n if (collision) {\n const clash = `${collision.node}~${collision.copy}`\n refuse(\n 'repeat-id-collision',\n `The ${ordinal(collision.copy)} copy of \"${collision.node}\" takes the id \"${clash}\", which the answer already gives another node: rename \"${clash}\".`,\n [id, clash],\n )\n continue\n }\n for (const node of subtree) copies.slice(1).forEach((_values, index) => taken.add(`${node}~${index + 2}`))\n items.push({ id, parent: parentOf.get(id) as string, subtree, copies })\n }\n\n // A placeholder in no repeated item has no copy to take a value from.\n for (const id of order) {\n if (inItem.has(id)) continue\n const positions = nodePositions(nodeOf(id) as RawNode)\n if (!positions.size) continue\n refuse(\n 'repeat-placeholder-without-value',\n `\"${id}\" uses ${placeholders(positions)} and sits in no item with \"${AI_REPEAT_KEY}\": write its text out, or put \"${AI_REPEAT_KEY}\" on the item it repeats in.`,\n [id],\n )\n }\n\n if (violations.length) return { ok: false, violations }\n if (!items.length) return unchanged\n\n const drawn: Record<string, unknown> = { ...nodes }\n const sourceIds: Record<string, string> = {}\n for (const item of items) {\n const members = new Set(item.subtree)\n const idIn = (node: string, copy: number) => (copy === 1 || !members.has(node) ? node : `${node}~${copy}`)\n item.copies.forEach((values, index) => {\n const copy = index + 1\n for (const node of item.subtree) {\n const source = nodeOf(node) as RawNode\n const clone: RawNode = { ...source }\n delete clone[AI_REPEAT_KEY]\n if (source['props'] !== undefined) clone['props'] = fill(source['props'], values)\n if (source['sx'] !== undefined) clone['sx'] = fill(source['sx'], values)\n if (Array.isArray(source['nodes'])) {\n clone['nodes'] = source['nodes'].map((child: unknown) => (typeof child === 'string' ? idIn(child, copy) : child))\n }\n if (node !== item.id && typeof source['parentId'] === 'string') clone['parentId'] = idIn(source['parentId'], copy)\n const id = idIn(node, copy)\n drawn[id] = clone\n if (copy > 1) sourceIds[id] = node\n }\n })\n // Every copy in the item's place, in order: the parent as drawn so far,\n // which an item beside this one may already have drawn into.\n const parent = drawn[item.parent] as RawNode\n const siblings = Array.isArray(parent['nodes']) ? [...parent['nodes']] : []\n siblings.splice(siblings.indexOf(item.id), 1, ...item.copies.map((_values, index) => idIn(item.id, index + 1)))\n drawn[item.parent] = { ...parent, nodes: siblings }\n }\n return { ok: true, tree: { ...input, nodes: drawn }, sourceIds, items: items.length }\n}\n"],"names":["REUSABLE_INSTANCE_COMPONENT_ID","AI_TYPED_LIST_MIN_ITEMS","AI_REPEAT_KEY","AI_REPEAT_MAX_COPIES","PLACEHOLDER","WHOLE_PLACEHOLDER","EXAMPLE","isRecord","value","Array","isArray","isScalar","Number","isFinite","childIds","node","children","filter","id","positionsIn","into","match","matchAll","add","inner","Object","values","nodePositions","Set","fill","whole","exec","replace","_token","position","String","map","fromEntries","entries","key","ordinal","word","tens","suffix","placeholders","positions","list","sort","a","b","length","join","slice","expandAiRepeatedItems","input","options","unchanged","ok","tree","sourceIds","items","rootId","nodes","nodeOf","undefined","parentOf","Map","order","queue","index","push","child","has","set","marked","prototype","hasOwnProperty","call","subtreeOf","seen","stack","out","next","pop","reverse","inline","byHand","some","violations","rule","code","message","detail","nodeIds","ancestorsOf","parent","get","refuse","noun","inItem","flatMap","topLevel","taken","keys","outer","find","ancestor","includes","listed","copy","malformed","findIndex","every","copies","subtree","users","used","highest","gap","short","unfilled","long","collision","_values","clash","forEach","size","drawn","item","members","idIn","source","clone","siblings","splice","indexOf"],"mappings":"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"}
|