@instruments/materialgraph 0.10.0 → 0.11.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 (42) hide show
  1. package/browse-types.d.ts +147 -0
  2. package/browse-types.js +1 -0
  3. package/by-colour-types.d.ts +56 -0
  4. package/client-browse.d.ts +13 -3
  5. package/client-browse.js +12 -2
  6. package/client-exploration.d.ts +9 -0
  7. package/client-exploration.js +7 -0
  8. package/client-source-material-comments.d.ts +51 -0
  9. package/client-source-material-comments.js +40 -0
  10. package/client.d.ts +28 -22
  11. package/client.js +33 -24
  12. package/colour-aggregate-types.d.ts +58 -0
  13. package/colours-client.d.ts +8 -2
  14. package/colours-client.js +15 -2
  15. package/composition-client.d.ts +33 -0
  16. package/composition-client.js +27 -0
  17. package/composition-types.d.ts +46 -0
  18. package/coordinate-client.d.ts +23 -0
  19. package/coordinate-client.js +25 -0
  20. package/exploration-types.d.ts +110 -0
  21. package/exploration-types.js +1 -0
  22. package/fan-deck-types.d.ts +4 -1
  23. package/index.d.ts +4 -1
  24. package/operations.d.ts +1 -1
  25. package/operations.js +25 -0
  26. package/package.json +1 -1
  27. package/palette-search-types.d.ts +31 -0
  28. package/run-types.d.ts +132 -0
  29. package/runs.d.ts +35 -1
  30. package/runs.js +61 -1
  31. package/schedule-types.d.ts +128 -0
  32. package/schema-resource-types.d.ts +1 -1
  33. package/search-refinement-types.d.ts +28 -1
  34. package/search-request-types.d.ts +172 -0
  35. package/search-request-types.js +1 -0
  36. package/slot-pool-types.d.ts +370 -0
  37. package/slot-pool-types.js +1 -0
  38. package/source-material-validation.d.ts +5 -1
  39. package/source-material-validation.js +111 -4
  40. package/types.d.ts +149 -199
  41. package/validation.d.ts +12 -0
  42. package/validation.js +23 -0
@@ -88,6 +88,43 @@ export interface ColourStatsGroup {
88
88
  productTypes: number;
89
89
  variants: number;
90
90
  }
91
+ /**
92
+ * One cell of the brand x category x colour-family matrix — the shape that
93
+ * answers questions no single dimension can, such as "how many whites does
94
+ * Benjamin Moore offer in paint".
95
+ */
96
+ export interface ColourStatsRow {
97
+ /** Opaque brand id — the join key for brand reads. Never parse it. */
98
+ brandId: string;
99
+ brandSlug: string;
100
+ brandName: string;
101
+ /**
102
+ * Product-type key. NULL means these variants carry NO accepted primary
103
+ * product type — a real population, kept so the matrix sums to the corpus,
104
+ * not an error and not a residual bucket.
105
+ */
106
+ categoryKey: string | null;
107
+ family: string;
108
+ /**
109
+ * Distinct variants at this (brand, category, family) carrying an ACCEPTED
110
+ * `colour_family`. Not every variant of the brand.
111
+ */
112
+ variants: number;
113
+ }
114
+ /** How to narrow the matrix. Passing ANY of these asks for `rows`. */
115
+ export interface ColourStatsParams {
116
+ /** `"brand,category"` — ask for the whole matrix, unscoped. */
117
+ groupBy?: string;
118
+ brandId?: string;
119
+ brandSlug?: string;
120
+ /**
121
+ * A product-type key, or the literal `"null"` for the unclassified
122
+ * population. Omitting it means every category — a different question.
123
+ */
124
+ categoryKey?: string;
125
+ family?: string;
126
+ limit?: number;
127
+ }
91
128
  /** Where each section came from, how fresh it is, and what it does NOT answer. */
92
129
  export interface ColourStatsBasis {
93
130
  corpus: string;
@@ -95,11 +132,32 @@ export interface ColourStatsBasis {
95
132
  groups: string;
96
133
  groupsRefreshedAt: string | null;
97
134
  groupsVariantCount: number;
135
+ /**
136
+ * Where `rows` came from, its freshness, and what it EXCLUDES — present only
137
+ * when `rows` is. Read it: the matrix deliberately omits Samplize, which is a
138
+ * sampling channel printing other manufacturers' colours rather than a maker.
139
+ */
140
+ rows?: string;
98
141
  omissions: string[];
99
142
  }
100
143
  export interface ColourStatsResponse {
101
144
  corpus: ColourStatsCorpus;
102
145
  families: ColourStatsFamily[];
103
146
  groups: ColourStatsGroup[];
147
+ /**
148
+ * The brand x category x colour-family matrix. Present ONLY when you asked
149
+ * for it; ABSENT means nobody asked, never that the matrix is empty.
150
+ *
151
+ * `families` above is NOT scoped by the same parameters and stays
152
+ * platform-wide under all of them. Scoped counts live here.
153
+ */
154
+ rows?: ColourStatsRow[];
155
+ /**
156
+ * Rows matching your query BEFORE the response cap — the honest total.
157
+ * A shortfall against `rows.length` means `rows` is a prefix.
158
+ */
159
+ rowsMatched?: number;
160
+ /** TRUE when the matrix exceeded the cap and `rows` is a prefix. */
161
+ rowsTruncated?: boolean;
104
162
  basis: ColourStatsBasis;
105
163
  }
@@ -32,7 +32,7 @@
32
32
  * FROM PRODUCT IMAGERY, not declared by the manufacturer. Report visual
33
33
  * likeness, never a stated colour specification.
34
34
  */
35
- import type { CategoryColourProfilesResponse, ColourProfilesParams, ColourStatsResponse } from "./colour-aggregate-types.js";
35
+ import type { CategoryColourProfilesResponse, ColourProfilesParams, ColourStatsParams, ColourStatsResponse } from "./colour-aggregate-types.js";
36
36
  import type { QueryParams } from "./http-transport.js";
37
37
  import type { SdkOperationId } from "./operations.js";
38
38
  import type { SearchGradientInput, SearchGradientResponse, SearchPaletteInput, SearchPaletteResponse } from "./palette-search-types.js";
@@ -87,8 +87,14 @@ export declare class ColoursClient {
87
87
  * coverage per product-type group. `basis` states the source and freshness of
88
88
  * each section plus `basis.omissions` — what this call deliberately does not
89
89
  * answer, listed rather than silently absent.
90
+ *
91
+ * Pass `{ groupBy: "brand,category" }` for the whole brand x category x
92
+ * family matrix in one call, or a `brandSlug`/`categoryKey` scope for a slice
93
+ * of it — either way it arrives as `rows`, each row carrying `brandId` and
94
+ * `brandSlug` to join on. Without any of those parameters the payload is the
95
+ * platform-wide one and `rows` is absent. `families` is never scoped by them.
90
96
  */
91
- stats(signal?: AbortSignal): Promise<ColourStatsResponse>;
97
+ stats(params?: ColourStatsParams, signal?: AbortSignal): Promise<ColourStatsResponse>;
92
98
  /**
93
99
  * THE QUESTION: "what goes with this WHOLE PALETTE?" — N colours at once, at
94
100
  * stated proportions, not one colour repeated (POST `/api/v1/search/palettes`).
package/colours-client.js CHANGED
@@ -53,9 +53,22 @@ export class ColoursClient {
53
53
  * coverage per product-type group. `basis` states the source and freshness of
54
54
  * each section plus `basis.omissions` — what this call deliberately does not
55
55
  * answer, listed rather than silently absent.
56
+ *
57
+ * Pass `{ groupBy: "brand,category" }` for the whole brand x category x
58
+ * family matrix in one call, or a `brandSlug`/`categoryKey` scope for a slice
59
+ * of it — either way it arrives as `rows`, each row carrying `brandId` and
60
+ * `brandSlug` to join on. Without any of those parameters the payload is the
61
+ * platform-wide one and `rows` is absent. `families` is never scoped by them.
56
62
  */
57
- stats(signal) {
58
- return this.#transport.get("get_colour_stats", undefined, signal);
63
+ stats(params = {}, signal) {
64
+ return this.#transport.get("get_colour_stats", {
65
+ groupBy: params.groupBy,
66
+ brandId: params.brandId,
67
+ brandSlug: params.brandSlug,
68
+ categoryKey: params.categoryKey,
69
+ family: params.family,
70
+ limit: params.limit,
71
+ }, signal);
59
72
  }
60
73
  /**
61
74
  * THE QUESTION: "what goes with this WHOLE PALETTE?" — N colours at once, at
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The COMPOSITION lens: the two synchronous scheme surfaces, as thin wrappers
3
+ * over the shared {@link HttpTransport}. `MaterialGraphClient.varyScheme` and
4
+ * `.slotPools` delegate here; the contract lives in this file.
5
+ *
6
+ * They are two altitudes of the same capability. `varyScheme` re-derives a
7
+ * scheme MaterialGraph itself composed; `slotPools` hands the ranked candidates
8
+ * to a composer that is not MaterialGraph, and keeps none of the ownership.
9
+ */
10
+ import type { VarySchemesRequest, VarySchemesResponse } from "./composition-types.js";
11
+ import { HttpTransport } from "./http-transport.js";
12
+ import type { SlotPoolsRequest, SlotPoolsResponse } from "./slot-pool-types.js";
13
+ /**
14
+ * THE QUESTION: "show me the same brief, decided differently." Re-derives an
15
+ * option B from a succeeded compose Run along ONE constraint axis. Deterministic
16
+ * and synchronous — the response IS the hydrated scheme (no Run envelope),
17
+ * stamped with axis + source provenance whose `notes` are the receipts.
18
+ * Requires the `mg:read` scope.
19
+ */
20
+ export declare function varyScheme(transport: HttpTransport, body: VarySchemesRequest, signal?: AbortSignal): Promise<VarySchemesResponse>;
21
+ /**
22
+ * THE QUESTION: "for each of these slots, what should I be choosing between?"
23
+ * Up to 24 self-contained tasks in, one ranked and gated candidate pool each
24
+ * out, correlated by YOUR `taskKey`. Synchronous, uncached and project-free —
25
+ * no Run, no programme, no state kept on the MaterialGraph side.
26
+ *
27
+ * READ THE POOLS, NOT JUST THE CANDIDATES. A task whose search failed comes back
28
+ * with a `search-failed` shortfall while the rest answer normally; a candidate
29
+ * with `eligible: false` is LABELLED rather than dropped (read `flags`); and a
30
+ * criterion that graded `missing` or `not_evaluated` was never a failure.
31
+ * Requires the `mg:read` scope.
32
+ */
33
+ export declare function slotPools(transport: HttpTransport, body: SlotPoolsRequest, signal?: AbortSignal): Promise<SlotPoolsResponse>;
@@ -0,0 +1,27 @@
1
+ import { HttpTransport } from "./http-transport.js";
2
+ import { resolveOperation } from "./operations.js";
3
+ /**
4
+ * THE QUESTION: "show me the same brief, decided differently." Re-derives an
5
+ * option B from a succeeded compose Run along ONE constraint axis. Deterministic
6
+ * and synchronous — the response IS the hydrated scheme (no Run envelope),
7
+ * stamped with axis + source provenance whose `notes` are the receipts.
8
+ * Requires the `mg:read` scope.
9
+ */
10
+ export function varyScheme(transport, body, signal) {
11
+ return transport.requestJson(resolveOperation("vary_schemes"), { body, signal });
12
+ }
13
+ /**
14
+ * THE QUESTION: "for each of these slots, what should I be choosing between?"
15
+ * Up to 24 self-contained tasks in, one ranked and gated candidate pool each
16
+ * out, correlated by YOUR `taskKey`. Synchronous, uncached and project-free —
17
+ * no Run, no programme, no state kept on the MaterialGraph side.
18
+ *
19
+ * READ THE POOLS, NOT JUST THE CANDIDATES. A task whose search failed comes back
20
+ * with a `search-failed` shortfall while the rest answer normally; a candidate
21
+ * with `eligible: false` is LABELLED rather than dropped (read `flags`); and a
22
+ * criterion that graded `missing` or `not_evaluated` was never a failure.
23
+ * Requires the `mg:read` scope.
24
+ */
25
+ export function slotPools(transport, body, signal) {
26
+ return transport.requestJson(resolveOperation("slot_pools"), { body, signal });
27
+ }
@@ -284,6 +284,34 @@ export interface ReviewProgrammeSuspendPayload {
284
284
  categorySource?: SlotCategorySource;
285
285
  provenance: ProgrammeProvenance;
286
286
  }>;
287
+ /**
288
+ * Lines this room usually carries that the brief never named.
289
+ *
290
+ * Offered, never imposed: a programme that proceeds without them is a legal
291
+ * answer. `essential` marks the ones whose absence makes the room unbuildable
292
+ * as specified; `ffe` marks furniture and lighting the catalogue does not
293
+ * serve yet, carried because a bedroom with no bed on the schedule is a gap
294
+ * worth seeing coming. Add one with an `add-slot` correction.
295
+ */
296
+ unstated?: Array<{
297
+ spaceId: string;
298
+ key: string;
299
+ name: string;
300
+ element: SlotElement;
301
+ /**
302
+ * Absent and `null` both mean the graph has no category for this line, and a
303
+ * reader must treat them as one answer.
304
+ *
305
+ * The distinction does not survive the wire. A `null` set server-side
306
+ * arrives as an absent key on the far side of the workflow runtime, so a
307
+ * client that branched on which one it received would be reading transport
308
+ * noise as meaning. An FF&E line the catalogue does not serve — a table
309
+ * lamp, bed linen, ironmongery — has no category under either reading.
310
+ */
311
+ category?: string | null;
312
+ weight: "essential" | "optional";
313
+ ffe?: boolean;
314
+ }>;
287
315
  }
288
316
  /**
289
317
  * Resume grammar for the `review-programme` step: drop a slot, drop a space
@@ -310,6 +338,24 @@ export interface ReviewProgrammeResumeData {
310
338
  action: "set-slot-category";
311
339
  slotId: string;
312
340
  category: string;
341
+ }
342
+ /**
343
+ * ADD a line the brief never named — usually one the payload offered under
344
+ * `unstated`, though any line is legal. Every other verb here subtracts,
345
+ * which made the programme a ceiling: whatever the brief happened to
346
+ * mention was the most a schedule could ever contain.
347
+ *
348
+ * `category` may be null or absent, because some real lines — grout,
349
+ * ironmongery, sanitaryware — have no catalog category yet. Such a slot is
350
+ * skipped at retrieval with a counted `no-category` shortfall, which is the
351
+ * honest treatment of a line we can hold but not yet fill.
352
+ */
353
+ | {
354
+ action: "add-slot";
355
+ spaceId: string;
356
+ name: string;
357
+ element: SlotElement;
358
+ category?: string | null;
313
359
  }>;
314
360
  }
315
361
  /**
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The COORDINATION lens: given several materials already chosen, what completes
3
+ * them. A thin wrapper over the shared {@link HttpTransport};
4
+ * `MaterialGraphClient.coordinate` delegates here.
5
+ *
6
+ * Extracted from `client.ts`, which sits above the repository's source-size
7
+ * limit, in the same per-lens shape as `brands-client` / `codes-client` /
8
+ * `colours-client`. Behaviour is unchanged.
9
+ */
10
+ import { HttpTransport } from "./http-transport.js";
11
+ import type { CoordinateInput, CoordinateResponse } from "./types.js";
12
+ /**
13
+ * THE QUESTION: "here is my whole scheme so far — what completes it?" The
14
+ * multi-seed form of `pairings`: lift is SUMMED across seeds, so a companion
15
+ * suiting one pick ranks below one suiting several. Returns demand-lift-ranked
16
+ * companions with colour swatches and an annotate-only `colourFit` that never
17
+ * reorders in v1.
18
+ *
19
+ * Instead use `pairings` for a single material, and `colours.palette()` when the
20
+ * scheme is COLOURS rather than materials. Check `unresolved` before presenting:
21
+ * a reference that resolved to nothing is named there, not dropped.
22
+ */
23
+ export declare function coordinate(transport: HttpTransport, input: CoordinateInput, signal?: AbortSignal): Promise<CoordinateResponse>;
@@ -0,0 +1,25 @@
1
+ /**
2
+ * The COORDINATION lens: given several materials already chosen, what completes
3
+ * them. A thin wrapper over the shared {@link HttpTransport};
4
+ * `MaterialGraphClient.coordinate` delegates here.
5
+ *
6
+ * Extracted from `client.ts`, which sits above the repository's source-size
7
+ * limit, in the same per-lens shape as `brands-client` / `codes-client` /
8
+ * `colours-client`. Behaviour is unchanged.
9
+ */
10
+ import { HttpTransport } from "./http-transport.js";
11
+ import { resolveOperation } from "./operations.js";
12
+ /**
13
+ * THE QUESTION: "here is my whole scheme so far — what completes it?" The
14
+ * multi-seed form of `pairings`: lift is SUMMED across seeds, so a companion
15
+ * suiting one pick ranks below one suiting several. Returns demand-lift-ranked
16
+ * companions with colour swatches and an annotate-only `colourFit` that never
17
+ * reorders in v1.
18
+ *
19
+ * Instead use `pairings` for a single material, and `colours.palette()` when the
20
+ * scheme is COLOURS rather than materials. Check `unresolved` before presenting:
21
+ * a reference that resolved to nothing is named there, not dropped.
22
+ */
23
+ export function coordinate(transport, input, signal) {
24
+ return transport.requestJson(resolveOperation("coordinate_materials"), { body: input, signal });
25
+ }
@@ -0,0 +1,110 @@
1
+ import type { VariantId } from "./identifiers.js";
2
+ export type GraphOperator = "colourways" | "same_category" | "still_listed" | "looks_like" | "same_colour" | "pairs_with" | "often_specified_with" | "substitutes_for" | "more_durable" | "outdoor_suitable" | "lower_cost" | "more_sustainable";
3
+ export interface GraphOperatorAvailability {
4
+ operator: GraphOperator;
5
+ operatorClass: "identity" | "perceptual" | "relational" | "spec";
6
+ label: string;
7
+ available: boolean;
8
+ basis: string;
9
+ count?: number;
10
+ }
11
+ export interface GraphOperatorEvidence {
12
+ variantId: VariantId;
13
+ operators: GraphOperatorAvailability[];
14
+ }
15
+ export interface CandidateReadInput {
16
+ operator: "looks_like";
17
+ corpusScope?: "all" | "materialBankOrderable";
18
+ limit?: number;
19
+ excludeVariantIds?: VariantId[];
20
+ }
21
+ export interface CandidateReadImage {
22
+ url: string;
23
+ source: "r2" | "origin";
24
+ /** Null means this image has not been analysed for a uniform light background. */
25
+ isIsolated: boolean | null;
26
+ }
27
+ export interface CandidateReadPaletteSwatch {
28
+ hex: string;
29
+ proportion: number;
30
+ name?: string | null;
31
+ }
32
+ export interface CandidateReadCard {
33
+ variantId: VariantId;
34
+ productId: string;
35
+ brandSlug: string;
36
+ materialBankId: string | null;
37
+ brand: string;
38
+ product: string;
39
+ variantName: string | null;
40
+ color: string | null;
41
+ image: CandidateReadImage | null;
42
+ palette: CandidateReadPaletteSwatch[];
43
+ }
44
+ export interface CandidateRankEvidence {
45
+ rank: number;
46
+ distance: number;
47
+ similarity: number;
48
+ basis: "active_main_image_embedding";
49
+ provenanceGrade: "measured";
50
+ displayImageMatchedEvidence: boolean | null;
51
+ }
52
+ export interface CandidateReadCandidate extends CandidateReadCard {
53
+ evidence: CandidateRankEvidence;
54
+ reason: string;
55
+ }
56
+ export interface CandidateSeedEvidence {
57
+ evidenceImageSha256: string;
58
+ displayImageSha256: string | null;
59
+ basis: "active_main_image_embedding";
60
+ provenanceGrade: "measured";
61
+ displayImageMatchedEvidence: boolean | null;
62
+ }
63
+ export interface CandidateReadReceipt {
64
+ operator: "looks_like";
65
+ corpusScope: {
66
+ scope: "all" | "materialBankOrderable";
67
+ description: string;
68
+ } | null;
69
+ requestedLimit: number;
70
+ returnedCount: number;
71
+ exclusions: {
72
+ requested: number;
73
+ unique: number;
74
+ applied: number;
75
+ };
76
+ dedupe: {
77
+ retrieved: number;
78
+ removed: number;
79
+ truncated: number;
80
+ projectionMisses: number;
81
+ };
82
+ timing: {
83
+ /** Internal seed projection completion; not a consumer response milestone. */
84
+ seedProjectionMs: number;
85
+ retrievalMs: number;
86
+ projectionMs: number;
87
+ completeMs: number;
88
+ };
89
+ }
90
+ interface CandidateReadResponseBase {
91
+ seed: CandidateReadCard;
92
+ receipt: CandidateReadReceipt;
93
+ }
94
+ export type CandidateReadResponse = (CandidateReadResponseBase & {
95
+ status: "ready";
96
+ seedEvidence: CandidateSeedEvidence;
97
+ candidates: CandidateReadCandidate[];
98
+ reason: null;
99
+ }) | (CandidateReadResponseBase & {
100
+ status: "no_candidates" | "no_unseen_candidates" | "bounded_retrieval_unavailable";
101
+ seedEvidence: CandidateSeedEvidence;
102
+ candidates: [];
103
+ reason: string;
104
+ }) | (CandidateReadResponseBase & {
105
+ status: "operator_unavailable";
106
+ seedEvidence: null;
107
+ candidates: [];
108
+ reason: string;
109
+ });
110
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -26,7 +26,10 @@ export interface FanDeckFamily {
26
26
  count: number;
27
27
  }
28
28
  export interface BrandFanDeck {
29
- /** The brands the deck covers, as resolved from the slug. */
29
+ /**
30
+ * The brand SLUGS the deck resolved to — round-trippable identifiers, not
31
+ * display names. The maker's name as it should be shown is on every swatch.
32
+ */
30
33
  brands: string[];
31
34
  /** Grouped by `families` order, light to dark within each family. */
32
35
  swatches: FanDeckSwatch[];
package/index.d.ts CHANGED
@@ -1,13 +1,15 @@
1
1
  export { MaterialGraphClient, DEFAULT_BASE_URL, MAX_BATCH_IDS, } from "./client.js";
2
- export type { MaterialGraphClientOptions, BrowseNamespace } from "./client.js";
2
+ export type { MaterialGraphClientOptions, BrowseNamespace, ExplorationNamespace, SourceMaterialCommentsNamespace, } from "./client.js";
3
3
  export { MATERIALGRAPH_API_VERSION, SDK_OPERATIONS } from "./operations.js";
4
4
  export type { SdkOperation, SdkOperationId } from "./operations.js";
5
5
  export type * from "./identifiers.js";
6
+ export type * from "./exploration-types.js";
6
7
  export { TERMINAL_RUN_EVENT_TYPES } from "./run-types.js";
7
8
  export type * from "./run-types.js";
8
9
  export type * from "./schedule-types.js";
9
10
  export { VARY_AXES } from "./composition-types.js";
10
11
  export type * from "./composition-types.js";
12
+ export type * from "./slot-pool-types.js";
11
13
  export { PROJECT_EVENT_KINDS } from "./project-types.js";
12
14
  export type * from "./project-types.js";
13
15
  export { COMPOSITION_PHASE_EVENT_TYPES, COMPOSITION_PROGRAMME_EVENT_TYPES, COMPOSITION_REVIEW_CRITERIA_EVENT_TYPES, parseRunEvent, } from "./run-events.js";
@@ -16,6 +18,7 @@ export { MaterialGraphError } from "./errors.js";
16
18
  export type { MaterialGraphErrorInit, MaterialGraphErrorKind, MaterialGraphRequestMetadata, ProblemDetail, RateLimit, SanitizedErrorValue, SanitizedIssue, SimpleErrorBody, } from "./errors.js";
17
19
  export type * from "./types.js";
18
20
  export type * from "./match-types.js";
21
+ export type * from "./browse-types.js";
19
22
  export type * from "./by-colour-types.js";
20
23
  export { MATCH_IMAGE_TYPES, MATCH_OUTCOMES, MATCH_MATERIAL_FUNCTIONS, MATCH_STREAM_EVENT_TYPES, MATCH_SURFACE_STATUSES, MATCH_WORKFLOW_STEPS, } from "./match-stream-types.js";
21
24
  export type * from "./match-stream-types.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 ["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 ["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 ["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 ["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 ["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 ["search", "POST", "/api/v1/search", "search_materials_post"], 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 ["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
@@ -24,6 +24,18 @@ const OPERATION_DEFINITIONS = [
24
24
  "/api/v1/materials/{variantId}/assets",
25
25
  "list_material_assets",
26
26
  ],
27
+ [
28
+ "exploration.operators",
29
+ "GET",
30
+ "/api/v1/materials/{variantId}/operators",
31
+ "list_material_operators",
32
+ ],
33
+ [
34
+ "exploration.candidates",
35
+ "POST",
36
+ "/api/v1/materials/{variantId}/candidates",
37
+ "read_material_candidates",
38
+ ],
27
39
  ["schema", "GET", "/api/v1/schema/blocks", "list_schema_blocks"],
28
40
  ["schema", "GET", "/api/v1/schema/attributes", "list_schema_attributes"],
29
41
  ["schema", "GET", "/api/v1/schema/verticals", "list_schema_verticals"],
@@ -176,6 +188,18 @@ const OPERATION_DEFINITIONS = [
176
188
  "/api/v1/source-material/{batchId}",
177
189
  "get_source_material_batch",
178
190
  ],
191
+ [
192
+ "sourceMaterialComments",
193
+ "GET",
194
+ "/api/v1/source-material/{batchId}/sources/{sourceId}/comments",
195
+ "list_source_material_comments",
196
+ ],
197
+ [
198
+ "sourceMaterialComments",
199
+ "POST",
200
+ "/api/v1/source-material/{batchId}/sources/{sourceId}/comments",
201
+ "post_source_material_comment",
202
+ ],
179
203
  ["capabilities", "GET", "/api/v1/capabilities", "list_public_capabilities"],
180
204
  ["createRun", "POST", "/api/v1/runs", "create_public_run"],
181
205
  ["listRuns", "GET", "/api/v1/runs", "list_public_runs"],
@@ -195,6 +219,7 @@ const OPERATION_DEFINITIONS = [
195
219
  ["resumeRun", "POST", "/api/v1/runs/{runId}/resume", "resume_public_run"],
196
220
  ["cancelRun", "POST", "/api/v1/runs/{runId}/cancel", "cancel_public_run"],
197
221
  ["varyScheme", "POST", "/api/v1/schemes/vary", "vary_schemes"],
222
+ ["slotPools", "POST", "/api/v1/schemes/pools", "slot_pools"],
198
223
  ["createProject", "POST", "/api/v1/projects", "create_box_project"],
199
224
  ["listProjects", "GET", "/api/v1/projects", "list_box_projects"],
200
225
  ["getProject", "GET", "/api/v1/projects/{projectId}", "get_box_project"],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@instruments/materialgraph",
3
- "version": "0.10.0",
3
+ "version": "0.11.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -86,6 +86,18 @@ export interface MultiColourMatchBase {
86
86
  imageUrl: string | null;
87
87
  /** MB has retired or hidden this SKU. */
88
88
  retired: boolean;
89
+ /**
90
+ * The catalog GROUP — "Flooring", "Textile Materials", "Coatings" — or null
91
+ * when the material has no accepted primary product type.
92
+ *
93
+ * A palette query is cross-category BY INTENT: a designer building a scheme,
94
+ * not browsing one aisle. So this is the field that says whether a result
95
+ * answers the question — one real palette returned 30 of 40 results in a
96
+ * single category while every one of the fourteen groups held something
97
+ * closer on the same colours (MG-1245). Group by it, and keep null as its own
98
+ * bucket: null means UNKNOWN, not uncategorised, and it is not rare.
99
+ */
100
+ category: string | null;
89
101
  /** The candidate's full extracted palette — the evidence scored against. */
90
102
  palette: CandidateSwatch[];
91
103
  /** The aggregate match score in [0,1]; higher is closer. */
@@ -105,6 +117,23 @@ export interface GradientMatch extends MultiColourMatchBase {
105
117
  /** One receipt per sampled point along the path, in path order. */
106
118
  samples: ColourMatchReceipt[];
107
119
  }
120
+ /**
121
+ * The hue-family ADMISSION gate the page was scored under: a candidate swatch
122
+ * may satisfy a query colour only if colorscope's `isHueCompatible` admits it
123
+ * at these exact thresholds. A refused swatch is absent from that colour's
124
+ * matching entirely — it did not merely rank low. Admission, not ranking: it
125
+ * decides which swatches count, never their order. Server-side and fixed (no
126
+ * request knob); the receipt exists so a threshold change is visible on the
127
+ * wire.
128
+ */
129
+ export interface HueGateReceipt {
130
+ /** Below this query chroma the colour is achromatic and any hue is admitted. */
131
+ achromaticQueryChroma: number;
132
+ /** A swatch must carry at least this share of the query colour's chroma. */
133
+ minChromaRatio: number;
134
+ /** Floor on the cosine agreement between the two hue vectors. */
135
+ minHueCosine: number;
136
+ }
108
137
  /**
109
138
  * A PAGE, NOT A CORPUS. `count` is `matches.length` under `limit` (24 default,
110
139
  * 48 max) — this surface states no corpus total and has no cursor, so "N
@@ -120,6 +149,8 @@ export interface SearchPaletteResponse {
120
149
  }>;
121
150
  logic: PaletteLogic;
122
151
  };
152
+ /** The hue-family admission gate this page was scored under. */
153
+ hueGate: HueGateReceipt;
123
154
  /** `matches.length`, capped by `limit`. Never a corpus total. */
124
155
  count: number;
125
156
  matches: PaletteMatch[];