@instruments/materialgraph 0.15.0 → 0.17.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/by-colour-types.d.ts +15 -0
- package/catalogue-client.d.ts +5 -1
- package/catalogue-client.js +8 -0
- package/catalogue-types.d.ts +37 -0
- package/codes-client.d.ts +1 -1
- package/codes-client.js +1 -1
- package/codes-types.d.ts +3 -3
- package/composition-types.d.ts +21 -0
- package/exploration-types.d.ts +2 -0
- package/index.d.ts +2 -0
- package/operations.d.ts +1 -1
- package/operations.js +7 -0
- package/package.json +1 -1
- package/query-understanding-types.d.ts +184 -0
- package/resolve-types.d.ts +1 -1
- package/search-collapse-types.d.ts +69 -0
- package/search-collapse-types.js +1 -0
- package/search-refinement-types.d.ts +17 -8
- package/search-response-receipt-types.d.ts +123 -0
- package/search-response-receipt-types.js +1 -0
- package/search-result-validation.js +21 -0
- package/search-window-types.d.ts +17 -0
- package/search-window-types.js +1 -0
- package/spec-types.d.ts +7 -1
- package/types.d.ts +17 -22
package/by-colour-types.d.ts
CHANGED
|
@@ -100,6 +100,15 @@ export interface ColourFamilyGate {
|
|
|
100
100
|
*/
|
|
101
101
|
dropped: number;
|
|
102
102
|
}
|
|
103
|
+
/** Receipt for the hard category gate and its treatment of unknown typing. */
|
|
104
|
+
export interface ColourCategoryGate {
|
|
105
|
+
/** Category names or keys the caller asked the gate to keep. */
|
|
106
|
+
requested: string[];
|
|
107
|
+
/** Only accepted primary product types can establish membership. */
|
|
108
|
+
requiresAcceptedPrimaryProductType: true;
|
|
109
|
+
/** Unknown/unclassified variants were ineligible, not proven non-members. */
|
|
110
|
+
unclassifiedVariantsExcluded: true;
|
|
111
|
+
}
|
|
103
112
|
/**
|
|
104
113
|
* Receipt for the colour-identity collapse that turns a variant-grain ranking
|
|
105
114
|
* into a page of TILES — one per (brand, product, dominant hex), one per stored
|
|
@@ -177,6 +186,12 @@ export interface ByColourResponse {
|
|
|
177
186
|
* what says so in counts rather than adjectives.
|
|
178
187
|
*/
|
|
179
188
|
familyGate?: ColourFamilyGate;
|
|
189
|
+
/**
|
|
190
|
+
* Present only when `category` was asked for. It states that variants without
|
|
191
|
+
* an accepted primary product type were excluded by the hard gate; absence
|
|
192
|
+
* means no category gate ran.
|
|
193
|
+
*/
|
|
194
|
+
categoryGate?: ColourCategoryGate;
|
|
180
195
|
/**
|
|
181
196
|
* What the colour-identity collapse cost this page. Matches are TILES: a page
|
|
182
197
|
* can be SHORTER than `limit` when the pool collapsed harder than the
|
package/catalogue-client.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CatalogueDocumentAccessResult, CatalogueReferenceBatchResponse } from "./catalogue-types.js";
|
|
1
|
+
import type { CatalogDocumentList, CatalogProductReferenceList, CatalogueDocumentAccessResult, CatalogueReferenceBatchResponse } from "./catalogue-types.js";
|
|
2
2
|
import type { HttpTransport } from "./http-transport.js";
|
|
3
3
|
import type { VariantId } from "./identifiers.js";
|
|
4
4
|
/** Catalogue publication operations inherited by the public SDK client. */
|
|
@@ -13,6 +13,10 @@ export declare class CatalogueClient {
|
|
|
13
13
|
catalogueReferences(input: {
|
|
14
14
|
variantIds: VariantId[];
|
|
15
15
|
}, signal?: AbortSignal): Promise<CatalogueReferenceBatchResponse>;
|
|
16
|
+
/** List immutable catalog documents retained from verified source material. */
|
|
17
|
+
catalogs(signal?: AbortSignal): Promise<CatalogDocumentList>;
|
|
18
|
+
/** Read every verified product/page reference for one retained catalog. */
|
|
19
|
+
catalogReferences(catalogId: string, signal?: AbortSignal): Promise<CatalogProductReferenceList>;
|
|
16
20
|
/** Resolve browser-safe access to one immutable catalogue document. */
|
|
17
21
|
catalogueDocumentAccess(documentId: string, signal?: AbortSignal): Promise<CatalogueDocumentAccessResult>;
|
|
18
22
|
}
|
package/catalogue-client.js
CHANGED
|
@@ -13,6 +13,14 @@ export class CatalogueClient {
|
|
|
13
13
|
catalogueReferences(input, signal) {
|
|
14
14
|
return this.#transport.requestJson(resolveOperation("get_catalogue_references_batch"), { body: input, signal });
|
|
15
15
|
}
|
|
16
|
+
/** List immutable catalog documents retained from verified source material. */
|
|
17
|
+
catalogs(signal) {
|
|
18
|
+
return this.#transport.requestJson(resolveOperation("list_catalog_documents"), { signal });
|
|
19
|
+
}
|
|
20
|
+
/** Read every verified product/page reference for one retained catalog. */
|
|
21
|
+
catalogReferences(catalogId, signal) {
|
|
22
|
+
return this.#transport.requestJson(resolveOperation("list_catalog_product_references"), { pathParams: { catalogId }, signal });
|
|
23
|
+
}
|
|
16
24
|
/** Resolve browser-safe access to one immutable catalogue document. */
|
|
17
25
|
catalogueDocumentAccess(documentId, signal) {
|
|
18
26
|
return this.#transport.requestJson(resolveOperation("get_catalogue_document_access"), { pathParams: { documentId }, signal });
|
package/catalogue-types.d.ts
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
/** A verified product location in a specific immutable brand publication. */
|
|
2
2
|
export interface CatalogueReference {
|
|
3
|
+
anchor: {
|
|
4
|
+
coordinateSpace: "normalized_0_1000";
|
|
5
|
+
height: number;
|
|
6
|
+
kind: "printed_code";
|
|
7
|
+
width: number;
|
|
8
|
+
x: number;
|
|
9
|
+
y: number;
|
|
10
|
+
};
|
|
3
11
|
variantId: string;
|
|
4
12
|
brand: {
|
|
5
13
|
id: string;
|
|
@@ -63,3 +71,32 @@ export type CatalogueDocumentAccessResult = {
|
|
|
63
71
|
documentId: string;
|
|
64
72
|
status: "unresolved_document" | "unavailable" | "forbidden" | "upstream_failure";
|
|
65
73
|
};
|
|
74
|
+
export interface CatalogDocument {
|
|
75
|
+
brand: {
|
|
76
|
+
id: string;
|
|
77
|
+
name: string;
|
|
78
|
+
};
|
|
79
|
+
document: {
|
|
80
|
+
contentScope: "full_document" | "cover_only";
|
|
81
|
+
id: string;
|
|
82
|
+
mediaType: "application/pdf";
|
|
83
|
+
pageCount: number;
|
|
84
|
+
};
|
|
85
|
+
id: string;
|
|
86
|
+
kind: "document";
|
|
87
|
+
productStatus: "partial" | "not_processed";
|
|
88
|
+
title: string;
|
|
89
|
+
}
|
|
90
|
+
export interface CatalogDocumentList {
|
|
91
|
+
catalogs: CatalogDocument[];
|
|
92
|
+
source: "verified-source-material-registry";
|
|
93
|
+
}
|
|
94
|
+
export interface CatalogProductReferenceList {
|
|
95
|
+
catalog: CatalogDocument;
|
|
96
|
+
coverage: {
|
|
97
|
+
pagesWithReferences: number;
|
|
98
|
+
references: number;
|
|
99
|
+
};
|
|
100
|
+
references: CatalogueReference[];
|
|
101
|
+
source: "verified-source-material-registry";
|
|
102
|
+
}
|
package/codes-client.d.ts
CHANGED
|
@@ -45,7 +45,7 @@ export declare class CodesClient {
|
|
|
45
45
|
* The vocabulary for stating a code context (GET `/api/v1/codes/context`):
|
|
46
46
|
* seeded jurisdictions and their coverage tier, the occupancy groups the
|
|
47
47
|
* registry keys on, finish locations, dimensions, classification scales with
|
|
48
|
-
* classes ordered best-first, and which `
|
|
48
|
+
* classes ordered best-first, and which `room` term correlates to which
|
|
49
49
|
* regulatory axes.
|
|
50
50
|
*
|
|
51
51
|
* Start here — every value the other two calls accept is listed in this one
|
package/codes-client.js
CHANGED
|
@@ -14,7 +14,7 @@ export class CodesClient {
|
|
|
14
14
|
* The vocabulary for stating a code context (GET `/api/v1/codes/context`):
|
|
15
15
|
* seeded jurisdictions and their coverage tier, the occupancy groups the
|
|
16
16
|
* registry keys on, finish locations, dimensions, classification scales with
|
|
17
|
-
* classes ordered best-first, and which `
|
|
17
|
+
* classes ordered best-first, and which `room` term correlates to which
|
|
18
18
|
* regulatory axes.
|
|
19
19
|
*
|
|
20
20
|
* Start here — every value the other two calls accept is listed in this one
|
package/codes-types.d.ts
CHANGED
|
@@ -62,7 +62,7 @@ export interface CodeContextRequest {
|
|
|
62
62
|
*/
|
|
63
63
|
spaceType?: string;
|
|
64
64
|
/**
|
|
65
|
-
*
|
|
65
|
+
* A `room` term id (e.g. `"hotel_room"`) to correlate the regulatory axes
|
|
66
66
|
* from. Explicit `occupancyGroup` / `spaceType` always win. A room that
|
|
67
67
|
* correlates to neither axis is a 400 naming the axis — never a guess.
|
|
68
68
|
*/
|
|
@@ -224,7 +224,7 @@ export interface ResolvedCodeContext {
|
|
|
224
224
|
spaceType: string;
|
|
225
225
|
sprinklered: boolean;
|
|
226
226
|
basis: OpenEnum<"explicit" | "derived_from_room">;
|
|
227
|
-
/** The `
|
|
227
|
+
/** The `room` term the axes were correlated from, or null. */
|
|
228
228
|
roomType: string | null;
|
|
229
229
|
}
|
|
230
230
|
/**
|
|
@@ -271,7 +271,7 @@ export interface CodeContextResponse {
|
|
|
271
271
|
/** Ordered BEST FIRST: index 0 outranks index 1. */
|
|
272
272
|
classes: string[];
|
|
273
273
|
}[];
|
|
274
|
-
/** `
|
|
274
|
+
/** `room` → regulatory axes. `null` where the registry refuses to correlate. */
|
|
275
275
|
roomCorrelations: {
|
|
276
276
|
roomType: string;
|
|
277
277
|
label: string;
|
package/composition-types.d.ts
CHANGED
|
@@ -86,6 +86,23 @@ export interface CompliancePresetRule {
|
|
|
86
86
|
export interface CompliancePreset {
|
|
87
87
|
rules: CompliancePresetRule[];
|
|
88
88
|
}
|
|
89
|
+
/** Exact project regulatory axes used to attach bounded code citations. */
|
|
90
|
+
export interface ProgrammeRegulatoryAxes {
|
|
91
|
+
jurisdictionId: string;
|
|
92
|
+
occupancyGroup: string;
|
|
93
|
+
sprinklered: boolean;
|
|
94
|
+
}
|
|
95
|
+
/** One caller-declared Programme space. `spaceType` remains open descriptive text. */
|
|
96
|
+
export interface ComposeDeclaredSpace {
|
|
97
|
+
name: string;
|
|
98
|
+
spaceType?: string;
|
|
99
|
+
/** Exact active canonical `room` id used for bounded code evaluation. */
|
|
100
|
+
regulatoryRoomType?: string;
|
|
101
|
+
}
|
|
102
|
+
/** The spaces this run is explicitly for; omit to retain brief inference. */
|
|
103
|
+
export interface ComposeDeclaredScope {
|
|
104
|
+
spaces: ComposeDeclaredSpace[];
|
|
105
|
+
}
|
|
89
106
|
/**
|
|
90
107
|
* The `inputJson` for a `compose-material-schemes` run. `batchId` is required;
|
|
91
108
|
* everything else has a server default. `anchors` (max 24) carry externally
|
|
@@ -101,6 +118,10 @@ export interface ComposeMaterialSchemesInput {
|
|
|
101
118
|
exclusions?: SchemeExclusions;
|
|
102
119
|
anchors?: ComposeAnchorInput[];
|
|
103
120
|
compliancePreset?: CompliancePreset;
|
|
121
|
+
/** Omit to leave Programme code coverage explicitly unevaluated. */
|
|
122
|
+
regulatoryAxes?: ProgrammeRegulatoryAxes;
|
|
123
|
+
/** Explicit caller-held space facts; regulatoryRoomType is never inferred. */
|
|
124
|
+
scope?: ComposeDeclaredScope;
|
|
104
125
|
}
|
|
105
126
|
/**
|
|
106
127
|
* The state of one criterion verdict cell (MG-627: the shared MaterialGraph
|
package/exploration-types.d.ts
CHANGED
package/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export type * from "./run-events.js";
|
|
|
17
17
|
export { MATERIALGRAPH_PROBLEM_EXTENSIONS, MaterialGraphError, } from "./errors.js";
|
|
18
18
|
export type { MaterialGraphErrorInit, MaterialGraphErrorKind, MaterialGraphRequestMetadata, ProblemDetail, RateLimit, SanitizedErrorValue, SanitizedIssue, SimpleErrorBody, } from "./errors.js";
|
|
19
19
|
export type * from "./types.js";
|
|
20
|
+
export type * from "./search-collapse-types.js";
|
|
20
21
|
export type * from "./match-types.js";
|
|
21
22
|
export type * from "./browse-types.js";
|
|
22
23
|
export type * from "./catalogue-types.js";
|
|
@@ -38,6 +39,7 @@ export type * from "./material-asset-types.js";
|
|
|
38
39
|
export type * from "./material-block-types.js";
|
|
39
40
|
export type * from "./schema-resource-types.js";
|
|
40
41
|
export type * from "./search-refinement-types.js";
|
|
42
|
+
export type * from "./search-window-types.js";
|
|
41
43
|
export { CERTIFICATION_PROGRAMME_ATTRIBUTE_ID } from "./spec-types.js";
|
|
42
44
|
export type * from "./spec-types.js";
|
|
43
45
|
export { certificationProgramme, certificationProgrammeCriterion, hasSpec, specCriterion, specRangeCriterion, specTerm, } from "./specifications.js";
|
package/operations.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const MATERIALGRAPH_API_VERSION = "0.7.0";
|
|
2
|
-
declare const OPERATION_DEFINITIONS: readonly [readonly ["search", "POST", "/api/v1/search", "search_materials_post"], readonly ["planQuery", "POST", "/api/v1/search/plan", "plan_material_query"], readonly ["searchGet", "GET", "/api/v1/search", "search_materials_get"], readonly ["match", "POST", "/api/v1/search/match", "match_material"], readonly ["byColour", "GET", "/api/v1/search/colours", "search_by_colour"], readonly ["material", "GET", "/api/v1/materials/{variantId}", "get_material"], readonly ["catalogueReferences", "POST", "/api/v1/catalogues/references", "get_catalogue_references_batch"], readonly ["catalogueDocumentAccess", "GET", "/api/v1/catalogues/documents/{documentId}", "get_catalogue_document_access"], readonly ["siblings", "GET", "/api/v1/materials/{variantId}/siblings", "get_material_siblings"], readonly ["materialBlocks", "GET", "/api/v1/materials/{variantId}/blocks", "list_material_blocks"], readonly ["materialAssets", "GET", "/api/v1/materials/{variantId}/assets", "list_material_assets"], readonly ["exploration.operators", "GET", "/api/v1/materials/{variantId}/operators", "list_material_operators"], readonly ["exploration.candidates", "POST", "/api/v1/materials/{variantId}/candidates", "read_material_candidates"], readonly ["schema", "GET", "/api/v1/schema/blocks", "list_schema_blocks"], readonly ["schema", "GET", "/api/v1/schema/attributes", "list_schema_attributes"], readonly ["schema", "GET", "/api/v1/schema/verticals", "list_schema_verticals"], readonly ["schema", "GET", "/api/v1/schema/product-types", "list_schema_product_types"], readonly ["schema", "GET", "/api/v1/schema/units", "list_schema_units"], readonly ["schema", "GET", "/api/v1/schema/value-dictionaries", "list_schema_value_dictionaries"], readonly ["schema", "GET", "/api/v1/schema/source-requirements", "list_schema_source_requirements"], readonly ["schema", "GET", "/api/v1/schema/product-type-templates", "list_schema_product_type_templates"], readonly ["schema", "GET", "/api/v1/schema/mappings", "list_schema_mappings"], readonly ["pairings", "GET", "/api/v1/materials/{variantId}/pairings", "get_material_pairings"], readonly ["associatedFinishes", "GET", "/api/v1/associated/finishes", "list_associated_finishes"], readonly ["associatedProducts", "GET", "/api/v1/associated/products", "list_associated_products"], readonly ["materials", "POST", "/api/v1/materials/batch", "get_materials_batch_post"], readonly ["materialsCached", "GET", "/api/v1/materials/batch", "get_materials_batch_get"], readonly ["browse", "GET", "/api/v1/search/browse", "search_browse_by_colour"], readonly ["colourFacets", "GET", "/api/v1/colours/facets", "get_colour_facets"], readonly ["colours.profiles", "GET", "/api/v1/colours/profiles", "get_category_colour_profiles"], readonly ["colours.stats", "GET", "/api/v1/colours/stats", "get_colour_stats"], readonly ["resolveColour", "GET", "/api/v1/search/colours/resolve", "resolve_colour_name"], readonly ["suggestColour", "GET", "/api/v1/search/colours/suggest", "suggest_colour_names"], readonly ["suggest", "GET", "/api/v1/search/suggest", "search_suggest"], readonly ["resolveAttribute", "GET", "/api/v1/catalog/attributes/resolve", "catalog_resolve_attribute"], readonly ["resolveAttributeValue", "GET", "/api/v1/catalog/attributes/{attributeId}/values/resolve", "catalog_resolve_value"], readonly ["searchVocabulary", "GET", "/api/v1/catalog/vocabulary/search", "catalog_vocabulary_search"], readonly ["resolve", "POST", "/api/v1/resolve", "resolve_phrases"], readonly ["bySpec", "GET", "/api/v1/search/specifications", "catalog_by_spec"], readonly ["taxonomy", "GET", "/api/v1/taxonomy/categories", "get_category_taxonomy"], readonly ["whoami", "GET", "/api/v1/whoami", "whoami"], readonly ["coordinate", "POST", "/api/v1/pairings/coordinate", "coordinate_materials"], readonly ["demand", "GET", "/api/v1/demand", "get_material_demand"], readonly ["colours.palette", "POST", "/api/v1/search/palettes", "search_by_palette"], readonly ["extractPalette", "POST", "/api/v1/search/palettes/extract", "extract_image_palette"], readonly ["colours.gradient", "POST", "/api/v1/search/gradients", "search_by_gradient"], readonly ["specificationFacets", "GET", "/api/v1/catalog/specifications/facets", "list_spec_facets"], readonly ["attributeValues", "GET", "/api/v1/catalog/attributes/{attributeId}/values", "list_attribute_values"], readonly ["applicableSpecs", "GET", "/api/v1/taxonomy/categories/{key}/specs", "get_applicable_specs"], readonly ["glossary", "GET", "/api/v1/glossary/{term}", "explain_material_term"], readonly ["brands", "GET", "/api/v1/brands", "list_brands"], readonly ["brand", "GET", "/api/v1/brands/{brandSlug}", "get_brand_profile"], readonly ["brandColourDeck", "GET", "/api/v1/brands/{brandSlug}/colours", "brand_colour_deck"], readonly ["uploadSourceMaterial", "POST", "/api/v1/source-material", "upload_source_material"], readonly ["sourceMaterialBatch", "GET", "/api/v1/source-material/{batchId}", "get_source_material_batch"], readonly ["sourceMaterialComments", "GET", "/api/v1/source-material/{batchId}/sources/{sourceId}/comments", "list_source_material_comments"], readonly ["sourceMaterialComments", "POST", "/api/v1/source-material/{batchId}/sources/{sourceId}/comments", "post_source_material_comment"], readonly ["capabilities", "GET", "/api/v1/capabilities", "list_public_capabilities"], readonly ["createRun", "POST", "/api/v1/runs", "create_public_run"], readonly ["listRuns", "GET", "/api/v1/runs", "list_public_runs"], readonly ["run", "GET", "/api/v1/runs/{runId}", "get_public_run"], readonly ["runSchedule", "GET", "/api/v1/runs/{runId}/schedule", "get_run_finish_schedule"], readonly ["streamRunEvents", "GET", "/api/v1/runs/{runId}/events", "list_public_run_events"], readonly ["resumeRun", "POST", "/api/v1/runs/{runId}/resume", "resume_public_run"], readonly ["cancelRun", "POST", "/api/v1/runs/{runId}/cancel", "cancel_public_run"], readonly ["varyScheme", "POST", "/api/v1/schemes/vary", "vary_schemes"], readonly ["slotPools", "POST", "/api/v1/schemes/pools", "slot_pools"], readonly ["createProject", "POST", "/api/v1/projects", "create_box_project"], readonly ["listProjects", "GET", "/api/v1/projects", "list_box_projects"], readonly ["getProject", "GET", "/api/v1/projects/{projectId}", "get_box_project"], readonly ["appendProjectEvent", "POST", "/api/v1/projects/{projectId}/events", "append_box_project_event"], readonly ["demandBatch", "POST", "/api/v1/demand/batch", "get_demand_batch"], readonly ["codeAdvisory", "POST", "/api/v1/codes/advisory", "resolveCodeAdvisory"], readonly ["codes.context", "GET", "/api/v1/codes/context", "list_code_context"], readonly ["codes.requirements", "GET", "/api/v1/codes/requirements", "list_code_requirements"]];
|
|
2
|
+
declare const OPERATION_DEFINITIONS: readonly [readonly ["catalogs", "GET", "/api/v1/catalogs", "list_catalog_documents"], readonly ["catalogReferences", "GET", "/api/v1/catalogs/{catalogId}/references", "list_catalog_product_references"], readonly ["search", "POST", "/api/v1/search", "search_materials_post"], readonly ["planQuery", "POST", "/api/v1/search/plan", "plan_material_query"], readonly ["searchGet", "GET", "/api/v1/search", "search_materials_get"], readonly ["match", "POST", "/api/v1/search/match", "match_material"], readonly ["byColour", "GET", "/api/v1/search/colours", "search_by_colour"], readonly ["material", "GET", "/api/v1/materials/{variantId}", "get_material"], readonly ["catalogueReferences", "POST", "/api/v1/catalogues/references", "get_catalogue_references_batch"], readonly ["catalogueDocumentAccess", "GET", "/api/v1/catalogues/documents/{documentId}", "get_catalogue_document_access"], readonly ["siblings", "GET", "/api/v1/materials/{variantId}/siblings", "get_material_siblings"], readonly ["materialBlocks", "GET", "/api/v1/materials/{variantId}/blocks", "list_material_blocks"], readonly ["materialAssets", "GET", "/api/v1/materials/{variantId}/assets", "list_material_assets"], readonly ["exploration.operators", "GET", "/api/v1/materials/{variantId}/operators", "list_material_operators"], readonly ["exploration.candidates", "POST", "/api/v1/materials/{variantId}/candidates", "read_material_candidates"], readonly ["schema", "GET", "/api/v1/schema/blocks", "list_schema_blocks"], readonly ["schema", "GET", "/api/v1/schema/attributes", "list_schema_attributes"], readonly ["schema", "GET", "/api/v1/schema/verticals", "list_schema_verticals"], readonly ["schema", "GET", "/api/v1/schema/product-types", "list_schema_product_types"], readonly ["schema", "GET", "/api/v1/schema/units", "list_schema_units"], readonly ["schema", "GET", "/api/v1/schema/value-dictionaries", "list_schema_value_dictionaries"], readonly ["schema", "GET", "/api/v1/schema/source-requirements", "list_schema_source_requirements"], readonly ["schema", "GET", "/api/v1/schema/product-type-templates", "list_schema_product_type_templates"], readonly ["schema", "GET", "/api/v1/schema/mappings", "list_schema_mappings"], readonly ["pairings", "GET", "/api/v1/materials/{variantId}/pairings", "get_material_pairings"], readonly ["associatedFinishes", "GET", "/api/v1/associated/finishes", "list_associated_finishes"], readonly ["associatedProducts", "GET", "/api/v1/associated/products", "list_associated_products"], readonly ["materials", "POST", "/api/v1/materials/batch", "get_materials_batch_post"], readonly ["materialsCached", "GET", "/api/v1/materials/batch", "get_materials_batch_get"], readonly ["browse", "GET", "/api/v1/search/browse", "search_browse_by_colour"], readonly ["colourFacets", "GET", "/api/v1/colours/facets", "get_colour_facets"], readonly ["colours.profiles", "GET", "/api/v1/colours/profiles", "get_category_colour_profiles"], readonly ["colours.stats", "GET", "/api/v1/colours/stats", "get_colour_stats"], readonly ["resolveColour", "GET", "/api/v1/search/colours/resolve", "resolve_colour_name"], readonly ["suggestColour", "GET", "/api/v1/search/colours/suggest", "suggest_colour_names"], readonly ["suggest", "GET", "/api/v1/search/suggest", "search_suggest"], readonly ["resolveAttribute", "GET", "/api/v1/catalog/attributes/resolve", "catalog_resolve_attribute"], readonly ["resolveAttributeValue", "GET", "/api/v1/catalog/attributes/{attributeId}/values/resolve", "catalog_resolve_value"], readonly ["searchVocabulary", "GET", "/api/v1/catalog/vocabulary/search", "catalog_vocabulary_search"], readonly ["resolve", "POST", "/api/v1/resolve", "resolve_phrases"], readonly ["bySpec", "GET", "/api/v1/search/specifications", "catalog_by_spec"], readonly ["taxonomy", "GET", "/api/v1/taxonomy/categories", "get_category_taxonomy"], readonly ["whoami", "GET", "/api/v1/whoami", "whoami"], readonly ["coordinate", "POST", "/api/v1/pairings/coordinate", "coordinate_materials"], readonly ["demand", "GET", "/api/v1/demand", "get_material_demand"], readonly ["colours.palette", "POST", "/api/v1/search/palettes", "search_by_palette"], readonly ["extractPalette", "POST", "/api/v1/search/palettes/extract", "extract_image_palette"], readonly ["colours.gradient", "POST", "/api/v1/search/gradients", "search_by_gradient"], readonly ["specificationFacets", "GET", "/api/v1/catalog/specifications/facets", "list_spec_facets"], readonly ["attributeValues", "GET", "/api/v1/catalog/attributes/{attributeId}/values", "list_attribute_values"], readonly ["applicableSpecs", "GET", "/api/v1/taxonomy/categories/{key}/specs", "get_applicable_specs"], readonly ["glossary", "GET", "/api/v1/glossary/{term}", "explain_material_term"], readonly ["brands", "GET", "/api/v1/brands", "list_brands"], readonly ["brand", "GET", "/api/v1/brands/{brandSlug}", "get_brand_profile"], readonly ["brandColourDeck", "GET", "/api/v1/brands/{brandSlug}/colours", "brand_colour_deck"], readonly ["uploadSourceMaterial", "POST", "/api/v1/source-material", "upload_source_material"], readonly ["sourceMaterialBatch", "GET", "/api/v1/source-material/{batchId}", "get_source_material_batch"], readonly ["sourceMaterialComments", "GET", "/api/v1/source-material/{batchId}/sources/{sourceId}/comments", "list_source_material_comments"], readonly ["sourceMaterialComments", "POST", "/api/v1/source-material/{batchId}/sources/{sourceId}/comments", "post_source_material_comment"], readonly ["capabilities", "GET", "/api/v1/capabilities", "list_public_capabilities"], readonly ["createRun", "POST", "/api/v1/runs", "create_public_run"], readonly ["listRuns", "GET", "/api/v1/runs", "list_public_runs"], readonly ["run", "GET", "/api/v1/runs/{runId}", "get_public_run"], readonly ["runSchedule", "GET", "/api/v1/runs/{runId}/schedule", "get_run_finish_schedule"], readonly ["streamRunEvents", "GET", "/api/v1/runs/{runId}/events", "list_public_run_events"], readonly ["resumeRun", "POST", "/api/v1/runs/{runId}/resume", "resume_public_run"], readonly ["cancelRun", "POST", "/api/v1/runs/{runId}/cancel", "cancel_public_run"], readonly ["varyScheme", "POST", "/api/v1/schemes/vary", "vary_schemes"], readonly ["slotPools", "POST", "/api/v1/schemes/pools", "slot_pools"], readonly ["createProject", "POST", "/api/v1/projects", "create_box_project"], readonly ["listProjects", "GET", "/api/v1/projects", "list_box_projects"], readonly ["getProject", "GET", "/api/v1/projects/{projectId}", "get_box_project"], readonly ["appendProjectEvent", "POST", "/api/v1/projects/{projectId}/events", "append_box_project_event"], readonly ["demandBatch", "POST", "/api/v1/demand/batch", "get_demand_batch"], readonly ["codeAdvisory", "POST", "/api/v1/codes/advisory", "resolveCodeAdvisory"], readonly ["codes.context", "GET", "/api/v1/codes/context", "list_code_context"], readonly ["codes.requirements", "GET", "/api/v1/codes/requirements", "list_code_requirements"]];
|
|
3
3
|
export type SdkOperationId = (typeof OPERATION_DEFINITIONS)[number][3];
|
|
4
4
|
export type SdkOperation = Readonly<{
|
|
5
5
|
clientMethod: (typeof OPERATION_DEFINITIONS)[number][0];
|
package/operations.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { MaterialGraphError } from "./errors.js";
|
|
2
2
|
export const MATERIALGRAPH_API_VERSION = "0.7.0";
|
|
3
3
|
const OPERATION_DEFINITIONS = [
|
|
4
|
+
["catalogs", "GET", "/api/v1/catalogs", "list_catalog_documents"],
|
|
5
|
+
[
|
|
6
|
+
"catalogReferences",
|
|
7
|
+
"GET",
|
|
8
|
+
"/api/v1/catalogs/{catalogId}/references",
|
|
9
|
+
"list_catalog_product_references",
|
|
10
|
+
],
|
|
4
11
|
["search", "POST", "/api/v1/search", "search_materials_post"],
|
|
5
12
|
["planQuery", "POST", "/api/v1/search/plan", "plan_material_query"],
|
|
6
13
|
["searchGet", "GET", "/api/v1/search", "search_materials_get"],
|
package/package.json
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SearchFilter } from "./search-refinement-types.js";
|
|
1
2
|
import type { OpenEnum } from "./types.js";
|
|
2
3
|
export type QuerySenseKind = OpenEnum<"brand" | "product" | "paint_identity" | "category" | "material" | "colour" | "attribute" | "attribute_value" | "certification">;
|
|
3
4
|
export interface QuerySense {
|
|
@@ -26,6 +27,181 @@ export interface QuerySense {
|
|
|
26
27
|
};
|
|
27
28
|
reason?: string;
|
|
28
29
|
}
|
|
30
|
+
export interface CanonicalLexicalAuthorityReceipt {
|
|
31
|
+
authority: OpenEnum<"taxonomy" | "colorscope">;
|
|
32
|
+
version: string;
|
|
33
|
+
revision: string;
|
|
34
|
+
digest?: string;
|
|
35
|
+
}
|
|
36
|
+
export interface CanonicalLexicalReading {
|
|
37
|
+
authority: OpenEnum<"taxonomy" | "colorscope">;
|
|
38
|
+
identity: string;
|
|
39
|
+
outcome: OpenEnum<"equivalent" | "ambiguous" | "declined">;
|
|
40
|
+
executionStatus: OpenEnum<"applied" | "suppressed" | "executable" | "recognized-but-unexecutable" | "declined">;
|
|
41
|
+
role: OpenEnum<"primary" | "secondary"> | null;
|
|
42
|
+
kind?: OpenEnum<"domain" | "core-colour" | "paint">;
|
|
43
|
+
label?: string;
|
|
44
|
+
libraryId?: string;
|
|
45
|
+
code?: string;
|
|
46
|
+
aliasCount?: number;
|
|
47
|
+
matchForm?: OpenEnum<"name" | "code" | "authoritative-term">;
|
|
48
|
+
collisionCount?: number;
|
|
49
|
+
familyId?: string;
|
|
50
|
+
hex?: string;
|
|
51
|
+
level?: OpenEnum<"family" | "tone-band" | "branch" | "concept">;
|
|
52
|
+
lifecycle?: {
|
|
53
|
+
introducedAt: string;
|
|
54
|
+
reviewedAt?: string;
|
|
55
|
+
status: string;
|
|
56
|
+
};
|
|
57
|
+
provenance?: {
|
|
58
|
+
basis: string;
|
|
59
|
+
snapshot?: string;
|
|
60
|
+
source: string;
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export interface CanonicalLexicalMatch {
|
|
64
|
+
original: string;
|
|
65
|
+
canonical: string;
|
|
66
|
+
rule: OpenEnum<"exact" | "plural-to-singular">;
|
|
67
|
+
span: {
|
|
68
|
+
start: number;
|
|
69
|
+
end: number;
|
|
70
|
+
};
|
|
71
|
+
coverage: number;
|
|
72
|
+
readings: CanonicalLexicalReading[];
|
|
73
|
+
receipt: {
|
|
74
|
+
original: string;
|
|
75
|
+
canonical: string;
|
|
76
|
+
rule: OpenEnum<"exact" | "plural-to-singular">;
|
|
77
|
+
authorities: CanonicalLexicalAuthorityReceipt[];
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
export interface CanonicalLexicalReceipt {
|
|
81
|
+
original: string;
|
|
82
|
+
outcome: OpenEnum<"resolved" | "ambiguous" | "declined" | "partial" | "unresolved">;
|
|
83
|
+
matches: CanonicalLexicalMatch[];
|
|
84
|
+
unresolved: CanonicalLexicalMatch[];
|
|
85
|
+
}
|
|
86
|
+
export interface QueryResidualReceipt {
|
|
87
|
+
kind: OpenEnum<"compound" | "descriptive" | "ambiguous" | "empty">;
|
|
88
|
+
tokens: string[];
|
|
89
|
+
resolvedTokens: string[];
|
|
90
|
+
unresolvedTokens: string[];
|
|
91
|
+
resolvedRatio: number;
|
|
92
|
+
comparisonFrame: boolean;
|
|
93
|
+
}
|
|
94
|
+
/** Deterministic criteria compiled from the query before retrieval. */
|
|
95
|
+
export interface QueryCriteriaReceipt {
|
|
96
|
+
applied: Array<{
|
|
97
|
+
criterion: SearchFilter;
|
|
98
|
+
lane: OpenEnum<"filter" | "preference">;
|
|
99
|
+
lexicalSignal?: {
|
|
100
|
+
attributeId: string;
|
|
101
|
+
canonical: string;
|
|
102
|
+
identity: string;
|
|
103
|
+
original: string;
|
|
104
|
+
relation: OpenEnum<"equivalent" | "broader-storage-term">;
|
|
105
|
+
span: {
|
|
106
|
+
start: number;
|
|
107
|
+
end: number;
|
|
108
|
+
};
|
|
109
|
+
storedTerm: string;
|
|
110
|
+
};
|
|
111
|
+
source: OpenEnum<"compiled" | "taxonomy-adapter">;
|
|
112
|
+
span: string;
|
|
113
|
+
}>;
|
|
114
|
+
conflicts: Array<{
|
|
115
|
+
attributeId: string;
|
|
116
|
+
caller: SearchFilter;
|
|
117
|
+
compiled: SearchFilter;
|
|
118
|
+
reason: string;
|
|
119
|
+
}>;
|
|
120
|
+
exclusions: Array<{
|
|
121
|
+
criterion: SearchFilter;
|
|
122
|
+
execution: OpenEnum<"blocked-positive-only-contract">;
|
|
123
|
+
lane: OpenEnum<"hard" | "soft">;
|
|
124
|
+
missingValuePolicy: OpenEnum<"retain-unknown">;
|
|
125
|
+
span: string;
|
|
126
|
+
}>;
|
|
127
|
+
preferences: SearchFilter[];
|
|
128
|
+
residualText: string | null;
|
|
129
|
+
unresolved: Array<{
|
|
130
|
+
code: OpenEnum<"missing-searchable-attribute" | "missing-dimension-pair-contract" | "missing-explicit-comparator" | "negative-criterion-contract-blocked" | "registry-contract-drift" | "unsupported-numeric-format" | "unsupported-unit" | "unsupported-strict-comparator">;
|
|
131
|
+
reason: string;
|
|
132
|
+
span: string;
|
|
133
|
+
}>;
|
|
134
|
+
}
|
|
135
|
+
/** How the query named or inferred a product type before retrieval. */
|
|
136
|
+
export interface QueryProductTypeReceipt {
|
|
137
|
+
kind: OpenEnum<"leaf" | "group" | "vector" | "ambiguous" | "none">;
|
|
138
|
+
gate: OpenEnum<"hard" | "constrain" | "none">;
|
|
139
|
+
pass: OpenEnum<"taxonomy" | "synonym" | "display-name" | "group" | "head-noun" | "vector" | "none">;
|
|
140
|
+
reason: string;
|
|
141
|
+
displayName: string | null;
|
|
142
|
+
productTypeId: string | null;
|
|
143
|
+
groupKey: string | null;
|
|
144
|
+
productTypeIds: string[];
|
|
145
|
+
similarity: number | null;
|
|
146
|
+
margin: number | null;
|
|
147
|
+
residualText: string;
|
|
148
|
+
vectorPassRan: boolean;
|
|
149
|
+
registryVersion: string;
|
|
150
|
+
durationMs: number;
|
|
151
|
+
candidates: Array<{
|
|
152
|
+
productTypeId: string;
|
|
153
|
+
displayName: string;
|
|
154
|
+
similarity: number;
|
|
155
|
+
}>;
|
|
156
|
+
}
|
|
157
|
+
/** The selected retrieval arm; null when the path is browse or criteria-only. */
|
|
158
|
+
export interface QueryArmReceipt {
|
|
159
|
+
arm: OpenEnum<"dense" | "lexical" | "colour"> | null;
|
|
160
|
+
reason: string;
|
|
161
|
+
outcome: OpenEnum<"dense" | "lexical" | "colour" | "browse" | "criteria-only" | "ambiguous">;
|
|
162
|
+
decidedBy: OpenEnum<"deterministic" | "model">;
|
|
163
|
+
productTypeGate: OpenEnum<"hard" | "constrain" | "none">;
|
|
164
|
+
productTypeIds: string[];
|
|
165
|
+
residual: QueryResidualReceipt;
|
|
166
|
+
registryVersion: string;
|
|
167
|
+
}
|
|
168
|
+
export interface QueryAmbiguityReceipt {
|
|
169
|
+
outcome: OpenEnum<"applied" | "abstained" | "refused" | "timeout">;
|
|
170
|
+
modelId: string | null;
|
|
171
|
+
providerRan: boolean;
|
|
172
|
+
durationMs: number;
|
|
173
|
+
timeoutMs: number;
|
|
174
|
+
validation: OpenEnum<"valid" | "invalid" | "not-run">;
|
|
175
|
+
refusalCode: string | null;
|
|
176
|
+
confidence: number | null;
|
|
177
|
+
routing: OpenEnum<"compound" | "descriptive"> | null;
|
|
178
|
+
productTypeIds: string[];
|
|
179
|
+
changedArm: boolean;
|
|
180
|
+
}
|
|
181
|
+
export interface QueryCategoryScopeReceipt {
|
|
182
|
+
source: OpenEnum<"caller" | "anchor">;
|
|
183
|
+
mechanism: OpenEnum<"sql-predicate" | "allowlist" | "prune">;
|
|
184
|
+
variantCount: number | null;
|
|
185
|
+
ceiling: number;
|
|
186
|
+
specScanBounded?: boolean;
|
|
187
|
+
[key: string]: unknown;
|
|
188
|
+
}
|
|
189
|
+
export interface QuerySpecAllowlistReceipt {
|
|
190
|
+
limit: number;
|
|
191
|
+
returned: number;
|
|
192
|
+
truncated: boolean;
|
|
193
|
+
emptyMeansScarcity: boolean;
|
|
194
|
+
}
|
|
195
|
+
export interface QueryUnsatisfiableNarrowing {
|
|
196
|
+
narrowing: OpenEnum<"product-type">;
|
|
197
|
+
gate: OpenEnum<"hard">;
|
|
198
|
+
productTypeId: string;
|
|
199
|
+
displayName: string;
|
|
200
|
+
productTypeIds: string[];
|
|
201
|
+
pass: string;
|
|
202
|
+
evidence: OpenEnum<"zero-accepted-variants">;
|
|
203
|
+
relaxedTo: OpenEnum<"none">;
|
|
204
|
+
}
|
|
29
205
|
/** Inspectable interpretation of the raw query by ordinary MaterialGraph search. */
|
|
30
206
|
export interface QueryUnderstanding {
|
|
31
207
|
version: OpenEnum<"1">;
|
|
@@ -35,4 +211,12 @@ export interface QueryUnderstanding {
|
|
|
35
211
|
status: OpenEnum<"resolved" | "ambiguous" | "partial" | "unresolved">;
|
|
36
212
|
mode: OpenEnum<"image" | "colour" | "text" | "lexical" | "entity-browse">;
|
|
37
213
|
senses: QuerySense[];
|
|
214
|
+
canonicalLexical?: CanonicalLexicalReceipt;
|
|
215
|
+
criteria?: QueryCriteriaReceipt;
|
|
216
|
+
productType?: QueryProductTypeReceipt;
|
|
217
|
+
arm?: QueryArmReceipt;
|
|
218
|
+
ambiguity?: QueryAmbiguityReceipt;
|
|
219
|
+
categoryScope?: QueryCategoryScopeReceipt;
|
|
220
|
+
specAllowlist?: QuerySpecAllowlistReceipt;
|
|
221
|
+
unsatisfiableNarrowing?: QueryUnsatisfiableNarrowing;
|
|
38
222
|
}
|
package/resolve-types.d.ts
CHANGED
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* - `category` — a product-category taxonomy node key.
|
|
26
26
|
* - `attribute` — a registry attribute id: the LEFT half of an `attribute:value`
|
|
27
27
|
* pair, for `mg.bySpec()` or `search({ filters })`.
|
|
28
|
-
* - `attribute_value` — a value-dictionary term, namespaced (`
|
|
28
|
+
* - `attribute_value` — a value-dictionary term, namespaced (`sheen.matte`):
|
|
29
29
|
* the RIGHT half.
|
|
30
30
|
* - `jurisdiction` — a code jurisdiction id (`us-tx`), for `mg.codeAdvisory()`.
|
|
31
31
|
* - `occupancy_group` — an IBC occupancy group (`R-1`), the other axis the code
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The product-collapsed view of a search result — what `collapse: "product"`
|
|
3
|
+
* hands back beside each card. Kept out of `types.ts` for the same reason
|
|
4
|
+
* `palette-search-types.ts` and `by-colour-types.ts` are: that file is at its
|
|
5
|
+
* source-size ceiling, and this is a self-contained corner of the contract.
|
|
6
|
+
*
|
|
7
|
+
* READ THIS FIRST, because the default is the opposite of what "duplicates"
|
|
8
|
+
* intuition suggests. MaterialGraph search is VARIANT-based: without `collapse`,
|
|
9
|
+
* every matching variant comes back as its own result, and that is correct —
|
|
10
|
+
* twelve SKUs of one tile are twelve separately orderable products, not twelve
|
|
11
|
+
* copies of one. Product grouping is an optional VIEW over that, not a fix for
|
|
12
|
+
* it.
|
|
13
|
+
*
|
|
14
|
+
* When you do ask for the view, the product arrives CARRYING its variants
|
|
15
|
+
* (`SearchResultItem.variants`) rather than a bare count, so a colourway strip
|
|
16
|
+
* renders from the same response as the card. That array is CAPPED at 12, while
|
|
17
|
+
* `SearchResultItem.siblingCount` stays the complete tally — so a truncated list
|
|
18
|
+
* is decidable from the response alone: `(siblingCount ?? 0) + 1 >
|
|
19
|
+
* variants.length`. A full-length array is never on its own evidence that the
|
|
20
|
+
* product holds no further variants.
|
|
21
|
+
*/
|
|
22
|
+
import type { VariantId } from "./identifiers.js";
|
|
23
|
+
import type { SearchResultSignals } from "./types.js";
|
|
24
|
+
/**
|
|
25
|
+
* One variant of a product-collapsed result.
|
|
26
|
+
*
|
|
27
|
+
* A slim shape, deliberately: the fields a colourway strip renders, projected
|
|
28
|
+
* from the row the engine already held in memory, so the array costs no extra
|
|
29
|
+
* query. It is NOT a nested search result — no `attributes`, `palette`,
|
|
30
|
+
* `verdict` or `productType` — because those come from per-result reads the
|
|
31
|
+
* engine issues for the card only. Fetch the variant by `variantId` when you
|
|
32
|
+
* need its full record.
|
|
33
|
+
*/
|
|
34
|
+
export interface CollapsedVariant {
|
|
35
|
+
/** Opaque — round-trip verbatim. */
|
|
36
|
+
variantId: VariantId;
|
|
37
|
+
/** The variant's own label; for paint, the colourway name. Null when unnamed. */
|
|
38
|
+
variantName: string | null;
|
|
39
|
+
/** The variant's coarse colour family. */
|
|
40
|
+
color: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* `#rrggbb` dominant colour EXTRACTED FROM the variant's image — a visual
|
|
43
|
+
* likeness, never a manufacturer-declared colour specification. ABSENT means
|
|
44
|
+
* no palette is on record: unknown, never "this variant has no colour".
|
|
45
|
+
*/
|
|
46
|
+
hex?: string;
|
|
47
|
+
imageUrl: string | null;
|
|
48
|
+
/**
|
|
49
|
+
* The variant's Material Bank SKU, on the same contract as the result item's:
|
|
50
|
+
* ABSENT means no MB identity is on record, never that it cannot be ordered.
|
|
51
|
+
*/
|
|
52
|
+
materialBankId?: string;
|
|
53
|
+
/** This variant's own fused score — the value the array is ordered by. */
|
|
54
|
+
score: number;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* One member of a collapsed result's `SearchResultItem.anatomy` — the
|
|
58
|
+
* EXPLAIN-only readout of the same grouping {@link CollapsedVariant} publishes.
|
|
59
|
+
* Where a collapsed variant is what a surface renders, this is what an operator
|
|
60
|
+
* inspects: it carries the per-arm `signals` that made the variant a candidate.
|
|
61
|
+
*/
|
|
62
|
+
export interface SearchAnatomyMember {
|
|
63
|
+
/** Opaque — round-trip verbatim. */
|
|
64
|
+
variantId: VariantId;
|
|
65
|
+
variantName: string | null;
|
|
66
|
+
color: string | null;
|
|
67
|
+
score: number;
|
|
68
|
+
signals: SearchResultSignals;
|
|
69
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -76,6 +76,13 @@ export type SearchFilter = {
|
|
|
76
76
|
attributeId: string;
|
|
77
77
|
hasValue: true;
|
|
78
78
|
trust?: SearchFilterTrust;
|
|
79
|
+
}
|
|
80
|
+
/** Date-sensitive presence is currently executable only for EPD expiration. */
|
|
81
|
+
| {
|
|
82
|
+
attributeId: "epd_expiration_date";
|
|
83
|
+
hasValue: true;
|
|
84
|
+
asOf: string;
|
|
85
|
+
trust?: SearchFilterTrust;
|
|
79
86
|
} | {
|
|
80
87
|
attributeId: string;
|
|
81
88
|
/** Inclusive lower bound. Omit for a ceiling-only range. */
|
|
@@ -90,29 +97,31 @@ export interface SearchSuggestion {
|
|
|
90
97
|
/** Complete replacement request, not a partial patch. */
|
|
91
98
|
request: SearchInput;
|
|
92
99
|
}
|
|
93
|
-
/** One
|
|
100
|
+
/** One reading a {@link SearchDisambiguation} offers. */
|
|
94
101
|
export interface SearchInterpretation {
|
|
95
102
|
id: string;
|
|
96
103
|
label: string;
|
|
97
104
|
kind: string;
|
|
98
|
-
/** True for the reading that
|
|
105
|
+
/** True for the reading that ran; all false means the engine chose none. */
|
|
99
106
|
isDefault: boolean;
|
|
100
107
|
/** The colour this reading resolved to, when the ambiguity was a colour one. */
|
|
101
108
|
hex?: string;
|
|
102
109
|
/** Complete replacement request, not a partial patch. */
|
|
103
110
|
request: SearchInput;
|
|
104
111
|
}
|
|
112
|
+
/** The governed ambiguity classes emitted by MaterialGraph search. */
|
|
113
|
+
export type SearchDisambiguationKind = "compliance-phrase" | "colour-material" | "paint-colour" | "paint-identity";
|
|
105
114
|
/**
|
|
106
|
-
* The server saying a query had
|
|
115
|
+
* The server saying a query had multiple defensible readings.
|
|
107
116
|
*
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
*
|
|
117
|
+
* The reading that ran is flagged `isDefault`; every reading is false when the
|
|
118
|
+
* engine deliberately chose none. Each carries a complete executable request,
|
|
119
|
+
* so choosing a reading is a re-issue rather than a patch. Ignoring this block does not
|
|
111
120
|
* make the ambiguity go away — it makes it invisible to the person who asked.
|
|
112
121
|
*/
|
|
113
122
|
export interface SearchDisambiguation {
|
|
114
|
-
/**
|
|
115
|
-
kind:
|
|
123
|
+
/** Compliance, colour-material, paint-colour, or paint-identity ambiguity. */
|
|
124
|
+
kind: SearchDisambiguationKind;
|
|
116
125
|
/** The ambiguous term or phrase. */
|
|
117
126
|
term: string;
|
|
118
127
|
interpretations: SearchInterpretation[];
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module sdk/search-response-receipt-types
|
|
3
|
+
* @description Inspectable routing, rerank, and compound-constraint receipts
|
|
4
|
+
* emitted by ordinary Search responses.
|
|
5
|
+
*/
|
|
6
|
+
import type { OpenEnum } from "./types.js";
|
|
7
|
+
/** The primary ranking source a query resolved to and reports as its mode. */
|
|
8
|
+
export type SearchMode = OpenEnum<"image" | "colour" | "text" | "lexical" | "entity-browse">;
|
|
9
|
+
/** Rerank-term report (absent in colour mode — there colour IS the source). */
|
|
10
|
+
export interface SearchRerankReport {
|
|
11
|
+
colour?: OpenEnum<"ok" | "failed" | "skipped">;
|
|
12
|
+
colourWeight?: number;
|
|
13
|
+
colourLabel?: string;
|
|
14
|
+
}
|
|
15
|
+
/** One stage in the explain-only ledger of transformations that actually ran. */
|
|
16
|
+
export type SearchQueryTransformStage = {
|
|
17
|
+
stage: OpenEnum<"normalise" | "resolve-spec" | "resolve-paint" | "resolve-brand">;
|
|
18
|
+
applied: true;
|
|
19
|
+
} | {
|
|
20
|
+
stage: OpenEnum<"normalise" | "resolve-spec" | "resolve-paint" | "resolve-brand">;
|
|
21
|
+
applied: false;
|
|
22
|
+
reason: string;
|
|
23
|
+
};
|
|
24
|
+
/** Explain-only category gate selected by query understanding. */
|
|
25
|
+
export interface SearchCategoryAnchor {
|
|
26
|
+
/**
|
|
27
|
+
* A leaf type id; the group key when `source` is `"group"`; or the canonical
|
|
28
|
+
* category noun when `source` is `"head-noun"`. Gate on `productTypeIds`.
|
|
29
|
+
*/
|
|
30
|
+
productTypeId: string;
|
|
31
|
+
/**
|
|
32
|
+
* The leaf type ids a `"group"` or `"head-noun"` anchor expanded to; absent
|
|
33
|
+
* for leaf sources.
|
|
34
|
+
*/
|
|
35
|
+
productTypeIds?: readonly string[];
|
|
36
|
+
displayName: string;
|
|
37
|
+
similarity: number;
|
|
38
|
+
margin: number | null;
|
|
39
|
+
source: OpenEnum<"taxonomy" | "synonym" | "display-name" | "group" | "head-noun" | "vector">;
|
|
40
|
+
/** Hard category eligibility is applied inside lexical candidate selection. */
|
|
41
|
+
candidateSource?: OpenEnum<"lexical">;
|
|
42
|
+
applied: boolean;
|
|
43
|
+
}
|
|
44
|
+
/** Explain-only brand gate selected by query understanding. */
|
|
45
|
+
export interface SearchBrandAnchor {
|
|
46
|
+
brandSlug: string;
|
|
47
|
+
brandName: string;
|
|
48
|
+
confidence: number;
|
|
49
|
+
margin: number | null;
|
|
50
|
+
tier: OpenEnum<"exact_id" | "exact_alias" | "lexical" | "semantic">;
|
|
51
|
+
variantCount: number;
|
|
52
|
+
applied: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** A real brand candidate the engine deliberately declined to gate on. */
|
|
55
|
+
export interface SearchBrandSkip {
|
|
56
|
+
reason: OpenEnum<"ambiguous" | "weak-tier" | "too-broad">;
|
|
57
|
+
candidates?: string[];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* EXPLAIN-only receipt of the query shape that executed. This is distinct from
|
|
61
|
+
* the separate Search Plan compiler operation: it reports execution and never
|
|
62
|
+
* causes it.
|
|
63
|
+
*/
|
|
64
|
+
export interface SearchExecutionPlan {
|
|
65
|
+
grain: OpenEnum<"variant" | "product">;
|
|
66
|
+
weights: {
|
|
67
|
+
image: number;
|
|
68
|
+
category: number;
|
|
69
|
+
colour: number;
|
|
70
|
+
lexical: number;
|
|
71
|
+
text: number;
|
|
72
|
+
};
|
|
73
|
+
queryTransform: SearchQueryTransformStage[];
|
|
74
|
+
categoryAnchor?: SearchCategoryAnchor;
|
|
75
|
+
brandAnchor?: SearchBrandAnchor;
|
|
76
|
+
brandSkipped?: SearchBrandSkip;
|
|
77
|
+
}
|
|
78
|
+
/** Why a compound colour constraint returned a full or short page. */
|
|
79
|
+
export interface CompoundColourAbundanceReceipt {
|
|
80
|
+
grain: OpenEnum<"variant" | "product">;
|
|
81
|
+
requested: number;
|
|
82
|
+
eligible: number;
|
|
83
|
+
candidateWindow: number;
|
|
84
|
+
sourceExhausted: boolean;
|
|
85
|
+
state: OpenEnum<"filled" | "corpus_scarcity" | "evidence_unavailable" | "retrieval_window_exhausted">;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Eligibility proof for an explicit or taxonomy-backed colour inside a compound
|
|
89
|
+
* text query. Counts describe the bounded candidate pool, not the whole corpus.
|
|
90
|
+
*/
|
|
91
|
+
export interface CompoundColourConstraintReceipt {
|
|
92
|
+
basis: OpenEnum<"explicit" | "detected-strong">;
|
|
93
|
+
family: string;
|
|
94
|
+
queryHexes: string[];
|
|
95
|
+
considered: number;
|
|
96
|
+
kept: number;
|
|
97
|
+
dropped: number;
|
|
98
|
+
unknown: number;
|
|
99
|
+
adjacent: number;
|
|
100
|
+
abundance?: CompoundColourAbundanceReceipt;
|
|
101
|
+
}
|
|
102
|
+
/** Why a hard form constraint returned a full or short page. */
|
|
103
|
+
export interface CompoundFormAbundanceReceipt {
|
|
104
|
+
grain: OpenEnum<"variant" | "product">;
|
|
105
|
+
requested: number;
|
|
106
|
+
eligible: number;
|
|
107
|
+
candidateWindow: number;
|
|
108
|
+
sourceExhausted: boolean;
|
|
109
|
+
state: OpenEnum<"filled" | "corpus_scarcity" | "evidence_unavailable" | "retrieval_window_exhausted">;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Hard form eligibility for a compound text query. Product and variant names
|
|
113
|
+
* may retrieve a candidate but never prove that it satisfies the form.
|
|
114
|
+
*/
|
|
115
|
+
export interface CompoundFormConstraintReceipt {
|
|
116
|
+
instruction: OpenEnum<"subway" | "plank" | "square" | "hexagon" | "penny-round">;
|
|
117
|
+
considered: number;
|
|
118
|
+
kept: number;
|
|
119
|
+
dropped: number;
|
|
120
|
+
contradicted: number;
|
|
121
|
+
unknown: number;
|
|
122
|
+
abundance: CompoundFormAbundanceReceipt;
|
|
123
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -49,6 +49,23 @@ function checkPaletteSwatch(value, what, fail) {
|
|
|
49
49
|
if (record.name !== undefined)
|
|
50
50
|
requireNullableString(record.name, `${what}.name`, fail);
|
|
51
51
|
}
|
|
52
|
+
/**
|
|
53
|
+
* `variants[]` — one entry of a product-collapsed result's ranked variant list
|
|
54
|
+
* (`collapsedVariantSchema`). A SLIM projection, not a nested result item: the
|
|
55
|
+
* checks here are the whole shape.
|
|
56
|
+
*/
|
|
57
|
+
function checkCollapsedVariant(value, what, fail) {
|
|
58
|
+
const record = requireRecord(value, what, fail);
|
|
59
|
+
requireString(record.variantId, `${what}.variantId`, fail);
|
|
60
|
+
requireNullableString(record.variantName, `${what}.variantName`, fail);
|
|
61
|
+
requireNullableString(record.color, `${what}.color`, fail);
|
|
62
|
+
// `.optional()`, NOT nullable: the emit path omits the key when no palette is
|
|
63
|
+
// on record rather than sending null.
|
|
64
|
+
requireOptionalString(record.hex, `${what}.hex`, fail);
|
|
65
|
+
requireNullableString(record.imageUrl, `${what}.imageUrl`, fail);
|
|
66
|
+
requireOptionalString(record.materialBankId, `${what}.materialBankId`, fail);
|
|
67
|
+
requireNumber(record.score, `${what}.score`, fail);
|
|
68
|
+
}
|
|
52
69
|
/** `colourMeta` — three independently optional strings. */
|
|
53
70
|
function checkColourMeta(value, what, fail) {
|
|
54
71
|
const record = requireRecord(value, what, fail);
|
|
@@ -192,6 +209,10 @@ export function checkSearchResultItem(value, what, fail) {
|
|
|
192
209
|
if (record.siblingCount !== undefined) {
|
|
193
210
|
requireIntegerAtLeast(record.siblingCount, `${what}.siblingCount`, fail, 1);
|
|
194
211
|
}
|
|
212
|
+
if (record.variants !== undefined) {
|
|
213
|
+
const variants = requireArray(record.variants, `${what}.variants`, fail);
|
|
214
|
+
variants.forEach((variant, index) => checkCollapsedVariant(variant, `${what}.variants[${index}]`, fail));
|
|
215
|
+
}
|
|
195
216
|
if (record.visualMeanings !== undefined) {
|
|
196
217
|
const meanings = requireArray(record.visualMeanings, `${what}.visualMeanings`, fail);
|
|
197
218
|
meanings.forEach((meaning, index) => checkVisualMeaning(meaning, `${what}.visualMeanings[${index}]`, fail));
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The bounded candidate window that produced a search page. */
|
|
2
|
+
export interface SearchWindowReceipt {
|
|
3
|
+
/** Versioned budget profile; interpret the remaining fields under this version. */
|
|
4
|
+
profile: "interactive-r1" | (string & {});
|
|
5
|
+
/** Candidate depth used by the final retrieval. */
|
|
6
|
+
candidateTier: number;
|
|
7
|
+
/** Every candidate retrieval, including required fallbacks and optional recovery. */
|
|
8
|
+
retrievalRounds: number;
|
|
9
|
+
/** Candidate-retrieval wall time only, in milliseconds. */
|
|
10
|
+
retrievalMs: number;
|
|
11
|
+
/** True when the serving source proved there were no more candidates. */
|
|
12
|
+
exhaustive: boolean;
|
|
13
|
+
/** True when product-grain scarcity caused one jump to the deep ceiling. */
|
|
14
|
+
deepened: boolean;
|
|
15
|
+
/** True when a still-short page exhausted its bounded recovery allowance. */
|
|
16
|
+
budgetExhausted: boolean;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/spec-types.d.ts
CHANGED
|
@@ -70,10 +70,16 @@ export interface SpecTermFilter {
|
|
|
70
70
|
* {@link CERTIFICATION_PROGRAMME_ATTRIBUTE_ID} (a programme is matched by name,
|
|
71
71
|
* never by bare presence).
|
|
72
72
|
*/
|
|
73
|
-
export
|
|
73
|
+
export type SpecPresenceFilter = {
|
|
74
74
|
attributeId: string;
|
|
75
75
|
hasValue: true;
|
|
76
76
|
}
|
|
77
|
+
/** Date-sensitive presence is currently executable only for EPD expiration. */
|
|
78
|
+
| {
|
|
79
|
+
attributeId: "epd_expiration_date";
|
|
80
|
+
hasValue: true;
|
|
81
|
+
asOf: string;
|
|
82
|
+
};
|
|
77
83
|
/**
|
|
78
84
|
* A certification-programme criterion — a {@link SpecTermFilter} pinned to the
|
|
79
85
|
* virtual {@link CERTIFICATION_PROGRAMME_ATTRIBUTE_ID}. Structurally assignable
|
package/types.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { BySpecVerdict } from "./by-spec-types.js";
|
|
|
5
5
|
* These interfaces intentionally have NO runtime dependency on any
|
|
6
6
|
* `@materialgraph/*` package — they are a standalone, publishable mirror of the
|
|
7
7
|
* shapes in `apps/web/public/openapi.yaml` and the captured fixtures under
|
|
8
|
-
* `
|
|
8
|
+
* `src/__tests__/fixtures/v0.5.0/`. The `contract-parity` test re-checks them
|
|
9
9
|
* against the real Zod schemas so the mirror cannot silently drift.
|
|
10
10
|
* TOLERANT-PARSING CONTRACT: the public surface declares open response enums —
|
|
11
11
|
* "clients must tolerate unknown enum values and unknown fields". Every union
|
|
@@ -30,8 +30,11 @@ import type { CorpusScopeReceipt } from "./corpus-scope-types.js";
|
|
|
30
30
|
import type { Cursor, ProductId, VariantId } from "./identifiers.js";
|
|
31
31
|
import type { MaterialDetail, MaterialTile } from "./material-types.js";
|
|
32
32
|
import type { QueryUnderstanding } from "./query-understanding-types.js";
|
|
33
|
+
import type { CollapsedVariant, SearchAnatomyMember } from "./search-collapse-types.js";
|
|
33
34
|
import type { SearchDisambiguation, SearchSuggestion } from "./search-refinement-types.js";
|
|
34
|
-
|
|
35
|
+
import type { CompoundColourConstraintReceipt, CompoundFormConstraintReceipt, SearchExecutionPlan, SearchMode, SearchRerankReport } from "./search-response-receipt-types.js";
|
|
36
|
+
import type { SearchWindowReceipt } from "./search-window-types.js";
|
|
37
|
+
export type * from "./search-response-receipt-types.js";
|
|
35
38
|
export type OpenEnum<T extends string> = T | (string & {});
|
|
36
39
|
/**
|
|
37
40
|
* A JSON value, recursively — exactly what survives a `jsonb` round-trip
|
|
@@ -105,15 +108,6 @@ export interface VisualMeaning {
|
|
|
105
108
|
version?: string;
|
|
106
109
|
appliedAt?: string;
|
|
107
110
|
}
|
|
108
|
-
/** One member of a collapsed result's {@link SearchResultItem.anatomy}. */
|
|
109
|
-
export interface SearchAnatomyMember {
|
|
110
|
-
/** Opaque — round-trip verbatim. */
|
|
111
|
-
variantId: VariantId;
|
|
112
|
-
variantName: string | null;
|
|
113
|
-
color: string | null;
|
|
114
|
-
score: number;
|
|
115
|
-
signals: SearchResultSignals;
|
|
116
|
-
}
|
|
117
111
|
/**
|
|
118
112
|
* One material in a search / match result list.
|
|
119
113
|
*
|
|
@@ -246,7 +240,10 @@ export interface SearchResultItem {
|
|
|
246
240
|
* `includeBelowFloor`.
|
|
247
241
|
*/
|
|
248
242
|
admittedOnColour?: boolean;
|
|
243
|
+
/** Variants HIDDEN behind this card by `collapse: "product"` — the COMPLETE tally, even when {@link variants} is capped. */
|
|
249
244
|
siblingCount?: number;
|
|
245
|
+
/** The product's matching variants, MOST RELEVANT FIRST — present exactly under `collapse: "product"`, capped, and led by the group's RANKING representative, which is NOT always this item. {@link CollapsedVariant} states the full contract. */
|
|
246
|
+
variants?: CollapsedVariant[];
|
|
250
247
|
visualMeanings?: VisualMeaning[];
|
|
251
248
|
/**
|
|
252
249
|
* The shared report card for this hit against the request's `filters` (required
|
|
@@ -389,14 +386,6 @@ export interface SearchRefinementReceipt {
|
|
|
389
386
|
schemaVersion: string;
|
|
390
387
|
projectionVersion: number;
|
|
391
388
|
}
|
|
392
|
-
/** The single candidate source a query resolved to. */
|
|
393
|
-
export type SearchMode = OpenEnum<"image" | "colour" | "text" | "lexical" | "entity-browse">;
|
|
394
|
-
/** Rerank-term report (absent in colour mode — there colour IS the source). */
|
|
395
|
-
export interface SearchRerankReport {
|
|
396
|
-
colour?: OpenEnum<"ok" | "failed" | "skipped">;
|
|
397
|
-
colourWeight?: number;
|
|
398
|
-
colourLabel?: string;
|
|
399
|
-
}
|
|
400
389
|
/**
|
|
401
390
|
* The search response envelope. `view` discriminates the `results` union:
|
|
402
391
|
* `"full"` (default) carries {@link SearchResultItem}s, `"card"` the lean
|
|
@@ -416,9 +405,14 @@ export interface SearchResponse {
|
|
|
416
405
|
suggestions: SearchSuggestion[];
|
|
417
406
|
mode: SearchMode;
|
|
418
407
|
maxScore: number;
|
|
419
|
-
/** Opaque keyset for the next page. Absent = end of the walk, not an error. */
|
|
420
408
|
cursor?: Cursor;
|
|
409
|
+
window?: SearchWindowReceipt;
|
|
421
410
|
rerank?: SearchRerankReport;
|
|
411
|
+
/** Hard compound eligibility and abundance receipts, when applied. */
|
|
412
|
+
colourConstraint?: CompoundColourConstraintReceipt;
|
|
413
|
+
formConstraint?: CompoundFormConstraintReceipt;
|
|
414
|
+
/** Explain-only receipt of the query shape and transform ledger that ran. */
|
|
415
|
+
plan?: SearchExecutionPlan;
|
|
422
416
|
counts?: SearchCounts;
|
|
423
417
|
/**
|
|
424
418
|
* The `#rrggbb` colours the colour signal ACTUALLY ran on, after
|
|
@@ -443,8 +437,9 @@ export interface SearchResponse {
|
|
|
443
437
|
/** A detected mood term overridden by a stronger colour reading. */
|
|
444
438
|
supersededMoodId?: string;
|
|
445
439
|
/**
|
|
446
|
-
* Present when the query had
|
|
447
|
-
*
|
|
440
|
+
* Present when the query had multiple defensible readings. Says which one
|
|
441
|
+
* ran, or leaves every reading non-default when the engine chose none. Every
|
|
442
|
+
* reading carries a complete executable replacement request.
|
|
448
443
|
*/
|
|
449
444
|
disambiguation?: SearchDisambiguation;
|
|
450
445
|
/** Structured receipt of the standard query-understanding decisions. */
|