@instruments/materialgraph 0.18.0 → 0.20.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.
Files changed (69) hide show
  1. package/association-types.d.ts +29 -4
  2. package/attribution-types.d.ts +51 -0
  3. package/attribution-types.js +13 -0
  4. package/browse-types.d.ts +14 -3
  5. package/by-colour-types.d.ts +33 -6
  6. package/by-spec-types.d.ts +4 -0
  7. package/catalogue-client.d.ts +54 -0
  8. package/catalogue-client.js +16 -0
  9. package/catalogue-types.d.ts +3 -1
  10. package/citation-types.d.ts +34 -0
  11. package/citation-types.js +1 -0
  12. package/client-browse.d.ts +1 -0
  13. package/client-browse.js +1 -0
  14. package/client-vocabulary.d.ts +10 -0
  15. package/client-vocabulary.js +32 -0
  16. package/client.d.ts +22 -45
  17. package/client.js +40 -55
  18. package/colours-client.d.ts +8 -3
  19. package/colours-client.js +8 -0
  20. package/composition-types.d.ts +6 -0
  21. package/corpus-scope-types.d.ts +1 -1
  22. package/errors.d.ts +1 -1
  23. package/errors.js +2 -0
  24. package/identify-types.d.ts +72 -0
  25. package/identify-types.js +7 -0
  26. package/index.d.ts +10 -0
  27. package/json-value-types.d.ts +8 -0
  28. package/json-value-types.js +1 -0
  29. package/match-stream-types.d.ts +13 -0
  30. package/match-types.d.ts +13 -0
  31. package/material-block-types.d.ts +4 -0
  32. package/material-resources-client.d.ts +3 -0
  33. package/material-resources-client.js +4 -0
  34. package/material-types.d.ts +24 -0
  35. package/operations.d.ts +1 -1
  36. package/operations.js +64 -2
  37. package/package.json +8 -1
  38. package/palette-completion-types.d.ts +115 -0
  39. package/palette-completion-types.js +1 -0
  40. package/palette-search-types.d.ts +16 -2
  41. package/render-assets-types.d.ts +65 -0
  42. package/render-assets-types.js +1 -0
  43. package/run-events.d.ts +13 -0
  44. package/samplize-catalogue-types.d.ts +92 -0
  45. package/samplize-catalogue-types.js +1 -0
  46. package/samplize-colorvec.d.ts +70 -0
  47. package/samplize-colorvec.js +167 -0
  48. package/schedule-reference-types.d.ts +46 -0
  49. package/schedule-reference-types.js +1 -0
  50. package/schedule-references-client.d.ts +14 -0
  51. package/schedule-references-client.js +26 -0
  52. package/schedule-types.d.ts +34 -0
  53. package/search-card-types.d.ts +53 -0
  54. package/search-card-types.js +1 -0
  55. package/search-mood-types.d.ts +6 -0
  56. package/search-mood-types.js +1 -0
  57. package/search-refinement-types.d.ts +5 -0
  58. package/search-request-types.d.ts +5 -0
  59. package/search-response-receipt-types.d.ts +8 -0
  60. package/search-result-validation.js +10 -0
  61. package/slot-pool-types.d.ts +2 -0
  62. package/spec-types.d.ts +6 -1
  63. package/specifications.d.ts +3 -1
  64. package/specifications.js +4 -0
  65. package/substitute-types.d.ts +102 -0
  66. package/substitute-types.js +1 -0
  67. package/taxonomy-coverage-types.d.ts +34 -0
  68. package/taxonomy-coverage-types.js +1 -0
  69. package/types.d.ts +42 -57
@@ -11,6 +11,7 @@
11
11
  * Present them as separate sections, and never describe a pairing as available.
12
12
  */
13
13
  import type { Cursor, VariantId } from "./identifiers.js";
14
+ import type { ProductTypeReceipt } from "./material-types.js";
14
15
  /**
15
16
  * Why an association is believed.
16
17
  *
@@ -42,8 +43,16 @@ export interface DeclaredAssociation {
42
43
  brand: string;
43
44
  product: string;
44
45
  variantName: string | null;
46
+ /** The role played by this endpoint of the declared edge. */
47
+ role: "finish" | "product";
48
+ /** The directed relationship asserted by the manufacturer. */
49
+ relation: "applicable_finish";
50
+ /** Accepted sampleability when known; absent means unknown. */
51
+ sampleable?: boolean;
45
52
  /** Canonical thumbnail; null when the variant has no eligible image. */
46
53
  imageUrl: string | null;
54
+ /** Review receipt; proposed types are never accepted categories. */
55
+ productTypeReceipt: ProductTypeReceipt;
47
56
  declared: DeclaredProvenance;
48
57
  }
49
58
  /**
@@ -77,12 +86,13 @@ export interface AssociatedOptions {
77
86
  */
78
87
  limit?: number;
79
88
  /**
80
- * Orderability scope. `material_bank` returns only associations pointing at a
81
- * variant carrying a Material Bank SKU — the ones a caller can actually
82
- * order. Today every visible variant carries one, so this currently removes
83
- * nothing; it tracks orderability rather than a snapshot of it.
89
+ * Source identity scope. `material_bank` returns associations pointing at a
90
+ * variant carrying a Material Bank SKU. A SKU alone does not establish current
91
+ * sampleability; use `sampleableOnly` for an accepted availability fact.
84
92
  */
85
93
  corpus?: "all" | "material_bank";
94
+ /** Return only associations whose effective sampleability is true. */
95
+ sampleableOnly?: boolean;
86
96
  /**
87
97
  * The previous response's `nextCursor`, passed back verbatim. A cursor is
88
98
  * bound to its subject, direction and corpus — replaying it against a
@@ -134,6 +144,21 @@ export interface ApplicabilitySourceEntry {
134
144
  factRevisions: string[];
135
145
  /** Active facts from this source only. */
136
146
  facts: ApplicabilityFact[];
147
+ /** Source endpoints that could not be resolved during reconciliation. */
148
+ unresolved: UnresolvedApplicabilityEndpoint[];
149
+ }
150
+ export interface UnresolvedApplicabilityEndpoint {
151
+ subjectLocator: string;
152
+ subjectKind: "product" | "variant" | "unknown";
153
+ finishLocator: string;
154
+ finishKind: "variant" | "unknown";
155
+ reason: "subject_unresolved" | "finish_unresolved" | "both_unresolved" | "unsupported_subject_kind";
156
+ declaringBrandId: string | null;
157
+ source: {
158
+ authority: string;
159
+ locator: string;
160
+ revision: string;
161
+ };
137
162
  }
138
163
  /** Source-grained response; sources are never merged or given hidden precedence. */
139
164
  export interface ApplicabilityResponse {
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Result attribution (MG-1131) — joining an outcome back to the ranking that
3
+ * produced it.
4
+ *
5
+ * When someone orders a sample days after a search, a list of SKUs cannot say
6
+ * which response returned it or on what basis it was ranked. Store
7
+ * {@link SearchResultItem.resultId} next to the order row and
8
+ * {@link ResponseAttribution} beside the search, and both questions become a
9
+ * join in your own warehouse.
10
+ *
11
+ * MaterialGraph keeps no ledger of these ids. What you store IS the record.
12
+ */
13
+ /**
14
+ * The ranking basis, in one vocabulary across both ranked routes.
15
+ *
16
+ * The first five values are `search()`'s `mode` verbatim, and there
17
+ * `attribution.basis === mode` always. `"match"` is what `match()` reports;
18
+ * that route has no `mode`, so this is the only field its outcomes can be
19
+ * grouped by.
20
+ */
21
+ export type AttributionBasis = "image" | "colour" | "text" | "lexical" | "entity-browse" | "match";
22
+ /**
23
+ * Envelope-level attribution receipt, on every successful ranked response.
24
+ *
25
+ * Store this beside the search and each result's `resultId` beside the outcome
26
+ * (an order, a save, a click), and "which sample was ordered off which ranking,
27
+ * on what basis" becomes a join in your own warehouse.
28
+ *
29
+ * A `resultId` is `<responseId>:<rank>`, rank being 1-based within the response
30
+ * that returned it — unique across pages, because each page is its own
31
+ * response. On the Match stream lane it also carries the surface id, so a hit
32
+ * sent twice (on its `surface` frame and again inside `complete`) keeps one key.
33
+ *
34
+ * Both ids are OPAQUE: store them verbatim, never parse them. Group on
35
+ * `responseId` and `basis`.
36
+ *
37
+ * Both fields are optional in the SDK types for one reason only: a server
38
+ * predating MG-1131 does not send them. Every current response does.
39
+ */
40
+ export interface ResponseAttribution {
41
+ /**
42
+ * This response's stable id — the same value as the `X-Request-Id` header.
43
+ * Opaque: store it verbatim, never parse it. Group your stored outcomes by
44
+ * this field to recover the response that produced them.
45
+ */
46
+ responseId: string;
47
+ /** How this ranking was produced. The field to group outcomes by. */
48
+ basis: AttributionBasis;
49
+ /** ISO-8601 timestamp of when the response was assembled. */
50
+ issuedAt: string;
51
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Result attribution (MG-1131) — joining an outcome back to the ranking that
3
+ * produced it.
4
+ *
5
+ * When someone orders a sample days after a search, a list of SKUs cannot say
6
+ * which response returned it or on what basis it was ranked. Store
7
+ * {@link SearchResultItem.resultId} next to the order row and
8
+ * {@link ResponseAttribution} beside the search, and both questions become a
9
+ * join in your own warehouse.
10
+ *
11
+ * MaterialGraph keeps no ledger of these ids. What you store IS the record.
12
+ */
13
+ export {};
package/browse-types.d.ts CHANGED
@@ -26,6 +26,8 @@ export interface BrowseResultItem {
26
26
  productId: ProductId | null;
27
27
  color: string | null;
28
28
  variantName: string | null;
29
+ /** MaterialGraph record creation time, not a manufacturer release date. */
30
+ recordCreatedAt: string | null;
29
31
  imageUrl: string | null;
30
32
  scalars: {
31
33
  l: number | null;
@@ -165,11 +167,20 @@ export interface BrowseParams {
165
167
  */
166
168
  types?: string;
167
169
  /**
168
- * Comma-separated brand slugs (`farrow-ball`) or display names
169
- * (`Farrow & Ball`), case-insensitive. One brand plus a colour `sort` is that
170
- * brand's fan deck. An unknown brand is a 400 naming it, never an empty page.
170
+ * Comma-separated canonical brand ids, exact slugs (`farrow-ball`), or exact
171
+ * display names (`Farrow & Ball`). Canonical ids and slugs are case-sensitive
172
+ * and opaque; display names are case-insensitive. One brand plus a colour `sort` is that brand's
173
+ * fan deck. An unknown brand is a typed 400 naming it, and an exact display
174
+ * name shared by multiple brands is a typed 400 with the candidates; neither
175
+ * becomes an empty page.
171
176
  */
172
177
  brands?: string;
178
+ /**
179
+ * Positive manufacturer declarations. accepts_finishes includes variants of
180
+ * product-level declarations; it does not assert variant-specific applicability.
181
+ * Absence means no role filter.
182
+ */
183
+ role?: "finish" | "accepts_finishes";
173
184
  /**
174
185
  * Typed attribute filters, in the SAME grammar `search` takes — a term, a
175
186
  * term SET (OR within the entry), a presence check or a numeric range, each
@@ -99,6 +99,15 @@ export interface ColourFamilyGate {
99
99
  * once the page is cut to `limit`; this is the gate's own cost.
100
100
  */
101
101
  dropped: number;
102
+ /**
103
+ * Rows dropped a SECOND time, after the page was hydrated with the brand's
104
+ * declared `colour_hex`. A paint's chip photograph and its published hex are
105
+ * different colours and can fall in different families, so the page is
106
+ * re-gated on the hex it reports — every `hex` you receive belongs to the
107
+ * family you asked for. Absent means hydration moved nothing across a
108
+ * boundary.
109
+ */
110
+ droppedOnPublishedHex?: number;
102
111
  }
103
112
  /** Receipt for the hard category gate and its treatment of unknown typing. */
104
113
  export interface ColourCategoryGate {
@@ -169,12 +178,17 @@ export interface ByColourResponse {
169
178
  colours: string[];
170
179
  categories?: string[];
171
180
  /**
172
- * Echoed brand filter as resolved SLUGS — what the names you passed
173
- * resolved to. Present only when a brand scope applied.
181
+ * Echoed brand filter as resolved SLUGS — what the canonical ids, slugs,
182
+ * or exact names you passed resolved to. Present only when a brand scope
183
+ * applied.
174
184
  */
175
185
  brands?: string[];
176
186
  /** Echoed `family` filter, normalised. Present only when one was applied. */
177
187
  family?: string;
188
+ /** Applied single-colour containment order. */
189
+ order?: "representative" | "nearest";
190
+ /** Applied maximum OKLab distance to each reported match hex. */
191
+ maxColourDistance?: number;
178
192
  oklab?: OklabTriple;
179
193
  };
180
194
  /** `matches.length` — THIS PAGE. Not a corpus total; this surface states none. */
@@ -186,6 +200,12 @@ export interface ByColourResponse {
186
200
  * what says so in counts rather than adjectives.
187
201
  */
188
202
  familyGate?: ColourFamilyGate;
203
+ /** Applied `maxColourDistance` threshold and its page-bounded drop count. */
204
+ proximityGate?: {
205
+ maxColourDistance: number;
206
+ considered: number;
207
+ dropped: number;
208
+ };
189
209
  /**
190
210
  * Present only when `category` was asked for. It states that variants without
191
211
  * an accepted primary product type were excluded by the hard gate; absence
@@ -230,8 +250,10 @@ export interface ByColourParams {
230
250
  /** HARD category filter — display names or taxonomy ids (repeatable). */
231
251
  category?: string | string[];
232
252
  /**
233
- * HARD brand filter (repeatable) — a brand SLUG (`sherwin-williams`) or its
234
- * display name (`Sherwin-Williams`), case-insensitive.
253
+ * HARD brand filter (repeatable) — a canonical brand id, exact brand SLUG
254
+ * (`sherwin-williams`), or exact display name (`Sherwin-Williams`). Canonical
255
+ * ids and slugs are case-sensitive and opaque; display names are
256
+ * case-insensitive.
235
257
  *
236
258
  * This is how the CROSS-BRAND question is asked: pass one brand's colour as
237
259
  * `hex` and scope to another to get that brand's nearest colours to it. It is
@@ -239,8 +261,9 @@ export interface ByColourParams {
239
261
  * filtering a returned page instead comes back short, because a
240
262
  * nearest-neighbour scan does not know to look further.
241
263
  *
242
- * An unknown brand is a 400 naming it, never an empty page. Omitting it (or
243
- * passing an empty list) searches every brand.
264
+ * An unknown brand is a typed 400 naming it, and an exact display name shared
265
+ * by multiple brands is a typed 400 with the candidates; neither becomes an
266
+ * empty page. Omitting it (or passing an empty list) searches every brand.
244
267
  */
245
268
  brand?: string | string[];
246
269
  /**
@@ -260,6 +283,10 @@ export interface ByColourParams {
260
283
  * drop.
261
284
  */
262
285
  family?: string;
286
+ /** Single-colour order; omitted keeps representative browsing order. */
287
+ order?: "representative" | "nearest";
288
+ /** Maximum OKLab distance to each match's reported hex. Single-colour only. */
289
+ maxColourDistance?: number;
263
290
  /** Narrow retrieval inside the server query; absent means the whole graph. */
264
291
  corpusScope?: CorpusScope;
265
292
  limit?: number;
@@ -1,4 +1,5 @@
1
1
  import type { ValueResolution } from "./catalog-discovery-types.js";
2
+ import type { VerdictCitation } from "./citation-types.js";
2
3
  import type { VariantId } from "./identifiers.js";
3
4
  /**
4
5
  * One criterion a match satisfied, with the trust behind it.
@@ -71,6 +72,7 @@ export interface BySpecVerdictCell {
71
72
  * - `proposed` — the value is awaiting acceptance and is not yet on record.
72
73
  */
73
74
  trustGap: "below_confidence" | "basis_unmet" | "proposed" | null;
75
+ citation?: VerdictCitation;
74
76
  }
75
77
  /**
76
78
  * A match's full report card: every cell, the rolled-up grade, weakest confidence.
@@ -131,6 +133,8 @@ export interface BySpecUnresolvedCriterion {
131
133
  attributeId: string;
132
134
  /** The parsed value — never overwritten by the attribute id when that id is unknown. */
133
135
  value: string;
136
+ /** Why pre-flight declined it; absent on responses captured before classification. */
137
+ reason?: "unknown_attribute_or_term" | "not_a_specification";
134
138
  /** Ranked candidates for whichever half failed. See {@link ValueResolution}. */
135
139
  resolution: ValueResolution;
136
140
  }
@@ -1,10 +1,64 @@
1
1
  import type { CatalogDocumentList, CatalogPageListResult, CatalogProductReferenceReadResult, CatalogueChannelCollectionsResponse, CatalogueCollectionsOptions, CatalogueDocumentAccessResult, CataloguePageRepresentationReadResult, CatalogueReferenceBatchResponse } from "./catalogue-types.js";
2
2
  import type { HttpTransport } from "./http-transport.js";
3
3
  import type { VariantId } from "./identifiers.js";
4
+ import type { IdentifySelectedPageInput, IdentifySelectedPageResult } from "./identify-types.js";
5
+ import type { SamplizeCatalogueOptions, SamplizeCataloguePage } from "./samplize-catalogue-types.js";
6
+ import type { SamplizeColorVecCache } from "./samplize-colorvec.js";
4
7
  /** Catalogue publication operations inherited by the public SDK client. */
5
8
  export declare class CatalogueClient {
6
9
  #private;
7
10
  protected constructor(transport: HttpTransport);
11
+ /** Identify the canonical graph subject for one explicitly selected page. */
12
+ identify(input: IdentifySelectedPageInput, signal?: AbortSignal): Promise<IdentifySelectedPageResult>;
13
+ /** Complete producer-owned vectors and classifications for portable colour matching. */
14
+ samplizeColorVecCache(sourceVersion: string, signal?: AbortSignal): Promise<SamplizeColorVecCache>;
15
+ /** MG-owned full-catalogue facets and directional colour refinement before page limiting. */
16
+ samplizeCatalogueSearch(input: {
17
+ palette?: Array<{
18
+ hex: string;
19
+ proportion: number;
20
+ }>;
21
+ query?: string;
22
+ reference?: string;
23
+ direction?: "similar" | "lighter" | "darker" | "muted";
24
+ lightnessMin?: number;
25
+ lightnessMax?: number;
26
+ temperatureMin?: number;
27
+ temperatureMax?: number;
28
+ family?: string[];
29
+ lightness?: string[];
30
+ intensity?: string[];
31
+ brand?: string[];
32
+ sourceVersion: string;
33
+ limit?: number;
34
+ }, signal?: AbortSignal): Promise<{
35
+ target?: {
36
+ ref: string;
37
+ hex: string;
38
+ name?: string;
39
+ source: string;
40
+ confidence?: number;
41
+ };
42
+ embeddingVersion?: string;
43
+ rankingVersion?: string;
44
+ dictionaryVersion?: string;
45
+ eligibleCount?: number;
46
+ groups?: Array<{
47
+ hex: string;
48
+ proportion: number;
49
+ quota: number;
50
+ ids: string[];
51
+ shortfall: number;
52
+ }>;
53
+ ids: string[];
54
+ limited: boolean;
55
+ sourceVersion: string;
56
+ counts: Record<string, Record<string, number>>;
57
+ countBasis: string;
58
+ basis: string;
59
+ }>;
60
+ /** Complete version-pinned Samplize paint corpus; stock never limits eligibility. */
61
+ samplizeCatalogue(options?: SamplizeCatalogueOptions, signal?: AbortSignal): Promise<SamplizeCataloguePage>;
8
62
  /**
9
63
  * Read exact, verified brand-publication page relationships for variants.
10
64
  * Missing evidence stays explicit; this operation never guesses a page from
@@ -5,6 +5,22 @@ export class CatalogueClient {
5
5
  constructor(transport) {
6
6
  this.#transport = transport;
7
7
  }
8
+ /** Identify the canonical graph subject for one explicitly selected page. */
9
+ identify(input, signal) {
10
+ return this.#transport.requestJson(resolveOperation("retrieval.identify"), { body: input, signal });
11
+ }
12
+ /** Complete producer-owned vectors and classifications for portable colour matching. */
13
+ samplizeColorVecCache(sourceVersion, signal) {
14
+ return this.#transport.requestJson(resolveOperation("samplize_colorvec_cache"), { query: { sourceVersion }, signal });
15
+ }
16
+ /** MG-owned full-catalogue facets and directional colour refinement before page limiting. */
17
+ samplizeCatalogueSearch(input, signal) {
18
+ return this.#transport.requestJson(resolveOperation("samplize_catalogue_search"), { body: input, signal });
19
+ }
20
+ /** Complete version-pinned Samplize paint corpus; stock never limits eligibility. */
21
+ samplizeCatalogue(options = {}, signal) {
22
+ return this.#transport.requestJson(resolveOperation("samplize_catalogue_products"), { query: { ...options }, signal });
23
+ }
8
24
  /**
9
25
  * Read exact, verified brand-publication page relationships for variants.
10
26
  * Missing evidence stays explicit; this operation never guesses a page from
@@ -2,6 +2,8 @@
2
2
  export interface CatalogueReference {
3
3
  anchor: {
4
4
  coordinateSpace: "normalized_0_1000";
5
+ /** Page carrying the printed code; defaults to page.documentPage. Do not draw it on another page. */
6
+ documentPage?: number;
5
7
  height: number;
6
8
  kind: "printed_code";
7
9
  width: number;
@@ -53,7 +55,7 @@ export interface CatalogueReference {
53
55
  brandItemCode: string;
54
56
  };
55
57
  status: "verified";
56
- isPrimary: true;
58
+ isPrimary: boolean;
57
59
  }
58
60
  export type CatalogueReferenceResult = {
59
61
  variantId: string;
@@ -0,0 +1,34 @@
1
+ /** Small handle carried by a verdict cell. Resolve it only when evidence is opened. */
2
+ export interface VerdictCitation {
3
+ citationId: string;
4
+ sourceType: string;
5
+ count: number;
6
+ }
7
+ export interface ResolvedVerdictCitation {
8
+ citationId: string;
9
+ sourceType: string;
10
+ source: {
11
+ kind: "source_record" | "source_material" | "source_fact" | "url" | "asset" | "download" | "manual_note" | "agent_output";
12
+ /** Canonical source/fact/asset/download id, a public source URL, or the claim-source handle when no public reference is available. */
13
+ ref: string;
14
+ title?: string;
15
+ url?: string;
16
+ /** Same-origin public asset proxy path when retained bytes are available. */
17
+ publicPath?: string;
18
+ sourceId?: string;
19
+ sourceFactId?: string;
20
+ sourceAssetId?: string;
21
+ sourceDownloadId?: string;
22
+ locator?: {
23
+ page?: number;
24
+ selector?: string;
25
+ xPath?: string;
26
+ imageBox?: {
27
+ x: number;
28
+ y: number;
29
+ width: number;
30
+ height: number;
31
+ };
32
+ };
33
+ };
34
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -52,6 +52,7 @@ export declare function browseQuery(params: BrowseParams): {
52
52
  count: BrowseParams["count"];
53
53
  types: BrowseParams["types"];
54
54
  brands: BrowseParams["brands"];
55
+ role: BrowseParams["role"];
55
56
  filters: string[] | undefined;
56
57
  facetCounts: string | undefined;
57
58
  corpusScope: BrowseParams["corpusScope"];
package/client-browse.js CHANGED
@@ -28,6 +28,7 @@ export function browseQuery(params) {
28
28
  count: params.count,
29
29
  types: params.types,
30
30
  brands: params.brands,
31
+ role: params.role,
31
32
  filters: params.filters?.map((entry) => JSON.stringify(entry)),
32
33
  facetCounts: params.facetCounts?.join(","),
33
34
  corpusScope: params.corpusScope,
@@ -0,0 +1,10 @@
1
+ import { HttpTransport } from "./http-transport.js";
2
+ import type { ColourFacetsResponse, ResolveAttributeOptions, ResolveAttributeResponse, ResolveAttributeValueOptions, ResolveAttributeValueResponse, ResolveColourResponse, SuggestColourResponse, SuggestOptions, SuggestResponse } from "./types.js";
3
+ export declare function colourFacets(transport: HttpTransport, signal?: AbortSignal): Promise<ColourFacetsResponse>;
4
+ export declare function resolveColour(transport: HttpTransport, name: string, signal?: AbortSignal): Promise<ResolveColourResponse>;
5
+ export declare function suggestColour(transport: HttpTransport, q: string, options?: {
6
+ limit?: number;
7
+ }, signal?: AbortSignal): Promise<SuggestColourResponse>;
8
+ export declare function suggest(transport: HttpTransport, q: string, options?: SuggestOptions, signal?: AbortSignal): Promise<SuggestResponse>;
9
+ export declare function resolveAttribute(transport: HttpTransport, q: string, options?: ResolveAttributeOptions, signal?: AbortSignal): Promise<ResolveAttributeResponse>;
10
+ export declare function resolveAttributeValue(transport: HttpTransport, attributeId: string, query: string, options?: ResolveAttributeValueOptions, signal?: AbortSignal): Promise<ResolveAttributeValueResponse>;
@@ -0,0 +1,32 @@
1
+ import { HttpTransport } from "./http-transport.js";
2
+ import { resolveOperation } from "./operations.js";
3
+ import { suggestQuery } from "./suggest-types.js";
4
+ export function colourFacets(transport, signal) {
5
+ return transport.requestJson(resolveOperation("get_colour_facets"), { signal });
6
+ }
7
+ export function resolveColour(transport, name, signal) {
8
+ return transport.requestJson(resolveOperation("resolve_colour_name"), { query: { name }, signal });
9
+ }
10
+ export function suggestColour(transport, q, options, signal) {
11
+ return transport.requestJson(resolveOperation("suggest_colour_names"), { query: { q, limit: options?.limit }, signal });
12
+ }
13
+ export function suggest(transport, q, options, signal) {
14
+ return transport.requestJson(resolveOperation("search_suggest"), { query: suggestQuery(q, options), signal });
15
+ }
16
+ export function resolveAttribute(transport, q, options, signal) {
17
+ return transport.requestJson(resolveOperation("catalog_resolve_attribute"), {
18
+ query: {
19
+ q,
20
+ limit: options?.limit,
21
+ facetableOnly: options?.facetableOnly,
22
+ },
23
+ signal,
24
+ });
25
+ }
26
+ export function resolveAttributeValue(transport, attributeId, query, options, signal) {
27
+ return transport.requestJson(resolveOperation("catalog_resolve_value"), {
28
+ query: { q: query, limit: options?.limit },
29
+ pathParams: { attributeId },
30
+ signal,
31
+ });
32
+ }
package/client.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { CatalogueClient } from "./catalogue-client.js";
2
2
  import type { MaterialGraphClientOptions } from "./client-config.js";
3
3
  import { type RateLimit } from "./errors.js";
4
+ import { ScheduleReferencesClient } from "./schedule-references-client.js";
4
5
  export * from "./client-config.js";
5
6
  import { type BrowseNamespace } from "./client-browse.js";
6
7
  import { type ExplorationNamespace } from "./client-exploration.js";
@@ -11,6 +12,7 @@ export type { SourceMaterialCommentsNamespace } from "./client-source-material-c
11
12
  import type { ApplicabilityOptions, AssociatedOptions } from "./association-types.js";
12
13
  import type { BrandsOptions } from "./brand-types.js";
13
14
  import type { ByColourParams, ByColourResponse } from "./by-colour-types.js";
15
+ import type { ResolvedVerdictCitation } from "./citation-types.js";
14
16
  import { CodesClient } from "./codes-client.js";
15
17
  import type { CodeAdvisoryInput, CodeAdvisoryResponse } from "./codes-types.js";
16
18
  import { ColoursClient } from "./colours-client.js";
@@ -26,6 +28,8 @@ import type { CapabilityManifestResponse, CreatePublicRunRequest, CreatePublicRu
26
28
  import type { FinishScheduleResponse, GetRunScheduleOptions } from "./schedule-types.js";
27
29
  import type { SchemaResource, SchemaResourceResponse } from "./schema-resource-types.js";
28
30
  import type { SlotPoolsRequest, SlotPoolsResponse } from "./slot-pool-types.js";
31
+ import type { FindSubstitutesOptions, FindSubstitutesResponse } from "./substitute-types.js";
32
+ import type { ProductTypeCoverageOptions, ProductTypeStatusCoverage } from "./taxonomy-coverage-types.js";
29
33
  import type { ApplicableSpecsResponse, BrandOptions, BySpecOptions, BySpecResponse, ColourFacetsResponse, CoordinateInput, CoordinateResponse, DemandBatchInput, DemandBatchResponse, DemandParams, DemandResponse, ExtractPaletteInput, ExtractPaletteResponse, GlossaryTermResponse, MaterialResponse, MaterialsBatchDetailResponse, MaterialsBatchGetOptions, MaterialsBatchOptions, MaterialsBatchTileResponse, PairingsOptions, PairingsResponse, ResolveAttributeOptions, ResolveAttributeResponse, ResolveAttributeValueOptions, ResolveAttributeValueResponse, ResolveColourResponse, SearchGetParams, SearchInput, SearchResponse, SiblingsResponse, SpecFacetsDistributionResponse, SpecFacetsListResponse, SuggestColourResponse, SuggestOptions, SuggestResponse, TaxonomyResponse, VocabularySearchOptions, WhoamiResponse } from "./types.js";
30
34
  /**
31
35
  * The MaterialGraph client — every lens on the graph, on one object.
@@ -64,6 +68,7 @@ import type { ApplicableSpecsResponse, BrandOptions, BySpecOptions, BySpecRespon
64
68
  */
65
69
  export declare class MaterialGraphClient extends CatalogueClient {
66
70
  #private;
71
+ readonly scheduleReferences: ScheduleReferencesClient;
67
72
  readonly baseUrl: string;
68
73
  /**
69
74
  * THE QUESTION: "show me everything in this category / this brand, in a plain
@@ -218,6 +223,7 @@ export declare class MaterialGraphClient extends CatalogueClient {
218
223
  siblings(variantId: VariantId, signal?: AbortSignal): Promise<SiblingsResponse>;
219
224
  materialBlocks(variantId: VariantId, signal?: AbortSignal): Promise<import("./material-block-types.js").MaterialBlockProjection>;
220
225
  materialAssets(variantId: VariantId, signal?: AbortSignal): Promise<import("./material-asset-types.js").MaterialAssetProjection>;
226
+ materialRenderAssets(variantId: VariantId, signal?: AbortSignal): Promise<import("./render-assets-types.js").MaterialRenderAssets>;
221
227
  materialDocuments(variantId: VariantId, options?: MaterialDocumentPageOptions, signal?: AbortSignal): Promise<import("./material-asset-types.js").MaterialDocumentPage>;
222
228
  /**
223
229
  * THE QUESTION: "what does the schema DEFINE?" — the governed static registry.
@@ -238,10 +244,12 @@ export declare class MaterialGraphClient extends CatalogueClient {
238
244
  *
239
245
  * READ `item.source` BEFORE PHRASING: the rail mixes three tiers of evidence —
240
246
  * `cospec` (real orders), `considered` (board activity), `colour` (palette
241
- * look-alike). Only `cospec` supports "specified together". `cospecCount` tells
247
+ * look-alike). Only `cospec` supports "sampled together". `cospecCount` tells
242
248
  * you how much of the rail is real order evidence.
243
249
  */
244
250
  pairings(variantId: VariantId, options?: PairingsOptions, signal?: AbortSignal): Promise<PairingsResponse>;
251
+ /** Find bounded, exact-spec substitutes for one opaque variant id. */
252
+ findSubstitutes(variantId: VariantId, options?: FindSubstitutesOptions, signal?: AbortSignal): Promise<FindSubstitutesResponse>;
245
253
  /** "What finishes does the manufacturer declare for THIS product?" — {@link declaredFinishes}. */
246
254
  associatedFinishes(variantId: VariantId, options?: AssociatedOptions, signal?: AbortSignal): Promise<import("./association-types.js").DeclaredAssociationsResponse>;
247
255
  /** "What products does the manufacturer declare THIS finish for?" — {@link declaredProducts}. */
@@ -277,58 +285,19 @@ export declare class MaterialGraphClient extends CatalogueClient {
277
285
  view?: "tile";
278
286
  idKind?: MaterialsBatchGetOptions["idKind"];
279
287
  }, signal?: AbortSignal): Promise<MaterialsBatchTileResponse>;
280
- /**
281
- * THE QUESTION: "what colour WORDS may I use?" — family, mood and undertone
282
- * with live counts. Vocabulary, not values: instead use `colours.profiles()`
283
- * for a category's palette, {@link MaterialGraphClient.byColour} to search by a
284
- * colour, {@link MaterialGraphClient.resolveColour} to turn a NAME into a hex.
285
- */
288
+ /** Vocabulary families and counts; use `colours.profiles()` for a material palette. */
286
289
  colourFacets(signal?: AbortSignal): Promise<ColourFacetsResponse>;
287
- /**
288
- * THE QUESTION: "what hex is 'Hague Blue'?" — the step before
289
- * {@link MaterialGraphClient.byColour} when you hold a name rather than a hex.
290
- * A `null` match means unrecognised, not "no such colour".
291
- */
290
+ /** Resolve a colour name to its canonical hex when recognised. */
292
291
  resolveColour(name: string, signal?: AbortSignal): Promise<ResolveColourResponse>;
293
292
  /** Ranked colour-name typeahead (GET `/api/v1/search/colours/suggest`). */
294
293
  suggestColour(q: string, options?: {
295
294
  limit?: number;
296
295
  }, signal?: AbortSignal): Promise<SuggestColourResponse>;
297
- /**
298
- * THE QUESTION: "what is the user starting to type?" It ranks NAMES, not
299
- * materials — instead use {@link MaterialGraphClient.search} once they commit,
300
- * {@link MaterialGraphClient.suggestColour} for colour names, and
301
- * {@link MaterialGraphClient.searchVocabulary} for attribute/value tokens.
302
- *
303
- * Entity typeahead across products, brands and categories
304
- * (GET `/api/v1/search/suggest`). Built for per-keystroke use: one indexed
305
- * lookup, no embedding call and no model. Every suggestion carries the
306
- * `refId` it resolves to — a product id, a brand slug, or a product-type key
307
- * — so selecting one should navigate to that entity rather than re-running
308
- * `label` as a search.
309
- *
310
- * @example
311
- * const { suggestions } = await client.suggest("carr", { kind: "product" });
312
- */
296
+ /** Entity typeahead. Navigate using the selected `refId`; use `search()` for materials. */
313
297
  suggest(q: string, options?: SuggestOptions, signal?: AbortSignal): Promise<SuggestResponse>;
314
- /**
315
- * THE QUESTION: "the user said 'fire rating' — which canonical attribute is
316
- * that?" Free text in, canonical `attributeId`s out; pair with
317
- * {@link MaterialGraphClient.resolveAttributeValue} for the VALUE, then spend
318
- * the pair on {@link MaterialGraphClient.bySpec} or `search({ filters })`.
319
- * Instead use {@link MaterialGraphClient.specificationFacets} to browse rather
320
- * than resolve.
321
- */
298
+ /** Resolve free text to a canonical attribute id. */
322
299
  resolveAttribute(q: string, options?: ResolveAttributeOptions, signal?: AbortSignal): Promise<ResolveAttributeResponse>;
323
- /**
324
- * THE QUESTION: "the user said 'class A' — what canonical term is that, under
325
- * THIS attribute?" The value half of the pair
326
- * {@link MaterialGraphClient.resolveAttribute} starts. Read
327
- * `resolution.recommendedAction`, not just `best`: `ambiguous` means ask.
328
- *
329
- * @param attributeId Canonical vocabulary, not an opaque id — discover it, do
330
- * not invent it.
331
- */
300
+ /** Resolve a value under a canonical attribute id; inspect `recommendedAction` for ambiguity. */
332
301
  resolveAttributeValue(attributeId: string, query: string, options?: ResolveAttributeValueOptions, signal?: AbortSignal): Promise<ResolveAttributeValueResponse>;
333
302
  /** "Is this phrase an attribute or a value?" — see {@link searchVocabularyRequest}. */
334
303
  searchVocabulary(query: string, options?: VocabularySearchOptions, signal?: AbortSignal): Promise<import("./catalog-discovery-types.js").VocabularySearchResponse>;
@@ -364,6 +333,12 @@ export declare class MaterialGraphClient extends CatalogueClient {
364
333
  * {@link MaterialGraphClient.applicableSpecs}). Discover, never hand-write.
365
334
  */
366
335
  taxonomy(signal?: AbortSignal): Promise<TaxonomyResponse>;
336
+ /**
337
+ * Exact current primary-type status counts by retained source category path.
338
+ * `comparisonThreshold` is a reporting cutoff only: it never promotes a
339
+ * proposal into an accepted category.
340
+ */
341
+ productTypeCoverage(options?: ProductTypeCoverageOptions, signal?: AbortSignal): Promise<ProductTypeStatusCoverage>;
367
342
  /**
368
343
  * THE QUESTION: "what is this key allowed to do?" Check `scopes` before
369
344
  * offering a capability: the write surfaces need `mg:ingest` / `mg:compose`,
@@ -535,6 +510,8 @@ export declare class MaterialGraphClient extends CatalogueClient {
535
510
  * `GET /api/v1/runs/{runId}/schedule.xlsx` with the same bearer key.
536
511
  */
537
512
  runSchedule(runId: RunId, options?: GetRunScheduleOptions): Promise<FinishScheduleResponse>;
513
+ /** Follow a verdict cell's citation handle to its canonical claim source. */
514
+ citation(citationId: string, signal?: AbortSignal): Promise<ResolvedVerdictCitation>;
538
515
  /**
539
516
  * Resume a suspended Run (POST `/api/v1/runs/{runId}/resume`).
540
517
  *