@elytracms/studio 0.0.92 → 0.0.93
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/convex/asset-alt-migration.test.ts +127 -0
- package/convex/asset-replace.test.ts +168 -0
- package/convex/asset-revalidate.test.ts +6 -6
- package/convex/assets.ts +41 -5
- package/convex/cms.ts +25 -11
- package/convex/contract-parity.test.ts +18 -3
- package/convex/document-revalidate.test.ts +10 -12
- package/convex/orphan-hydration.test.ts +116 -0
- package/convex/rail-write-parity.test.ts +11 -8
- package/convex/schema.ts +6 -0
- package/dist/components/ai/proposal-card.js +2 -1
- package/dist/components/ai/proposal-card.js.map +1 -1
- package/dist/components/ai/translate-document-dialog.js +4 -2
- package/dist/components/ai/translate-document-dialog.js.map +1 -1
- package/dist/components/ai/translate-skipped.d.ts +19 -0
- package/dist/components/ai/translate-skipped.js +46 -0
- package/dist/components/ai/translate-skipped.js.map +1 -0
- package/dist/components/assets/asset-detail.js +18 -8
- package/dist/components/assets/asset-detail.js.map +1 -1
- package/dist/components/assets/asset-metadata.d.ts +15 -4
- package/dist/components/assets/asset-metadata.js +15 -2
- package/dist/components/assets/asset-metadata.js.map +1 -1
- package/dist/components/assets/asset-search.js +4 -1
- package/dist/components/assets/asset-search.js.map +1 -1
- package/dist/components/assets/asset-selection.d.ts +0 -8
- package/dist/components/assets/asset-selection.js +4 -23
- package/dist/components/assets/asset-selection.js.map +1 -1
- package/dist/components/assets/asset-thumb.js +3 -2
- package/dist/components/assets/asset-thumb.js.map +1 -1
- package/dist/components/assets/assets-collection-view-source.d.ts +3 -3
- package/dist/components/assets/assets-collection-view-source.js +9 -5
- package/dist/components/assets/assets-collection-view-source.js.map +1 -1
- package/dist/components/assets/assets-store.d.ts +14 -0
- package/dist/components/assets/assets-store.js +23 -1
- package/dist/components/assets/assets-store.js.map +1 -1
- package/dist/components/assets/replace-file.d.ts +22 -0
- package/dist/components/assets/replace-file.js +59 -0
- package/dist/components/assets/replace-file.js.map +1 -0
- package/dist/components/builder/blocks-model.d.ts +14 -26
- package/dist/components/builder/blocks-model.js +35 -41
- package/dist/components/builder/blocks-model.js.map +1 -1
- package/dist/components/builder/blocks-panel.d.ts +7 -3
- package/dist/components/builder/blocks-panel.js +6 -5
- package/dist/components/builder/blocks-panel.js.map +1 -1
- package/dist/components/builder/builder-store.d.ts +104 -15
- package/dist/components/builder/builder-store.js +156 -31
- package/dist/components/builder/builder-store.js.map +1 -1
- package/dist/components/builder/canvas-body.d.ts +30 -0
- package/dist/components/builder/canvas-body.js +38 -0
- package/dist/components/builder/canvas-body.js.map +1 -0
- package/dist/components/builder/canvas-chrome-css.js +7 -0
- package/dist/components/builder/canvas-chrome-css.js.map +1 -1
- package/dist/components/builder/canvas-dnd.d.ts +7 -7
- package/dist/components/builder/canvas-dnd.js +5 -5
- package/dist/components/builder/canvas-dnd.js.map +1 -1
- package/dist/components/builder/canvas-render-context.d.ts +27 -19
- package/dist/components/builder/canvas-render-context.js +42 -43
- package/dist/components/builder/canvas-render-context.js.map +1 -1
- package/dist/components/builder/canvas-runs.d.ts +45 -0
- package/dist/components/builder/canvas-runs.js +51 -0
- package/dist/components/builder/canvas-runs.js.map +1 -0
- package/dist/components/builder/canvas.js +32 -5
- package/dist/components/builder/canvas.js.map +1 -1
- package/dist/components/builder/clipboard-actions.d.ts +15 -0
- package/dist/components/builder/clipboard-actions.js +44 -7
- package/dist/components/builder/clipboard-actions.js.map +1 -1
- package/dist/components/builder/composition-field-editor.d.ts +3 -15
- package/dist/components/builder/composition-field-editor.js +29 -40
- package/dist/components/builder/composition-field-editor.js.map +1 -1
- package/dist/components/builder/delete-key.d.ts +5 -0
- package/dist/components/builder/delete-key.js +4 -0
- package/dist/components/builder/delete-key.js.map +1 -1
- package/dist/components/builder/insert-context.d.ts +17 -25
- package/dist/components/builder/insert-context.js +45 -92
- package/dist/components/builder/insert-context.js.map +1 -1
- package/dist/components/builder/page-tree.d.ts +3 -3
- package/dist/components/builder/page-tree.js +3 -3
- package/dist/components/builder/page-tree.js.map +1 -1
- package/dist/components/builder/placement-refusal.d.ts +18 -0
- package/dist/components/builder/placement-refusal.js +46 -0
- package/dist/components/builder/placement-refusal.js.map +1 -0
- package/dist/components/builder/property-inspector.js +4 -0
- package/dist/components/builder/property-inspector.js.map +1 -1
- package/dist/components/builder/reuse-context.js +65 -27
- package/dist/components/builder/reuse-context.js.map +1 -1
- package/dist/components/builder/reuse.d.ts +79 -1
- package/dist/components/builder/reuse.js +69 -2
- package/dist/components/builder/reuse.js.map +1 -1
- package/dist/components/builder/run-inspector.d.ts +11 -0
- package/dist/components/builder/run-inspector.js +33 -0
- package/dist/components/builder/run-inspector.js.map +1 -0
- package/dist/components/cms/asset-field.d.ts +38 -1
- package/dist/components/cms/asset-field.js +182 -58
- package/dist/components/cms/asset-field.js.map +1 -1
- package/dist/components/cms/asset-picker-core.d.ts +16 -0
- package/dist/components/cms/asset-picker-core.js +20 -0
- package/dist/components/cms/asset-picker-core.js.map +1 -1
- package/dist/components/cms/asset-picker.js +12 -18
- package/dist/components/cms/asset-picker.js.map +1 -1
- package/dist/components/cms/bulk-actions.d.ts +3 -19
- package/dist/components/cms/bulk-actions.js +3 -24
- package/dist/components/cms/bulk-actions.js.map +1 -1
- package/dist/components/cms/cell.js.map +1 -1
- package/dist/components/cms/cms-store.d.ts +5 -4
- package/dist/components/cms/cms-store.js +16 -36
- package/dist/components/cms/cms-store.js.map +1 -1
- package/dist/components/cms/detail-editor.js +0 -1
- package/dist/components/cms/detail-editor.js.map +1 -1
- package/dist/components/cms/document-diff-view.d.ts +3 -1
- package/dist/components/cms/document-diff-view.js +12 -7
- package/dist/components/cms/document-diff-view.js.map +1 -1
- package/dist/components/cms/field-anchors.d.ts +7 -4
- package/dist/components/cms/field-anchors.js +9 -7
- package/dist/components/cms/field-anchors.js.map +1 -1
- package/dist/components/cms/field-control-lib.d.ts +15 -1
- package/dist/components/cms/field-control-lib.js +22 -3
- package/dist/components/cms/field-control-lib.js.map +1 -1
- package/dist/components/cms/gate-validation.d.ts +21 -30
- package/dist/components/cms/gate-validation.js +11 -32
- package/dist/components/cms/gate-validation.js.map +1 -1
- package/dist/components/cms/object-array-field.js +4 -4
- package/dist/components/cms/object-array-field.js.map +1 -1
- package/dist/components/cms/prop-fields.d.ts +7 -2
- package/dist/components/cms/prop-fields.js +13 -6
- package/dist/components/cms/prop-fields.js.map +1 -1
- package/dist/components/cms/rich-text/embed-picker.d.ts +1 -1
- package/dist/components/cms/rich-text/embed-picker.js.map +1 -1
- package/dist/components/cms/rich-text/insert.d.ts +20 -9
- package/dist/components/cms/rich-text/insert.js +25 -17
- package/dist/components/cms/rich-text/insert.js.map +1 -1
- package/dist/components/cms/use-publish-controller.d.ts +1 -2
- package/dist/components/cms/use-publish-controller.js +7 -19
- package/dist/components/cms/use-publish-controller.js.map +1 -1
- package/dist/components/cms/versions-pane.js +8 -1
- package/dist/components/cms/versions-pane.js.map +1 -1
- package/dist/components/collection-view/cms-collection-view-source.js +3 -1
- package/dist/components/collection-view/cms-collection-view-source.js.map +1 -1
- package/dist/components/components/transfer-dialog.js +2 -1
- package/dist/components/components/transfer-dialog.js.map +1 -1
- package/dist/components/components/transfer.d.ts +10 -10
- package/dist/components/components/transfer.js +13 -12
- package/dist/components/components/transfer.js.map +1 -1
- package/dist/lib/ai/apply-content.js +56 -116
- package/dist/lib/ai/apply-content.js.map +1 -1
- package/dist/lib/ai/chat-context.d.ts +8 -0
- package/dist/lib/ai/chat-context.js +37 -6
- package/dist/lib/ai/chat-context.js.map +1 -1
- package/dist/lib/ai/chat-state.d.ts +6 -0
- package/dist/lib/ai/chat-state.js.map +1 -1
- package/dist/lib/ai/constraints.d.ts +20 -5
- package/dist/lib/ai/constraints.js +125 -33
- package/dist/lib/ai/constraints.js.map +1 -1
- package/dist/lib/ai/fake-provider.d.ts +16 -3
- package/dist/lib/ai/fake-provider.js +22 -6
- package/dist/lib/ai/fake-provider.js.map +1 -1
- package/dist/lib/ai/index.d.ts +2 -0
- package/dist/lib/ai/index.js +2 -0
- package/dist/lib/ai/index.js.map +1 -1
- package/dist/lib/ai/leash.d.ts +34 -0
- package/dist/lib/ai/leash.js +28 -0
- package/dist/lib/ai/leash.js.map +1 -0
- package/dist/lib/ai/rich-text-input.d.ts +8 -8
- package/dist/lib/ai/rich-text-input.js +2 -1
- package/dist/lib/ai/rich-text-input.js.map +1 -1
- package/dist/lib/ai/rich-text-translate.d.ts +27 -4
- package/dist/lib/ai/rich-text-translate.js +28 -10
- package/dist/lib/ai/rich-text-translate.js.map +1 -1
- package/dist/lib/ai/shape.d.ts +13 -13
- package/dist/lib/ai/shape.js +69 -93
- package/dist/lib/ai/shape.js.map +1 -1
- package/dist/lib/ai/tools.d.ts +36 -41
- package/dist/lib/ai/tools.js +83 -87
- package/dist/lib/ai/tools.js.map +1 -1
- package/dist/lib/ai/translate-document.d.ts +32 -4
- package/dist/lib/ai/translate-document.js +144 -46
- package/dist/lib/ai/translate-document.js.map +1 -1
- package/dist/lib/ai/types.d.ts +34 -23
- package/dist/lib/ai/types.js.map +1 -1
- package/dist/lib/ai/update-fields.d.ts +15 -12
- package/dist/lib/ai/update-fields.js +112 -188
- package/dist/lib/ai/update-fields.js.map +1 -1
- package/dist/lib/ai/writer-form.d.ts +116 -0
- package/dist/lib/ai/writer-form.js +429 -0
- package/dist/lib/ai/writer-form.js.map +1 -0
- package/dist/lib/assets/upload.d.ts +31 -2
- package/dist/lib/assets/upload.js +61 -6
- package/dist/lib/assets/upload.js.map +1 -1
- package/dist/lib/clipboard/os-clipboard.d.ts +10 -2
- package/dist/lib/clipboard/os-clipboard.js +8 -4
- package/dist/lib/clipboard/os-clipboard.js.map +1 -1
- package/dist/lib/clipboard/paste-target.d.ts +18 -9
- package/dist/lib/clipboard/paste-target.js +8 -7
- package/dist/lib/clipboard/paste-target.js.map +1 -1
- package/dist/lib/cms/field-patch.d.ts +0 -10
- package/dist/lib/cms/field-patch.js +4 -30
- package/dist/lib/cms/field-patch.js.map +1 -1
- package/dist/lib/cms-views/view-model.d.ts +3 -3
- package/dist/lib/collection-view/collection-view-source.d.ts +7 -3
- package/dist/lib/collection-view/collection-view-source.js.map +1 -1
- package/dist/lib/data/collection-content.js +3 -2
- package/dist/lib/data/collection-content.js.map +1 -1
- package/dist/lib/dnd/drop-rules.d.ts +25 -31
- package/dist/lib/dnd/drop-rules.js +53 -59
- package/dist/lib/dnd/drop-rules.js.map +1 -1
- package/dist/lib/engine-version.d.ts +1 -1
- package/dist/lib/engine-version.js +1 -1
- package/dist/lib/engine-version.js.map +1 -1
- package/dist/lib/i18n/messages.de.js +40 -3
- package/dist/lib/i18n/messages.de.js.map +1 -1
- package/dist/lib/i18n/messages.en.d.ts +34 -2
- package/dist/lib/i18n/messages.en.js +43 -3
- package/dist/lib/i18n/messages.en.js.map +1 -1
- package/dist/lib/operations/project-runtime-config.d.ts +25 -6
- package/dist/lib/operations/project-runtime-config.js +37 -10
- package/dist/lib/operations/project-runtime-config.js.map +1 -1
- package/dist/lib/operations/publish-with-revision.d.ts +33 -1
- package/dist/lib/operations/publish-with-revision.js +32 -0
- package/dist/lib/operations/publish-with-revision.js.map +1 -1
- package/dist/lib/operations/runtime-validator.d.ts +19 -68
- package/dist/lib/operations/runtime-validator.js +12 -138
- package/dist/lib/operations/runtime-validator.js.map +1 -1
- package/dist/lib/operations/studio-operations.d.ts +9 -2
- package/dist/lib/operations/studio-operations.js +13 -11
- package/dist/lib/operations/studio-operations.js.map +1 -1
- package/dist/lib/persistence/convex-adapter.js +6 -1
- package/dist/lib/persistence/convex-adapter.js.map +1 -1
- package/dist/lib/persona/labels.js +3 -1
- package/dist/lib/persona/labels.js.map +1 -1
- package/dist/lib/workspace/index.d.ts +8 -11
- package/dist/lib/workspace/index.js +12 -24
- package/dist/lib/workspace/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/components/cms/cms-composition-validators.d.ts +0 -16
- package/dist/components/cms/cms-composition-validators.js +0 -133
- package/dist/components/cms/cms-composition-validators.js.map +0 -1
- package/dist/components/cms/publish-clean.d.ts +0 -28
- package/dist/components/cms/publish-clean.js +0 -38
- package/dist/components/cms/publish-clean.js.map +0 -1
- package/dist/lib/assets/asset-placements.d.ts +0 -28
- package/dist/lib/assets/asset-placements.js +0 -83
- package/dist/lib/assets/asset-placements.js.map +0 -1
|
@@ -28,6 +28,25 @@ import { BOUND_UNIT_NOUN, fieldJsonSchema, fieldTypeOf } from '@elytracms/core/c
|
|
|
28
28
|
import { MARKDOWN_PROSE_DESCRIPTION } from '@elytracms/core/rich-text';
|
|
29
29
|
/** The note appended when a field's constraint projection is knowingly partial. */
|
|
30
30
|
export const INCOMPLETE_CONSTRAINTS_NOTE = 'further validation rules apply that are not expressible here — keep the value conventional and plausible';
|
|
31
|
+
/**
|
|
32
|
+
* What the catalog says about a composition (`blocks`) — its writer form is NONE
|
|
33
|
+
* (`FIELD_TYPES.blocks.writer === 'composition'`, ratified 4c, EC-593): the assistant
|
|
34
|
+
* changes component props, never which components there are. Said in the prose because
|
|
35
|
+
* the omission must be VISIBLE, not a field the model simply never hears of.
|
|
36
|
+
*/
|
|
37
|
+
export const COMPOSITION_NOTE = 'page-builder composition: the assistant never adds, moves or removes its components (that is done on the canvas) — change one component prop with blockId + prop (getDocument lists the components and their props)';
|
|
38
|
+
/**
|
|
39
|
+
* Whether a field's validation has rules its projection cannot state (RULES D13): a
|
|
40
|
+
* schema whose projection is knowingly partial (`schemaComplete: false`), or a FUNCTION
|
|
41
|
+
* `validate` — normalisation stamps `schemaComplete` on a schema-form validator only, so
|
|
42
|
+
* a declared `validate` without it is a function no consumer can read.
|
|
43
|
+
*/
|
|
44
|
+
function hasUnstatedRules(field) {
|
|
45
|
+
const validation = field.validation;
|
|
46
|
+
if (!validation)
|
|
47
|
+
return false;
|
|
48
|
+
return validation.schemaComplete === false || (validation.validate !== undefined && validation.schemaComplete === undefined);
|
|
49
|
+
}
|
|
31
50
|
/**
|
|
32
51
|
* The prose form of `format: 'date-time'` (EC-505). The JSON-Schema keyword rides
|
|
33
52
|
* on the target shape for the provider's validator; the CATALOG has no JSON Schema
|
|
@@ -63,13 +82,29 @@ export function plainTextBoundPhrase(field) {
|
|
|
63
82
|
return `at most ${max} ${noun}`;
|
|
64
83
|
return undefined;
|
|
65
84
|
}
|
|
66
|
-
/**
|
|
67
|
-
function
|
|
85
|
+
/** The declared sub-fields of an object or an asset placement (`[]` for any other type). */
|
|
86
|
+
function subFieldsOf(field) {
|
|
87
|
+
return field.type === 'object' ? field.fields : field.type === 'asset' ? (field.fields ?? []) : [];
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The clauses only the DECLARATION can say, for a field and every sub-field below it,
|
|
91
|
+
* name-prefixed (`note: at most 400 plain-text characters`, `label: required`):
|
|
92
|
+
* - a plain-text bound ({@link plainTextBoundPhrase}, EC-581);
|
|
93
|
+
* - a sub-field's `required` (RULES F3d — the shape's JSON `required` carried it, the
|
|
94
|
+
* prose never did); the field's own is said by {@link describeFieldConstraints};
|
|
95
|
+
* - a sub-field's rules the projection cannot state ({@link hasUnstatedRules}).
|
|
96
|
+
*/
|
|
97
|
+
function declarationClauses(field, prefix = '') {
|
|
68
98
|
const own = plainTextBoundPhrase(field);
|
|
69
99
|
const out = own !== undefined ? [`${prefix}${own}`] : [];
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
100
|
+
for (const sub of subFieldsOf(field)) {
|
|
101
|
+
const subPrefix = `${prefix}${sub.name}: `;
|
|
102
|
+
if (sub.validation?.required === true)
|
|
103
|
+
out.push(`${subPrefix}required`);
|
|
104
|
+
out.push(...declarationClauses(sub, subPrefix));
|
|
105
|
+
if (hasUnstatedRules(sub))
|
|
106
|
+
out.push(`${subPrefix}${INCOMPLETE_CONSTRAINTS_NOTE}`);
|
|
107
|
+
}
|
|
73
108
|
return out;
|
|
74
109
|
}
|
|
75
110
|
/**
|
|
@@ -103,35 +138,69 @@ export function richTextWriterSchema(field) {
|
|
|
103
138
|
* - relation → `{ collection, id }` (the envelope minus `type`): the lens rebuilds
|
|
104
139
|
* a bare reference into its envelope;
|
|
105
140
|
* - rich text → a markdown string (`richTextWriterSchema`) — the engine converts it
|
|
106
|
-
* wherever it sits (`
|
|
107
|
-
* - an `object` → its own projection with every subfield in ITS writer form
|
|
141
|
+
* wherever it sits (`writer-form.ts`, EC-593);
|
|
142
|
+
* - an `object` → its own projection with every subfield in ITS writer form;
|
|
143
|
+
* - a composition (`blocks`) → NONE (`undefined`): its structure is the canvas's
|
|
144
|
+
* (ratified 4c, EC-593) — a target shape omits it and says so.
|
|
108
145
|
*
|
|
109
146
|
* Writer objects are closed (`additionalProperties: false`): a writer inventing keys
|
|
110
147
|
* is a fault, where a stored envelope carrying extra keys is drift the lens
|
|
111
|
-
* tolerates (EC-556 §B) — which is why the projection itself stays open.
|
|
112
|
-
*
|
|
148
|
+
* tolerates (EC-556 §B) — which is why the projection itself stays open.
|
|
149
|
+
*
|
|
150
|
+
* With a `leash` (the create target shape, EC-381 → EC-593) every relation / asset id
|
|
151
|
+
* — at EVERY depth, not only a top-level field — is an ENUM over what the model
|
|
152
|
+
* searched for that position (a relation's target, an asset's `accept`), and a position
|
|
153
|
+
* with nothing searched is omitted (empty beats wrong). Without one (the catalog prose)
|
|
154
|
+
* the plain writer forms are described.
|
|
113
155
|
*/
|
|
114
|
-
export function writerFieldSchema(field) {
|
|
115
|
-
return writerForm(field, fieldJsonSchema(field));
|
|
156
|
+
export function writerFieldSchema(field, leash) {
|
|
157
|
+
return writerForm(field, fieldJsonSchema(field), leash);
|
|
158
|
+
}
|
|
159
|
+
/** An id enum over searched candidates, labelled for the model to choose against. */
|
|
160
|
+
function candidateEnum(candidates, asset) {
|
|
161
|
+
const label = candidates.map((c) => (c.label ? `${c.id} (${c.label})` : c.id)).join(', ');
|
|
162
|
+
return {
|
|
163
|
+
type: 'string',
|
|
164
|
+
enum: candidates.map((c) => c.id),
|
|
165
|
+
description: asset
|
|
166
|
+
? `Choose an EXISTING library asset id, one of: ${label}. Leave empty if none fits.`
|
|
167
|
+
: `Choose one of: ${label}`,
|
|
168
|
+
};
|
|
116
169
|
}
|
|
117
170
|
/** EC-581: the writer form is DECLARED per type (`FIELD_TYPES[type].writer`); built here. */
|
|
118
|
-
function writerForm(field, base) {
|
|
171
|
+
function writerForm(field, base, leash) {
|
|
119
172
|
switch (fieldTypeOf(field).writer) {
|
|
120
173
|
case 'markdown':
|
|
121
174
|
return richTextWriterSchema(field);
|
|
175
|
+
case 'composition':
|
|
176
|
+
return undefined;
|
|
122
177
|
case 'placement': {
|
|
123
178
|
if (field.type !== 'asset')
|
|
124
179
|
return base;
|
|
125
180
|
// `type`/`id` belong to the envelope; the projection never lets a sub-field
|
|
126
181
|
// of that name shadow them, and neither does the writer form.
|
|
127
182
|
const subfields = (field.fields ?? []).filter((sub) => sub.name !== 'type' && sub.name !== 'id');
|
|
128
|
-
|
|
183
|
+
const candidates = leash?.assetCandidates(field);
|
|
184
|
+
if (candidates !== undefined && candidates.length === 0)
|
|
185
|
+
return undefined;
|
|
186
|
+
const idSchema = (item) => candidates !== undefined ? candidateEnum(candidates, true) : bareAssetId(item);
|
|
187
|
+
return perItem(field.multiple, base, (item) => subfields.length === 0
|
|
188
|
+
? idSchema(item)
|
|
189
|
+
: writerObject(subfields, { ...item, properties: { ...propertiesOf(item), id: idSchema(item) } }, leash));
|
|
190
|
+
}
|
|
191
|
+
case 'reference': {
|
|
192
|
+
if (field.type !== 'relation')
|
|
193
|
+
return base;
|
|
194
|
+
if (!leash)
|
|
195
|
+
return perItem(field.multiple, base, bareReference);
|
|
196
|
+
const candidates = leash.relationCandidates(field.target);
|
|
197
|
+
if (candidates.length === 0)
|
|
198
|
+
return undefined;
|
|
199
|
+
return perItem(field.multiple, base, () => candidateEnum(candidates, false));
|
|
129
200
|
}
|
|
130
|
-
case 'reference':
|
|
131
|
-
return field.type === 'relation' ? perItem(field.multiple, base, bareReference) : base;
|
|
132
201
|
case 'object':
|
|
133
202
|
return field.type === 'object'
|
|
134
|
-
? perItem(field.multiple, base, (item) => writerObject(field.fields, item))
|
|
203
|
+
? perItem(field.multiple, base, (item) => writerObject(field.fields, item, leash))
|
|
135
204
|
: base;
|
|
136
205
|
case 'value':
|
|
137
206
|
return base;
|
|
@@ -159,15 +228,27 @@ function bareReference(envelope) {
|
|
|
159
228
|
: [];
|
|
160
229
|
return { ...envelope, properties, required, additionalProperties: false };
|
|
161
230
|
}
|
|
162
|
-
/**
|
|
163
|
-
|
|
231
|
+
/**
|
|
232
|
+
* An object-shaped node with each declared subfield in its writer form, closed. A
|
|
233
|
+
* sub-field with no writer form here (nothing searched for its id) is omitted, and
|
|
234
|
+
* leaves the `required` list with it.
|
|
235
|
+
*/
|
|
236
|
+
function writerObject(fields, node, leash) {
|
|
164
237
|
const properties = { ...propertiesOf(node) };
|
|
238
|
+
let required = Array.isArray(node.required) ? node.required : undefined;
|
|
165
239
|
for (const sub of fields) {
|
|
166
240
|
const subBase = properties[sub.name];
|
|
167
|
-
if (subBase
|
|
168
|
-
|
|
241
|
+
if (subBase === undefined)
|
|
242
|
+
continue;
|
|
243
|
+
const written = writerForm(sub, subBase, leash);
|
|
244
|
+
if (written !== undefined)
|
|
245
|
+
properties[sub.name] = written;
|
|
246
|
+
else {
|
|
247
|
+
delete properties[sub.name];
|
|
248
|
+
required = required?.filter((name) => name !== sub.name);
|
|
249
|
+
}
|
|
169
250
|
}
|
|
170
|
-
return { ...node, properties, additionalProperties: false };
|
|
251
|
+
return { ...node, properties, ...(required ? { required } : {}), additionalProperties: false };
|
|
171
252
|
}
|
|
172
253
|
/**
|
|
173
254
|
* Drop `pattern` wherever `format` is present (EC-473/EC-474 req 6). Returns the
|
|
@@ -229,14 +310,19 @@ export function toModelFacingSchema(schema) {
|
|
|
229
310
|
* Human-readable phrases for the constraint keywords of ONE schema node, in a stable
|
|
230
311
|
* order — the form a model reads best. Node-level only: nested `items`/`properties`
|
|
231
312
|
* are {@link describeSchemaDeep}'s business. Total over the projection's numeric,
|
|
232
|
-
* string and
|
|
233
|
-
*
|
|
234
|
-
* `
|
|
313
|
+
* string, array and option vocabulary. An `enum` IS phrased (RULES D14, EC-593): the
|
|
314
|
+
* catalog is prose only, so a `select`'s options never reached the update path that
|
|
315
|
+
* authors through it. A `const` is not (a relation's `collection` is the envelope's,
|
|
316
|
+
* not a rule the writer chooses against).
|
|
235
317
|
*/
|
|
236
318
|
function describeSchemaConstraints(schema) {
|
|
237
319
|
const out = [];
|
|
238
320
|
const num = (value) => typeof value === 'number' ? value : undefined;
|
|
239
321
|
const text = (value) => typeof value === 'string' ? value : undefined;
|
|
322
|
+
if (Array.isArray(schema.enum) && schema.enum.length > 0) {
|
|
323
|
+
// Quoted and `|`-separated: the clause itself is joined with commas.
|
|
324
|
+
out.push(`one of ${schema.enum.map((option) => JSON.stringify(option)).join(' | ')}`);
|
|
325
|
+
}
|
|
240
326
|
const minLength = num(schema.minLength);
|
|
241
327
|
const maxLength = num(schema.maxLength);
|
|
242
328
|
if (minLength !== undefined && maxLength !== undefined) {
|
|
@@ -335,18 +421,24 @@ export function describeFieldConstraints(field) {
|
|
|
335
421
|
const out = [];
|
|
336
422
|
if (field.validation?.required === true)
|
|
337
423
|
out.push('required');
|
|
338
|
-
// EC-556: the prose tells a WRITER what to write, so it reads the writer form
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
424
|
+
// EC-556: the prose tells a WRITER what to write, so it reads the writer form —
|
|
425
|
+
// and a type with NO writer form says why (EC-593, ratified 4c).
|
|
426
|
+
const writer = writerFieldSchema(field);
|
|
427
|
+
if (writer === undefined)
|
|
428
|
+
out.push(COMPOSITION_NOTE);
|
|
429
|
+
else
|
|
430
|
+
out.push(...describeSchemaDeep(writer));
|
|
431
|
+
// EC-581 / EC-593: what only the declaration can say — a plain-text bound, a
|
|
432
|
+
// sub-field's `required`, a sub-field's unstated rules — at every depth the writer
|
|
433
|
+
// form reaches (`note: at most 400 plain-text characters …`, `label: required`).
|
|
434
|
+
out.push(...declarationClauses(field));
|
|
344
435
|
if (field.validation?.unique === true)
|
|
345
436
|
out.push('unique across the collection');
|
|
346
437
|
// The one thing the projection cannot say about itself: that it is partial (an
|
|
347
|
-
// opaque vendor, a `.refine()`,
|
|
348
|
-
//
|
|
349
|
-
|
|
438
|
+
// opaque vendor, a `.refine()`, — EC-522 — a rule at a position the field's shape
|
|
439
|
+
// has no counterpart for, or — RULES D13 — a validate FUNCTION, which no projection
|
|
440
|
+
// can read at all). Set at config resolve, read here, nowhere else.
|
|
441
|
+
if (hasUnstatedRules(field))
|
|
350
442
|
out.push(INCOMPLETE_CONSTRAINTS_NOTE);
|
|
351
443
|
return out;
|
|
352
444
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constraints.js","sourceRoot":"","sources":["../../../src/lib/ai/constraints.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model-facing constraint rendering (EC-473, tuned by EC-505).\n *\n * The engine has ONE constraint projection: `fieldJsonSchema` merges a field's\n * declarative rules (`validation.min`/`max`/`pattern`) with the fragment derived\n * from a schema-form `validation.validate` (EC-522: nested `items`/`properties`\n * bounds included, fitted to the field's type at config resolve). This module turns\n * that projection into what the MODEL should see — which is not the same artifact a\n * JSON-Schema consumer wants:\n *\n * - **a regex is a poor instruction for a model.** `z.string().email()` emits a\n * ~200-character pattern and `z.iso.date()` a leap-year monster (measured,\n * EC-474 §3); `format` + bounds says the same thing in four tokens. So on the AI\n * path a `pattern` is dropped wherever a `format` is present. The JSON Schema\n * OUTPUT artifact keeps it — different consumer, different needs.\n * - **a date is one instant string** (EC-505 → EC-586). The projection used to say\n * `type: ['string','number']` (an epoch was stored as-is) and this module narrowed\n * it for the model; since EC-586 every write canonicalises a date to ONE ISO-8601\n * UTC instant, so the projection itself says `type: 'string'` and there is nothing\n * left to narrow.\n * - **incompleteness must be stated.** When `validation.schemaComplete` is `false`\n * the projection is a partial view of the rule, and the model is told so rather\n * than being handed a half-truth as the whole rule. (An `ai.hint` is exactly the\n * right place to say what the dropped refinement wants — the note nudges toward\n * writing one.)\n */\nimport { BOUND_UNIT_NOUN, fieldJsonSchema, fieldTypeOf } from '@elytracms/core/cms-core'\nimport type { FieldDef, JsonSchema } from '@elytracms/core/cms-core'\nimport { MARKDOWN_PROSE_DESCRIPTION } from '@elytracms/core/rich-text'\n\n/** The note appended when a field's constraint projection is knowingly partial. */\nexport const INCOMPLETE_CONSTRAINTS_NOTE =\n 'further validation rules apply that are not expressible here — keep the value conventional and plausible'\n\n/**\n * The prose form of `format: 'date-time'` (EC-505). The JSON-Schema keyword rides\n * on the target shape for the provider's validator; the CATALOG has no JSON Schema\n * at all — it is prose only, and the chat update path authors date values through\n * it. So the format is said in words too, or the only channel that path has says\n * nothing about the one format the engine accepts.\n *\n * Kept to three words deliberately: measured at 6 tokens, against 20 for the same\n * note with a worked example — and it rides every date field of every turn.\n */\nexport const ISO_DATE_NOTE = 'ISO 8601 date'\n\nfunction isSchemaNode(value: unknown): value is JsonSchema {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * The phrase for a field's declared `min`/`max` in the UNIT its type declares\n * (`FIELD_TYPES[type].bounds`, EC-581) — or `undefined` when the field declares none\n * or the unit has a JSON-Schema keyword the projection already carries. Today that is\n * rich text: its bounds count PLAIN-TEXT characters of the stored value (ratified\n * 2a(iii)), which no keyword on the markdown string the model writes can express.\n */\nexport function plainTextBoundPhrase(field: FieldDef): string | undefined {\n if (fieldTypeOf(field).bounds(field) !== 'plain-text') return undefined\n const min = typeof field.validation?.min === 'number' ? field.validation.min : undefined\n const max = typeof field.validation?.max === 'number' ? field.validation.max : undefined\n const noun = BOUND_UNIT_NOUN['plain-text']\n if (min !== undefined && max !== undefined) return `${min}–${max} ${noun}`\n if (min !== undefined) return `at least ${min} ${noun}`\n if (max !== undefined) return `at most ${max} ${noun}`\n return undefined\n}\n\n/** {@link plainTextBoundPhrase} for a field and every sub-field below it, name-prefixed. */\nfunction plainTextBoundClauses(field: FieldDef, prefix = ''): string[] {\n const own = plainTextBoundPhrase(field)\n const out = own !== undefined ? [`${prefix}${own}`] : []\n const subs = field.type === 'object' ? field.fields : field.type === 'asset' ? (field.fields ?? []) : []\n for (const sub of subs) out.push(...plainTextBoundClauses(sub, `${prefix}${sub.name}: `))\n return out\n}\n\n/**\n * A rich-text field's WRITER form (EC-379, D2 of EC-556): a MARKDOWN string. The\n * description carries the allowed subset (from the engine converter — one source\n * of truth); the engine converts the markdown into the v2 storage value and\n * rejects out-of-subset constructs with explicit issues.\n *\n * EC-563/EC-581: the declared bounds are said in their unit — plain-text characters,\n * markup not counted — in the description, read off the per-FieldType definition.\n * They used to ride as `minLength`/`maxLength` on the markdown string: a different\n * unit (markdown characters) than anything enforced, and a provider validating the\n * structured output would have enforced the wrong one.\n */\nexport function richTextWriterSchema(field: FieldDef): JsonSchema {\n const schema: JsonSchema = { type: 'string' }\n const bound = plainTextBoundPhrase(field)\n schema.description = `Rich text, written as ${MARKDOWN_PROSE_DESCRIPTION} Write genuine, publishable prose.${bound ? ` Length: ${bound}.` : ''}`\n return schema\n}\n\n/**\n * The WRITER-facing form of one field, at EVERY depth (EC-556): what a model should\n * hand in. Derived from the validator-facing projection (`fieldJsonSchema` — the\n * value at rest, every merged constraint included) by one rule: **the writer omits\n * exactly what the write-time lens (`selfTypeFieldValue`) restores.**\n *\n * - asset, no per-use sub-fields → the bare id (the projection's `id` property):\n * the lens wraps a bare id string into `{ type: 'asset', id }`;\n * - asset WITH sub-fields → the envelope itself, `type` included: the lens wraps a\n * string, never an object missing its `type`, and the sub-fields need a place;\n * - relation → `{ collection, id }` (the envelope minus `type`): the lens rebuilds\n * a bare reference into its envelope;\n * - rich text → a markdown string (`richTextWriterSchema`) — the engine converts it\n * wherever it sits (`apply-content.ts`);\n * - an `object` → its own projection with every subfield in ITS writer form.\n *\n * Writer objects are closed (`additionalProperties: false`): a writer inventing keys\n * is a fault, where a stored envelope carrying extra keys is drift the lens\n * tolerates (EC-556 §B) — which is why the projection itself stays open. The\n * top-level relation/asset id ENUM (EC-381) is the target shape's own override.\n */\nexport function writerFieldSchema(field: FieldDef): JsonSchema {\n return writerForm(field, fieldJsonSchema(field))\n}\n\n/** EC-581: the writer form is DECLARED per type (`FIELD_TYPES[type].writer`); built here. */\nfunction writerForm(field: FieldDef, base: JsonSchema): JsonSchema {\n switch (fieldTypeOf(field).writer) {\n case 'markdown':\n return richTextWriterSchema(field)\n case 'placement': {\n if (field.type !== 'asset') return base\n // `type`/`id` belong to the envelope; the projection never lets a sub-field\n // of that name shadow them, and neither does the writer form.\n const subfields = (field.fields ?? []).filter((sub) => sub.name !== 'type' && sub.name !== 'id')\n return perItem(field.multiple, base, (item) =>\n subfields.length === 0 ? bareAssetId(item) : writerObject(subfields, item),\n )\n }\n case 'reference':\n return field.type === 'relation' ? perItem(field.multiple, base, bareReference) : base\n case 'object':\n return field.type === 'object'\n ? perItem(field.multiple, base, (item) => writerObject(field.fields, item))\n : base\n case 'value':\n return base\n }\n}\n\n/** Apply `one` to the item schema of a `multiple` field, or to the field's own schema. */\nfunction perItem(multiple: boolean, base: JsonSchema, one: (item: JsonSchema) => JsonSchema): JsonSchema {\n if (!multiple) return one(base)\n return isSchemaNode(base.items) ? { ...base, items: one(base.items) } : base\n}\n\nfunction propertiesOf(node: JsonSchema): Record<string, JsonSchema> {\n const properties = node.properties\n return isSchemaNode(properties) ? (properties as Record<string, JsonSchema>) : {}\n}\n\n/** The envelope's `id` property — the bare id string the lens wraps. */\nfunction bareAssetId(envelope: JsonSchema): JsonSchema {\n return propertiesOf(envelope).id ?? { type: 'string' }\n}\n\n/** The reference envelope minus the `type` discriminator the lens restores. */\nfunction bareReference(envelope: JsonSchema): JsonSchema {\n const { type: _discriminator, ...properties } = propertiesOf(envelope)\n const required = Array.isArray(envelope.required)\n ? envelope.required.filter((key) => key !== 'type')\n : []\n return { ...envelope, properties, required, additionalProperties: false }\n}\n\n/** An object-shaped node with each declared subfield in its writer form, closed. */\nfunction writerObject(fields: readonly FieldDef[], node: JsonSchema): JsonSchema {\n const properties: Record<string, JsonSchema> = { ...propertiesOf(node) }\n for (const sub of fields) {\n const subBase = properties[sub.name]\n if (subBase !== undefined) properties[sub.name] = writerForm(sub, subBase)\n }\n return { ...node, properties, additionalProperties: false }\n}\n\n/**\n * Drop `pattern` wherever `format` is present (EC-473/EC-474 req 6). Returns the\n * same object when there is nothing to strip, so callers can rely on identity.\n */\nexport function stripRedundantPattern(schema: JsonSchema): JsonSchema {\n if (schema.format === undefined || schema.pattern === undefined) return schema\n const { pattern: _pattern, ...rest } = schema\n return rest\n}\n\n/**\n * Apply a node transform through a schema tree (`items` + `properties`), preserving\n * object identity wherever nothing changed — `buildTargetShape` relies on that to\n * avoid copying a property it did not touch.\n */\nfunction mapSchemaDeep(schema: JsonSchema, transform: (node: JsonSchema) => JsonSchema): JsonSchema {\n let out = transform(schema)\n const items = out.items\n if (typeof items === 'object' && items !== null && !Array.isArray(items)) {\n const next = mapSchemaDeep(items as JsonSchema, transform)\n if (next !== items) out = { ...out, items: next }\n }\n const properties = out.properties\n if (typeof properties === 'object' && properties !== null && !Array.isArray(properties)) {\n let changed = false\n const nextProps: Record<string, JsonSchema> = {}\n for (const [key, value] of Object.entries(properties as Record<string, unknown>)) {\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const next = mapSchemaDeep(value as JsonSchema, transform)\n nextProps[key] = next\n if (next !== value) changed = true\n } else {\n nextProps[key] = value as JsonSchema\n }\n }\n if (changed) out = { ...out, properties: nextProps }\n }\n return out\n}\n\n/** Recursively strip redundant patterns through `items` / `properties`. */\nexport function stripRedundantPatternsDeep(schema: JsonSchema): JsonSchema {\n return mapSchemaDeep(schema, stripRedundantPattern)\n}\n\n/**\n * The whole model-facing rewrite of a projected schema (EC-505): redundant patterns\n * stripped everywhere in the tree — an `object` field's SUBfield gets the same\n * treatment as a top-level one. Identity-preserving. (The date-union narrowing that\n * also ran here is gone: a date is one instant string at rest since EC-586.)\n */\nexport function toModelFacingSchema(schema: JsonSchema): JsonSchema {\n return mapSchemaDeep(schema, stripRedundantPattern)\n}\n\n/**\n * Human-readable phrases for the constraint keywords of ONE schema node, in a stable\n * order — the form a model reads best. Node-level only: nested `items`/`properties`\n * are {@link describeSchemaDeep}'s business. Total over the projection's numeric,\n * string and array vocabulary; `enum`/`const` are deliberately not phrased — they\n * ride the target SHAPE as JSON Schema, and a `select`'s options or a relation's\n * `collection` const would otherwise repeat on every catalog line.\n */\nfunction describeSchemaConstraints(schema: JsonSchema): string[] {\n const out: string[] = []\n const num = (value: unknown): number | undefined =>\n typeof value === 'number' ? value : undefined\n const text = (value: unknown): string | undefined =>\n typeof value === 'string' ? value : undefined\n\n const minLength = num(schema.minLength)\n const maxLength = num(schema.maxLength)\n if (minLength !== undefined && maxLength !== undefined) {\n out.push(`${minLength}–${maxLength} characters`)\n } else if (minLength !== undefined) out.push(`at least ${minLength} characters`)\n else if (maxLength !== undefined) out.push(`at most ${maxLength} characters`)\n\n const minimum = num(schema.minimum)\n const maximum = num(schema.maximum)\n if (minimum !== undefined && maximum !== undefined) out.push(`between ${minimum} and ${maximum}`)\n else if (minimum !== undefined) out.push(`at least ${minimum}`)\n else if (maximum !== undefined) out.push(`at most ${maximum}`)\n\n // EC-522: the projection carried these already; the prose never said them.\n const exclusiveMinimum = num(schema.exclusiveMinimum)\n const exclusiveMaximum = num(schema.exclusiveMaximum)\n if (exclusiveMinimum !== undefined) out.push(`more than ${exclusiveMinimum}`)\n if (exclusiveMaximum !== undefined) out.push(`less than ${exclusiveMaximum}`)\n const multipleOf = num(schema.multipleOf)\n if (multipleOf !== undefined) out.push(`a multiple of ${multipleOf}`)\n\n const minItems = num(schema.minItems)\n const maxItems = num(schema.maxItems)\n if (minItems !== undefined) out.push(`at least ${minItems} items`)\n if (maxItems !== undefined) out.push(`at most ${maxItems} items`)\n if (schema.uniqueItems === true) out.push('no duplicate items')\n\n // EC-473: date bounds finally reach a consumer. `formatMinimum`/`formatMaximum`\n // is the projection's machine form; this is the form a model acts on.\n const from = text(schema.formatMinimum)\n const to = text(schema.formatMaximum)\n if (from !== undefined) out.push(`not earlier than ${from}`)\n if (to !== undefined) out.push(`not later than ${to}`)\n\n const format = text(schema.format)\n // EC-505: `date-time` is said in words rather than skipped — the catalog carries\n // no JSON Schema, so this is the only place the update path learns the format.\n if (format === 'date-time') out.push(ISO_DATE_NOTE)\n else if (format !== undefined) out.push(`format: ${format}`)\n // Only a pattern that is NOT explained by a format is worth the tokens.\n const pattern = text(schema.pattern)\n if (pattern !== undefined && format === undefined) out.push(`matching /${pattern}/`)\n\n return out\n}\n\n/**\n * The phrases of one projected schema node AND everything below it (EC-522): a\n * `multiple` field's per-item bounds become an `each item: …` clause, an object's\n * subfield bounds a `<name>: …` clause, recursively. The projection is the ONLY\n * input — since EC-522 the merge carries nested `items`/`properties` constraints\n * itself, so this module never looks past `fieldJsonSchema` (EC-505's direct read\n * of the derived fragment's `items` is gone, and with it the second place that\n * understood fragment structure).\n *\n * Which side a schema addresses is still the executor's call, not this module's:\n * `validateDocument` hands the validator the field's WHOLE value — a `multiple`\n * field's array — so the per-item form is `z.array(z.string().min(3))`, and a\n * bare `z.string().min(3)` there is a config error at load (EC-522), never a\n * silently mis-applied bound.\n */\nfunction describeSchemaDeep(schema: JsonSchema): string[] {\n const out = describeSchemaConstraints(schema)\n if (isSchemaNode(schema.items)) {\n const itemParts = describeSchemaDeep(schema.items)\n if (itemParts.length > 0) out.push(`each item: ${itemParts.join(', ')}`)\n }\n if (isSchemaNode(schema.properties)) {\n for (const [name, sub] of Object.entries(schema.properties)) {\n if (!isSchemaNode(sub)) continue\n const subParts = describeSchemaDeep(sub)\n if (subParts.length > 0) out.push(`${name}: ${subParts.join(', ')}`)\n }\n }\n return out\n}\n\n/**\n * Human-readable constraint phrases for one field, in a stable order — the form a\n * model reads best (and the form the collections catalog carries, where there is no\n * JSON Schema to hand the model at all). Empty when the field constrains nothing.\n */\nexport function describeFieldConstraints(field: FieldDef): string[] {\n const out: string[] = []\n if (field.validation?.required === true) out.push('required')\n // EC-556: the prose tells a WRITER what to write, so it reads the writer form.\n out.push(...describeSchemaDeep(writerFieldSchema(field)))\n // EC-581: a bound whose unit has no schema keyword — rich text's plain-text\n // characters — is said in its unit, read off the per-FieldType definition, at every\n // depth the writer form reaches (`note: at most 400 plain-text characters …`).\n out.push(...plainTextBoundClauses(field))\n if (field.validation?.unique === true) out.push('unique across the collection')\n // The one thing the projection cannot say about itself: that it is partial (an\n // opaque vendor, a `.refine()`, or — EC-522 — a rule at a position the field's\n // shape has no counterpart for). Set at config resolve, read here, nowhere else.\n if (field.validation?.schemaComplete === false) out.push(INCOMPLETE_CONSTRAINTS_NOTE)\n return out\n}\n\n/** The constraint phrases as one clause (`min 2 characters; required`), or `undefined`. */\nexport function constraintSentence(field: FieldDef): string | undefined {\n const parts = describeFieldConstraints(field)\n return parts.length > 0 ? parts.join('; ') : undefined\n}\n"]}
|
|
1
|
+
{"version":3,"file":"constraints.js","sourceRoot":"","sources":["../../../src/lib/ai/constraints.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model-facing constraint rendering (EC-473, tuned by EC-505).\n *\n * The engine has ONE constraint projection: `fieldJsonSchema` merges a field's\n * declarative rules (`validation.min`/`max`/`pattern`) with the fragment derived\n * from a schema-form `validation.validate` (EC-522: nested `items`/`properties`\n * bounds included, fitted to the field's type at config resolve). This module turns\n * that projection into what the MODEL should see — which is not the same artifact a\n * JSON-Schema consumer wants:\n *\n * - **a regex is a poor instruction for a model.** `z.string().email()` emits a\n * ~200-character pattern and `z.iso.date()` a leap-year monster (measured,\n * EC-474 §3); `format` + bounds says the same thing in four tokens. So on the AI\n * path a `pattern` is dropped wherever a `format` is present. The JSON Schema\n * OUTPUT artifact keeps it — different consumer, different needs.\n * - **a date is one instant string** (EC-505 → EC-586). The projection used to say\n * `type: ['string','number']` (an epoch was stored as-is) and this module narrowed\n * it for the model; since EC-586 every write canonicalises a date to ONE ISO-8601\n * UTC instant, so the projection itself says `type: 'string'` and there is nothing\n * left to narrow.\n * - **incompleteness must be stated.** When `validation.schemaComplete` is `false`\n * the projection is a partial view of the rule, and the model is told so rather\n * than being handed a half-truth as the whole rule. (An `ai.hint` is exactly the\n * right place to say what the dropped refinement wants — the note nudges toward\n * writing one.)\n */\nimport { BOUND_UNIT_NOUN, fieldJsonSchema, fieldTypeOf } from '@elytracms/core/cms-core'\nimport type { FieldDef, JsonSchema } from '@elytracms/core/cms-core'\nimport { MARKDOWN_PROSE_DESCRIPTION } from '@elytracms/core/rich-text'\nimport type { AssetCandidate, RelationCandidate, WriterLeash } from './types'\n\n/** The note appended when a field's constraint projection is knowingly partial. */\nexport const INCOMPLETE_CONSTRAINTS_NOTE =\n 'further validation rules apply that are not expressible here — keep the value conventional and plausible'\n\n/**\n * What the catalog says about a composition (`blocks`) — its writer form is NONE\n * (`FIELD_TYPES.blocks.writer === 'composition'`, ratified 4c, EC-593): the assistant\n * changes component props, never which components there are. Said in the prose because\n * the omission must be VISIBLE, not a field the model simply never hears of.\n */\nexport const COMPOSITION_NOTE =\n 'page-builder composition: the assistant never adds, moves or removes its components (that is done on the canvas) — change one component prop with blockId + prop (getDocument lists the components and their props)'\n\n/**\n * Whether a field's validation has rules its projection cannot state (RULES D13): a\n * schema whose projection is knowingly partial (`schemaComplete: false`), or a FUNCTION\n * `validate` — normalisation stamps `schemaComplete` on a schema-form validator only, so\n * a declared `validate` without it is a function no consumer can read.\n */\nfunction hasUnstatedRules(field: FieldDef): boolean {\n const validation = field.validation\n if (!validation) return false\n return validation.schemaComplete === false || (validation.validate !== undefined && validation.schemaComplete === undefined)\n}\n\n/**\n * The prose form of `format: 'date-time'` (EC-505). The JSON-Schema keyword rides\n * on the target shape for the provider's validator; the CATALOG has no JSON Schema\n * at all — it is prose only, and the chat update path authors date values through\n * it. So the format is said in words too, or the only channel that path has says\n * nothing about the one format the engine accepts.\n *\n * Kept to three words deliberately: measured at 6 tokens, against 20 for the same\n * note with a worked example — and it rides every date field of every turn.\n */\nexport const ISO_DATE_NOTE = 'ISO 8601 date'\n\nfunction isSchemaNode(value: unknown): value is JsonSchema {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/**\n * The phrase for a field's declared `min`/`max` in the UNIT its type declares\n * (`FIELD_TYPES[type].bounds`, EC-581) — or `undefined` when the field declares none\n * or the unit has a JSON-Schema keyword the projection already carries. Today that is\n * rich text: its bounds count PLAIN-TEXT characters of the stored value (ratified\n * 2a(iii)), which no keyword on the markdown string the model writes can express.\n */\nexport function plainTextBoundPhrase(field: FieldDef): string | undefined {\n if (fieldTypeOf(field).bounds(field) !== 'plain-text') return undefined\n const min = typeof field.validation?.min === 'number' ? field.validation.min : undefined\n const max = typeof field.validation?.max === 'number' ? field.validation.max : undefined\n const noun = BOUND_UNIT_NOUN['plain-text']\n if (min !== undefined && max !== undefined) return `${min}–${max} ${noun}`\n if (min !== undefined) return `at least ${min} ${noun}`\n if (max !== undefined) return `at most ${max} ${noun}`\n return undefined\n}\n\n/** The declared sub-fields of an object or an asset placement (`[]` for any other type). */\nfunction subFieldsOf(field: FieldDef): readonly FieldDef[] {\n return field.type === 'object' ? field.fields : field.type === 'asset' ? (field.fields ?? []) : []\n}\n\n/**\n * The clauses only the DECLARATION can say, for a field and every sub-field below it,\n * name-prefixed (`note: at most 400 plain-text characters`, `label: required`):\n * - a plain-text bound ({@link plainTextBoundPhrase}, EC-581);\n * - a sub-field's `required` (RULES F3d — the shape's JSON `required` carried it, the\n * prose never did); the field's own is said by {@link describeFieldConstraints};\n * - a sub-field's rules the projection cannot state ({@link hasUnstatedRules}).\n */\nfunction declarationClauses(field: FieldDef, prefix = ''): string[] {\n const own = plainTextBoundPhrase(field)\n const out = own !== undefined ? [`${prefix}${own}`] : []\n for (const sub of subFieldsOf(field)) {\n const subPrefix = `${prefix}${sub.name}: `\n if (sub.validation?.required === true) out.push(`${subPrefix}required`)\n out.push(...declarationClauses(sub, subPrefix))\n if (hasUnstatedRules(sub)) out.push(`${subPrefix}${INCOMPLETE_CONSTRAINTS_NOTE}`)\n }\n return out\n}\n\n/**\n * A rich-text field's WRITER form (EC-379, D2 of EC-556): a MARKDOWN string. The\n * description carries the allowed subset (from the engine converter — one source\n * of truth); the engine converts the markdown into the v2 storage value and\n * rejects out-of-subset constructs with explicit issues.\n *\n * EC-563/EC-581: the declared bounds are said in their unit — plain-text characters,\n * markup not counted — in the description, read off the per-FieldType definition.\n * They used to ride as `minLength`/`maxLength` on the markdown string: a different\n * unit (markdown characters) than anything enforced, and a provider validating the\n * structured output would have enforced the wrong one.\n */\nexport function richTextWriterSchema(field: FieldDef): JsonSchema {\n const schema: JsonSchema = { type: 'string' }\n const bound = plainTextBoundPhrase(field)\n schema.description = `Rich text, written as ${MARKDOWN_PROSE_DESCRIPTION} Write genuine, publishable prose.${bound ? ` Length: ${bound}.` : ''}`\n return schema\n}\n\n/**\n * The WRITER-facing form of one field, at EVERY depth (EC-556): what a model should\n * hand in. Derived from the validator-facing projection (`fieldJsonSchema` — the\n * value at rest, every merged constraint included) by one rule: **the writer omits\n * exactly what the write-time lens (`selfTypeFieldValue`) restores.**\n *\n * - asset, no per-use sub-fields → the bare id (the projection's `id` property):\n * the lens wraps a bare id string into `{ type: 'asset', id }`;\n * - asset WITH sub-fields → the envelope itself, `type` included: the lens wraps a\n * string, never an object missing its `type`, and the sub-fields need a place;\n * - relation → `{ collection, id }` (the envelope minus `type`): the lens rebuilds\n * a bare reference into its envelope;\n * - rich text → a markdown string (`richTextWriterSchema`) — the engine converts it\n * wherever it sits (`writer-form.ts`, EC-593);\n * - an `object` → its own projection with every subfield in ITS writer form;\n * - a composition (`blocks`) → NONE (`undefined`): its structure is the canvas's\n * (ratified 4c, EC-593) — a target shape omits it and says so.\n *\n * Writer objects are closed (`additionalProperties: false`): a writer inventing keys\n * is a fault, where a stored envelope carrying extra keys is drift the lens\n * tolerates (EC-556 §B) — which is why the projection itself stays open.\n *\n * With a `leash` (the create target shape, EC-381 → EC-593) every relation / asset id\n * — at EVERY depth, not only a top-level field — is an ENUM over what the model\n * searched for that position (a relation's target, an asset's `accept`), and a position\n * with nothing searched is omitted (empty beats wrong). Without one (the catalog prose)\n * the plain writer forms are described.\n */\nexport function writerFieldSchema(field: FieldDef, leash?: WriterLeash): JsonSchema | undefined {\n return writerForm(field, fieldJsonSchema(field), leash)\n}\n\n/** An id enum over searched candidates, labelled for the model to choose against. */\nfunction candidateEnum(candidates: readonly (RelationCandidate | AssetCandidate)[], asset: boolean): JsonSchema {\n const label = candidates.map((c) => (c.label ? `${c.id} (${c.label})` : c.id)).join(', ')\n return {\n type: 'string',\n enum: candidates.map((c) => c.id),\n description: asset\n ? `Choose an EXISTING library asset id, one of: ${label}. Leave empty if none fits.`\n : `Choose one of: ${label}`,\n }\n}\n\n/** EC-581: the writer form is DECLARED per type (`FIELD_TYPES[type].writer`); built here. */\nfunction writerForm(field: FieldDef, base: JsonSchema, leash?: WriterLeash): JsonSchema | undefined {\n switch (fieldTypeOf(field).writer) {\n case 'markdown':\n return richTextWriterSchema(field)\n case 'composition':\n return undefined\n case 'placement': {\n if (field.type !== 'asset') return base\n // `type`/`id` belong to the envelope; the projection never lets a sub-field\n // of that name shadow them, and neither does the writer form.\n const subfields = (field.fields ?? []).filter((sub) => sub.name !== 'type' && sub.name !== 'id')\n const candidates = leash?.assetCandidates(field)\n if (candidates !== undefined && candidates.length === 0) return undefined\n const idSchema = (item: JsonSchema): JsonSchema =>\n candidates !== undefined ? candidateEnum(candidates, true) : bareAssetId(item)\n return perItem(field.multiple, base, (item) =>\n subfields.length === 0\n ? idSchema(item)\n : writerObject(subfields, { ...item, properties: { ...propertiesOf(item), id: idSchema(item) } }, leash),\n )\n }\n case 'reference': {\n if (field.type !== 'relation') return base\n if (!leash) return perItem(field.multiple, base, bareReference)\n const candidates = leash.relationCandidates(field.target)\n if (candidates.length === 0) return undefined\n return perItem(field.multiple, base, () => candidateEnum(candidates, false))\n }\n case 'object':\n return field.type === 'object'\n ? perItem(field.multiple, base, (item) => writerObject(field.fields, item, leash))\n : base\n case 'value':\n return base\n }\n}\n\n/** Apply `one` to the item schema of a `multiple` field, or to the field's own schema. */\nfunction perItem(multiple: boolean, base: JsonSchema, one: (item: JsonSchema) => JsonSchema): JsonSchema {\n if (!multiple) return one(base)\n return isSchemaNode(base.items) ? { ...base, items: one(base.items) } : base\n}\n\nfunction propertiesOf(node: JsonSchema): Record<string, JsonSchema> {\n const properties = node.properties\n return isSchemaNode(properties) ? (properties as Record<string, JsonSchema>) : {}\n}\n\n/** The envelope's `id` property — the bare id string the lens wraps. */\nfunction bareAssetId(envelope: JsonSchema): JsonSchema {\n return propertiesOf(envelope).id ?? { type: 'string' }\n}\n\n/** The reference envelope minus the `type` discriminator the lens restores. */\nfunction bareReference(envelope: JsonSchema): JsonSchema {\n const { type: _discriminator, ...properties } = propertiesOf(envelope)\n const required = Array.isArray(envelope.required)\n ? envelope.required.filter((key) => key !== 'type')\n : []\n return { ...envelope, properties, required, additionalProperties: false }\n}\n\n/**\n * An object-shaped node with each declared subfield in its writer form, closed. A\n * sub-field with no writer form here (nothing searched for its id) is omitted, and\n * leaves the `required` list with it.\n */\nfunction writerObject(fields: readonly FieldDef[], node: JsonSchema, leash?: WriterLeash): JsonSchema {\n const properties: Record<string, JsonSchema> = { ...propertiesOf(node) }\n let required = Array.isArray(node.required) ? (node.required as string[]) : undefined\n for (const sub of fields) {\n const subBase = properties[sub.name]\n if (subBase === undefined) continue\n const written = writerForm(sub, subBase, leash)\n if (written !== undefined) properties[sub.name] = written\n else {\n delete properties[sub.name]\n required = required?.filter((name) => name !== sub.name)\n }\n }\n return { ...node, properties, ...(required ? { required } : {}), additionalProperties: false }\n}\n\n/**\n * Drop `pattern` wherever `format` is present (EC-473/EC-474 req 6). Returns the\n * same object when there is nothing to strip, so callers can rely on identity.\n */\nexport function stripRedundantPattern(schema: JsonSchema): JsonSchema {\n if (schema.format === undefined || schema.pattern === undefined) return schema\n const { pattern: _pattern, ...rest } = schema\n return rest\n}\n\n/**\n * Apply a node transform through a schema tree (`items` + `properties`), preserving\n * object identity wherever nothing changed — `buildTargetShape` relies on that to\n * avoid copying a property it did not touch.\n */\nfunction mapSchemaDeep(schema: JsonSchema, transform: (node: JsonSchema) => JsonSchema): JsonSchema {\n let out = transform(schema)\n const items = out.items\n if (typeof items === 'object' && items !== null && !Array.isArray(items)) {\n const next = mapSchemaDeep(items as JsonSchema, transform)\n if (next !== items) out = { ...out, items: next }\n }\n const properties = out.properties\n if (typeof properties === 'object' && properties !== null && !Array.isArray(properties)) {\n let changed = false\n const nextProps: Record<string, JsonSchema> = {}\n for (const [key, value] of Object.entries(properties as Record<string, unknown>)) {\n if (typeof value === 'object' && value !== null && !Array.isArray(value)) {\n const next = mapSchemaDeep(value as JsonSchema, transform)\n nextProps[key] = next\n if (next !== value) changed = true\n } else {\n nextProps[key] = value as JsonSchema\n }\n }\n if (changed) out = { ...out, properties: nextProps }\n }\n return out\n}\n\n/** Recursively strip redundant patterns through `items` / `properties`. */\nexport function stripRedundantPatternsDeep(schema: JsonSchema): JsonSchema {\n return mapSchemaDeep(schema, stripRedundantPattern)\n}\n\n/**\n * The whole model-facing rewrite of a projected schema (EC-505): redundant patterns\n * stripped everywhere in the tree — an `object` field's SUBfield gets the same\n * treatment as a top-level one. Identity-preserving. (The date-union narrowing that\n * also ran here is gone: a date is one instant string at rest since EC-586.)\n */\nexport function toModelFacingSchema(schema: JsonSchema): JsonSchema {\n return mapSchemaDeep(schema, stripRedundantPattern)\n}\n\n/**\n * Human-readable phrases for the constraint keywords of ONE schema node, in a stable\n * order — the form a model reads best. Node-level only: nested `items`/`properties`\n * are {@link describeSchemaDeep}'s business. Total over the projection's numeric,\n * string, array and option vocabulary. An `enum` IS phrased (RULES D14, EC-593): the\n * catalog is prose only, so a `select`'s options never reached the update path that\n * authors through it. A `const` is not (a relation's `collection` is the envelope's,\n * not a rule the writer chooses against).\n */\nfunction describeSchemaConstraints(schema: JsonSchema): string[] {\n const out: string[] = []\n const num = (value: unknown): number | undefined =>\n typeof value === 'number' ? value : undefined\n const text = (value: unknown): string | undefined =>\n typeof value === 'string' ? value : undefined\n\n if (Array.isArray(schema.enum) && schema.enum.length > 0) {\n // Quoted and `|`-separated: the clause itself is joined with commas.\n out.push(`one of ${schema.enum.map((option) => JSON.stringify(option)).join(' | ')}`)\n }\n\n const minLength = num(schema.minLength)\n const maxLength = num(schema.maxLength)\n if (minLength !== undefined && maxLength !== undefined) {\n out.push(`${minLength}–${maxLength} characters`)\n } else if (minLength !== undefined) out.push(`at least ${minLength} characters`)\n else if (maxLength !== undefined) out.push(`at most ${maxLength} characters`)\n\n const minimum = num(schema.minimum)\n const maximum = num(schema.maximum)\n if (minimum !== undefined && maximum !== undefined) out.push(`between ${minimum} and ${maximum}`)\n else if (minimum !== undefined) out.push(`at least ${minimum}`)\n else if (maximum !== undefined) out.push(`at most ${maximum}`)\n\n // EC-522: the projection carried these already; the prose never said them.\n const exclusiveMinimum = num(schema.exclusiveMinimum)\n const exclusiveMaximum = num(schema.exclusiveMaximum)\n if (exclusiveMinimum !== undefined) out.push(`more than ${exclusiveMinimum}`)\n if (exclusiveMaximum !== undefined) out.push(`less than ${exclusiveMaximum}`)\n const multipleOf = num(schema.multipleOf)\n if (multipleOf !== undefined) out.push(`a multiple of ${multipleOf}`)\n\n const minItems = num(schema.minItems)\n const maxItems = num(schema.maxItems)\n if (minItems !== undefined) out.push(`at least ${minItems} items`)\n if (maxItems !== undefined) out.push(`at most ${maxItems} items`)\n if (schema.uniqueItems === true) out.push('no duplicate items')\n\n // EC-473: date bounds finally reach a consumer. `formatMinimum`/`formatMaximum`\n // is the projection's machine form; this is the form a model acts on.\n const from = text(schema.formatMinimum)\n const to = text(schema.formatMaximum)\n if (from !== undefined) out.push(`not earlier than ${from}`)\n if (to !== undefined) out.push(`not later than ${to}`)\n\n const format = text(schema.format)\n // EC-505: `date-time` is said in words rather than skipped — the catalog carries\n // no JSON Schema, so this is the only place the update path learns the format.\n if (format === 'date-time') out.push(ISO_DATE_NOTE)\n else if (format !== undefined) out.push(`format: ${format}`)\n // Only a pattern that is NOT explained by a format is worth the tokens.\n const pattern = text(schema.pattern)\n if (pattern !== undefined && format === undefined) out.push(`matching /${pattern}/`)\n\n return out\n}\n\n/**\n * The phrases of one projected schema node AND everything below it (EC-522): a\n * `multiple` field's per-item bounds become an `each item: …` clause, an object's\n * subfield bounds a `<name>: …` clause, recursively. The projection is the ONLY\n * input — since EC-522 the merge carries nested `items`/`properties` constraints\n * itself, so this module never looks past `fieldJsonSchema` (EC-505's direct read\n * of the derived fragment's `items` is gone, and with it the second place that\n * understood fragment structure).\n *\n * Which side a schema addresses is still the executor's call, not this module's:\n * `validateDocument` hands the validator the field's WHOLE value — a `multiple`\n * field's array — so the per-item form is `z.array(z.string().min(3))`, and a\n * bare `z.string().min(3)` there is a config error at load (EC-522), never a\n * silently mis-applied bound.\n */\nfunction describeSchemaDeep(schema: JsonSchema): string[] {\n const out = describeSchemaConstraints(schema)\n if (isSchemaNode(schema.items)) {\n const itemParts = describeSchemaDeep(schema.items)\n if (itemParts.length > 0) out.push(`each item: ${itemParts.join(', ')}`)\n }\n if (isSchemaNode(schema.properties)) {\n for (const [name, sub] of Object.entries(schema.properties)) {\n if (!isSchemaNode(sub)) continue\n const subParts = describeSchemaDeep(sub)\n if (subParts.length > 0) out.push(`${name}: ${subParts.join(', ')}`)\n }\n }\n return out\n}\n\n/**\n * Human-readable constraint phrases for one field, in a stable order — the form a\n * model reads best (and the form the collections catalog carries, where there is no\n * JSON Schema to hand the model at all). Empty when the field constrains nothing.\n */\nexport function describeFieldConstraints(field: FieldDef): string[] {\n const out: string[] = []\n if (field.validation?.required === true) out.push('required')\n // EC-556: the prose tells a WRITER what to write, so it reads the writer form —\n // and a type with NO writer form says why (EC-593, ratified 4c).\n const writer = writerFieldSchema(field)\n if (writer === undefined) out.push(COMPOSITION_NOTE)\n else out.push(...describeSchemaDeep(writer))\n // EC-581 / EC-593: what only the declaration can say — a plain-text bound, a\n // sub-field's `required`, a sub-field's unstated rules — at every depth the writer\n // form reaches (`note: at most 400 plain-text characters …`, `label: required`).\n out.push(...declarationClauses(field))\n if (field.validation?.unique === true) out.push('unique across the collection')\n // The one thing the projection cannot say about itself: that it is partial (an\n // opaque vendor, a `.refine()`, — EC-522 — a rule at a position the field's shape\n // has no counterpart for, or — RULES D13 — a validate FUNCTION, which no projection\n // can read at all). Set at config resolve, read here, nowhere else.\n if (hasUnstatedRules(field)) out.push(INCOMPLETE_CONSTRAINTS_NOTE)\n return out\n}\n\n/** The constraint phrases as one clause (`min 2 characters; required`), or `undefined`. */\nexport function constraintSentence(field: FieldDef): string | undefined {\n const parts = describeFieldConstraints(field)\n return parts.length > 0 ? parts.join('; ') : undefined\n}\n"]}
|
|
@@ -112,6 +112,17 @@ export declare function fakeUpdateValueFrom(userText: string): string;
|
|
|
112
112
|
* else falls back to the configured default field.
|
|
113
113
|
*/
|
|
114
114
|
export declare function fakeUpdateFieldFrom(userText: string, fallback: string): string;
|
|
115
|
+
/**
|
|
116
|
+
* The scripted update flow's full TARGET (EC-593): a field, or one component prop
|
|
117
|
+
* inside it — `set the <field> component <id> <prop> to: …` names a component by its
|
|
118
|
+
* node id at any depth (`Set the body component p-home-quote-note value to: Hi`), so the
|
|
119
|
+
* keyless playground can drive a component-prop edit through the one converter.
|
|
120
|
+
*/
|
|
121
|
+
export declare function fakeUpdateTargetFrom(userText: string, fallback: string): {
|
|
122
|
+
field: string;
|
|
123
|
+
blockId?: string;
|
|
124
|
+
prop?: string;
|
|
125
|
+
};
|
|
115
126
|
/**
|
|
116
127
|
* A scripted, STATELESS fake chat model that drives the FULL create flow — and,
|
|
117
128
|
* for a user turn matching the update pattern, the EC-378 UPDATE flow — over the
|
|
@@ -135,11 +146,13 @@ export declare function fakeUpdateFieldFrom(userText: string, fallback: string):
|
|
|
135
146
|
* 1. no tool result yet → `getDocument({})` — target omitted on purpose:
|
|
136
147
|
* the executor resolves the document OPEN in the
|
|
137
148
|
* editor (the EC-378 current-document seam)
|
|
138
|
-
* 2. document read, no update → `updateFields({ changes: [{
|
|
139
|
-
*
|
|
149
|
+
* 2. document read, no update → `updateFields({ changes: [{
|
|
150
|
+
* ...fakeUpdateTargetFrom(<text>, updateField),
|
|
140
151
|
* value: fakeUpdateValueFrom(<last user text>) }] })`
|
|
141
152
|
* — "Set the body to: ## Neu" drives a markdown
|
|
142
|
-
* rich-text update deterministically (EC-379)
|
|
153
|
+
* rich-text update deterministically (EC-379);
|
|
154
|
+
* "Set the body component <id> <prop> to: X" one
|
|
155
|
+
* component prop at any depth (EC-593)
|
|
143
156
|
* 3. update result present → the update answer, word by word.
|
|
144
157
|
*/
|
|
145
158
|
export declare function createFakeCreateFlowChatModel(options?: FakeCreateFlowChatModelOptions): FakeChatModel;
|
|
@@ -180,8 +180,22 @@ export function fakeUpdateValueFrom(userText) {
|
|
|
180
180
|
* else falls back to the configured default field.
|
|
181
181
|
*/
|
|
182
182
|
export function fakeUpdateFieldFrom(userText, fallback) {
|
|
183
|
-
|
|
184
|
-
|
|
183
|
+
return fakeUpdateTargetFrom(userText, fallback).field;
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* The scripted update flow's full TARGET (EC-593): a field, or one component prop
|
|
187
|
+
* inside it — `set the <field> component <id> <prop> to: …` names a component by its
|
|
188
|
+
* node id at any depth (`Set the body component p-home-quote-note value to: Hi`), so the
|
|
189
|
+
* keyless playground can drive a component-prop edit through the one converter.
|
|
190
|
+
*/
|
|
191
|
+
export function fakeUpdateTargetFrom(userText, fallback) {
|
|
192
|
+
const match = /\b(?:set|change|update)\s+the\s+([A-Za-z]\w*)(?:\s+component\s+([\w-]+)\s+([A-Za-z]\w*))?\s+to\s*:/i.exec(userText);
|
|
193
|
+
if (!match)
|
|
194
|
+
return { field: fallback };
|
|
195
|
+
return {
|
|
196
|
+
field: match[1],
|
|
197
|
+
...(match[2] !== undefined && match[3] !== undefined ? { blockId: match[2], prop: match[3] } : {}),
|
|
198
|
+
};
|
|
185
199
|
}
|
|
186
200
|
/**
|
|
187
201
|
* A scripted, STATELESS fake chat model that drives the FULL create flow — and,
|
|
@@ -206,11 +220,13 @@ export function fakeUpdateFieldFrom(userText, fallback) {
|
|
|
206
220
|
* 1. no tool result yet → `getDocument({})` — target omitted on purpose:
|
|
207
221
|
* the executor resolves the document OPEN in the
|
|
208
222
|
* editor (the EC-378 current-document seam)
|
|
209
|
-
* 2. document read, no update → `updateFields({ changes: [{
|
|
210
|
-
*
|
|
223
|
+
* 2. document read, no update → `updateFields({ changes: [{
|
|
224
|
+
* ...fakeUpdateTargetFrom(<text>, updateField),
|
|
211
225
|
* value: fakeUpdateValueFrom(<last user text>) }] })`
|
|
212
226
|
* — "Set the body to: ## Neu" drives a markdown
|
|
213
|
-
* rich-text update deterministically (EC-379)
|
|
227
|
+
* rich-text update deterministically (EC-379);
|
|
228
|
+
* "Set the body component <id> <prop> to: X" one
|
|
229
|
+
* component prop at any depth (EC-593)
|
|
214
230
|
* 3. update result present → the update answer, word by word.
|
|
215
231
|
*/
|
|
216
232
|
export function createFakeCreateFlowChatModel(options = {}) {
|
|
@@ -233,7 +249,7 @@ export function createFakeCreateFlowChatModel(options = {}) {
|
|
|
233
249
|
return toolTurnParts('Proposing the change. ', 'updateFields', {
|
|
234
250
|
changes: [
|
|
235
251
|
{
|
|
236
|
-
|
|
252
|
+
...fakeUpdateTargetFrom(userText, updateField),
|
|
237
253
|
value: fakeUpdateValueFrom(userText),
|
|
238
254
|
},
|
|
239
255
|
],
|