@vectoriox/iox-ui 5.62.1 → 5.63.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/harness-core/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MotionId, MoodId, TintId, DensityId, DesignMotion, DesignChoices, DesignMode, StylePreset, ShapeId, AnimateId } from '@vectoriox/iox-ui/design-core';
|
|
2
|
-
import { FactKey, PathIssue, JsonSchema, SiteTemplate, ShapeEntry, AiGenerationStage, AiStep, SitePlan, PlanEdit, PlanChange, SiteAudit } from '@vectoriox/iox-ui/generation-core';
|
|
2
|
+
import { FactKey, PathIssue, PlainObject, JsonSchema, SiteTemplate, ShapeEntry, AiGenerationStage, AiStep, SitePlan, PlanEdit, PlanChange, SiteAudit } from '@vectoriox/iox-ui/generation-core';
|
|
3
3
|
export { JsonSchema } from '@vectoriox/iox-ui/generation-core';
|
|
4
4
|
|
|
5
5
|
declare const SPEC_HARNESS_SOURCE: {
|
|
@@ -2577,6 +2577,13 @@ declare function validateSiteAnalysis(value: unknown, ctx: AnalysisContext): Ana
|
|
|
2577
2577
|
/** The name a provider shows the format under (`json_schema.name`). */
|
|
2578
2578
|
declare const SITE_ANALYSIS_SCHEMA_NAME = "site_analysis";
|
|
2579
2579
|
declare function siteAnalysisJsonSchema(): JsonSchema;
|
|
2580
|
+
/** A model's analysis (the wire) → the document, and the faults only the wire can have (a fact stated twice). Never repairs. */
|
|
2581
|
+
declare function analysisFromWire(wire: unknown): {
|
|
2582
|
+
analysis: unknown;
|
|
2583
|
+
issues: AnalysisIssue[];
|
|
2584
|
+
};
|
|
2585
|
+
/** The document → the wire (what a model writes). */
|
|
2586
|
+
declare function analysisToWire(analysis: SiteAnalysis): PlainObject;
|
|
2580
2587
|
|
|
2581
2588
|
/**
|
|
2582
2589
|
* What the PLAN prompt is given (AI plan rev 3 §3f "Retrieval, not the whole knowledge base"): the one matched
|
|
@@ -2801,7 +2808,7 @@ declare function validateSiteReading(value: unknown, ctx: {
|
|
|
2801
2808
|
valid: boolean;
|
|
2802
2809
|
issues: ReadingIssue[];
|
|
2803
2810
|
};
|
|
2804
|
-
/** A valid reading's answer → `SiteReading` (the analysis alone answers `{ analysis }
|
|
2811
|
+
/** A valid reading's answer → `SiteReading` (the analysis alone answers `{ analysis }`; the facts made a map again). */
|
|
2805
2812
|
declare function decodeSiteReading(value: unknown, pictureCount: number): SiteReading;
|
|
2806
2813
|
/** A reference picture as the server read it: its measured palette (and where it is). */
|
|
2807
2814
|
interface MeasuredPicture {
|
|
@@ -2987,5 +2994,5 @@ type SiteAuditView = SiteAudit & {
|
|
|
2987
2994
|
advice: LintFinding[];
|
|
2988
2995
|
};
|
|
2989
2996
|
|
|
2990
|
-
export { ANIMATE_ADVICE_STEPS, AnalysisIssueCode, AnalysisLocale, AvoidCheck, BUSINESS_TYPES, BUSINESS_TYPE_IDS, BookingNeed, COPY_LENGTH_ORDER, CopyLength, GENERATION_LIMITS, HARNESS_SOURCE, LITTLE_MOVEMENT_AVOID, LITTLE_MOVEMENT_CAP, LintKind, MAX_ANALYSIS_MOODS, MAX_PIXEL_SAMPLES, MAX_READ_PICTURES, NEEDS, NEED_IDS, NeedSource, PALETTE_SIZE, PALETTE_THRESHOLDS, PictureRole, PlanChangeOutcome, PresetFit, RANK_WEIGHTS, READING_SHAPE, READ_ANIMATE, READ_WEIGHTS, RankReason, ReaderState, ReadingIssueCode, SITE_ANALYSIS_SCHEMA_NAME, SITE_READING_SCHEMA_NAME, SPEC_ANALYSIS_SHAPE, SPEC_BUSINESS_TYPES, SPEC_HARNESS_EXAMPLES, SPEC_HARNESS_SOURCE, SPEC_NEEDS, SPEC_STRUCTURES, SPEC_USER_AVOIDS, STRUCTURES, SiteReadRefusal, StyleReadGround, StyleReadHeadings, StyleReadMotion, StyleReadSourceKind, USER_AVOID_IDS, VoiceFormality, VoicePerson, addressesIn, analysisPromptContext, businessTypeById, calmerChoice, decodeSiteReading, inferNeeds, isLookRule, lintDesign, lookMatches, mapStyleRead, matchBusinessType, matchBusinessTypes, measurePalette, mergeStyleReads, motionAdvice, motionFor, normalizeAddress, oklchHue, paletteBrand, paletteGround, paletteSamples, pictureStyleRead, pixelSamples, presetDesign, presetHasSerifHeadings, presetLook, presetReason, rankStylePresets, rankWithReferences, readPalette, referenceSeed, seedPassesPreset, siteAnalysisJsonSchema, siteReadingJsonSchema, startingDesign, structureFor, userAvoidRule, validateSiteAnalysis, validateSiteReading, withoutAddress };
|
|
2997
|
+
export { ANIMATE_ADVICE_STEPS, AnalysisIssueCode, AnalysisLocale, AvoidCheck, BUSINESS_TYPES, BUSINESS_TYPE_IDS, BookingNeed, COPY_LENGTH_ORDER, CopyLength, GENERATION_LIMITS, HARNESS_SOURCE, LITTLE_MOVEMENT_AVOID, LITTLE_MOVEMENT_CAP, LintKind, MAX_ANALYSIS_MOODS, MAX_PIXEL_SAMPLES, MAX_READ_PICTURES, NEEDS, NEED_IDS, NeedSource, PALETTE_SIZE, PALETTE_THRESHOLDS, PictureRole, PlanChangeOutcome, PresetFit, RANK_WEIGHTS, READING_SHAPE, READ_ANIMATE, READ_WEIGHTS, RankReason, ReaderState, ReadingIssueCode, SITE_ANALYSIS_SCHEMA_NAME, SITE_READING_SCHEMA_NAME, SPEC_ANALYSIS_SHAPE, SPEC_BUSINESS_TYPES, SPEC_HARNESS_EXAMPLES, SPEC_HARNESS_SOURCE, SPEC_NEEDS, SPEC_STRUCTURES, SPEC_USER_AVOIDS, STRUCTURES, SiteReadRefusal, StyleReadGround, StyleReadHeadings, StyleReadMotion, StyleReadSourceKind, USER_AVOID_IDS, VoiceFormality, VoicePerson, addressesIn, analysisFromWire, analysisPromptContext, analysisToWire, businessTypeById, calmerChoice, decodeSiteReading, inferNeeds, isLookRule, lintDesign, lookMatches, mapStyleRead, matchBusinessType, matchBusinessTypes, measurePalette, mergeStyleReads, motionAdvice, motionFor, normalizeAddress, oklchHue, paletteBrand, paletteGround, paletteSamples, pictureStyleRead, pixelSamples, presetDesign, presetHasSerifHeadings, presetLook, presetReason, rankStylePresets, rankWithReferences, readPalette, referenceSeed, seedPassesPreset, siteAnalysisJsonSchema, siteReadingJsonSchema, startingDesign, structureFor, userAvoidRule, validateSiteAnalysis, validateSiteReading, withoutAddress };
|
|
2991
2998
|
export type { AiGenerationView, AnalysisContext, AnalysisIssue, AnalysisValidation, AvoidRule, BusinessType, BusinessTypeMatch, CheckRule, ColourSample, FactRead, GenerationFileView, GenerationReadersView, GenerationStartRequest, GoodFit, LintFinding, LintSite, LookCondition, LookDesign, LookRule, MeasuredPicture, MotionBasis, MotionInput, MotionStart, NeedDef, NeedId, PaletteColour, PaletteReading, PictureStyle, PlanRevisionView, PromptContext, PromptContextOptions, PromptSection, RankInput, RankedPreset, ReadingIssue, ReferenceSeed, SiteAnalysis, SiteAuditView, SiteNeed, SiteReaderView, SiteReading, StartingDesign, StructureChoice, StructureId, StyleHints, StyleRead, UserAvoidId };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MOOD_IDS, MoodId } from '@vectoriox/iox-ui/design-core';
|
|
2
2
|
import {
|
|
3
|
-
describeShapeKey, FACT_KEYS, FactKey, isPlainObject,
|
|
3
|
+
describeShapeKey, FACT_KEYS, FactKey, isPlainObject, jsonListOf, jsonOneOf, JsonSchema, jsonShapedObject, jsonText,
|
|
4
4
|
PathIssue, PathIssueCollector, pathAt, PlainObject, requiredShapeKeys, ShapeEntry, shapeKeys,
|
|
5
5
|
} from '@vectoriox/iox-ui/generation-core';
|
|
6
6
|
|
|
@@ -187,6 +187,11 @@ export function validateSiteAnalysis(value: unknown, ctx: AnalysisContext): Anal
|
|
|
187
187
|
* native strict modes accept (Anthropic `output_config.format`, OpenRouter `json_schema` + `strict`): every object
|
|
188
188
|
* closes with `additionalProperties: false`; no length, count or number bounds (the gate checks those). The
|
|
189
189
|
* schema is a hint the provider enforces; `validateSiteAnalysis` stays the gate.
|
|
190
|
+
*
|
|
191
|
+
* ONE difference from the document, the plan wire's rule "maps as lists" (vectoriox/iox-cms#47 — Claude refuses a
|
|
192
|
+
* grammar compiled too large, and a map of the five facts, each `{ value, quote }`, was 15 of the reading's 47
|
|
193
|
+
* properties): on the wire `facts` is a list `[{ fact, value, quote }]`, a stated fact once each. `analysisFromWire`
|
|
194
|
+
* makes it the map `validateSiteAnalysis` judges; `analysisToWire` is its inverse (fakes and specs write it).
|
|
190
195
|
*/
|
|
191
196
|
|
|
192
197
|
export type { JsonSchema } from '@vectoriox/iox-ui/generation-core';
|
|
@@ -201,19 +206,26 @@ const listOf = jsonListOf;
|
|
|
201
206
|
/** An object of `shape`: exactly its keys, its required ones required, each described by the table. */
|
|
202
207
|
const shaped = (shape: string, properties: Record<string, JsonSchema>): JsonSchema => jsonShapedObject(SHAPE[shape], properties, shape);
|
|
203
208
|
|
|
204
|
-
/**
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
209
|
+
/** A stated fact on the wire: which fact, then the document's `factRead` keys in the table's own words. */
|
|
210
|
+
const FACT_LINE_SHAPE: ShapeEntry = {
|
|
211
|
+
fact: `${FACT_KEYS.map(k => `'${k}'`).join(' | ')} — which fact (site.facts), each at most once`,
|
|
212
|
+
...SHAPE['factRead'],
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/** The analysis as the wire carries it: `facts` a list of fact lines, described in the table's words. */
|
|
216
|
+
const ANALYSIS_WIRE_SHAPE: ShapeEntry = {
|
|
217
|
+
...SHAPE['analysis'],
|
|
218
|
+
facts: `factLine[] — ${describeShapeKey(SHAPE['analysis'], 'facts').replace(/^\{ \[fact\]: factRead \} — /, '')}`,
|
|
219
|
+
};
|
|
208
220
|
|
|
209
221
|
export function siteAnalysisJsonSchema(): JsonSchema {
|
|
210
|
-
const
|
|
211
|
-
return
|
|
222
|
+
const factLine = jsonShapedObject(FACT_LINE_SHAPE, { fact: oneOf(FACT_KEYS), value: text(), quote: text() }, 'factLine');
|
|
223
|
+
return jsonShapedObject(ANALYSIS_WIRE_SHAPE, {
|
|
212
224
|
businessType: oneOf(BUSINESS_TYPE_IDS),
|
|
213
225
|
alternatives: listOf(oneOf(BUSINESS_TYPE_IDS)),
|
|
214
226
|
business: shaped('business', { name: text(), audience: text() }),
|
|
215
227
|
needs: listOf(shaped('need', { id: oneOf(NEED_IDS), from: oneOf(Object.values(NeedSource)), name: text() })),
|
|
216
|
-
facts:
|
|
228
|
+
facts: listOf(factLine),
|
|
217
229
|
missingFacts: listOf(oneOf(FACT_KEYS)),
|
|
218
230
|
voice: shaped('voice', {
|
|
219
231
|
tone: text(),
|
|
@@ -225,5 +237,28 @@ export function siteAnalysisJsonSchema(): JsonSchema {
|
|
|
225
237
|
avoid: listOf(oneOf(USER_AVOID_IDS)),
|
|
226
238
|
hero: shaped('hero', { headline: text(), lead: text() }),
|
|
227
239
|
locale: oneOf(Object.values(AnalysisLocale)),
|
|
240
|
+
}, 'analysis');
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/** A model's analysis (the wire) → the document, and the faults only the wire can have (a fact stated twice). Never repairs. */
|
|
244
|
+
export function analysisFromWire(wire: unknown): { analysis: unknown; issues: AnalysisIssue[] } {
|
|
245
|
+
if (!isPlainObject(wire)) return { analysis: wire, issues: [] };
|
|
246
|
+
if (!Array.isArray(wire['facts'])) return { analysis: wire, issues: [{ code: AnalysisIssueCode.Shape, path: 'facts', message: 'must be a list of { fact, value, quote }' }] };
|
|
247
|
+
const facts: PlainObject = {};
|
|
248
|
+
const issues: AnalysisIssue[] = [];
|
|
249
|
+
(wire['facts'] as unknown[]).forEach((line, i) => {
|
|
250
|
+
if (!isPlainObject(line) || typeof line['fact'] !== 'string') {
|
|
251
|
+
issues.push({ code: AnalysisIssueCode.Shape, path: `facts[${i}]`, message: 'must be { fact, value, quote }' });
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const { fact, ...read } = line;
|
|
255
|
+
if (fact in facts) issues.push({ code: AnalysisIssueCode.Duplicate, path: `facts[${i}].fact`, message: `"${fact}" is stated twice` });
|
|
256
|
+
else facts[fact as string] = read;
|
|
228
257
|
});
|
|
258
|
+
return { analysis: { ...wire, facts }, issues };
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** The document → the wire (what a model writes). */
|
|
262
|
+
export function analysisToWire(analysis: SiteAnalysis): PlainObject {
|
|
263
|
+
return { ...analysis, facts: Object.entries(analysis.facts).map(([fact, read]) => ({ fact, ...read })) };
|
|
229
264
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
|
|
7
7
|
import { paletteSamples, readPalette } from './palette';
|
|
8
8
|
import { StyleRead, StyleReadGround, StyleReadHeadings, StyleReadSourceKind } from './rank';
|
|
9
|
-
import { AnalysisIssue, MAX_ANALYSIS_MOODS, SiteAnalysis, siteAnalysisJsonSchema, validateSiteAnalysis } from './site-analysis';
|
|
9
|
+
import { AnalysisIssue, analysisFromWire, MAX_ANALYSIS_MOODS, SiteAnalysis, siteAnalysisJsonSchema, validateSiteAnalysis } from './site-analysis';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* The READING call (AI plan §3d step 1, §3k R2, M1-1): ONE `text.fast` call reads the owner's words AND the pictures
|
|
@@ -129,23 +129,32 @@ function validatePictures(c: Collector, raw: unknown, count: number): void {
|
|
|
129
129
|
c.oneOf(style, 'density', Object.keys(SPEC_AXES.densities), 'pictures.style');
|
|
130
130
|
}
|
|
131
131
|
|
|
132
|
+
/** The analysis on the wire, judged as the document it becomes: the wire's own faults, then `validateSiteAnalysis`'s. */
|
|
133
|
+
function analysisIssues(wire: unknown, prompt: string): AnalysisIssue[] {
|
|
134
|
+
const read = analysisFromWire(wire);
|
|
135
|
+
return [...read.issues, ...validateSiteAnalysis(read.analysis, { prompt }).issues];
|
|
136
|
+
}
|
|
137
|
+
|
|
132
138
|
/** The reading's gate: the analysis by `validateSiteAnalysis` (paths under `analysis.` when pictures came too), the pictures by `READING_SHAPE`. */
|
|
133
139
|
export function validateSiteReading(value: unknown, ctx: { prompt: string; pictureCount: number }): { valid: boolean; issues: ReadingIssue[] } {
|
|
134
|
-
if (ctx.pictureCount <= 0)
|
|
140
|
+
if (ctx.pictureCount <= 0) {
|
|
141
|
+
const issues = analysisIssues(value, ctx.prompt);
|
|
142
|
+
return { valid: issues.length === 0, issues };
|
|
143
|
+
}
|
|
135
144
|
const c = new Collector();
|
|
136
145
|
const reading = c.object(value, 'reading', '');
|
|
137
146
|
if (!reading) return { valid: false, issues: c.issues };
|
|
138
|
-
const
|
|
139
|
-
const issues: ReadingIssue[] = analysis.issues.map(i => ({ ...i, path: pathAt('analysis', i.path) }));
|
|
147
|
+
const issues: ReadingIssue[] = analysisIssues(reading['analysis'], ctx.prompt).map(i => ({ ...i, path: pathAt('analysis', i.path) }));
|
|
140
148
|
validatePictures(c, reading['pictures'], ctx.pictureCount);
|
|
141
149
|
issues.push(...c.issues);
|
|
142
150
|
return { valid: issues.length === 0, issues };
|
|
143
151
|
}
|
|
144
152
|
|
|
145
|
-
/** A valid reading's answer → `SiteReading` (the analysis alone answers `{ analysis }
|
|
153
|
+
/** A valid reading's answer → `SiteReading` (the analysis alone answers `{ analysis }`; the facts made a map again). */
|
|
146
154
|
export function decodeSiteReading(value: unknown, pictureCount: number): SiteReading {
|
|
147
|
-
if (pictureCount <= 0) return { analysis: value as SiteAnalysis };
|
|
148
|
-
|
|
155
|
+
if (pictureCount <= 0) return { analysis: analysisFromWire(value).analysis as SiteAnalysis };
|
|
156
|
+
const reading = value as SiteReading;
|
|
157
|
+
return { ...reading, analysis: analysisFromWire(reading.analysis).analysis as SiteAnalysis };
|
|
149
158
|
}
|
|
150
159
|
|
|
151
160
|
// ── Readings → ONE StyleRead ───────────────────────────────────────────────────────────────────────────
|